NetXen: Add multicast filter code
This patch will add manage the multicast filter from driver.
It will add capability to write multicast addresses to hardware.

Signed-by: Mithlesh Thukral <[EMAIL PROTECTED]>
---

 drivers/net/netxen/netxen_nic.h     |   24 +++++
 drivers/net/netxen/netxen_nic_hdr.h |    3 
 drivers/net/netxen/netxen_nic_hw.c  |  115 +++++++++++++++++++++++++-
 3 files changed, 139 insertions(+), 3 deletions(-)

diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index ad6688e..c74402f 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -261,6 +261,27 @@ #define netxen_set_msg_ctxid(config_word
 #define netxen_set_msg_opcode(config_word, val)        \
        ((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28)
 
+#define netxen_set_addr_ctl_id_pool0(config_word, val) \
+       ((config_word) &= ~3, (config_word) |= val & 0x3)
+#define netxen_set_addr_ctl_enable_xtnd_0(config_word) \
+       ((config_word) |= 1 << 2)
+#define netxen_set_addr_ctl_id_pool1(config_word, val) \
+       ((config_word) &= ~(0x3<<4), (config_word) |= (val & 0x3) << 4)
+#define netxen_set_addr_ctl_enable_xtnd_1(config_word) \
+       ((config_word) |= 1 << 6)
+#define netxen_set_addr_ctl_id_pool2(config_word, val) \
+       ((config_word) &= ~(0x3<<8), (config_word) |= (val & 0x3) << 8)
+#define netxen_set_addr_ctl_enable_xtnd_2(config_word) \
+       ((config_word) |= 1 << 10)
+#define netxen_set_addr_ctl_id_pool3(config_word, val) \
+       ((config_word) &= ~(0x3<<12), (config_word) |= (val & 0x3) << 12)
+#define netxen_set_addr_ctl_enable_xtnd_3(config_word) \
+       ((config_word) |= 1 << 14)
+#define netxen_set_addr_ctl_mode(config_word, val)     \
+       ((config_word) &= ~(0x3<<26), (config_word) |= (val & 0x3) << 26)
+#define netxen_set_addr_ctl_enable_poll(config_word, val)      \
+       ((config_word) &= ~(0xf<<30), (config_word) |= (val & 0xf) << 30)
+
 struct netxen_rcv_context {
        __le64 rcv_ring_addr;
        __le32 rcv_ring_size;
@@ -883,6 +904,9 @@ struct netxen_adapter {
        unsigned char mac_addr[ETH_ALEN];
        int mtu;
        int portnum;
+       u8 promisc;
+       u8 mc_enabled;
+       u8 max_mc_count;
 
        spinlock_t tx_lock;
        spinlock_t lock;
diff --git a/drivers/net/netxen/netxen_nic_hdr.h 
b/drivers/net/netxen/netxen_nic_hdr.h
index 608e37b..2bfecbc 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -545,6 +545,9 @@ #define NETXEN_MULTICAST_ADDR_HI_1  (NETX
 #define NETXEN_MULTICAST_ADDR_HI_2     (NETXEN_CRB_NIU + 0x1018)
 #define NETXEN_MULTICAST_ADDR_HI_3     (NETXEN_CRB_NIU + 0x101c)
 
+#define NETXEN_UNICAST_ADDR_BASE       (NETXEN_CRB_NIU + 0x1080)
+#define NETXEN_MULTICAST_ADDR_BASE     (NETXEN_CRB_NIU + 0x1100)
+
 #define        NETXEN_NIU_GB_MAC_CONFIG_0(I)           \
        (NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
 #define        NETXEN_NIU_GB_MAC_CONFIG_1(I)           \
diff --git a/drivers/net/netxen/netxen_nic_hw.c 
b/drivers/net/netxen/netxen_nic_hw.c
index baff17a..fff3844 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -303,6 +303,93 @@ int netxen_nic_set_mac(struct net_device
        return 0;
 }
 
+#define NETXEN_UNICAST_ADDR(port, index)       \
+       (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
+
+int netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
+{
+       u32 val = 0;
+       u16 port = physical_port[adapter->portnum];
+
+       if (adapter->mc_enabled)
+               return 0;
+       
+       netxen_set_addr_ctl_enable_poll(val, 0xf);
+
+       if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+               netxen_set_addr_ctl_mode(val, 0x3);
+       else
+               netxen_set_addr_ctl_mode(val, 0x0);
+
+       netxen_set_addr_ctl_id_pool0(val, 0x0);
+       netxen_set_addr_ctl_id_pool1(val, 0x1);
+       netxen_set_addr_ctl_id_pool2(val, 0x2);
+       netxen_set_addr_ctl_id_pool3(val, 0x3);
+
+       netxen_set_addr_ctl_enable_xtnd_0(val);
+       netxen_set_addr_ctl_enable_xtnd_1(val);
+       netxen_set_addr_ctl_enable_xtnd_2(val);
+       netxen_set_addr_ctl_enable_xtnd_3(val);
+       
+       netxen_crb_writelit_adapter(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
+       
+       val = 0xffffff;
+
+       netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port,0), val);
+       netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port,0)+4, 
+                                       val);
+       
+       memcpy(&val, adapter->mac_addr, 3);
+       netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port,1), val);
+
+       memcpy(&val, adapter->mac_addr+3, 3);
+       netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port,1) + 4,
+                                       val);
+
+       adapter->mc_enabled = 1;
+       return 0;
+}
+
+int netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
+{
+       u32 val =  0;
+       u16 port = physical_port[adapter->portnum];
+
+       if(!adapter->mc_enabled)
+               return 0;
+
+       netxen_crb_writelit_adapter(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
+
+       memcpy(&val, adapter->mac_addr, 3);
+       netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port,0), val);
+
+       memcpy(&val, adapter->mac_addr+3, 3);
+       netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port,0) + 4,
+                                       val);
+
+       adapter->mc_enabled = 0;
+       return 0;
+}
+
+#define NETXEN_MCAST_ADDR(port, index) \
+       (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
+
+int netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, int index, 
+                               u8 *addr)
+{
+       u32 hi = 0;
+       u32 lo = 0;
+       u16 port = physical_port[adapter->portnum];
+
+       memcpy(&hi, addr, 3);
+       memcpy(&lo, addr+3, 3);
+
+       netxen_crb_writelit_adapter(adapter, NETXEN_MCAST_ADDR(port,index), hi);
+       netxen_crb_writelit_adapter(adapter, NETXEN_MCAST_ADDR(port,index) + 4,
+                                       hi);
+       return 0;
+}
+
 /*
  * netxen_nic_set_multi - Multicast
  */
