summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/marvell/mvneta.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/marvell/mvneta.c')
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c88
1 files changed, 53 insertions, 35 deletions
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index bf1f5151c203..fb6d57deea56 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -286,7 +286,9 @@
#define MVNETA_LPI_CTRL_0 0x2cc0
#define MVNETA_LPI_CTRL_0_TS (0xff << 8)
#define MVNETA_LPI_CTRL_1 0x2cc4
-#define MVNETA_LPI_REQUEST_ENABLE BIT(0)
+#define MVNETA_LPI_CTRL_1_REQUEST_ENABLE BIT(0)
+#define MVNETA_LPI_CTRL_1_REQUEST_FORCE BIT(1)
+#define MVNETA_LPI_CTRL_1_MANUAL_MODE BIT(2)
#define MVNETA_LPI_CTRL_1_TW (0xfff << 4)
#define MVNETA_LPI_CTRL_2 0x2cc8
#define MVNETA_LPI_STATUS 0x2ccc
@@ -1779,7 +1781,7 @@ static int mvneta_txq_sent_desc_proc(struct mvneta_port *pp,
}
/* Set TXQ descriptors fields relevant for CSUM calculation */
-static u32 mvneta_txq_desc_csum(int l3_offs, int l3_proto,
+static u32 mvneta_txq_desc_csum(int l3_offs, __be16 l3_proto,
int ip_hdr_len, int l4_proto)
{
u32 command;
@@ -3859,7 +3861,7 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)
return -EINVAL;
}
- dev->mtu = mtu;
+ WRITE_ONCE(dev->mtu, mtu);
if (!netif_running(dev)) {
if (pp->bm_priv)
@@ -3958,8 +3960,8 @@ static struct mvneta_port *mvneta_pcs_to_port(struct phylink_pcs *pcs)
return container_of(pcs, struct mvneta_port, phylink_pcs);
}
-static unsigned int mvneta_pcs_query_inband(struct phylink_pcs *pcs,
- phy_interface_t interface)
+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
+ phy_interface_t interface)
{
/* When operating in an 802.3z mode, we must have AN enabled:
* "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
@@ -3981,7 +3983,7 @@ static unsigned int mvneta_pcs_query_inband(struct phylink_pcs *pcs,
return LINK_INBAND_DISABLE;
}
-static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
+static void mvneta_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
struct phylink_link_state *state)
{
struct mvneta_port *pp = mvneta_pcs_to_port(pcs);
@@ -4076,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct phylink_pcs *pcs)
}
static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
- .pcs_query_inband = mvneta_pcs_query_inband,
+ .pcs_inband_caps = mvneta_pcs_inband_caps,
.pcs_get_state = mvneta_pcs_get_state,
.pcs_config = mvneta_pcs_config,
.pcs_an_restart = mvneta_pcs_an_restart,
@@ -4276,23 +4278,31 @@ static void mvneta_mac_link_up(struct phylink_config *config,
mvneta_port_up(pp);
}
-static void mvneta_mac_disable_tx_lpi(struct phylink_config *config)
+static void mvneta_mac_disable_tx_lpi(struct phylink_config *config,
+ phy_interface_t interface)
{
struct mvneta_port *pp = netdev_priv(to_net_dev(config->dev));
u32 lpi1;
lpi1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
- lpi1 &= ~MVNETA_LPI_REQUEST_ENABLE;
+ lpi1 &= ~(MVNETA_LPI_CTRL_1_REQUEST_ENABLE |
+ MVNETA_LPI_CTRL_1_REQUEST_FORCE |
+ MVNETA_LPI_CTRL_1_MANUAL_MODE);
mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi1);
}
-static void mvneta_mac_enable_tx_lpi(struct phylink_config *config, u32 timer)
+static int mvneta_mac_enable_tx_lpi(struct phylink_config *config,
+ phy_interface_t interface, u32 timer,
+ bool tx_clk_stop)
{
struct mvneta_port *pp = netdev_priv(to_net_dev(config->dev));
u32 ts, tw, lpi0, lpi1, status;
- status = mvreg_read(pp, MVNETA_GMAC_STATUS);
+ if (interface != PHY_INTERFACE_MODE_SGMII &&
+ interface != PHY_INTERFACE_MODE_QSGMII)
+ return -EOPNOTSUPP;
+ status = mvreg_read(pp, MVNETA_GMAC_STATUS);
if (status & MVNETA_GMAC_SPEED_1000) {
/* At 1G speeds, the timer resolution are 1us, and
* 802.3 says tw is 16.5us. Round up to 17us.
@@ -4310,21 +4320,18 @@ static void mvneta_mac_enable_tx_lpi(struct phylink_config *config, u32 timer)
if (ts > 255)
ts = 255;
- /* Ensure LPI generation is disabled */
- lpi1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
- mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi1 & ~MVNETA_LPI_REQUEST_ENABLE);
-
/* Configure ts */
- lpi0 = mvreg_read(pp, MVNETA_LPI_CTRL_0) & ~MVNETA_LPI_CTRL_0_TS;
- lpi0 |= FIELD_PREP(MVNETA_LPI_CTRL_0_TS, ts);
+ lpi0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
+ lpi0 = u32_replace_bits(lpi0, ts, MVNETA_LPI_CTRL_0_TS);
mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi0);
- /* Configure tw */
- lpi1 &= ~MVNETA_LPI_CTRL_1_TW;
- lpi1 |= FIELD_PREP(MVNETA_LPI_CTRL_1_TW, tw);
+ /* Configure tw and enable LPI generation */
+ lpi1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
+ lpi1 = u32_replace_bits(lpi1, tw, MVNETA_LPI_CTRL_1_TW);
+ lpi1 |= MVNETA_LPI_CTRL_1_REQUEST_ENABLE;
+ mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi1);
- /* Enable LPI generation */
- mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi1 | MVNETA_LPI_REQUEST_ENABLE);
+ return 0;
}
static const struct phylink_mac_ops mvneta_phylink_ops = {
@@ -4423,6 +4430,7 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)
if (pp->neta_armada3700)
return 0;
+ netdev_lock(port->napi.dev);
spin_lock(&pp->lock);
/*
* Configuring the driver for a new CPU while the driver is
@@ -4430,6 +4438,7 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)
*/
if (pp->is_stopped) {
spin_unlock(&pp->lock);
+ netdev_unlock(port->napi.dev);
return 0;
}
netif_tx_stop_all_queues(pp->dev);
@@ -4449,7 +4458,7 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)
/* Mask all ethernet port interrupts */
on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
- napi_enable(&port->napi);
+ napi_enable_locked(&port->napi);
/*
* Enable per-CPU interrupts on the CPU that is
@@ -4470,6 +4479,8 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)
MVNETA_CAUSE_LINK_CHANGE);
netif_tx_start_all_queues(pp->dev);
spin_unlock(&pp->lock);
+ netdev_unlock(port->napi.dev);
+
return 0;
}
@@ -4833,11 +4844,9 @@ static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
int i;
for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
- memcpy(data + i * ETH_GSTRING_LEN,
- mvneta_statistics[i].name, ETH_GSTRING_LEN);
+ ethtool_puts(&data, mvneta_statistics[i].name);
if (!pp->bm_priv) {
- data += ETH_GSTRING_LEN * ARRAY_SIZE(mvneta_statistics);
page_pool_ethtool_stats_get_strings(data);
}
}
@@ -5136,7 +5145,7 @@ static int mvneta_ethtool_set_wol(struct net_device *dev,
}
static int mvneta_ethtool_get_eee(struct net_device *dev,
- struct ethtool_eee *eee)
+ struct ethtool_keee *eee)
{
struct mvneta_port *pp = netdev_priv(dev);
@@ -5144,10 +5153,16 @@ static int mvneta_ethtool_get_eee(struct net_device *dev,
}
static int mvneta_ethtool_set_eee(struct net_device *dev,
- struct ethtool_eee *eee)
+ struct ethtool_keee *eee)
{
struct mvneta_port *pp = netdev_priv(dev);
+ /* The Armada 37x documents do not give limits for this other than
+ * it being an 8-bit register.
+ */
+ if (eee->tx_lpi_enabled && eee->tx_lpi_timer > 255)
+ return -EINVAL;
+
return phylink_ethtool_set_eee(pp->phylink, eee);
}
@@ -5461,6 +5476,9 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
!phy_interface_mode_is_rgmii(phy_mode))
return -EINVAL;
+ /* Ensure LPI is disabled */
+ mvneta_mac_disable_tx_lpi(&pp->phylink_config, phy_mode);
+
return 0;
}
@@ -5551,8 +5569,13 @@ static int mvneta_probe(struct platform_device *pdev)
pp->phylink_config.type = PHYLINK_NETDEV;
pp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 |
MAC_100 | MAC_1000FD | MAC_2500FD;
+
+ /* Setup EEE. Choose 250us idle. Only supported in SGMII modes. */
+ __set_bit(PHY_INTERFACE_MODE_QSGMII, pp->phylink_config.lpi_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_SGMII, pp->phylink_config.lpi_interfaces);
pp->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD;
- pp->phylink_config.lpi_timer_limit_us = 255;
+ pp->phylink_config.lpi_timer_default = 250;
+ pp->phylink_config.eee_enabled_default = true;
phy_interface_set_rgmii(pp->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_QSGMII,
@@ -5580,11 +5603,6 @@ static int mvneta_probe(struct platform_device *pdev)
pp->phylink_config.supported_interfaces);
}
- /* Setup EEE. Choose 250us idle. */
- pp->phylink_config.eee.eee_enabled = true;
- pp->phylink_config.eee.tx_lpi_enabled = true;
- pp->phylink_config.eee.tx_lpi_timer = 250;
-
phylink = phylink_create(&pp->phylink_config, pdev->dev.fwnode,
phy_mode, &mvneta_phylink_ops);
if (IS_ERR(phylink)) {
@@ -5903,7 +5921,7 @@ MODULE_DEVICE_TABLE(of, mvneta_match);
static struct platform_driver mvneta_driver = {
.probe = mvneta_probe,
- .remove_new = mvneta_remove,
+ .remove = mvneta_remove,
.driver = {
.name = MVNETA_DRIVER_NAME,
.of_match_table = mvneta_match,