Commit 28fc06f5 authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

igb: move all multicast addresses into multicast table array

This patch moves all of the multicast addresses out of the free Receive
address registers and instead programs them all into the multicast table
array.  As a result the multicast filtering may not be as precise, but it
also greatly reduces the overhead for multicast addresses.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 009bc06e
...@@ -797,65 +797,6 @@ static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count) ...@@ -797,65 +797,6 @@ static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count)
hw->mac.ops.rar_set(hw, addr, i); hw->mac.ops.rar_set(hw, addr, i);
} }
/**
* igb_update_mc_addr_list - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
* @rar_used_count: the first RAR register free to program
* @rar_count: total number of supported Receive Address Registers
*
* Updates the Receive Address Registers and Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
* The parameter rar_count will usually be hw->mac.rar_entry_count
* unless there are workarounds that change this.
**/
void igb_update_mc_addr_list(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count,
u32 rar_used_count, u32 rar_count)
{
u32 hash_value;
u32 i;
u8 addr[6] = {0,0,0,0,0,0};
/*
* This function is essentially the same as that of
* igb_update_mc_addr_list_generic. However it also takes care
* of the special case where the register offset of the
* second set of RARs begins elsewhere. This is implicitly taken care by
* function e1000_rar_set_generic.
*/
/*
* Load the first set of multicast addresses into the exact
* filters (RAR). If there are not enough to fill the RAR
* array, clear the filters.
*/
for (i = rar_used_count; i < rar_count; i++) {
if (mc_addr_count) {
igb_rar_set(hw, mc_addr_list, i);
mc_addr_count--;
mc_addr_list += ETH_ALEN;
} else {
igb_rar_set(hw, addr, i);
}
}
/* Clear the old settings from the MTA */
hw_dbg("Clearing MTA\n");
for (i = 0; i < hw->mac.mta_reg_count; i++) {
array_wr32(E1000_MTA, i, 0);
wrfl();
}
/* Load any remaining multicast addresses into the hash table. */
for (; mc_addr_count > 0; mc_addr_count--) {
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
hw_dbg("Hash value = 0x%03X\n", hash_value);
igb_mta_set(hw, hash_value);
mc_addr_list += ETH_ALEN;
}
}
/** /**
* igb_shutdown_fiber_serdes_link_82575 - Remove link during power down * igb_shutdown_fiber_serdes_link_82575 - Remove link during power down
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#ifndef _E1000_82575_H_ #ifndef _E1000_82575_H_
#define _E1000_82575_H_ #define _E1000_82575_H_
void igb_update_mc_addr_list(struct e1000_hw*, u8*, u32, u32, u32);
extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
......
...@@ -338,6 +338,10 @@ struct e1000_mac_info { ...@@ -338,6 +338,10 @@ struct e1000_mac_info {
u16 ifs_ratio; u16 ifs_ratio;
u16 ifs_step_size; u16 ifs_step_size;
u16 mta_reg_count; u16 mta_reg_count;
/* Maximum size of the MTA register table in all supported adapters */
#define MAX_MTA_REG 128
u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count; u16 rar_entry_count;
u8 forced_speed_duplex; u8 forced_speed_duplex;
......
...@@ -260,6 +260,41 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value) ...@@ -260,6 +260,41 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
wrfl(); wrfl();
} }
/**
* igb_update_mc_addr_list - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
*
* Updates entire Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void igb_update_mc_addr_list(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count)
{
u32 hash_value, hash_bit, hash_reg;
int i;
/* clear mta_shadow */
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
/* update mta_shadow from mc_addr_list */
for (i = 0; (u32) i < mc_addr_count; i++) {
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
hash_bit = hash_value & 0x1F;
hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
mc_addr_list += (ETH_ALEN);
}
/* replace the entire MTA table */
for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
wrfl();
}
/** /**
* igb_hash_mc_addr - Generate a multicast hash value * igb_hash_mc_addr - Generate a multicast hash value
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
......
...@@ -51,6 +51,8 @@ s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, ...@@ -51,6 +51,8 @@ s32 igb_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed,
u16 *duplex); u16 *duplex);
s32 igb_id_led_init(struct e1000_hw *hw); s32 igb_id_led_init(struct e1000_hw *hw);
s32 igb_led_off(struct e1000_hw *hw); s32 igb_led_off(struct e1000_hw *hw);
void igb_update_mc_addr_list(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count);
s32 igb_setup_link(struct e1000_hw *hw); s32 igb_setup_link(struct e1000_hw *hw);
s32 igb_validate_mdi_setting(struct e1000_hw *hw); s32 igb_validate_mdi_setting(struct e1000_hw *hw);
s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
......
...@@ -127,7 +127,7 @@ static void igb_restore_vlan(struct igb_adapter *); ...@@ -127,7 +127,7 @@ static void igb_restore_vlan(struct igb_adapter *);
static void igb_ping_all_vfs(struct igb_adapter *); static void igb_ping_all_vfs(struct igb_adapter *);
static void igb_msg_task(struct igb_adapter *); static void igb_msg_task(struct igb_adapter *);
static int igb_rcv_msg_from_vf(struct igb_adapter *, u32); static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
static void igb_set_mc_list_pools(struct igb_adapter *, int, u16); static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
static void igb_vmm_control(struct igb_adapter *); static void igb_vmm_control(struct igb_adapter *);
static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *); static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
static void igb_restore_vf_multicasts(struct igb_adapter *adapter); static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
...@@ -2535,7 +2535,6 @@ static void igb_set_multi(struct net_device *netdev) ...@@ -2535,7 +2535,6 @@ static void igb_set_multi(struct net_device *netdev)
{ {
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
struct e1000_mac_info *mac = &hw->mac;
struct dev_mc_list *mc_ptr; struct dev_mc_list *mc_ptr;
u8 *mta_list = NULL; u8 *mta_list = NULL;
u32 rctl; u32 rctl;
...@@ -2558,13 +2557,18 @@ static void igb_set_multi(struct net_device *netdev) ...@@ -2558,13 +2557,18 @@ static void igb_set_multi(struct net_device *netdev)
} }
wr32(E1000_RCTL, rctl); wr32(E1000_RCTL, rctl);
if (netdev->mc_count) { if (!netdev->mc_count) {
mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); /* nothing to program, so clear mc list */
if (!mta_list) { igb_update_mc_addr_list(hw, NULL, 0);
dev_err(&adapter->pdev->dev, igb_restore_vf_multicasts(adapter);
"failed to allocate multicast filter list\n"); return;
return; }
}
mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC);
if (!mta_list) {
dev_err(&adapter->pdev->dev,
"failed to allocate multicast filter list\n");
return;
} }
/* The shared function expects a packed array of only addresses. */ /* The shared function expects a packed array of only addresses. */
...@@ -2576,14 +2580,9 @@ static void igb_set_multi(struct net_device *netdev) ...@@ -2576,14 +2580,9 @@ static void igb_set_multi(struct net_device *netdev)
memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
mc_ptr = mc_ptr->next; mc_ptr = mc_ptr->next;
} }
igb_update_mc_addr_list(hw, mta_list, i, igb_update_mc_addr_list(hw, mta_list, i);
adapter->vfs_allocated_count + 1,
mac->rar_entry_count);
igb_set_mc_list_pools(adapter, i, mac->rar_entry_count);
igb_restore_vf_multicasts(adapter);
kfree(mta_list); kfree(mta_list);
igb_restore_vf_multicasts(adapter);
} }
/* Need to wait a few seconds after link up to get diagnostic information from /* Need to wait a few seconds after link up to get diagnostic information from
...@@ -5468,19 +5467,6 @@ static void igb_io_resume(struct pci_dev *pdev) ...@@ -5468,19 +5467,6 @@ static void igb_io_resume(struct pci_dev *pdev)
igb_get_hw_control(adapter); igb_get_hw_control(adapter);
} }
static void igb_set_mc_list_pools(struct igb_adapter *adapter,
int entry_count, u16 total_rar_filters)
{
struct e1000_hw *hw = &adapter->hw;
int i = adapter->vfs_allocated_count + 1;
if ((i + entry_count) < total_rar_filters)
total_rar_filters = i + entry_count;
for (; i < total_rar_filters; i++)
igb_set_rah_pool(hw, adapter->vfs_allocated_count, i);
}
static int igb_set_vf_mac(struct igb_adapter *adapter, static int igb_set_vf_mac(struct igb_adapter *adapter,
int vf, unsigned char *mac_addr) int vf, unsigned char *mac_addr)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment