[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <200706011114.l51BEZTx004682@dut39.unminc.com>
Date: Fri, 1 Jun 2007 04:14:35 -0700
From: Mithlesh Thukral <mithlesh@...xen.com>
To: netdev@...r.kernel.org
Cc: amitkale@...xen.com, jeff@...zik.org, mithlesh@...xen.com,
netxenproj@...syssoft.com, rob@...xen.com
Subject: [PATCH 2/5] NetXen: Multicast filter for NetXen driver
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 <mithlesh@...xen.com>
---
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 majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists