aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_hw.c
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/netxen_nic_hw.c
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/netxen_nic_hw.c')
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c133
1 files changed, 124 insertions, 9 deletions
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/*