Commit 794e5bc8 authored by Andre Guedes's avatar Andre Guedes Committed by Jeff Kirsher
Browse files

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: default avatarAndre Guedes <andre.guedes@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 83ba21b9
Loading
Loading
Loading
Loading
+47 −33
Original line number Diff line number Diff line
@@ -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;

	for (i = 0; i < max_entries; i++) {
		entry = &adapter->mac_table[i];

		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))
		return false;
			continue;

	if (!ether_addr_equal(addr, entry->addr))
		return false;
		return i;
	}

	return true;
	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;
}

/**