diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bcmsysport.c')
| -rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.c | 126 |
1 files changed, 59 insertions, 67 deletions
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 60dde29974bf..bc4e1f3b3752 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -27,30 +27,6 @@ #include "bcmsysport.h" -/* I/O accessors register helpers */ -#define BCM_SYSPORT_IO_MACRO(name, offset) \ -static inline u32 name##_readl(struct bcm_sysport_priv *priv, u32 off) \ -{ \ - u32 reg = readl_relaxed(priv->base + offset + off); \ - return reg; \ -} \ -static inline void name##_writel(struct bcm_sysport_priv *priv, \ - u32 val, u32 off) \ -{ \ - writel_relaxed(val, priv->base + offset + off); \ -} \ - -BCM_SYSPORT_IO_MACRO(intrl2_0, SYS_PORT_INTRL2_0_OFFSET); -BCM_SYSPORT_IO_MACRO(intrl2_1, SYS_PORT_INTRL2_1_OFFSET); -BCM_SYSPORT_IO_MACRO(umac, SYS_PORT_UMAC_OFFSET); -BCM_SYSPORT_IO_MACRO(gib, SYS_PORT_GIB_OFFSET); -BCM_SYSPORT_IO_MACRO(tdma, SYS_PORT_TDMA_OFFSET); -BCM_SYSPORT_IO_MACRO(rxchk, SYS_PORT_RXCHK_OFFSET); -BCM_SYSPORT_IO_MACRO(txchk, SYS_PORT_TXCHK_OFFSET); -BCM_SYSPORT_IO_MACRO(rbuf, SYS_PORT_RBUF_OFFSET); -BCM_SYSPORT_IO_MACRO(tbuf, SYS_PORT_TBUF_OFFSET); -BCM_SYSPORT_IO_MACRO(topctrl, SYS_PORT_TOPCTRL_OFFSET); - /* On SYSTEMPORT Lite, any register after RDMA_STATUS has the exact * same layout, except it has been moved by 4 bytes up, *sigh* */ @@ -295,6 +271,8 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = { /* RBUF misc statistics */ STAT_RBUF("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt, RBUF_OVFL_DISC_CNTR), STAT_RBUF("rbuf_err_cnt", mib.rbuf_err_cnt, RBUF_ERR_PKT_CNTR), + /* RDMA misc statistics */ + STAT_RDMA("rdma_ovflow_cnt", mib.rdma_ovflow_cnt, RDMA_OVFL_DISC_CNTR), STAT_MIB_SOFT("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), STAT_MIB_SOFT("rx_dma_failed", mib.rx_dma_failed), STAT_MIB_SOFT("tx_dma_failed", mib.tx_dma_failed), @@ -308,8 +286,8 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = { static void bcm_sysport_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strlcpy(info->bus_info, "platform", sizeof(info->bus_info)); + strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); + strscpy(info->bus_info, "platform", sizeof(info->bus_info)); } static u32 bcm_sysport_get_msglvl(struct net_device *dev) @@ -333,6 +311,7 @@ static inline bool bcm_sysport_lite_stat_valid(enum bcm_sysport_stat_type type) case BCM_SYSPORT_STAT_NETDEV64: case BCM_SYSPORT_STAT_RXCHK: case BCM_SYSPORT_STAT_RBUF: + case BCM_SYSPORT_STAT_RDMA: case BCM_SYSPORT_STAT_SOFT: return true; default: @@ -367,32 +346,22 @@ static void bcm_sysport_get_strings(struct net_device *dev, { struct bcm_sysport_priv *priv = netdev_priv(dev); const struct bcm_sysport_stats *s; - char buf[128]; - int i, j; + int i; switch (stringset) { case ETH_SS_STATS: - for (i = 0, j = 0; i < BCM_SYSPORT_STATS_LEN; i++) { + for (i = 0; i < BCM_SYSPORT_STATS_LEN; i++) { s = &bcm_sysport_gstrings_stats[i]; if (priv->is_lite && !bcm_sysport_lite_stat_valid(s->type)) continue; - memcpy(data + j * ETH_GSTRING_LEN, s->stat_string, - ETH_GSTRING_LEN); - j++; + ethtool_puts(&data, s->stat_string); } for (i = 0; i < dev->num_tx_queues; i++) { - snprintf(buf, sizeof(buf), "txq%d_packets", i); - memcpy(data + j * ETH_GSTRING_LEN, buf, - ETH_GSTRING_LEN); - j++; - - snprintf(buf, sizeof(buf), "txq%d_bytes", i); - memcpy(data + j * ETH_GSTRING_LEN, buf, - ETH_GSTRING_LEN); - j++; + ethtool_sprintf(&data, "txq%d_packets", i); + ethtool_sprintf(&data, "txq%d_bytes", i); } break; default: @@ -436,6 +405,14 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv) if (val == ~0) rbuf_writel(priv, 0, s->reg_offset); break; + case BCM_SYSPORT_STAT_RDMA: + if (!priv->is_lite) + continue; + + val = rdma_readl(priv, s->reg_offset); + if (val == ~0) + rdma_writel(priv, 0, s->reg_offset); + break; } j += s->stat_sizeof; @@ -457,10 +434,10 @@ static void bcm_sysport_update_tx_stats(struct bcm_sysport_priv *priv, for (q = 0; q < priv->netdev->num_tx_queues; q++) { ring = &priv->tx_rings[q]; do { - start = u64_stats_fetch_begin_irq(&priv->syncp); + start = u64_stats_fetch_begin(&priv->syncp); bytes = ring->bytes; packets = ring->packets; - } while (u64_stats_fetch_retry_irq(&priv->syncp, start)); + } while (u64_stats_fetch_retry(&priv->syncp, start)); *tx_bytes += bytes; *tx_packets += packets; @@ -504,9 +481,9 @@ static void bcm_sysport_get_stats(struct net_device *dev, if (s->stat_sizeof == sizeof(u64) && s->type == BCM_SYSPORT_STAT_NETDEV64) { do { - start = u64_stats_fetch_begin_irq(syncp); + start = u64_stats_fetch_begin(syncp); data[i] = *(u64 *)p; - } while (u64_stats_fetch_retry_irq(syncp, start)); + } while (u64_stats_fetch_retry(syncp, start)); } else data[i] = *(u32 *)p; j++; @@ -1042,7 +1019,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget) if (priv->dim.use_dim) { dim_update_sample(priv->dim.event_ctr, priv->dim.packets, priv->dim.bytes, &dim_sample); - net_dim(&priv->dim.dim, dim_sample); + net_dim(&priv->dim.dim, &dim_sample); } return work_done; @@ -1348,6 +1325,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n", skb->data, skb_len); ret = NETDEV_TX_OK; + dev_kfree_skb_any(skb); goto out; } @@ -1517,7 +1495,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv, /* Initialize SW view of the ring */ spin_lock_init(&ring->lock); ring->priv = priv; - netif_tx_napi_add(priv->netdev, &ring->napi, bcm_sysport_tx_poll, 64); + netif_napi_add_tx(priv->netdev, &ring->napi, bcm_sysport_tx_poll); ring->index = index; ring->size = size; ring->clean_index = 0; @@ -1878,10 +1856,10 @@ static void bcm_sysport_get_stats64(struct net_device *dev, &stats->tx_packets); do { - start = u64_stats_fetch_begin_irq(&priv->syncp); + start = u64_stats_fetch_begin(&priv->syncp); stats->rx_packets = stats64->rx_packets; stats->rx_bytes = stats64->rx_bytes; - } while (u64_stats_fetch_retry_irq(&priv->syncp, start)); + } while (u64_stats_fetch_retry(&priv->syncp, start)); } static void bcm_sysport_netif_start(struct net_device *dev) @@ -1955,7 +1933,11 @@ static int bcm_sysport_open(struct net_device *dev) unsigned int i; int ret; - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) { + netdev_err(dev, "could not enable priv clock\n"); + return ret; + } /* Reset UniMAC */ umac_reset(priv); @@ -1991,6 +1973,9 @@ static int bcm_sysport_open(struct net_device *dev) goto out_clk_disable; } + /* Indicate that the MAC is responsible for PHY PM */ + phydev->mac_managed_pm = true; + /* Reset house keeping link status */ priv->old_duplex = -1; priv->old_link = -1; @@ -2180,13 +2165,9 @@ static int bcm_sysport_rule_set(struct bcm_sysport_priv *priv, if (nfc->fs.ring_cookie != RX_CLS_FLOW_WAKE) return -EOPNOTSUPP; - /* All filters are already in use, we cannot match more rules */ - if (bitmap_weight(priv->filters, RXCHK_BRCM_TAG_MAX) == - RXCHK_BRCM_TAG_MAX) - return -ENOSPC; - index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX); if (index >= RXCHK_BRCM_TAG_MAX) + /* All filters are already in use, we cannot match more rules */ return -ENOSPC; /* Location is the classification ID, and index is the position @@ -2420,7 +2401,7 @@ static int bcm_sysport_netdevice_event(struct notifier_block *nb, if (dev->netdev_ops != &bcm_sysport_netdev_ops) return NOTIFY_DONE; - if (!dsa_slave_dev_check(info->upper_dev)) + if (!dsa_user_dev_check(info->upper_dev)) return NOTIFY_DONE; if (info->linking) @@ -2521,9 +2502,9 @@ static int bcm_sysport_probe(struct platform_device *pdev) priv->irq0 = platform_get_irq(pdev, 0); if (!priv->is_lite) { priv->irq1 = platform_get_irq(pdev, 1); - priv->wol_irq = platform_get_irq(pdev, 2); + priv->wol_irq = platform_get_irq_optional(pdev, 2); } else { - priv->wol_irq = platform_get_irq(pdev, 1); + priv->wol_irq = platform_get_irq_optional(pdev, 1); } if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) { ret = -EINVAL; @@ -2568,7 +2549,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, dev); dev->ethtool_ops = &bcm_sysport_ethtool_ops; dev->netdev_ops = &bcm_sysport_netdev_ops; - netif_napi_add(dev, &priv->napi, bcm_sysport_poll, 64); + netif_napi_add(dev, &priv->napi, bcm_sysport_poll); dev->features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | @@ -2585,8 +2566,10 @@ static int bcm_sysport_probe(struct platform_device *pdev) device_set_wakeup_capable(&pdev->dev, 1); priv->wol_clk = devm_clk_get_optional(&pdev->dev, "sw_sysportwol"); - if (IS_ERR(priv->wol_clk)) - return PTR_ERR(priv->wol_clk); + if (IS_ERR(priv->wol_clk)) { + ret = PTR_ERR(priv->wol_clk); + goto err_deregister_fixed_link; + } /* Set the needed headroom once and for all */ BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8); @@ -2612,7 +2595,11 @@ static int bcm_sysport_probe(struct platform_device *pdev) goto err_deregister_notifier; } - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(&pdev->dev, "could not enable priv clock\n"); + goto err_deregister_netdev; + } priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; dev_info(&pdev->dev, @@ -2626,6 +2613,8 @@ static int bcm_sysport_probe(struct platform_device *pdev) return 0; +err_deregister_netdev: + unregister_netdev(dev); err_deregister_notifier: unregister_netdevice_notifier(&priv->netdev_notifier); err_deregister_fixed_link: @@ -2636,7 +2625,7 @@ err_free_netdev: return ret; } -static int bcm_sysport_remove(struct platform_device *pdev) +static void bcm_sysport_remove(struct platform_device *pdev) { struct net_device *dev = dev_get_drvdata(&pdev->dev); struct bcm_sysport_priv *priv = netdev_priv(dev); @@ -2651,8 +2640,6 @@ static int bcm_sysport_remove(struct platform_device *pdev) of_phy_deregister_fixed_link(dn); free_netdev(dev); dev_set_drvdata(&pdev->dev, NULL); - - return 0; } static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv) @@ -2797,7 +2784,12 @@ static int __maybe_unused bcm_sysport_resume(struct device *d) if (!netif_running(dev)) return 0; - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) { + netdev_err(dev, "could not enable priv clock\n"); + return ret; + } + if (priv->wolopts) clk_disable_unprepare(priv->wol_clk); @@ -2889,7 +2881,7 @@ static SIMPLE_DEV_PM_OPS(bcm_sysport_pm_ops, static struct platform_driver bcm_sysport_driver = { .probe = bcm_sysport_probe, - .remove = bcm_sysport_remove, + .remove = bcm_sysport_remove, .driver = { .name = "brcm-systemport", .of_match_table = bcm_sysport_of_match, |
