From: Radu Bulie <radu-andrei.bu...@nxp.com>

This patch adds allmulticast option for memac, dtsec
and 10GEC controllers.

Signed-off-by: Radu Bulie <radu-andrei.bu...@nxp.com>
---
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c   | 10 +++++++
 drivers/net/ethernet/freescale/fman/fman_dtsec.c | 19 ++++++++++++++
 drivers/net/ethernet/freescale/fman/fman_dtsec.h |  1 +
 drivers/net/ethernet/freescale/fman/fman_memac.c | 32 +++++++++++++++++++++--
 drivers/net/ethernet/freescale/fman/fman_memac.h |  1 +
 drivers/net/ethernet/freescale/fman/fman_tgec.c  | 33 +++++++++++++++++++++---
 drivers/net/ethernet/freescale/fman/fman_tgec.h  |  1 +
 drivers/net/ethernet/freescale/fman/mac.c        |  3 +++
 drivers/net/ethernet/freescale/fman/mac.h        |  2 ++
 9 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 2f53e8b..092c6c2 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -454,6 +454,16 @@ static void dpaa_set_rx_mode(struct net_device *net_dev)
                                  err);
        }
 
+       if (!!(net_dev->flags & IFF_ALLMULTI) != priv->mac_dev->allmulti) {
+               priv->mac_dev->allmulti = !priv->mac_dev->allmulti;
+               err = priv->mac_dev->set_allmulti(priv->mac_dev->fman_mac,
+                                                 priv->mac_dev->allmulti);
+               if (err < 0)
+                       netif_err(priv, drv, net_dev,
+                                 "mac_dev->set_allmulti() = %d\n",
+                                 err);
+       }
+
        err = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
        if (err < 0)
                netif_err(priv, drv, net_dev, "mac_dev->set_multi() = %d\n",
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c 
b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index ea43b49..9a581fa 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1117,6 +1117,25 @@ int dtsec_add_hash_mac_address(struct fman_mac *dtsec, 
enet_addr_t *eth_addr)
        return 0;
 }
 
+int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable)
+{
+       u32 tmp;
+       struct dtsec_regs __iomem *regs = dtsec->regs;
+
+       if (!is_init_done(dtsec->dtsec_drv_param))
+               return -EINVAL;
+
+       tmp = ioread32be(&regs->rctrl);
+       if (enable)
+               tmp |= RCTRL_MPROM;
+       else
+               tmp &= ~RCTRL_MPROM;
+
+       iowrite32be(tmp, &regs->rctrl);
+
+       return 0;
+}
+
 int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h 
b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
index c4467c0..1a689ad 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h
@@ -55,5 +55,6 @@ int dtsec_set_exception(struct fman_mac *dtsec,
 int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
 int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr);
 int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version);
+int dtsec_set_allmulti(struct fman_mac *dtsec, bool enable);
 
 #endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c 
b/drivers/net/ethernet/freescale/fman/fman_memac.c
index c029688..446a97b 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -350,6 +350,7 @@ struct fman_mac {
        struct fman_rev_info fm_rev_info;
        bool basex_if;
        struct phy_device *pcsphy;
+       bool allmulti_enabled;
 };
 
 static void add_addr_in_paddr(struct memac_regs __iomem *regs, u8 *adr,
@@ -940,6 +941,29 @@ int memac_add_hash_mac_address(struct fman_mac *memac, 
enet_addr_t *eth_addr)
        return 0;
 }
 
+int memac_set_allmulti(struct fman_mac *memac, bool enable)
+{
+       u32 entry;
+       struct memac_regs __iomem *regs = memac->regs;
+
+       if (!is_init_done(memac->memac_drv_param))
+               return -EINVAL;
+
+       if (enable) {
+               for (entry = 0; entry < HASH_TABLE_SIZE; entry++)
+                       iowrite32be(entry | HASH_CTRL_MCAST_EN,
+                                   &regs->hashtable_ctrl);
+       } else {
+               for (entry = 0; entry < HASH_TABLE_SIZE; entry++)
+                       iowrite32be(entry & ~HASH_CTRL_MCAST_EN,
+                                   &regs->hashtable_ctrl);
+       }
+
+       memac->allmulti_enabled = enable;
+
+       return 0;
+}
+
 int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr)
 {
        struct memac_regs __iomem *regs = memac->regs;
@@ -963,8 +987,12 @@ int memac_del_hash_mac_address(struct fman_mac *memac, 
enet_addr_t *eth_addr)
                        break;
                }
        }
-       if (list_empty(&memac->multicast_addr_hash->lsts[hash]))
-               iowrite32be(hash & ~HASH_CTRL_MCAST_EN, &regs->hashtable_ctrl);
+
+       if (!memac->allmulti_enabled) {
+               if (list_empty(&memac->multicast_addr_hash->lsts[hash]))
+                       iowrite32be(hash & ~HASH_CTRL_MCAST_EN,
+                                   &regs->hashtable_ctrl);
+       }
 
        return 0;
 }
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h 
b/drivers/net/ethernet/freescale/fman/fman_memac.h
index c4a6646..b5a5033 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.h
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.h
@@ -57,5 +57,6 @@ int memac_set_exception(struct fman_mac *memac,
                        enum fman_mac_exceptions exception, bool enable);
 int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
 int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr);
