|
13 | 13 | * Vineet Gupta |
14 | 14 | */ |
15 | 15 |
|
| 16 | +#include <linux/crc32.h> |
16 | 17 | #include <linux/etherdevice.h> |
17 | 18 | #include <linux/interrupt.h> |
18 | 19 | #include <linux/io.h> |
@@ -450,6 +451,41 @@ static int arc_emac_open(struct net_device *ndev) |
450 | 451 | return 0; |
451 | 452 | } |
452 | 453 |
|
| 454 | +/** |
| 455 | + * arc_emac_set_rx_mode - Change the receive filtering mode. |
| 456 | + * @ndev: Pointer to the network device. |
| 457 | + * |
| 458 | + * This function enables/disables promiscuous or all-multicast mode |
| 459 | + * and updates the multicast filtering list of the network device. |
| 460 | + */ |
| 461 | +static void arc_emac_set_rx_mode(struct net_device *ndev) |
| 462 | +{ |
| 463 | + struct arc_emac_priv *priv = netdev_priv(ndev); |
| 464 | + |
| 465 | + if (ndev->flags & IFF_PROMISC) { |
| 466 | + arc_reg_or(priv, R_CTRL, PROM_MASK); |
| 467 | + } else { |
| 468 | + arc_reg_clr(priv, R_CTRL, PROM_MASK); |
| 469 | + |
| 470 | + if (ndev->flags & IFF_ALLMULTI) { |
| 471 | + arc_reg_set(priv, R_LAFL, ~0); |
| 472 | + arc_reg_set(priv, R_LAFH, ~0); |
| 473 | + } else { |
| 474 | + struct netdev_hw_addr *ha; |
| 475 | + unsigned int filter[2] = { 0, 0 }; |
| 476 | + int bit; |
| 477 | + |
| 478 | + netdev_for_each_mc_addr(ha, ndev) { |
| 479 | + bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26; |
| 480 | + filter[bit >> 5] |= 1 << (bit & 31); |
| 481 | + } |
| 482 | + |
| 483 | + arc_reg_set(priv, R_LAFL, filter[0]); |
| 484 | + arc_reg_set(priv, R_LAFH, filter[1]); |
| 485 | + } |
| 486 | + } |
| 487 | +} |
| 488 | + |
453 | 489 | /** |
454 | 490 | * arc_emac_stop - Close the network device. |
455 | 491 | * @ndev: Pointer to the network device. |
@@ -620,6 +656,7 @@ static const struct net_device_ops arc_emac_netdev_ops = { |
620 | 656 | .ndo_start_xmit = arc_emac_tx, |
621 | 657 | .ndo_set_mac_address = arc_emac_set_address, |
622 | 658 | .ndo_get_stats = arc_emac_stats, |
| 659 | + .ndo_set_rx_mode = arc_emac_set_rx_mode, |
623 | 660 | }; |
624 | 661 |
|
625 | 662 | static int arc_emac_probe(struct platform_device *pdev) |
|
0 commit comments