aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/arm/am79c961a.c77
1 files changed, 40 insertions, 37 deletions
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 084b67fbe7aa..79d88a0b00a3 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -196,6 +196,42 @@ am79c961_ramtest(struct net_device *dev, unsigned int val)
196 return errorcount; 196 return errorcount;
197} 197}
198 198
199static void am79c961_mc_hash(char *addr, u16 *hash)
200{
201 if (addr[0] & 0x01) {
202 int idx, bit;
203 u32 crc;
204
205 crc = ether_crc_le(ETH_ALEN, addr);
206
207 idx = crc >> 30;
208 bit = (crc >> 26) & 15;
209
210 hash[idx] |= 1 << bit;
211 }
212}
213
214static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
215{
216 unsigned int mode = MODE_PORT_10BT;
217
218 if (dev->flags & IFF_PROMISC) {
219 mode |= MODE_PROMISC;
220 memset(hash, 0xff, 4 * sizeof(*hash));
221 } else if (dev->flags & IFF_ALLMULTI) {
222 memset(hash, 0xff, 4 * sizeof(*hash));
223 } else {
224 struct netdev_hw_addr *ha;
225
226 memset(hash, 0, 4 * sizeof(*hash));
227
228 netdev_for_each_mc_addr(ha, dev)
229 am79c961_mc_hash(ha->addr, hash);
230 }
231
232 return mode;
233}
234
199static void 235static void
200am79c961_init_for_open(struct net_device *dev) 236am79c961_init_for_open(struct net_device *dev)
201{ 237{
@@ -203,6 +239,7 @@ am79c961_init_for_open(struct net_device *dev)
203 unsigned long flags; 239 unsigned long flags;
204 unsigned char *p; 240 unsigned char *p;
205 u_int hdr_addr, first_free_addr; 241 u_int hdr_addr, first_free_addr;
242 u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
206 int i; 243 int i;
207 244
208 /* 245 /*
@@ -218,16 +255,12 @@ am79c961_init_for_open(struct net_device *dev)
218 write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */ 255 write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */
219 256
220 for (i = LADRL; i <= LADRH; i++) 257 for (i = LADRL; i <= LADRH; i++)
221 write_rreg (dev->base_addr, i, 0); 258 write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);
222 259
223 for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2) 260 for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
224 write_rreg (dev->base_addr, i, p[0] | (p[1] << 8)); 261 write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
225 262
226 i = MODE_PORT_10BT; 263 write_rreg (dev->base_addr, MODE, mode);
227 if (dev->flags & IFF_PROMISC)
228 i |= MODE_PROMISC;
229
230 write_rreg (dev->base_addr, MODE, i);
231 write_rreg (dev->base_addr, POLLINT, 0); 264 write_rreg (dev->base_addr, POLLINT, 0);
232 write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS); 265 write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
233 write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS); 266 write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
@@ -340,21 +373,6 @@ am79c961_close(struct net_device *dev)
340 return 0; 373 return 0;
341} 374}
342 375
343static void am79c961_mc_hash(char *addr, unsigned short *hash)
344{
345 if (addr[0] & 0x01) {
346 int idx, bit;
347 u32 crc;
348
349 crc = ether_crc_le(ETH_ALEN, addr);
350
351 idx = crc >> 30;
352 bit = (crc >> 26) & 15;
353
354 hash[idx] |= 1 << bit;
355 }
356}
357
358/* 376/*
359 * Set or clear promiscuous/multicast mode filter for this adapter. 377 * Set or clear promiscuous/multicast mode filter for this adapter.
360 */ 378 */
@@ -362,24 +380,9 @@ static void am79c961_setmulticastlist (struct net_device *dev)
362{ 380{
363 struct dev_priv *priv = netdev_priv(dev); 381 struct dev_priv *priv = netdev_priv(dev);
364 unsigned long flags; 382 unsigned long flags;
365 unsigned short multi_hash[4], mode; 383 u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
366 int i, stopped; 384 int i, stopped;
367 385
368 mode = MODE_PORT_10BT;
369
370 if (dev->flags & IFF_PROMISC) {
371 mode |= MODE_PROMISC;
372 } else if (dev->flags & IFF_ALLMULTI) {
373 memset(multi_hash, 0xff, sizeof(multi_hash));
374 } else {
375 struct netdev_hw_addr *ha;
376
377 memset(multi_hash, 0x00, sizeof(multi_hash));
378
379 netdev_for_each_mc_addr(ha, dev)
380 am79c961_mc_hash(ha->addr, multi_hash);
381 }
382
383 spin_lock_irqsave(&priv->chip_lock, flags); 386 spin_lock_irqsave(&priv->chip_lock, flags);
384 387
385 stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP; 388 stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;