diff options
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
-rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 211 |
1 files changed, 138 insertions, 73 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index decfbf91e83d..c1f57d96e63f 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -38,6 +38,7 @@ #include <linux/ptp_classify.h> #include <linux/reset.h> #include <linux/firmware/xlnx-zynqmp.h> +#include <linux/inetdevice.h> #include "macb.h" /* This structure is only used for MACB on SiFive FU540 devices */ @@ -84,8 +85,7 @@ struct sifive_fu540_macb_mgmt { #define GEM_MTU_MIN_SIZE ETH_MIN_MTU #define MACB_NETIF_LSO NETIF_F_TSO -#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) -#define MACB_WOL_ENABLED (0x1 << 1) +#define MACB_WOL_ENABLED BIT(0) #define HS_SPEED_10000M 4 #define MACB_SERDES_RATE_10G 1 @@ -530,19 +530,9 @@ static void macb_set_tx_clk(struct macb *bp, int speed) if (bp->phy_interface == PHY_INTERFACE_MODE_MII) return; - switch (speed) { - case SPEED_10: - rate = 2500000; - break; - case SPEED_100: - rate = 25000000; - break; - case SPEED_1000: - rate = 125000000; - break; - default: + rate = rgmii_clock(speed); + if (rate < 0) return; - } rate_rounded = clk_round_rate(bp->tx_clk, rate); if (rate_rounded < 0) @@ -578,6 +568,7 @@ static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, } static void macb_usx_pcs_get_state(struct phylink_pcs *pcs, + unsigned int neg_mode, struct phylink_link_state *state) { struct macb *bp = container_of(pcs, struct macb, phylink_usx_pcs); @@ -608,7 +599,7 @@ static int macb_usx_pcs_config(struct phylink_pcs *pcs, return 0; } -static void macb_pcs_get_state(struct phylink_pcs *pcs, +static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, struct phylink_link_state *state) { state->link = 0; @@ -687,7 +678,7 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode, u32 pcsctrl, old_pcsctrl; old_pcsctrl = gem_readl(bp, PCSCNTRL); - if (phylink_mode_fixed(mode)) + if (mode == MLO_AN_FIXED) pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG); else pcsctrl = old_pcsctrl | GEM_BIT(PCSAUTONEG); @@ -915,23 +906,15 @@ static int macb_mii_probe(struct net_device *dev) return 0; } -static int macb_mdiobus_register(struct macb *bp) +static int macb_mdiobus_register(struct macb *bp, struct device_node *mdio_np) { struct device_node *child, *np = bp->pdev->dev.of_node; /* If we have a child named mdio, probe it instead of looking for PHYs * directly under the MAC node */ - child = of_get_child_by_name(np, "mdio"); - if (child) { - int ret = of_mdiobus_register(bp->mii_bus, child); - - of_node_put(child); - return ret; - } - - if (of_phy_is_fixed_link(np)) - return mdiobus_register(bp->mii_bus); + if (mdio_np) + return of_mdiobus_register(bp->mii_bus, mdio_np); /* Only create the PHY from the device tree if at least one PHY is * described. Otherwise scan the entire MDIO bus. We do this to support @@ -953,8 +936,17 @@ static int macb_mdiobus_register(struct macb *bp) static int macb_mii_init(struct macb *bp) { + struct device_node *mdio_np, *np = bp->pdev->dev.of_node; int err = -ENXIO; + /* With fixed-link, we don't need to register the MDIO bus, + * except if we have a child named "mdio" in the device tree. + * In that case, some devices may be attached to the MACB's MDIO bus. + */ + mdio_np = of_get_child_by_name(np, "mdio"); + if (!mdio_np && of_phy_is_fixed_link(np)) + return macb_mii_probe(bp->dev); + /* Enable management port */ macb_writel(bp, NCR, MACB_BIT(MPE)); @@ -976,7 +968,7 @@ static int macb_mii_init(struct macb *bp) dev_set_drvdata(&bp->dev->dev, bp->mii_bus); - err = macb_mdiobus_register(bp); + err = macb_mdiobus_register(bp, mdio_np); if (err) goto err_out_free_mdiobus; @@ -991,6 +983,8 @@ err_out_unregister_bus: err_out_free_mdiobus: mdiobus_free(bp->mii_bus); err_out: + of_node_put(mdio_np); + return err; } @@ -1792,9 +1786,9 @@ static int macb_tx_poll(struct napi_struct *napi, int budget) return work_done; } -static void macb_hresp_error_task(struct tasklet_struct *t) +static void macb_hresp_error_task(struct work_struct *work) { - struct macb *bp = from_tasklet(bp, t, hresp_err_tasklet); + struct macb *bp = from_work(bp, work, hresp_err_bh_work); struct net_device *dev = bp->dev; struct macb_queue *queue; unsigned int q; @@ -1984,17 +1978,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (status & MACB_BIT(ISR_ROVR)) { /* We missed at least one packet */ + spin_lock(&bp->stats_lock); if (macb_is_gem(bp)) bp->hw_stats.gem.rx_overruns++; else bp->hw_stats.macb.rx_overruns++; + spin_unlock(&bp->stats_lock); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) queue_writel(queue, ISR, MACB_BIT(ISR_ROVR)); } if (status & MACB_BIT(HRESP)) { - tasklet_schedule(&bp->hresp_err_tasklet); + queue_work(system_bh_wq, &bp->hresp_err_bh_work); netdev_err(dev, "DMA bus error: HRESP not OK\n"); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) @@ -2477,6 +2473,12 @@ static void macb_free_consistent(struct macb *bp) unsigned int q; int size; + if (bp->rx_ring_tieoff) { + dma_free_coherent(&bp->pdev->dev, macb_dma_desc_get_size(bp), + bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma); + bp->rx_ring_tieoff = NULL; + } + bp->macbgem_ops.mog_free_rx_buffers(bp); for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { @@ -2568,6 +2570,16 @@ static int macb_alloc_consistent(struct macb *bp) if (bp->macbgem_ops.mog_alloc_rx_buffers(bp)) goto out_err; + /* Required for tie off descriptor for PM cases */ + if (!(bp->caps & MACB_CAPS_QUEUE_DISABLE)) { + bp->rx_ring_tieoff = dma_alloc_coherent(&bp->pdev->dev, + macb_dma_desc_get_size(bp), + &bp->rx_ring_tieoff_dma, + GFP_KERNEL); + if (!bp->rx_ring_tieoff) + goto out_err; + } + return 0; out_err: @@ -2575,6 +2587,19 @@ out_err: return -ENOMEM; } +static void macb_init_tieoff(struct macb *bp) +{ + struct macb_dma_desc *desc = bp->rx_ring_tieoff; + + if (bp->caps & MACB_CAPS_QUEUE_DISABLE) + return; + /* Setup a wrapping descriptor with no free slots + * (WRAP and USED) to tie off/disable unused RX queues. + */ + macb_set_addr(bp, desc, MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED)); + desc->ctrl = 0; +} + static void gem_init_rings(struct macb *bp) { struct macb_queue *queue; @@ -2598,6 +2623,7 @@ static void gem_init_rings(struct macb *bp) gem_rx_refill(queue); } + macb_init_tieoff(bp); } static void macb_init_rings(struct macb *bp) @@ -2615,6 +2641,8 @@ static void macb_init_rings(struct macb *bp) bp->queues[0].tx_head = 0; bp->queues[0].tx_tail = 0; desc->ctrl |= MACB_BIT(TX_WRAP); + + macb_init_tieoff(bp); } static void macb_reset_hw(struct macb *bp) @@ -3022,7 +3050,7 @@ static int macb_change_mtu(struct net_device *dev, int new_mtu) if (netif_running(dev)) return -EBUSY; - dev->mtu = new_mtu; + WRITE_ONCE(dev->mtu, new_mtu); return 0; } @@ -3076,6 +3104,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) if (!netif_running(bp->dev)) return nstat; + spin_lock_irq(&bp->stats_lock); gem_update_stats(bp); nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors + @@ -3105,6 +3134,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) nstat->tx_aborted_errors = hwstat->tx_excessive_collisions; nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors; nstat->tx_fifo_errors = hwstat->tx_underrun; + spin_unlock_irq(&bp->stats_lock); return nstat; } @@ -3112,12 +3142,13 @@ static struct net_device_stats *gem_get_stats(struct macb *bp) static void gem_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { - struct macb *bp; + struct macb *bp = netdev_priv(dev); - bp = netdev_priv(dev); + spin_lock_irq(&bp->stats_lock); gem_update_stats(bp); memcpy(data, &bp->ethtool_stats, sizeof(u64) * (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES)); + spin_unlock_irq(&bp->stats_lock); } static int gem_get_sset_count(struct net_device *dev, int sset) @@ -3167,6 +3198,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) return gem_get_stats(bp); /* read stats from hardware */ + spin_lock_irq(&bp->stats_lock); macb_update_stats(bp); /* Convert HW stats into netdevice stats */ @@ -3200,6 +3232,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) nstat->tx_carrier_errors = hwstat->tx_carrier_errors; nstat->tx_fifo_errors = hwstat->tx_underruns; /* Don't know about heartbeat or window errors... */ + spin_unlock_irq(&bp->stats_lock); return nstat; } @@ -3246,13 +3279,11 @@ static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct macb *bp = netdev_priv(netdev); - if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) { - phylink_ethtool_get_wol(bp->phylink, wol); - wol->supported |= WAKE_MAGIC; + phylink_ethtool_get_wol(bp->phylink, wol); + wol->supported |= (WAKE_MAGIC | WAKE_ARP); - if (bp->wol & MACB_WOL_ENABLED) - wol->wolopts |= WAKE_MAGIC; - } + /* Add macb wolopts to phy wolopts */ + wol->wolopts |= bp->wolopts; } static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) @@ -3262,22 +3293,15 @@ static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) /* Pass the order to phylink layer */ ret = phylink_ethtool_set_wol(bp->phylink, wol); - /* Don't manage WoL on MAC if handled by the PHY - * or if there's a failure in talking to the PHY - */ - if (!ret || ret != -EOPNOTSUPP) + /* Don't manage WoL on MAC, if PHY set_wol() fails */ + if (ret && ret != -EOPNOTSUPP) return ret; - if (!(bp->wol & MACB_WOL_HAS_MAGIC_PACKET) || - (wol->wolopts & ~WAKE_MAGIC)) - return -EOPNOTSUPP; - - if (wol->wolopts & WAKE_MAGIC) - bp->wol |= MACB_WOL_ENABLED; - else - bp->wol &= ~MACB_WOL_ENABLED; + bp->wolopts = (wol->wolopts & WAKE_MAGIC) ? WAKE_MAGIC : 0; + bp->wolopts |= (wol->wolopts & WAKE_ARP) ? WAKE_ARP : 0; + bp->wol = (wol->wolopts) ? MACB_WOL_ENABLED : 0; - device_set_wakeup_enable(&bp->pdev->dev, bp->wol & MACB_WOL_ENABLED); + device_set_wakeup_enable(&bp->pdev->dev, bp->wol); return 0; } @@ -3376,7 +3400,7 @@ static s32 gem_get_ptp_max_adj(void) } static int gem_get_ts_info(struct net_device *dev, - struct ethtool_ts_info *info) + struct kernel_ethtool_ts_info *info) { struct macb *bp = netdev_priv(dev); @@ -3387,8 +3411,6 @@ static int gem_get_ts_info(struct net_device *dev, info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; @@ -3400,7 +3422,8 @@ static int gem_get_ts_info(struct net_device *dev, (1 << HWTSTAMP_FILTER_NONE) | (1 << HWTSTAMP_FILTER_ALL); - info->phc_index = bp->ptp_clock ? ptp_clock_index(bp->ptp_clock) : -1; + if (bp->ptp_clock) + info->phc_index = ptp_clock_index(bp->ptp_clock); return 0; } @@ -3417,7 +3440,7 @@ static struct macb_ptp_info gem_ptp_info = { #endif static int macb_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info) + struct kernel_ethtool_ts_info *info) { struct macb *bp = netdev_priv(netdev); @@ -4161,6 +4184,8 @@ static int macb_init(struct platform_device *pdev) dev->ethtool_ops = &macb_ethtool_ops; } + netdev_sw_irq_coalesce_default_on(dev); + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; /* Set features */ @@ -4817,10 +4842,11 @@ static const struct macb_config pc302gem_config = { }; static const struct macb_config sama5d2_config = { - .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, + .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_JUMBO, .dma_burst_length = 16, .clk_init = macb_clk_init, .init = macb_init, + .jumbo_max_len = 10240, .usrio = &macb_default_usrio, }; @@ -4917,7 +4943,8 @@ static const struct macb_config sama7g5_emac_config = { static const struct macb_config versal_config = { .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO | - MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH | MACB_CAPS_NEED_TSUCLK, + MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH | MACB_CAPS_NEED_TSUCLK | + MACB_CAPS_QUEUE_DISABLE, .dma_burst_length = 16, .clk_init = macb_clk_init, .init = init_reset_optional, @@ -5053,9 +5080,7 @@ static int macb_probe(struct platform_device *pdev) bp->max_tx_length = GEM_MAX_TX_LEN; bp->wol = 0; - if (of_property_read_bool(np, "magic-packet")) - bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; - device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET); + device_set_wakeup_capable(&pdev->dev, 1); bp->usrio = macb_config->usrio; @@ -5079,6 +5104,7 @@ static int macb_probe(struct platform_device *pdev) } } spin_lock_init(&bp->lock); + spin_lock_init(&bp->stats_lock); /* setup capabilities */ macb_configure_caps(bp, macb_config); @@ -5097,12 +5123,12 @@ static int macb_probe(struct platform_device *pdev) goto err_out_free_netdev; } - /* MTU range: 68 - 1500 or 10240 */ + /* MTU range: 68 - 1518 or 10240 */ dev->min_mtu = GEM_MTU_MIN_SIZE; if ((bp->caps & MACB_CAPS_JUMBO) && bp->jumbo_max_len) dev->max_mtu = bp->jumbo_max_len - ETH_HLEN - ETH_FCS_LEN; else - dev->max_mtu = ETH_DATA_LEN; + dev->max_mtu = 1536 - ETH_HLEN - ETH_FCS_LEN; if (bp->caps & MACB_CAPS_BD_RD_PREFETCH) { val = GEM_BFEXT(RXBD_RDBUFF, gem_readl(bp, DCFG10)); @@ -5150,7 +5176,7 @@ static int macb_probe(struct platform_device *pdev) goto err_out_unregister_mdio; } - tasklet_setup(&bp->hresp_err_tasklet, macb_hresp_error_task); + INIT_WORK(&bp->hresp_err_bh_work, macb_hresp_error_task); netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n", macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID), @@ -5194,7 +5220,7 @@ static void macb_remove(struct platform_device *pdev) mdiobus_free(bp->mii_bus); unregister_netdev(dev); - tasklet_kill(&bp->hresp_err_tasklet); + cancel_work_sync(&bp->hresp_err_bh_work); pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); if (!pm_runtime_suspended(&pdev->dev)) { @@ -5211,10 +5237,13 @@ static int __maybe_unused macb_suspend(struct device *dev) { struct net_device *netdev = dev_get_drvdata(dev); struct macb *bp = netdev_priv(netdev); + struct in_ifaddr *ifa = NULL; struct macb_queue *queue; + struct in_device *idev; unsigned long flags; unsigned int q; int err; + u32 tmp; if (!device_may_wakeup(&bp->dev->dev)) phy_exit(bp->sgmii_phy); @@ -5223,18 +5252,54 @@ static int __maybe_unused macb_suspend(struct device *dev) return 0; if (bp->wol & MACB_WOL_ENABLED) { + /* Check for IP address in WOL ARP mode */ + idev = __in_dev_get_rcu(bp->dev); + if (idev) + ifa = rcu_dereference(idev->ifa_list); + if ((bp->wolopts & WAKE_ARP) && !ifa) { + netdev_err(netdev, "IP address not assigned as required by WoL walk ARP\n"); + return -EOPNOTSUPP; + } spin_lock_irqsave(&bp->lock, flags); - /* Flush all status bits */ - macb_writel(bp, TSR, -1); - macb_writel(bp, RSR, -1); + + /* Disable Tx and Rx engines before disabling the queues, + * this is mandatory as per the IP spec sheet + */ + tmp = macb_readl(bp, NCR); + macb_writel(bp, NCR, tmp & ~(MACB_BIT(TE) | MACB_BIT(RE))); for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { + /* Disable RX queues */ + if (bp->caps & MACB_CAPS_QUEUE_DISABLE) { + queue_writel(queue, RBQP, MACB_BIT(QUEUE_DISABLE)); + } else { + /* Tie off RX queues */ + queue_writel(queue, RBQP, + lower_32_bits(bp->rx_ring_tieoff_dma)); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + queue_writel(queue, RBQPH, + upper_32_bits(bp->rx_ring_tieoff_dma)); +#endif + } /* Disable all interrupts */ queue_writel(queue, IDR, -1); queue_readl(queue, ISR); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) queue_writel(queue, ISR, -1); } + /* Enable Receive engine */ + macb_writel(bp, NCR, tmp | MACB_BIT(RE)); + /* Flush all status bits */ + macb_writel(bp, TSR, -1); + macb_writel(bp, RSR, -1); + + tmp = (bp->wolopts & WAKE_MAGIC) ? MACB_BIT(MAG) : 0; + if (bp->wolopts & WAKE_ARP) { + tmp |= MACB_BIT(ARP); + /* write IP address into register */ + tmp |= MACB_BFEXT(IP, be32_to_cpu(ifa->ifa_local)); + } + /* Change interrupt handler and * Enable WoL IRQ on queue 0 */ @@ -5250,7 +5315,7 @@ static int __maybe_unused macb_suspend(struct device *dev) return err; } queue_writel(bp->queues, IER, GEM_BIT(WOL)); - gem_writel(bp, WOL, MACB_BIT(MAG)); + gem_writel(bp, WOL, tmp); } else { err = devm_request_irq(dev, bp->queues[0].irq, macb_wol_interrupt, IRQF_SHARED, netdev->name, bp->queues); @@ -5262,7 +5327,7 @@ static int __maybe_unused macb_suspend(struct device *dev) return err; } queue_writel(bp->queues, IER, MACB_BIT(WOL)); - macb_writel(bp, WOL, MACB_BIT(MAG)); + macb_writel(bp, WOL, tmp); } spin_unlock_irqrestore(&bp->lock, flags); @@ -5420,7 +5485,7 @@ static const struct dev_pm_ops macb_pm_ops = { static struct platform_driver macb_driver = { .probe = macb_probe, - .remove_new = macb_remove, + .remove = macb_remove, .driver = { .name = "macb", .of_match_table = of_match_ptr(macb_dt_ids), |