diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-09-03 10:48:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-03 23:01:45 -0400 |
commit | ff41f8dcc63b4d027ed314ae909df53746c40632 (patch) | |
tree | f3465a5e04b48150fad1b4b24eff51e7772f2bef /drivers | |
parent | 55f9d6786de2f9cf37db50dbe8ae16f887f3ad7f (diff) |
igb: add support for set_rx_mode netdevice operation
This patch adds support for the set_rx_mode netdevice operation so that igb
can better support multiple unicast addresses.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/igb/igb_main.c | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 7a054d99bff1..95089a8feeec 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -94,7 +94,7 @@ static void igb_clean_all_tx_rings(struct igb_adapter *); | |||
94 | static void igb_clean_all_rx_rings(struct igb_adapter *); | 94 | static void igb_clean_all_rx_rings(struct igb_adapter *); |
95 | static void igb_clean_tx_ring(struct igb_ring *); | 95 | static void igb_clean_tx_ring(struct igb_ring *); |
96 | static void igb_clean_rx_ring(struct igb_ring *); | 96 | static void igb_clean_rx_ring(struct igb_ring *); |
97 | static void igb_set_multi(struct net_device *); | 97 | static void igb_set_rx_mode(struct net_device *); |
98 | static void igb_update_phy_info(unsigned long); | 98 | static void igb_update_phy_info(unsigned long); |
99 | static void igb_watchdog(unsigned long); | 99 | static void igb_watchdog(unsigned long); |
100 | static void igb_watchdog_task(struct work_struct *); | 100 | static void igb_watchdog_task(struct work_struct *); |
@@ -928,7 +928,7 @@ static void igb_configure(struct igb_adapter *adapter) | |||
928 | int i; | 928 | int i; |
929 | 929 | ||
930 | igb_get_hw_control(adapter); | 930 | igb_get_hw_control(adapter); |
931 | igb_set_multi(netdev); | 931 | igb_set_rx_mode(netdev); |
932 | 932 | ||
933 | igb_restore_vlan(adapter); | 933 | igb_restore_vlan(adapter); |
934 | 934 | ||
@@ -1169,7 +1169,8 @@ static const struct net_device_ops igb_netdev_ops = { | |||
1169 | .ndo_stop = igb_close, | 1169 | .ndo_stop = igb_close, |
1170 | .ndo_start_xmit = igb_xmit_frame_adv, | 1170 | .ndo_start_xmit = igb_xmit_frame_adv, |
1171 | .ndo_get_stats = igb_get_stats, | 1171 | .ndo_get_stats = igb_get_stats, |
1172 | .ndo_set_multicast_list = igb_set_multi, | 1172 | .ndo_set_rx_mode = igb_set_rx_mode, |
1173 | .ndo_set_multicast_list = igb_set_rx_mode, | ||
1173 | .ndo_set_mac_address = igb_set_mac, | 1174 | .ndo_set_mac_address = igb_set_mac, |
1174 | .ndo_change_mtu = igb_change_mtu, | 1175 | .ndo_change_mtu = igb_change_mtu, |
1175 | .ndo_do_ioctl = igb_ioctl, | 1176 | .ndo_do_ioctl = igb_ioctl, |
@@ -2519,48 +2520,70 @@ static int igb_set_mac(struct net_device *netdev, void *p) | |||
2519 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 2520 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
2520 | memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); | 2521 | memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); |
2521 | 2522 | ||
2522 | hw->mac.ops.rar_set(hw, hw->mac.addr, 0); | 2523 | igb_rar_set(hw, hw->mac.addr, 0); |
2523 | |||
2524 | igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); | 2524 | igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0); |
2525 | 2525 | ||
2526 | return 0; | 2526 | return 0; |
2527 | } | 2527 | } |
2528 | 2528 | ||
2529 | /** | 2529 | /** |
2530 | * igb_set_multi - Multicast and Promiscuous mode set | 2530 | * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set |
2531 | * @netdev: network interface device structure | 2531 | * @netdev: network interface device structure |
2532 | * | 2532 | * |
2533 | * The set_multi entry point is called whenever the multicast address | 2533 | * The set_rx_mode entry point is called whenever the unicast or multicast |
2534 | * list or the network interface flags are updated. This routine is | 2534 | * address lists or the network interface flags are updated. This routine is |
2535 | * responsible for configuring the hardware for proper multicast, | 2535 | * responsible for configuring the hardware for proper unicast, multicast, |
2536 | * promiscuous mode, and all-multi behavior. | 2536 | * promiscuous mode, and all-multi behavior. |
2537 | **/ | 2537 | **/ |
2538 | static void igb_set_multi(struct net_device *netdev) | 2538 | static void igb_set_rx_mode(struct net_device *netdev) |
2539 | { | 2539 | { |
2540 | struct igb_adapter *adapter = netdev_priv(netdev); | 2540 | struct igb_adapter *adapter = netdev_priv(netdev); |
2541 | struct e1000_hw *hw = &adapter->hw; | 2541 | struct e1000_hw *hw = &adapter->hw; |
2542 | struct dev_mc_list *mc_ptr; | 2542 | unsigned int rar_entries = hw->mac.rar_entry_count - |
2543 | (adapter->vfs_allocated_count + 1); | ||
2544 | struct dev_mc_list *mc_ptr = netdev->mc_list; | ||
2543 | u8 *mta_list = NULL; | 2545 | u8 *mta_list = NULL; |
2544 | u32 rctl; | 2546 | u32 rctl; |
2545 | int i; | 2547 | int i; |
2546 | 2548 | ||
2547 | /* Check for Promiscuous and All Multicast modes */ | 2549 | /* Check for Promiscuous and All Multicast modes */ |
2548 | |||
2549 | rctl = rd32(E1000_RCTL); | 2550 | rctl = rd32(E1000_RCTL); |
2550 | 2551 | ||
2551 | if (netdev->flags & IFF_PROMISC) { | 2552 | if (netdev->flags & IFF_PROMISC) { |
2552 | rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); | 2553 | rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); |
2553 | rctl &= ~E1000_RCTL_VFE; | 2554 | rctl &= ~E1000_RCTL_VFE; |
2554 | } else { | 2555 | } else { |
2555 | if (netdev->flags & IFF_ALLMULTI) { | 2556 | if (netdev->flags & IFF_ALLMULTI) |
2556 | rctl |= E1000_RCTL_MPE; | 2557 | rctl |= E1000_RCTL_MPE; |
2558 | else | ||
2559 | rctl &= ~E1000_RCTL_MPE; | ||
2560 | |||
2561 | if (netdev->uc.count > rar_entries) | ||
2562 | rctl |= E1000_RCTL_UPE; | ||
2563 | else | ||
2557 | rctl &= ~E1000_RCTL_UPE; | 2564 | rctl &= ~E1000_RCTL_UPE; |
2558 | } else | ||
2559 | rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); | ||
2560 | rctl |= E1000_RCTL_VFE; | 2565 | rctl |= E1000_RCTL_VFE; |
2561 | } | 2566 | } |
2562 | wr32(E1000_RCTL, rctl); | 2567 | wr32(E1000_RCTL, rctl); |
2563 | 2568 | ||
2569 | if (netdev->uc.count && rar_entries) { | ||
2570 | struct netdev_hw_addr *ha; | ||
2571 | list_for_each_entry(ha, &netdev->uc.list, list) { | ||
2572 | if (!rar_entries) | ||
2573 | break; | ||
2574 | igb_rar_set(hw, ha->addr, rar_entries); | ||
2575 | igb_set_rah_pool(hw, adapter->vfs_allocated_count, | ||
2576 | rar_entries); | ||
2577 | rar_entries--; | ||
2578 | } | ||
2579 | } | ||
2580 | /* write the addresses in reverse order to avoid write combining */ | ||
2581 | for (; rar_entries > 0 ; rar_entries--) { | ||
2582 | wr32(E1000_RAH(rar_entries), 0); | ||
2583 | wr32(E1000_RAL(rar_entries), 0); | ||
2584 | } | ||
2585 | wrfl(); | ||
2586 | |||
2564 | if (!netdev->mc_count) { | 2587 | if (!netdev->mc_count) { |
2565 | /* nothing to program, so clear mc list */ | 2588 | /* nothing to program, so clear mc list */ |
2566 | igb_update_mc_addr_list(hw, NULL, 0); | 2589 | igb_update_mc_addr_list(hw, NULL, 0); |
@@ -2576,8 +2599,6 @@ static void igb_set_multi(struct net_device *netdev) | |||
2576 | } | 2599 | } |
2577 | 2600 | ||
2578 | /* The shared function expects a packed array of only addresses. */ | 2601 | /* The shared function expects a packed array of only addresses. */ |
2579 | mc_ptr = netdev->mc_list; | ||
2580 | |||
2581 | for (i = 0; i < netdev->mc_count; i++) { | 2602 | for (i = 0; i < netdev->mc_count; i++) { |
2582 | if (!mc_ptr) | 2603 | if (!mc_ptr) |
2583 | break; | 2604 | break; |
@@ -3938,7 +3959,7 @@ static int igb_set_vf_multicasts(struct igb_adapter *adapter, | |||
3938 | vf_data->vf_mc_hashes[i] = hash_list[i];; | 3959 | vf_data->vf_mc_hashes[i] = hash_list[i];; |
3939 | 3960 | ||
3940 | /* Flush and reset the mta with the new values */ | 3961 | /* Flush and reset the mta with the new values */ |
3941 | igb_set_multi(adapter->netdev); | 3962 | igb_set_rx_mode(adapter->netdev); |
3942 | 3963 | ||
3943 | return 0; | 3964 | return 0; |
3944 | } | 3965 | } |
@@ -4072,13 +4093,14 @@ static inline void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) | |||
4072 | adapter->vf_data[vf].num_vf_mc_hashes = 0; | 4093 | adapter->vf_data[vf].num_vf_mc_hashes = 0; |
4073 | 4094 | ||
4074 | /* Flush and reset the mta with the new values */ | 4095 | /* Flush and reset the mta with the new values */ |
4075 | igb_set_multi(adapter->netdev); | 4096 | igb_set_rx_mode(adapter->netdev); |
4076 | } | 4097 | } |
4077 | 4098 | ||
4078 | static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) | 4099 | static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) |
4079 | { | 4100 | { |
4080 | struct e1000_hw *hw = &adapter->hw; | 4101 | struct e1000_hw *hw = &adapter->hw; |
4081 | unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; | 4102 | unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; |
4103 | int rar_entry = hw->mac.rar_entry_count - (vf + 1); | ||
4082 | u32 reg, msgbuf[3]; | 4104 | u32 reg, msgbuf[3]; |
4083 | u8 *addr = (u8 *)(&msgbuf[1]); | 4105 | u8 *addr = (u8 *)(&msgbuf[1]); |
4084 | 4106 | ||
@@ -4086,8 +4108,8 @@ static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) | |||
4086 | igb_vf_reset_event(adapter, vf); | 4108 | igb_vf_reset_event(adapter, vf); |
4087 | 4109 | ||
4088 | /* set vf mac address */ | 4110 | /* set vf mac address */ |
4089 | igb_rar_set(hw, vf_mac, vf + 1); | 4111 | igb_rar_set(hw, vf_mac, rar_entry); |
4090 | igb_set_rah_pool(hw, vf, vf + 1); | 4112 | igb_set_rah_pool(hw, vf, rar_entry); |
4091 | 4113 | ||
4092 | /* enable transmit and receive for vf */ | 4114 | /* enable transmit and receive for vf */ |
4093 | reg = rd32(E1000_VFTE); | 4115 | reg = rd32(E1000_VFTE); |
@@ -5228,7 +5250,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) | |||
5228 | 5250 | ||
5229 | if (wufc) { | 5251 | if (wufc) { |
5230 | igb_setup_rctl(adapter); | 5252 | igb_setup_rctl(adapter); |
5231 | igb_set_multi(netdev); | 5253 | igb_set_rx_mode(netdev); |
5232 | 5254 | ||
5233 | /* turn on all-multi mode if wake on multicast is enabled */ | 5255 | /* turn on all-multi mode if wake on multicast is enabled */ |
5234 | if (wufc & E1000_WUFC_MC) { | 5256 | if (wufc & E1000_WUFC_MC) { |
@@ -5482,12 +5504,13 @@ static int igb_set_vf_mac(struct igb_adapter *adapter, | |||
5482 | int vf, unsigned char *mac_addr) | 5504 | int vf, unsigned char *mac_addr) |
5483 | { | 5505 | { |
5484 | struct e1000_hw *hw = &adapter->hw; | 5506 | struct e1000_hw *hw = &adapter->hw; |
5485 | int rar_entry = vf + 1; /* VF MAC addresses start at entry 1 */ | 5507 | /* VF MAC addresses start at end of receive addresses and moves |
5486 | 5508 | * torwards the first, as a result a collision should not be possible */ | |
5487 | igb_rar_set(hw, mac_addr, rar_entry); | 5509 | int rar_entry = hw->mac.rar_entry_count - (vf + 1); |
5488 | 5510 | ||
5489 | memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, ETH_ALEN); | 5511 | memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, ETH_ALEN); |
5490 | 5512 | ||
5513 | igb_rar_set(hw, mac_addr, rar_entry); | ||
5491 | igb_set_rah_pool(hw, vf, rar_entry); | 5514 | igb_set_rah_pool(hw, vf, rar_entry); |
5492 | 5515 | ||
5493 | return 0; | 5516 | return 0; |