+int memac_set_allmulti(struct fman_mac *memac, bool enable);
 
 #endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c 
b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 4b0f3a5..284735d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -217,6 +217,7 @@ struct fman_mac {
        struct tgec_cfg *cfg;
        void *fm;
        struct fman_rev_info fm_rev_info;
+       bool allmulti_enabled;
 };
 
 static void set_mac_address(struct tgec_regs __iomem *regs, u8 *adr)
@@ -564,6 +565,29 @@ int tgec_add_hash_mac_address(struct fman_mac *tgec, 
enet_addr_t *eth_addr)
        return 0;
 }
 
+int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
+{
+       u32 entry;
+       struct tgec_regs __iomem *regs = tgec->regs;
+
+       if (!is_init_done(tgec->cfg))
+               return -EINVAL;
+
+       if (enable) {
+               for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++)
+                       iowrite32be(entry | TGEC_HASH_MCAST_EN,
+                                   &regs->hashtable_ctrl);
+       } else {
+               for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++)
+                       iowrite32be(entry & ~TGEC_HASH_MCAST_EN,
+                                   &regs->hashtable_ctrl);
+       }
+
+       tgec->allmulti_enabled = enable;
+
+       return 0;
+}
+
 int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr)
 {
        struct tgec_regs __iomem *regs = tgec->regs;
@@ -591,9 +615,12 @@ int tgec_del_hash_mac_address(struct fman_mac *tgec, 
enet_addr_t *eth_addr)
                        break;
                }
        }
-       if (list_empty(&tgec->multicast_addr_hash->lsts[hash]))
-               iowrite32be((hash & ~TGEC_HASH_MCAST_EN),
-                           &regs->hashtable_ctrl);
+
+       if (!tgec->allmulti_enabled) {
+               if (list_empty(&tgec->multicast_addr_hash->lsts[hash]))
+                       iowrite32be((hash & ~TGEC_HASH_MCAST_EN),
+                                   &regs->hashtable_ctrl);
+       }
 
        return 0;
 }
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h 
b/drivers/net/ethernet/freescale/fman/fman_tgec.h
index 514bba9..cbbd3b4 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h
@@ -51,5 +51,6 @@ int tgec_set_exception(struct fman_mac *tgec,
 int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
 int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr);
 int tgec_get_version(struct fman_mac *tgec, u32 *mac_version);
+int tgec_set_allmulti(struct fman_mac *tgec, bool enable);
 
 #endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac.c 
b/drivers/net/ethernet/freescale/fman/mac.c
index 88c0a06..4829dcd 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -470,6 +470,7 @@ static void setup_dtsec(struct mac_device *mac_dev)
        mac_dev->set_tx_pause           = dtsec_set_tx_pause_frames;
        mac_dev->set_rx_pause           = dtsec_accept_rx_pause_frames;
        mac_dev->set_exception          = dtsec_set_exception;
+       mac_dev->set_allmulti           = dtsec_set_allmulti;
        mac_dev->set_multi              = set_multi;
        mac_dev->start                  = start;
        mac_dev->stop                   = stop;
@@ -488,6 +489,7 @@ static void setup_tgec(struct mac_device *mac_dev)
        mac_dev->set_tx_pause           = tgec_set_tx_pause_frames;
        mac_dev->set_rx_pause           = tgec_accept_rx_pause_frames;
        mac_dev->set_exception          = tgec_set_exception;
+       mac_dev->set_allmulti           = tgec_set_allmulti;
        mac_dev->set_multi              = set_multi;
        mac_dev->start                  = start;
        mac_dev->stop                   = stop;
@@ -506,6 +508,7 @@ static void setup_memac(struct mac_device *mac_dev)
        mac_dev->set_tx_pause           = memac_set_tx_pause_frames;
        mac_dev->set_rx_pause           = memac_accept_rx_pause_frames;
        mac_dev->set_exception          = memac_set_exception;
+       mac_dev->set_allmulti           = memac_set_allmulti;
        mac_dev->set_multi              = set_multi;
        mac_dev->start                  = start;
        mac_dev->stop                   = stop;
diff --git a/drivers/net/ethernet/freescale/fman/mac.h 
b/drivers/net/ethernet/freescale/fman/mac.h
index eefb335..b520cec 100644
--- a/drivers/net/ethernet/freescale/fman/mac.h
+++ b/drivers/net/ethernet/freescale/fman/mac.h
@@ -59,6 +59,7 @@ struct mac_device {
        bool rx_pause_active;
        bool tx_pause_active;
        bool promisc;
+       bool allmulti;
 
        int (*init)(struct mac_device *mac_dev);
        int (*start)(struct mac_device *mac_dev);
@@ -66,6 +67,7 @@ struct mac_device {
        void (*adjust_link)(struct mac_device *mac_dev);
        int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
        int (*change_addr)(struct fman_mac *mac_dev, enet_addr_t *enet_addr);
+       int (*set_allmulti)(struct fman_mac *mac_dev, bool enable);
        int (*set_multi)(struct net_device *net_dev,
                         struct mac_device *mac_dev);
        int (*set_rx_pause)(struct fman_mac *mac_dev, bool en);
-- 
2.1.0

Reply via email to