aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/cadence/macb_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c134
1 files changed, 94 insertions, 40 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index c049410bc888..262a28ff81fc 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Cadence MACB/GEM Ethernet Controller driver
*
* Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -2849,10 +2846,14 @@ static int macb_get_ts_info(struct net_device *netdev,
static void gem_enable_flow_filters(struct macb *bp, bool enable)
{
+ struct net_device *netdev = bp->dev;
struct ethtool_rx_fs_item *item;
u32 t2_scr;
int num_t2_scr;
+ if (!(netdev->features & NETIF_F_NTUPLE))
+ return;
+
num_t2_scr = GEM_BFEXT(T2SCR, gem_readl(bp, DCFG8));
list_for_each_entry(item, &bp->rx_fs_list.list, list) {
@@ -3012,8 +3013,7 @@ static int gem_add_flow_filter(struct net_device *netdev,
gem_prog_cmp_regs(bp, fs);
bp->rx_fs_list.count++;
/* enable filtering if NTUPLE on */
- if (netdev->features & NETIF_F_NTUPLE)
- gem_enable_flow_filters(bp, 1);
+ gem_enable_flow_filters(bp, 1);
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
return 0;
@@ -3201,6 +3201,50 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
}
+static inline void macb_set_txcsum_feature(struct macb *bp,
+ netdev_features_t features)
+{
+ u32 val;
+
+ if (!macb_is_gem(bp))
+ return;
+
+ val = gem_readl(bp, DMACFG);
+ if (features & NETIF_F_HW_CSUM)
+ val |= GEM_BIT(TXCOEN);
+ else
+ val &= ~GEM_BIT(TXCOEN);
+
+ gem_writel(bp, DMACFG, val);
+}
+
+static inline void macb_set_rxcsum_feature(struct macb *bp,
+ netdev_features_t features)
+{
+ struct net_device *netdev = bp->dev;
+ u32 val;
+
+ if (!macb_is_gem(bp))
+ return;
+
+ val = gem_readl(bp, NCFGR);
+ if ((features & NETIF_F_RXCSUM) && !(netdev->flags & IFF_PROMISC))
+ val |= GEM_BIT(RXCOEN);
+ else
+ val &= ~GEM_BIT(RXCOEN);
+
+ gem_writel(bp, NCFGR, val);
+}
+
+static inline void macb_set_rxflow_feature(struct macb *bp,
+ netdev_features_t features)
+{
+ if (!macb_is_gem(bp))
+ return;
+
+ gem_enable_flow_filters(bp, !!(features & NETIF_F_NTUPLE));
+}
+
static int macb_set_features(struct net_device *netdev,
netdev_features_t features)
{
@@ -3208,39 +3252,35 @@ static int macb_set_features(struct net_device *netdev,
netdev_features_t changed = features ^ netdev->features;
/* TX checksum offload */
- if ((changed & NETIF_F_HW_CSUM) && macb_is_gem(bp)) {
- u32 dmacfg;
-
- dmacfg = gem_readl(bp, DMACFG);
- if (features & NETIF_F_HW_CSUM)
- dmacfg |= GEM_BIT(TXCOEN);
- else
- dmacfg &= ~GEM_BIT(TXCOEN);
- gem_writel(bp, DMACFG, dmacfg);
- }
+ if (changed & NETIF_F_HW_CSUM)
+ macb_set_txcsum_feature(bp, features);
/* RX checksum offload */
- if ((changed & NETIF_F_RXCSUM) && macb_is_gem(bp)) {
- u32 netcfg;
-
- netcfg = gem_readl(bp, NCFGR);
- if (features & NETIF_F_RXCSUM &&
- !(netdev->flags & IFF_PROMISC))
- netcfg |= GEM_BIT(RXCOEN);
- else
- netcfg &= ~GEM_BIT(RXCOEN);
- gem_writel(bp, NCFGR, netcfg);
- }
+ if (changed & NETIF_F_RXCSUM)
+ macb_set_rxcsum_feature(bp, features);
/* RX Flow Filters */
- if ((changed & NETIF_F_NTUPLE) && macb_is_gem(bp)) {
- bool turn_on = features & NETIF_F_NTUPLE;
+ if (changed & NETIF_F_NTUPLE)
+ macb_set_rxflow_feature(bp, features);
- gem_enable_flow_filters(bp, turn_on);
- }
return 0;
}
+static void macb_restore_features(struct macb *bp)
+{
+ struct net_device *netdev = bp->dev;
+ netdev_features_t features = netdev->features;
+
+ /* TX checksum offload */
+ macb_set_txcsum_feature(bp, features);
+
+ /* RX checksum offload */
+ macb_set_rxcsum_feature(bp, features);
+
+ /* RX Flow Filters */
+ macb_set_rxflow_feature(bp, features);
+}
+
static const struct net_device_ops macb_netdev_ops = {
.ndo_open = macb_open,
.ndo_stop = macb_close,
@@ -3343,7 +3383,7 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
if (!err)
err = -ENODEV;
- dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to get macb_clk (%d)\n", err);
return err;
}
@@ -3352,7 +3392,7 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
if (!err)
err = -ENODEV;
- dev_err(&pdev->dev, "failed to get hclk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to get hclk (%d)\n", err);
return err;
}
@@ -3370,31 +3410,31 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
err = clk_prepare_enable(*pclk);
if (err) {
- dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to enable pclk (%d)\n", err);
return err;
}
err = clk_prepare_enable(*hclk);
if (err) {
- dev_err(&pdev->dev, "failed to enable hclk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to enable hclk (%d)\n", err);
goto err_disable_pclk;
}
err = clk_prepare_enable(*tx_clk);
if (err) {
- dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to enable tx_clk (%d)\n", err);
goto err_disable_hclk;
}
err = clk_prepare_enable(*rx_clk);
if (err) {
- dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to enable rx_clk (%d)\n", err);
goto err_disable_txclk;
}
err = clk_prepare_enable(*tsu_clk);
if (err) {
- dev_err(&pdev->dev, "failed to enable tsu_clk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to enable tsu_clk (%d)\n", err);
goto err_disable_rxclk;
}
@@ -3868,7 +3908,7 @@ static int at91ether_clk_init(struct platform_device *pdev, struct clk **pclk,
err = clk_prepare_enable(*pclk);
if (err) {
- dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err);
+ dev_err(&pdev->dev, "failed to enable pclk (%d)\n", err);
return err;
}
@@ -4140,7 +4180,7 @@ static int macb_probe(struct platform_device *pdev)
if (PTR_ERR(mac) == -EPROBE_DEFER) {
err = -EPROBE_DEFER;
goto err_out_free_netdev;
- } else if (!IS_ERR(mac)) {
+ } else if (!IS_ERR_OR_NULL(mac)) {
ether_addr_copy(bp->dev->dev_addr, mac);
} else {
macb_get_hwaddr(bp);
@@ -4273,6 +4313,12 @@ static int __maybe_unused macb_suspend(struct device *dev)
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
spin_unlock_irqrestore(&bp->lock, flags);
+
+ if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
+ bp->pm_data.usrio = macb_or_gem_readl(bp, USRIO);
+
+ if (netdev->hw_features & NETIF_F_NTUPLE)
+ bp->pm_data.scrt2 = gem_readl_n(bp, ETHT, SCRT2_ETHT);
}
netif_carrier_off(netdev);
@@ -4301,6 +4347,13 @@ static int __maybe_unused macb_resume(struct device *dev)
disable_irq_wake(bp->queues[0].irq);
} else {
macb_writel(bp, NCR, MACB_BIT(MPE));
+
+ if (netdev->hw_features & NETIF_F_NTUPLE)
+ gem_writel_n(bp, ETHT, SCRT2_ETHT, bp->pm_data.scrt2);
+
+ if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
+ macb_or_gem_writel(bp, USRIO, bp->pm_data.usrio);
+
for (q = 0, queue = bp->queues; q < bp->num_queues;
++q, ++queue)
napi_enable(&queue->napi);
@@ -4312,6 +4365,7 @@ static int __maybe_unused macb_resume(struct device *dev)
bp->macbgem_ops.mog_init_rings(bp);
macb_init_hw(bp);
macb_set_rx_mode(netdev);
+ macb_restore_features(bp);
netif_device_attach(netdev);
if (bp->ptp_info)
bp->ptp_info->ptp_init(netdev);