igc: Refactor igc_mac_entry_can_be_used()

The helper igc_mac_entry_can_be_used() implementation is a bit
convoluted since it does two different things: find a not-in-use slot
in mac_table or find an in-use slot where the address and address type
match. This patch does a code refactoring and break it up into two
helper functions.

With this patch we might traverse mac_table twice in some situations,
but this is not harmful performance-wise (mac_table has only 16 entries
and adding mac filters is not hot-path), and it improves igc_add_mac_
filter() readability considerably.

Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Andre Guedes 2020-03-18 16:01:00 -07:00 committed by Jeff Kirsher
parent 83ba21b9ef
commit 794e5bc817
1 changed files with 47 additions and 33 deletions

View File

@ -2176,25 +2176,44 @@ static void igc_nfc_filter_restore(struct igc_adapter *adapter)
spin_unlock(&adapter->nfc_lock);
}
/* If the filter to be added and an already existing filter express
* the same address and address type, it should be possible to only
* override the other configurations, for example the queue to steer
* traffic.
*/
static bool igc_mac_entry_can_be_used(const struct igc_mac_addr *entry,
const u8 *addr, const u8 flags)
static int igc_find_mac_filter(struct igc_adapter *adapter, const u8 *addr,
u8 flags)
{
if (!(entry->state & IGC_MAC_STATE_IN_USE))
return true;
int max_entries = adapter->hw.mac.rar_entry_count;
struct igc_mac_addr *entry;
int i;
if ((entry->state & IGC_MAC_STATE_SRC_ADDR) !=
(flags & IGC_MAC_STATE_SRC_ADDR))
return false;
for (i = 0; i < max_entries; i++) {
entry = &adapter->mac_table[i];
if (!ether_addr_equal(addr, entry->addr))
return false;
if (!(entry->state & IGC_MAC_STATE_IN_USE))
continue;
if (!ether_addr_equal(addr, entry->addr))
continue;
if ((entry->state & IGC_MAC_STATE_SRC_ADDR) !=
(flags & IGC_MAC_STATE_SRC_ADDR))
continue;
return true;
return i;
}
return -1;
}
static int igc_get_avail_mac_filter_slot(struct igc_adapter *adapter)
{
int max_entries = adapter->hw.mac.rar_entry_count;
struct igc_mac_addr *entry;
int i;
for (i = 0; i < max_entries; i++) {
entry = &adapter->mac_table[i];
if (!(entry->state & IGC_MAC_STATE_IN_USE))
return i;
}
return -1;
}
/**
@ -2212,33 +2231,28 @@ static bool igc_mac_entry_can_be_used(const struct igc_mac_addr *entry,
int igc_add_mac_filter(struct igc_adapter *adapter, const u8 *addr,
const s8 queue, const u8 flags)
{
struct igc_hw *hw = &adapter->hw;
int rar_entries = hw->mac.rar_entry_count;
int i;
int index;
if (!is_valid_ether_addr(addr))
return -EINVAL;
if (flags & IGC_MAC_STATE_SRC_ADDR)
return -ENOTSUPP;
/* Search for the first empty entry in the MAC table.
* Do not touch entries at the end of the table reserved for the VF MAC
* addresses.
*/
for (i = 0; i < rar_entries; i++) {
if (!igc_mac_entry_can_be_used(&adapter->mac_table[i],
addr, flags))
continue;
index = igc_find_mac_filter(adapter, addr, flags);
if (index >= 0)
goto update_queue_assignment;
ether_addr_copy(adapter->mac_table[i].addr, addr);
adapter->mac_table[i].queue = queue;
adapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE | flags;
index = igc_get_avail_mac_filter_slot(adapter);
if (index < 0)
return -ENOSPC;
igc_set_mac_filter_hw(adapter, i, addr, queue);
return 0;
}
ether_addr_copy(adapter->mac_table[index].addr, addr);
adapter->mac_table[index].state |= IGC_MAC_STATE_IN_USE | flags;
update_queue_assignment:
adapter->mac_table[index].queue = queue;
return -ENOSPC;
igc_set_mac_filter_hw(adapter, index, addr, queue);
return 0;
}
/**