aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2008-07-21 22:44:01 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-07-22 17:51:12 -0400
commit623621b07ebc5b72e0bdfa4a50bbb28f4587de0c (patch)
treea6e472bfa084e79f912ca1b6dcc06dd61332669f /drivers/net/netxen
parent7830b22cbc5f5e804469b74a3fe0d3a8ed88ca31 (diff)
netxen: hw multicast filtering
Enable multicast address filtering capabilities in the hardware. Upto 16 multicast addresses can be programmed for each physical port. Support "allmulti" mode, if enabled. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r--drivers/net/netxen/netxen_nic.h4
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h3
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c133
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h39
-rw-r--r--drivers/net/netxen/netxen_nic_init.c2
-rw-r--r--drivers/net/netxen/netxen_nic_main.c10
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c5
7 files changed, 147 insertions, 49 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 149bb60b0c46..fa1fbab65621 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -856,6 +856,9 @@ struct netxen_adapter {
856 int portnum; 856 int portnum;
857 u8 physical_port; 857 u8 physical_port;
858 858
859 uint8_t mc_enabled;
860 uint8_t max_mc_count;
861
859 struct work_struct watchdog_task; 862 struct work_struct watchdog_task;
860 struct timer_list watchdog_timer; 863 struct timer_list watchdog_timer;
861 struct work_struct tx_timeout_task; 864 struct work_struct tx_timeout_task;
@@ -909,7 +912,6 @@ struct netxen_adapter {
909 int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t); 912 int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
910 int (*set_mtu) (struct netxen_adapter *, int); 913 int (*set_mtu) (struct netxen_adapter *, int);
911 int (*set_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t); 914 int (*set_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
912 int (*unset_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
913 int (*phy_read) (struct netxen_adapter *, long reg, u32 *); 915 int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
914 int (*phy_write) (struct netxen_adapter *, long reg, u32 val); 916 int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
915 int (*init_port) (struct netxen_adapter *, int); 917 int (*init_port) (struct netxen_adapter *, int);
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 24d027e29c45..545180bf3be8 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -550,6 +550,9 @@ enum {
550#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018) 550#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018)
551#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c) 551#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c)
552 552
553#define NETXEN_UNICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1080)
554#define NETXEN_MULTICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1100)
555
553#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \ 556#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \
554 (NETXEN_CRB_NIU + 0x30000 + (I)*0x10000) 557 (NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
555#define NETXEN_NIU_GB_MAC_CONFIG_1(I) \ 558#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 fa6d034c242c..93466ec64074 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -154,7 +154,6 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
154 if (!is_valid_ether_addr(addr->sa_data)) 154 if (!is_valid_ether_addr(addr->sa_data))
155 return -EADDRNOTAVAIL; 155 return -EADDRNOTAVAIL;
156 156
157 DPRINTK(INFO, "valid ether addr\n");
158 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 157 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
159 158
160 if (adapter->macaddr_set) 159 if (adapter->macaddr_set)
@@ -163,6 +162,91 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
163 return 0; 162 return 0;
164} 163}
165 164
165#define NETXEN_UNICAST_ADDR(port, index) \
166 (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
167#define NETXEN_MCAST_ADDR(port, index) \
168 (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
169#define MAC_HI(addr) \
170 ((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
171#define MAC_LO(addr) \
172 ((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
173
174static int
175netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
176{
177 u32 val = 0;
178 u16 port = adapter->physical_port;
179 u8 *addr = adapter->netdev->dev_addr;
180
181 if (adapter->mc_enabled)
182 return 0;
183
184 netxen_nic_hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
185 val |= (1UL << (28+port));
186 netxen_nic_hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
187
188 /* add broadcast addr to filter */
189 val = 0xffffff;
190 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
191 netxen_crb_writelit_adapter(adapter,
192 NETXEN_UNICAST_ADDR(port, 0)+4, val);
193
194 /* add station addr to filter */
195 val = MAC_HI(addr);
196 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
197 val = MAC_LO(addr);
198 netxen_crb_writelit_adapter(adapter,
199 NETXEN_UNICAST_ADDR(port, 1)+4, val);
200
201 adapter->mc_enabled = 1;
202 return 0;
203}
204
205static int
206netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
207{
208 u32 val = 0;
209 u16 port = adapter->physical_port;
210 u8 *addr = adapter->netdev->dev_addr;
211
212 if (!adapter->mc_enabled)
213 return 0;
214
215 netxen_nic_hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
216 val &= ~(1UL << (28+port));
217 netxen_nic_hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
218
219 val = MAC_HI(addr);
220 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
221 val = MAC_LO(addr);
222 netxen_crb_writelit_adapter(adapter,
223 NETXEN_UNICAST_ADDR(port, 0)+4, val);
224
225 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
226 netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
227
228 adapter->mc_enabled = 0;
229 return 0;
230}
231
232static int
233netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
234 int index, u8 *addr)
235{
236 u32 hi = 0, lo = 0;
237 u16 port = adapter->physical_port;
238
239 lo = MAC_LO(addr);
240 hi = MAC_HI(addr);
241
242 netxen_crb_writelit_adapter(adapter,
243 NETXEN_MCAST_ADDR(port, index), hi);
244 netxen_crb_writelit_adapter(adapter,
245 NETXEN_MCAST_ADDR(port, index)+4, lo);
246
247 return 0;
248}
249
166/* 250/*
167 * netxen_nic_set_multi - Multicast 251 * netxen_nic_set_multi - Multicast
168 */ 252 */
@@ -170,17 +254,48 @@ void netxen_nic_set_multi(struct net_device *netdev)
170{ 254{
171 struct netxen_adapter *adapter = netdev_priv(netdev); 255 struct netxen_adapter *adapter = netdev_priv(netdev);
172 struct dev_mc_list *mc_ptr; 256 struct dev_mc_list *mc_ptr;
257 u8 null_addr[6];
258 int index = 0;
259
260 memset(null_addr, 0, 6);
173 261
174 mc_ptr = netdev->mc_list;
175 if (netdev->flags & IFF_PROMISC) { 262 if (netdev->flags & IFF_PROMISC) {
176 if (adapter->set_promisc) 263
177 adapter->set_promisc(adapter, 264 adapter->set_promisc(adapter,
178 NETXEN_NIU_PROMISC_MODE); 265 NETXEN_NIU_PROMISC_MODE);
179 } else { 266
180 if (adapter->unset_promisc) 267 /* Full promiscuous mode */
181 adapter->unset_promisc(adapter, 268 netxen_nic_disable_mcast_filter(adapter);
182 NETXEN_NIU_NON_PROMISC_MODE); 269
270 return;
271 }
272
273 if (netdev->mc_count == 0) {
274 adapter->set_promisc(adapter,
275 NETXEN_NIU_NON_PROMISC_MODE);
276 netxen_nic_disable_mcast_filter(adapter);
277 return;
278 }
279
280 adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
281 if (netdev->flags & IFF_ALLMULTI ||
282 netdev->mc_count > adapter->max_mc_count) {
283 netxen_nic_disable_mcast_filter(adapter);
284 return;
183 } 285 }
286
287 netxen_nic_enable_mcast_filter(adapter);
288
289 for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
290 netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
291
292 if (index != netdev->mc_count)
293 printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
294 netxen_nic_driver_name, netdev->name);
295
296 /* Clear out remaining addresses */
297 for (; index < adapter->max_mc_count; index++)
298 netxen_nic_set_mcast_addr(adapter, index, null_addr);
184} 299}
185 300
186/* 301/*
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index a3ea1dd98c41..90dd05796438 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -432,7 +432,8 @@ typedef enum {
432/* Promiscous mode options (GbE mode only) */ 432/* Promiscous mode options (GbE mode only) */
433typedef enum { 433typedef enum {
434 NETXEN_NIU_PROMISC_MODE = 0, 434 NETXEN_NIU_PROMISC_MODE = 0,
435 NETXEN_NIU_NON_PROMISC_MODE 435 NETXEN_NIU_NON_PROMISC_MODE,
436 NETXEN_NIU_ALLMULTI_MODE
436} netxen_niu_prom_mode_t; 437} netxen_niu_prom_mode_t;
437 438
438/* 439/*
@@ -478,42 +479,6 @@ typedef enum {
478#define netxen_xg_soft_reset(config_word) \ 479#define netxen_xg_soft_reset(config_word) \
479 ((config_word) |= 1 << 4) 480 ((config_word) |= 1 << 4)
480 481
481/*
482 * MAC Control Register
483 *
484 * Bit 0-1 : id_pool0
485 * Bit 2 : enable_xtnd0
486 * Bit 4-5 : id_pool1
487 * Bit 6 : enable_xtnd1
488 * Bit 8-9 : id_pool2
489 * Bit 10 : enable_xtnd2
490 * Bit 12-13 : id_pool3
491 * Bit 14 : enable_xtnd3
492 * Bit 24-25 : mode_select
493 * Bit 28-31 : enable_pool
494 */
495
496#define netxen_nic_mcr_set_id_pool0(config, val) \
497 ((config) |= ((val) &0x03))
498#define netxen_nic_mcr_set_enable_xtnd0(config) \
499 ((config) |= 1 << 3)
500#define netxen_nic_mcr_set_id_pool1(config, val) \
501 ((config) |= (((val) & 0x03) << 4))
502#define netxen_nic_mcr_set_enable_xtnd1(config) \
503 ((config) |= 1 << 6)
504#define netxen_nic_mcr_set_id_pool2(config, val) \
505 ((config) |= (((val) & 0x03) << 8))
506#define netxen_nic_mcr_set_enable_xtnd2(config) \
507 ((config) |= 1 << 10)
508#define netxen_nic_mcr_set_id_pool3(config, val) \
509 ((config) |= (((val) & 0x03) << 12))
510#define netxen_nic_mcr_set_enable_xtnd3(config) \
511 ((config) |= 1 << 14)
512#define netxen_nic_mcr_set_mode_select(config, val) \
513 ((config) |= (((val) & 0x03) << 24))
514#define netxen_nic_mcr_set_enable_pool(config, val) \
515 ((config) |= (((val) & 0x0f) << 28))
516
517/* Set promiscuous mode for a GbE interface */ 482/* Set promiscuous mode for a GbE interface */
518int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, 483int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
519 netxen_niu_prom_mode_t mode); 484 netxen_niu_prom_mode_t mode);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 37fd6bc93eb9..e35f1a4b4eb3 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -195,7 +195,6 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
195 adapter->macaddr_set = netxen_niu_macaddr_set; 195 adapter->macaddr_set = netxen_niu_macaddr_set;
196 adapter->set_mtu = netxen_nic_set_mtu_gb; 196 adapter->set_mtu = netxen_nic_set_mtu_gb;
197 adapter->set_promisc = netxen_niu_set_promiscuous_mode; 197 adapter->set_promisc = netxen_niu_set_promiscuous_mode;
198 adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
199 adapter->phy_read = netxen_niu_gbe_phy_read; 198 adapter->phy_read = netxen_niu_gbe_phy_read;
200 adapter->phy_write = netxen_niu_gbe_phy_write; 199 adapter->phy_write = netxen_niu_gbe_phy_write;
201 adapter->init_niu = netxen_nic_init_niu_gb; 200 adapter->init_niu = netxen_nic_init_niu_gb;
@@ -212,7 +211,6 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
212 adapter->set_mtu = netxen_nic_set_mtu_xgb; 211 adapter->set_mtu = netxen_nic_set_mtu_xgb;
213 adapter->init_port = netxen_niu_xg_init_port; 212 adapter->init_port = netxen_niu_xg_init_port;
214 adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode; 213 adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
215 adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
216 adapter->stop_port = netxen_niu_disable_xg_port; 214 adapter->stop_port = netxen_niu_disable_xg_port;
217 break; 215 break;
218 216
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 91b02ebc9a10..0ec6e7ebf90f 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -377,6 +377,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
377 adapter->portnum = pci_func_id; 377 adapter->portnum = pci_func_id;
378 adapter->status &= ~NETXEN_NETDEV_STATUS; 378 adapter->status &= ~NETXEN_NETDEV_STATUS;
379 adapter->rx_csum = 1; 379 adapter->rx_csum = 1;
380 adapter->max_mc_count = 16;
381 adapter->mc_enabled = 0;
380 382
381 netdev->open = netxen_nic_open; 383 netdev->open = netxen_nic_open;
382 netdev->stop = netxen_nic_close; 384 netdev->stop = netxen_nic_close;
@@ -589,6 +591,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
589 msleep(1); 591 msleep(1);
590 netxen_load_firmware(adapter); 592 netxen_load_firmware(adapter);
591 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); 593 netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
594
595 /* Initialize multicast addr pool owners */
596 val = 0x7654;
597 if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
598 val |= 0x0f000000;
599 netxen_crb_writelit_adapter(adapter,
600 NETXEN_MAC_ADDR_CNTL_REG, val);
601
592 } 602 }
593 603
594 /* clear the register for future unloads/loads */ 604 /* clear the register for future unloads/loads */
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index a3bc7cc67a6f..d9664a0e08bc 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -909,6 +909,11 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
909 else 909 else
910 reg = (reg & ~0x2000UL); 910 reg = (reg & ~0x2000UL);
911 911
912 if (mode == NETXEN_NIU_ALLMULTI_MODE)
913 reg = (reg | 0x1000UL);
914 else
915 reg = (reg & ~0x1000UL);
916
912 netxen_crb_writelit_adapter(adapter, 917 netxen_crb_writelit_adapter(adapter,
913 NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); 918 NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
914 919