diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/mvneta.c')
-rw-r--r-- | drivers/net/ethernet/marvell/mvneta.c | 88 |
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, |