diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2008-07-21 22:44:01 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-07-22 17:51:12 -0400 |
commit | 623621b07ebc5b72e0bdfa4a50bbb28f4587de0c (patch) | |
tree | a6e472bfa084e79f912ca1b6dcc06dd61332669f /drivers/net/netxen | |
parent | 7830b22cbc5f5e804469b74a3fe0d3a8ed88ca31 (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.h | 4 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 3 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 133 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.h | 39 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 2 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 10 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_niu.c | 5 |
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 | |||
174 | static int | ||
175 | netxen_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 | |||
205 | static int | ||
206 | netxen_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 | |||
232 | static int | ||
233 | netxen_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) */ |
433 | typedef enum { | 433 | typedef 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 */ |
518 | int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, | 483 | int 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 | ||