diff options
Diffstat (limited to 'drivers/net/e1000/e1000_main.c')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 40dbe4cfe556..ade483e6e6d0 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -126,7 +126,7 @@ static void e1000_clean_tx_ring(struct e1000_adapter *adapter, | |||
126 | struct e1000_tx_ring *tx_ring); | 126 | struct e1000_tx_ring *tx_ring); |
127 | static void e1000_clean_rx_ring(struct e1000_adapter *adapter, | 127 | static void e1000_clean_rx_ring(struct e1000_adapter *adapter, |
128 | struct e1000_rx_ring *rx_ring); | 128 | struct e1000_rx_ring *rx_ring); |
129 | static void e1000_set_multi(struct net_device *netdev); | 129 | static void e1000_set_rx_mode(struct net_device *netdev); |
130 | static void e1000_update_phy_info(unsigned long data); | 130 | static void e1000_update_phy_info(unsigned long data); |
131 | static void e1000_watchdog(unsigned long data); | 131 | static void e1000_watchdog(unsigned long data); |
132 | static void e1000_82547_tx_fifo_stall(unsigned long data); | 132 | static void e1000_82547_tx_fifo_stall(unsigned long data); |
@@ -487,7 +487,7 @@ static void e1000_configure(struct e1000_adapter *adapter) | |||
487 | struct net_device *netdev = adapter->netdev; | 487 | struct net_device *netdev = adapter->netdev; |
488 | int i; | 488 | int i; |
489 | 489 | ||
490 | e1000_set_multi(netdev); | 490 | e1000_set_rx_mode(netdev); |
491 | 491 | ||
492 | e1000_restore_vlan(adapter); | 492 | e1000_restore_vlan(adapter); |
493 | e1000_init_manageability(adapter); | 493 | e1000_init_manageability(adapter); |
@@ -900,7 +900,7 @@ e1000_probe(struct pci_dev *pdev, | |||
900 | netdev->stop = &e1000_close; | 900 | netdev->stop = &e1000_close; |
901 | netdev->hard_start_xmit = &e1000_xmit_frame; | 901 | netdev->hard_start_xmit = &e1000_xmit_frame; |
902 | netdev->get_stats = &e1000_get_stats; | 902 | netdev->get_stats = &e1000_get_stats; |
903 | netdev->set_multicast_list = &e1000_set_multi; | 903 | netdev->set_rx_mode = &e1000_set_rx_mode; |
904 | netdev->set_mac_address = &e1000_set_mac; | 904 | netdev->set_mac_address = &e1000_set_mac; |
905 | netdev->change_mtu = &e1000_change_mtu; | 905 | netdev->change_mtu = &e1000_change_mtu; |
906 | netdev->do_ioctl = &e1000_ioctl; | 906 | netdev->do_ioctl = &e1000_ioctl; |
@@ -2383,21 +2383,22 @@ e1000_set_mac(struct net_device *netdev, void *p) | |||
2383 | } | 2383 | } |
2384 | 2384 | ||
2385 | /** | 2385 | /** |
2386 | * e1000_set_multi - Multicast and Promiscuous mode set | 2386 | * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set |
2387 | * @netdev: network interface device structure | 2387 | * @netdev: network interface device structure |
2388 | * | 2388 | * |
2389 | * The set_multi entry point is called whenever the multicast address | 2389 | * The set_rx_mode entry point is called whenever the unicast or multicast |
2390 | * list or the network interface flags are updated. This routine is | 2390 | * address lists or the network interface flags are updated. This routine is |
2391 | * responsible for configuring the hardware for proper multicast, | 2391 | * responsible for configuring the hardware for proper unicast, multicast, |
2392 | * promiscuous mode, and all-multi behavior. | 2392 | * promiscuous mode, and all-multi behavior. |
2393 | **/ | 2393 | **/ |
2394 | 2394 | ||
2395 | static void | 2395 | static void |
2396 | e1000_set_multi(struct net_device *netdev) | 2396 | e1000_set_rx_mode(struct net_device *netdev) |
2397 | { | 2397 | { |
2398 | struct e1000_adapter *adapter = netdev_priv(netdev); | 2398 | struct e1000_adapter *adapter = netdev_priv(netdev); |
2399 | struct e1000_hw *hw = &adapter->hw; | 2399 | struct e1000_hw *hw = &adapter->hw; |
2400 | struct dev_mc_list *mc_ptr; | 2400 | struct dev_addr_list *uc_ptr; |
2401 | struct dev_addr_list *mc_ptr; | ||
2401 | uint32_t rctl; | 2402 | uint32_t rctl; |
2402 | uint32_t hash_value; | 2403 | uint32_t hash_value; |
2403 | int i, rar_entries = E1000_RAR_ENTRIES; | 2404 | int i, rar_entries = E1000_RAR_ENTRIES; |
@@ -2420,9 +2421,16 @@ e1000_set_multi(struct net_device *netdev) | |||
2420 | rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); | 2421 | rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); |
2421 | } else if (netdev->flags & IFF_ALLMULTI) { | 2422 | } else if (netdev->flags & IFF_ALLMULTI) { |
2422 | rctl |= E1000_RCTL_MPE; | 2423 | rctl |= E1000_RCTL_MPE; |
2423 | rctl &= ~E1000_RCTL_UPE; | ||
2424 | } else { | 2424 | } else { |
2425 | rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); | 2425 | rctl &= ~E1000_RCTL_MPE; |
2426 | } | ||
2427 | |||
2428 | uc_ptr = NULL; | ||
2429 | if (netdev->uc_count > rar_entries - 1) { | ||
2430 | rctl |= E1000_RCTL_UPE; | ||
2431 | } else if (!(netdev->flags & IFF_PROMISC)) { | ||
2432 | rctl &= ~E1000_RCTL_UPE; | ||
2433 | uc_ptr = netdev->uc_list; | ||
2426 | } | 2434 | } |
2427 | 2435 | ||
2428 | E1000_WRITE_REG(hw, RCTL, rctl); | 2436 | E1000_WRITE_REG(hw, RCTL, rctl); |
@@ -2432,7 +2440,10 @@ e1000_set_multi(struct net_device *netdev) | |||
2432 | if (hw->mac_type == e1000_82542_rev2_0) | 2440 | if (hw->mac_type == e1000_82542_rev2_0) |
2433 | e1000_enter_82542_rst(adapter); | 2441 | e1000_enter_82542_rst(adapter); |
2434 | 2442 | ||
2435 | /* load the first 14 multicast address into the exact filters 1-14 | 2443 | /* load the first 14 addresses into the exact filters 1-14. Unicast |
2444 | * addresses take precedence to avoid disabling unicast filtering | ||
2445 | * when possible. | ||
2446 | * | ||
2436 | * RAR 0 is used for the station MAC adddress | 2447 | * RAR 0 is used for the station MAC adddress |
2437 | * if there are not 14 addresses, go ahead and clear the filters | 2448 | * if there are not 14 addresses, go ahead and clear the filters |
2438 | * -- with 82571 controllers only 0-13 entries are filled here | 2449 | * -- with 82571 controllers only 0-13 entries are filled here |
@@ -2440,8 +2451,11 @@ e1000_set_multi(struct net_device *netdev) | |||
2440 | mc_ptr = netdev->mc_list; | 2451 | mc_ptr = netdev->mc_list; |
2441 | 2452 | ||
2442 | for (i = 1; i < rar_entries; i++) { | 2453 | for (i = 1; i < rar_entries; i++) { |
2443 | if (mc_ptr) { | 2454 | if (uc_ptr) { |
2444 | e1000_rar_set(hw, mc_ptr->dmi_addr, i); | 2455 | e1000_rar_set(hw, uc_ptr->da_addr, i); |
2456 | uc_ptr = uc_ptr->next; | ||
2457 | } else if (mc_ptr) { | ||
2458 | e1000_rar_set(hw, mc_ptr->da_addr, i); | ||
2445 | mc_ptr = mc_ptr->next; | 2459 | mc_ptr = mc_ptr->next; |
2446 | } else { | 2460 | } else { |
2447 | E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); | 2461 | E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); |
@@ -2450,6 +2464,7 @@ e1000_set_multi(struct net_device *netdev) | |||
2450 | E1000_WRITE_FLUSH(hw); | 2464 | E1000_WRITE_FLUSH(hw); |
2451 | } | 2465 | } |
2452 | } | 2466 | } |
2467 | WARN_ON(uc_ptr != NULL); | ||
2453 | 2468 | ||
2454 | /* clear the old settings from the multicast hash table */ | 2469 | /* clear the old settings from the multicast hash table */ |
2455 | 2470 | ||
@@ -2461,7 +2476,7 @@ e1000_set_multi(struct net_device *netdev) | |||
2461 | /* load any remaining addresses into the hash table */ | 2476 | /* load any remaining addresses into the hash table */ |
2462 | 2477 | ||
2463 | for (; mc_ptr; mc_ptr = mc_ptr->next) { | 2478 | for (; mc_ptr; mc_ptr = mc_ptr->next) { |
2464 | hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr); | 2479 | hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr); |
2465 | e1000_mta_set(hw, hash_value); | 2480 | e1000_mta_set(hw, hash_value); |
2466 | } | 2481 | } |
2467 | 2482 | ||
@@ -5070,7 +5085,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5070 | 5085 | ||
5071 | if (wufc) { | 5086 | if (wufc) { |
5072 | e1000_setup_rctl(adapter); | 5087 | e1000_setup_rctl(adapter); |
5073 | e1000_set_multi(netdev); | 5088 | e1000_set_rx_mode(netdev); |
5074 | 5089 | ||
5075 | /* turn on all-multi mode if wake on multicast is enabled */ | 5090 | /* turn on all-multi mode if wake on multicast is enabled */ |
5076 | if (wufc & E1000_WUFC_MC) { | 5091 | if (wufc & E1000_WUFC_MC) { |