diff options
author | Jacob Keller <jacob.e.keller@intel.com> | 2014-03-29 02:51:25 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2014-04-23 03:09:48 -0400 |
commit | 5d7daa35b9eb14b64acd208a900e44aeeee25eca (patch) | |
tree | 37685028dc69160e98000fee749417d4fae09fd6 /drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |
parent | b335e75bab9e578764fc7dd581b61075bfd8c655 (diff) |
ixgbe: improve mac filter handling
Add mac_table API based on work done for igb, which includes functions
to add and delete mac filters. This simplifies code for various entities
that use MAC filters such as VMDQ, SR-IOV, MACVLAN, and such.
Reported-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 188 |
1 files changed, 148 insertions, 40 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 84044ed1914d..39a1c07258b0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -3868,13 +3868,135 @@ static int ixgbe_write_mc_addr_list(struct net_device *netdev) | |||
3868 | return -ENOMEM; | 3868 | return -ENOMEM; |
3869 | 3869 | ||
3870 | #ifdef CONFIG_PCI_IOV | 3870 | #ifdef CONFIG_PCI_IOV |
3871 | if (adapter->num_vfs) | 3871 | ixgbe_restore_vf_multicasts(adapter); |
3872 | ixgbe_restore_vf_multicasts(adapter); | ||
3873 | #endif | 3872 | #endif |
3874 | 3873 | ||
3875 | return netdev_mc_count(netdev); | 3874 | return netdev_mc_count(netdev); |
3876 | } | 3875 | } |
3877 | 3876 | ||
3877 | #ifdef CONFIG_PCI_IOV | ||
3878 | void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter) | ||
3879 | { | ||
3880 | struct ixgbe_hw *hw = &adapter->hw; | ||
3881 | int i; | ||
3882 | for (i = 0; i < hw->mac.num_rar_entries; i++) { | ||
3883 | if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) | ||
3884 | hw->mac.ops.set_rar(hw, i, adapter->mac_table[i].addr, | ||
3885 | adapter->mac_table[i].queue, | ||
3886 | IXGBE_RAH_AV); | ||
3887 | else | ||
3888 | hw->mac.ops.clear_rar(hw, i); | ||
3889 | |||
3890 | adapter->mac_table[i].state &= ~(IXGBE_MAC_STATE_MODIFIED); | ||
3891 | } | ||
3892 | } | ||
3893 | #endif | ||
3894 | |||
3895 | static void ixgbe_sync_mac_table(struct ixgbe_adapter *adapter) | ||
3896 | { | ||
3897 | struct ixgbe_hw *hw = &adapter->hw; | ||
3898 | int i; | ||
3899 | for (i = 0; i < hw->mac.num_rar_entries; i++) { | ||
3900 | if (adapter->mac_table[i].state & IXGBE_MAC_STATE_MODIFIED) { | ||
3901 | if (adapter->mac_table[i].state & | ||
3902 | IXGBE_MAC_STATE_IN_USE) | ||
3903 | hw->mac.ops.set_rar(hw, i, | ||
3904 | adapter->mac_table[i].addr, | ||
3905 | adapter->mac_table[i].queue, | ||
3906 | IXGBE_RAH_AV); | ||
3907 | else | ||
3908 | hw->mac.ops.clear_rar(hw, i); | ||
3909 | |||
3910 | adapter->mac_table[i].state &= | ||
3911 | ~(IXGBE_MAC_STATE_MODIFIED); | ||
3912 | } | ||
3913 | } | ||
3914 | } | ||
3915 | |||
3916 | static void ixgbe_flush_sw_mac_table(struct ixgbe_adapter *adapter) | ||
3917 | { | ||
3918 | int i; | ||
3919 | struct ixgbe_hw *hw = &adapter->hw; | ||
3920 | |||
3921 | for (i = 0; i < hw->mac.num_rar_entries; i++) { | ||
3922 | adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED; | ||
3923 | adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE; | ||
3924 | memset(adapter->mac_table[i].addr, 0, ETH_ALEN); | ||
3925 | adapter->mac_table[i].queue = 0; | ||
3926 | } | ||
3927 | ixgbe_sync_mac_table(adapter); | ||
3928 | } | ||
3929 | |||
3930 | static int ixgbe_available_rars(struct ixgbe_adapter *adapter) | ||
3931 | { | ||
3932 | struct ixgbe_hw *hw = &adapter->hw; | ||
3933 | int i, count = 0; | ||
3934 | |||
3935 | for (i = 0; i < hw->mac.num_rar_entries; i++) { | ||
3936 | if (adapter->mac_table[i].state == 0) | ||
3937 | count++; | ||
3938 | } | ||
3939 | return count; | ||
3940 | } | ||
3941 | |||
3942 | /* this function destroys the first RAR entry */ | ||
3943 | static void ixgbe_mac_set_default_filter(struct ixgbe_adapter *adapter, | ||
3944 | u8 *addr) | ||
3945 | { | ||
3946 | struct ixgbe_hw *hw = &adapter->hw; | ||
3947 | |||
3948 | memcpy(&adapter->mac_table[0].addr, addr, ETH_ALEN); | ||
3949 | adapter->mac_table[0].queue = VMDQ_P(0); | ||
3950 | adapter->mac_table[0].state = (IXGBE_MAC_STATE_DEFAULT | | ||
3951 | IXGBE_MAC_STATE_IN_USE); | ||
3952 | hw->mac.ops.set_rar(hw, 0, adapter->mac_table[0].addr, | ||
3953 | adapter->mac_table[0].queue, | ||
3954 | IXGBE_RAH_AV); | ||
3955 | } | ||
3956 | |||
3957 | int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue) | ||
3958 | { | ||
3959 | struct ixgbe_hw *hw = &adapter->hw; | ||
3960 | int i; | ||
3961 | |||
3962 | if (is_zero_ether_addr(addr)) | ||
3963 | return -EINVAL; | ||
3964 | |||
3965 | for (i = 0; i < hw->mac.num_rar_entries; i++) { | ||
3966 | if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) | ||
3967 | continue; | ||
3968 | adapter->mac_table[i].state |= (IXGBE_MAC_STATE_MODIFIED | | ||
3969 | IXGBE_MAC_STATE_IN_USE); | ||
3970 | ether_addr_copy(adapter->mac_table[i].addr, addr); | ||
3971 | adapter->mac_table[i].queue = queue; | ||
3972 | ixgbe_sync_mac_table(adapter); | ||
3973 | return i; | ||
3974 | } | ||
3975 | return -ENOMEM; | ||
3976 | } | ||
3977 | |||
3978 | int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue) | ||
3979 | { | ||
3980 | /* search table for addr, if found, set to 0 and sync */ | ||
3981 | int i; | ||
3982 | struct ixgbe_hw *hw = &adapter->hw; | ||
3983 | |||
3984 | if (is_zero_ether_addr(addr)) | ||
3985 | return -EINVAL; | ||
3986 | |||
3987 | for (i = 0; i < hw->mac.num_rar_entries; i++) { | ||
3988 | if (ether_addr_equal(addr, adapter->mac_table[i].addr) && | ||
3989 | adapter->mac_table[i].queue == queue) { | ||
3990 | adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED; | ||
3991 | adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE; | ||
3992 | memset(adapter->mac_table[i].addr, 0, ETH_ALEN); | ||
3993 | adapter->mac_table[i].queue = 0; | ||
3994 | ixgbe_sync_mac_table(adapter); | ||
3995 | return 0; | ||
3996 | } | ||
3997 | } | ||
3998 | return -ENOMEM; | ||
3999 | } | ||
3878 | /** | 4000 | /** |
3879 | * ixgbe_write_uc_addr_list - write unicast addresses to RAR table | 4001 | * ixgbe_write_uc_addr_list - write unicast addresses to RAR table |
3880 | * @netdev: network interface device structure | 4002 | * @netdev: network interface device structure |
@@ -3884,39 +4006,23 @@ static int ixgbe_write_mc_addr_list(struct net_device *netdev) | |||
3884 | * 0 on no addresses written | 4006 | * 0 on no addresses written |
3885 | * X on writing X addresses to the RAR table | 4007 | * X on writing X addresses to the RAR table |
3886 | **/ | 4008 | **/ |
3887 | static int ixgbe_write_uc_addr_list(struct net_device *netdev) | 4009 | static int ixgbe_write_uc_addr_list(struct net_device *netdev, int vfn) |
3888 | { | 4010 | { |
3889 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 4011 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
3890 | struct ixgbe_hw *hw = &adapter->hw; | ||
3891 | unsigned int rar_entries = hw->mac.num_rar_entries - 1; | ||
3892 | int count = 0; | 4012 | int count = 0; |
3893 | 4013 | ||
3894 | /* In SR-IOV/VMDQ modes significantly less RAR entries are available */ | ||
3895 | if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) | ||
3896 | rar_entries = IXGBE_MAX_PF_MACVLANS - 1; | ||
3897 | |||
3898 | /* return ENOMEM indicating insufficient memory for addresses */ | 4014 | /* return ENOMEM indicating insufficient memory for addresses */ |
3899 | if (netdev_uc_count(netdev) > rar_entries) | 4015 | if (netdev_uc_count(netdev) > ixgbe_available_rars(adapter)) |
3900 | return -ENOMEM; | 4016 | return -ENOMEM; |
3901 | 4017 | ||
3902 | if (!netdev_uc_empty(netdev)) { | 4018 | if (!netdev_uc_empty(netdev)) { |
3903 | struct netdev_hw_addr *ha; | 4019 | struct netdev_hw_addr *ha; |
3904 | /* return error if we do not support writing to RAR table */ | ||
3905 | if (!hw->mac.ops.set_rar) | ||
3906 | return -ENOMEM; | ||
3907 | |||
3908 | netdev_for_each_uc_addr(ha, netdev) { | 4020 | netdev_for_each_uc_addr(ha, netdev) { |
3909 | if (!rar_entries) | 4021 | ixgbe_del_mac_filter(adapter, ha->addr, vfn); |
3910 | break; | 4022 | ixgbe_add_mac_filter(adapter, ha->addr, vfn); |
3911 | hw->mac.ops.set_rar(hw, rar_entries--, ha->addr, | ||
3912 | VMDQ_P(0), IXGBE_RAH_AV); | ||
3913 | count++; | 4023 | count++; |
3914 | } | 4024 | } |
3915 | } | 4025 | } |
3916 | /* write the addresses in reverse order to avoid write combining */ | ||
3917 | for (; rar_entries > 0 ; rar_entries--) | ||
3918 | hw->mac.ops.clear_rar(hw, rar_entries); | ||
3919 | |||
3920 | return count; | 4026 | return count; |
3921 | } | 4027 | } |
3922 | 4028 | ||
@@ -3975,7 +4081,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) | |||
3975 | * sufficient space to store all the addresses then enable | 4081 | * sufficient space to store all the addresses then enable |
3976 | * unicast promiscuous mode | 4082 | * unicast promiscuous mode |
3977 | */ | 4083 | */ |
3978 | count = ixgbe_write_uc_addr_list(netdev); | 4084 | count = ixgbe_write_uc_addr_list(netdev, VMDQ_P(0)); |
3979 | if (count < 0) { | 4085 | if (count < 0) { |
3980 | fctrl |= IXGBE_FCTRL_UPE; | 4086 | fctrl |= IXGBE_FCTRL_UPE; |
3981 | vmolr |= IXGBE_VMOLR_ROPE; | 4087 | vmolr |= IXGBE_VMOLR_ROPE; |
@@ -4287,20 +4393,10 @@ static void ixgbe_macvlan_set_rx_mode(struct net_device *dev, unsigned int pool, | |||
4287 | vmolr |= IXGBE_VMOLR_ROMPE; | 4393 | vmolr |= IXGBE_VMOLR_ROMPE; |
4288 | hw->mac.ops.update_mc_addr_list(hw, dev); | 4394 | hw->mac.ops.update_mc_addr_list(hw, dev); |
4289 | } | 4395 | } |
4290 | ixgbe_write_uc_addr_list(adapter->netdev); | 4396 | ixgbe_write_uc_addr_list(adapter->netdev, pool); |
4291 | IXGBE_WRITE_REG(hw, IXGBE_VMOLR(pool), vmolr); | 4397 | IXGBE_WRITE_REG(hw, IXGBE_VMOLR(pool), vmolr); |
4292 | } | 4398 | } |
4293 | 4399 | ||
4294 | static void ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, | ||
4295 | u8 *addr, u16 pool) | ||
4296 | { | ||
4297 | struct ixgbe_hw *hw = &adapter->hw; | ||
4298 | unsigned int entry; | ||
4299 | |||
4300 | entry = hw->mac.num_rar_entries - pool; | ||
4301 | hw->mac.ops.set_rar(hw, entry, addr, VMDQ_P(pool), IXGBE_RAH_AV); | ||
4302 | } | ||
4303 | |||
4304 | static void ixgbe_fwd_psrtype(struct ixgbe_fwd_adapter *vadapter) | 4400 | static void ixgbe_fwd_psrtype(struct ixgbe_fwd_adapter *vadapter) |
4305 | { | 4401 | { |
4306 | struct ixgbe_adapter *adapter = vadapter->real_adapter; | 4402 | struct ixgbe_adapter *adapter = vadapter->real_adapter; |
@@ -4780,7 +4876,9 @@ void ixgbe_up(struct ixgbe_adapter *adapter) | |||
4780 | void ixgbe_reset(struct ixgbe_adapter *adapter) | 4876 | void ixgbe_reset(struct ixgbe_adapter *adapter) |
4781 | { | 4877 | { |
4782 | struct ixgbe_hw *hw = &adapter->hw; | 4878 | struct ixgbe_hw *hw = &adapter->hw; |
4879 | struct net_device *netdev = adapter->netdev; | ||
4783 | int err; | 4880 | int err; |
4881 | u8 old_addr[ETH_ALEN]; | ||
4784 | 4882 | ||
4785 | if (ixgbe_removed(hw->hw_addr)) | 4883 | if (ixgbe_removed(hw->hw_addr)) |
4786 | return; | 4884 | return; |
@@ -4816,9 +4914,10 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) | |||
4816 | } | 4914 | } |
4817 | 4915 | ||
4818 | clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); | 4916 | clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); |
4819 | 4917 | /* do not flush user set addresses */ | |
4820 | /* reprogram the RAR[0] in case user changed it. */ | 4918 | memcpy(old_addr, &adapter->mac_table[0].addr, netdev->addr_len); |
4821 | hw->mac.ops.set_rar(hw, 0, hw->mac.addr, VMDQ_P(0), IXGBE_RAH_AV); | 4919 | ixgbe_flush_sw_mac_table(adapter); |
4920 | ixgbe_mac_set_default_filter(adapter, old_addr); | ||
4822 | 4921 | ||
4823 | /* update SAN MAC vmdq pool selection */ | 4922 | /* update SAN MAC vmdq pool selection */ |
4824 | if (hw->mac.san_mac_rar_index) | 4923 | if (hw->mac.san_mac_rar_index) |
@@ -5064,6 +5163,10 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
5064 | #endif /* CONFIG_IXGBE_DCB */ | 5163 | #endif /* CONFIG_IXGBE_DCB */ |
5065 | #endif /* IXGBE_FCOE */ | 5164 | #endif /* IXGBE_FCOE */ |
5066 | 5165 | ||
5166 | adapter->mac_table = kzalloc(sizeof(struct ixgbe_mac_addr) * | ||
5167 | hw->mac.num_rar_entries, | ||
5168 | GFP_ATOMIC); | ||
5169 | |||
5067 | /* Set MAC specific capability flags and exceptions */ | 5170 | /* Set MAC specific capability flags and exceptions */ |
5068 | switch (hw->mac.type) { | 5171 | switch (hw->mac.type) { |
5069 | case ixgbe_mac_82598EB: | 5172 | case ixgbe_mac_82598EB: |
@@ -7210,16 +7313,17 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p) | |||
7210 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 7313 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
7211 | struct ixgbe_hw *hw = &adapter->hw; | 7314 | struct ixgbe_hw *hw = &adapter->hw; |
7212 | struct sockaddr *addr = p; | 7315 | struct sockaddr *addr = p; |
7316 | int ret; | ||
7213 | 7317 | ||
7214 | if (!is_valid_ether_addr(addr->sa_data)) | 7318 | if (!is_valid_ether_addr(addr->sa_data)) |
7215 | return -EADDRNOTAVAIL; | 7319 | return -EADDRNOTAVAIL; |
7216 | 7320 | ||
7321 | ixgbe_del_mac_filter(adapter, hw->mac.addr, VMDQ_P(0)); | ||
7217 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 7322 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
7218 | memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); | 7323 | memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); |
7219 | 7324 | ||
7220 | hw->mac.ops.set_rar(hw, 0, hw->mac.addr, VMDQ_P(0), IXGBE_RAH_AV); | 7325 | ret = ixgbe_add_mac_filter(adapter, hw->mac.addr, VMDQ_P(0)); |
7221 | 7326 | return ret > 0 ? 0 : ret; | |
7222 | return 0; | ||
7223 | } | 7327 | } |
7224 | 7328 | ||
7225 | static int | 7329 | static int |
@@ -8225,6 +8329,8 @@ skip_sriov: | |||
8225 | goto err_sw_init; | 8329 | goto err_sw_init; |
8226 | } | 8330 | } |
8227 | 8331 | ||
8332 | ixgbe_mac_set_default_filter(adapter, hw->mac.perm_addr); | ||
8333 | |||
8228 | setup_timer(&adapter->service_timer, &ixgbe_service_timer, | 8334 | setup_timer(&adapter->service_timer, &ixgbe_service_timer, |
8229 | (unsigned long) adapter); | 8335 | (unsigned long) adapter); |
8230 | 8336 | ||
@@ -8357,6 +8463,7 @@ err_sw_init: | |||
8357 | ixgbe_disable_sriov(adapter); | 8463 | ixgbe_disable_sriov(adapter); |
8358 | adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; | 8464 | adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; |
8359 | iounmap(adapter->io_addr); | 8465 | iounmap(adapter->io_addr); |
8466 | kfree(adapter->mac_table); | ||
8360 | err_ioremap: | 8467 | err_ioremap: |
8361 | free_netdev(netdev); | 8468 | free_netdev(netdev); |
8362 | err_alloc_etherdev: | 8469 | err_alloc_etherdev: |
@@ -8430,6 +8537,7 @@ static void ixgbe_remove(struct pci_dev *pdev) | |||
8430 | 8537 | ||
8431 | e_dev_info("complete\n"); | 8538 | e_dev_info("complete\n"); |
8432 | 8539 | ||
8540 | kfree(adapter->mac_table); | ||
8433 | free_netdev(netdev); | 8541 | free_netdev(netdev); |
8434 | 8542 | ||
8435 | pci_disable_pcie_error_reporting(pdev); | 8543 | pci_disable_pcie_error_reporting(pdev); |