2013-09-30 20:12:32

by Rob Herring

[permalink] [raw]
Subject: [PATCH 0/3] calxedaxgmac: fixes for xgmac_set_rx_mode

From: Rob Herring <[email protected]>

This is a couple of fixes related to xgmac_set_rx_mode. The changes are
necessary for "bridge fdb add" to work correctly.

Rob

Rob Herring (3):
net: calxedaxgmac: fix clearing of old filter addresses
net: calxedaxgmac: add uc and mc filter addresses in promiscuous mode
net: calxedaxgmac: determine number of address filters at runtime

drivers/net/ethernet/calxeda/xgmac.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)

--
1.8.1.2


2013-09-30 20:12:34

by Rob Herring

[permalink] [raw]
Subject: [PATCH 3/3] net: calxedaxgmac: determine number of address filters at runtime

From: Rob Herring <[email protected]>

Highbank and Midway xgmac h/w have different number of MAC address filter
registers with 7 and 31, respectively. Highbank has been wrong, so fix it
and detect the number of filter registers at run-time. Unfortunately,
the version register is the same on both SOCs, so simply test if write to
the last filter register will take a value. It always reads as 0 if not.

Signed-off-by: Rob Herring <[email protected]>
---
drivers/net/ethernet/calxeda/xgmac.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 35da09b..48f5288 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -106,7 +106,6 @@
#define XGMAC_DMA_HW_FEATURE 0x00000f58 /* Enabled Hardware Features */

#define XGMAC_ADDR_AE 0x80000000
-#define XGMAC_MAX_FILTER_ADDR 31

/* PMT Control and Status */
#define XGMAC_PMT_POINTER_RESET 0x80000000
@@ -384,6 +383,7 @@ struct xgmac_priv {
struct device *device;
struct napi_struct napi;

+ int max_macs;
struct xgmac_extra_stats xstats;

spinlock_t stats_lock;
@@ -1296,7 +1296,7 @@ static void xgmac_set_rx_mode(struct net_device *dev)

memset(hash_filter, 0, sizeof(hash_filter));

- if (netdev_uc_count(dev) > XGMAC_MAX_FILTER_ADDR) {
+ if (netdev_uc_count(dev) > priv->max_macs) {
use_hash = true;
value |= XGMAC_FRAME_FILTER_HUC | XGMAC_FRAME_FILTER_HPF;
}
@@ -1319,7 +1319,7 @@ static void xgmac_set_rx_mode(struct net_device *dev)
goto out;
}

- if ((netdev_mc_count(dev) + reg - 1) > XGMAC_MAX_FILTER_ADDR) {
+ if ((netdev_mc_count(dev) + reg - 1) > priv->max_macs) {
use_hash = true;
value |= XGMAC_FRAME_FILTER_HMC | XGMAC_FRAME_FILTER_HPF;
} else {
@@ -1340,7 +1340,7 @@ static void xgmac_set_rx_mode(struct net_device *dev)
}

out:
- for (i = reg; i <= XGMAC_MAX_FILTER_ADDR; i++)
+ for (i = reg; i <= priv->max_macs; i++)
xgmac_set_mac_addr(ioaddr, NULL, i);
for (i = 0; i < XGMAC_NUM_HASH; i++)
writel(hash_filter[i], ioaddr + XGMAC_HASH(i));
@@ -1759,6 +1759,13 @@ static int xgmac_probe(struct platform_device *pdev)
uid = readl(priv->base + XGMAC_VERSION);
netdev_info(ndev, "h/w version is 0x%x\n", uid);

+ /* Figure out how many valid mac address filter registers we have */
+ writel(1, priv->base + XGMAC_ADDR_HIGH(31));
+ if (readl(priv->base + XGMAC_ADDR_HIGH(31)) == 1)
+ priv->max_macs = 31;
+ else
+ priv->max_macs = 7;
+
writel(0, priv->base + XGMAC_DMA_INTR_ENA);
ndev->irq = platform_get_irq(pdev, 0);
if (ndev->irq == -ENXIO) {
--
1.8.1.2

2013-09-30 20:12:33

by Rob Herring

[permalink] [raw]
Subject: [PATCH 1/3] net: calxedaxgmac: fix clearing of old filter addresses

From: Rob Herring <[email protected]>

In commit 2ee68f621af280 (net: calxedaxgmac: fix various errors in
xgmac_set_rx_mode), a fix to clean-up old address entries was added.
However, the loop to zero out the entries failed to increment the register
address resulting in only 1 entry getting cleared. Fix this to correctly
use the loop index. Also, the end of the loop condition was off by 1 and
should have been <= rather than <.

Signed-off-by: Rob Herring <[email protected]>
---
drivers/net/ethernet/calxeda/xgmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 78d6d6b..94358d2 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1342,8 +1342,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
}

out:
- for (i = reg; i < XGMAC_MAX_FILTER_ADDR; i++)
- xgmac_set_mac_addr(ioaddr, NULL, reg);
+ for (i = reg; i <= XGMAC_MAX_FILTER_ADDR; i++)
+ xgmac_set_mac_addr(ioaddr, NULL, i);
for (i = 0; i < XGMAC_NUM_HASH; i++)
writel(hash_filter[i], ioaddr + XGMAC_HASH(i));

--
1.8.1.2

2013-09-30 20:13:21

by Rob Herring

[permalink] [raw]
Subject: [PATCH 2/3] net: calxedaxgmac: add uc and mc filter addresses in promiscuous mode

From: Rob Herring <[email protected]>

Even in promiscuous mode, we need to add filter addresses for correct
operation. This fixes silent failures when using a bridge and adding
addresses using the "bridge fdb add" command.

Signed-off-by: Rob Herring <[email protected]>
---
drivers/net/ethernet/calxeda/xgmac.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 94358d2..35da09b 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1291,10 +1291,8 @@ static void xgmac_set_rx_mode(struct net_device *dev)
netdev_dbg(priv->dev, "# mcasts %d, # unicast %d\n",
netdev_mc_count(dev), netdev_uc_count(dev));

- if (dev->flags & IFF_PROMISC) {
- writel(XGMAC_FRAME_FILTER_PR, ioaddr + XGMAC_FRAME_FILTER);
- return;
- }
+ if (dev->flags & IFF_PROMISC)
+ value |= XGMAC_FRAME_FILTER_PR;

memset(hash_filter, 0, sizeof(hash_filter));

--
1.8.1.2

2013-10-02 20:12:13

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 0/3] calxedaxgmac: fixes for xgmac_set_rx_mode

From: Rob Herring <[email protected]>
Date: Mon, 30 Sep 2013 15:12:14 -0500

> This is a couple of fixes related to xgmac_set_rx_mode. The changes are
> necessary for "bridge fdb add" to work correctly.

Series applied, thanks Rob.