@@ -310,17 +397,39 @@ void netxen_nic_set_multi(struct net_dev
 {
        struct netxen_adapter *adapter = netdev_priv(netdev);
        struct dev_mc_list *mc_ptr;
+       u8 null_addr[] = {0, 0, 0, 0, 0, 0};
+       int index = 0;
 
        mc_ptr = netdev->mc_list;
-       if (netdev->flags & IFF_PROMISC) {
-               if (adapter->set_promisc)
+       if ((netdev->flags & IFF_PROMISC) || (netdev->mc_count >
+                                               adapter->max_mc_count)) {
+               if (adapter->set_promisc) {
                        adapter->set_promisc(adapter,
                                             NETXEN_NIU_PROMISC_MODE);
+                       netxen_nic_disable_mcast_filter(adapter);
+                       return;
+               }
        } else {
-               if (adapter->unset_promisc)
+               if ((netdev->mc_count == 0) && (adapter->unset_promisc)) {
                        adapter->unset_promisc(adapter,
                                               NETXEN_NIU_NON_PROMISC_MODE);
+                       netxen_nic_disable_mcast_filter(adapter);
+                       return;
+               }
        }
+       adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);
+       netxen_nic_enable_mcast_filter(adapter);
+
+       for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
+               netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
+
+       if (index != netdev->mc_count)
+               printk(KERN_ERR"%s: %s multicast address count mismatch\n",
+                               netxen_nic_driver_name, netdev->name);
+
+       /* Clear out the remaining addresses    */
+       for (; index < adapter->max_mc_count; index++)
+               netxen_nic_set_mcast_addr(adapter, index, null_addr);
 }
 
 /*
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to