Skip to content

Commit c9f53e6

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
ixgbe: Refactor MAC address configuration code
In the process of tracking down a memory leak when adding/removing FDB entries I had to go through the MAC address configuration code for ixgbe. In the process of doing so I found a number of issues that impacted readability and performance. This change updates the code in general to clean it up so it becomes clear what each step is doing. From what I can tell there a couple of bugs cleaned up in this code. First is the fact that the MAC addresses were being double counted for the PF. As a result once entries up to 63 had been used you could no longer add additional filters. A simple test case for this: for i in `seq 0 96` do ip link add link ens8 name mv$i type macvlan ip link set dev mv$i up done Test script: ethregs -s 0:8.0 | grep -e "RAH" | grep 8000....$ When things are working correctly RAL/H registers 1 - 97 will be consumed. In the failing case it will stop at 63 and prevent any further filters from being added. Signed-off-by: Alexander Duyck <[email protected]> Tested-by: Darin Miller <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 50985b5 commit c9f53e6

File tree

2 files changed

+100
-70
lines changed

2 files changed

+100
-70
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,9 +587,10 @@ static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring)
587587

588588
struct ixgbe_mac_addr {
589589
u8 addr[ETH_ALEN];
590-
u16 queue;
590+
u16 pool;
591591
u16 state; /* bitmask */
592592
};
593+
593594
#define IXGBE_MAC_STATE_DEFAULT 0x1
594595
#define IXGBE_MAC_STATE_MODIFIED 0x2
595596
#define IXGBE_MAC_STATE_IN_USE 0x4
@@ -883,9 +884,9 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
883884
void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter);
884885
#endif
885886
int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter,
886-
u8 *addr, u16 queue);
887+
const u8 *addr, u16 queue);
887888
int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter,
888-
u8 *addr, u16 queue);
889+
const u8 *addr, u16 queue);
889890
void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
890891
netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *, struct ixgbe_adapter *,
891892
struct ixgbe_ring *);

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 96 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4031,124 +4031,156 @@ static int ixgbe_write_mc_addr_list(struct net_device *netdev)
40314031
#ifdef CONFIG_PCI_IOV
40324032
void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter)
40334033
{
4034+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
40344035
struct ixgbe_hw *hw = &adapter->hw;
40354036
int i;
4036-
for (i = 0; i < hw->mac.num_rar_entries; i++) {
4037-
if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE)
4038-
hw->mac.ops.set_rar(hw, i, adapter->mac_table[i].addr,
4039-
adapter->mac_table[i].queue,
4037+
4038+
for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) {
4039+
mac_table->state &= ~IXGBE_MAC_STATE_MODIFIED;
4040+
4041+
if (mac_table->state & IXGBE_MAC_STATE_IN_USE)
4042+
hw->mac.ops.set_rar(hw, i,
4043+
mac_table->addr,
4044+
mac_table->pool,
40404045
IXGBE_RAH_AV);
40414046
else
40424047
hw->mac.ops.clear_rar(hw, i);
4043-
4044-
adapter->mac_table[i].state &= ~(IXGBE_MAC_STATE_MODIFIED);
40454048
}
40464049
}
4047-
#endif
40484050

4051+
#endif
40494052
static void ixgbe_sync_mac_table(struct ixgbe_adapter *adapter)
40504053
{
4054+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
40514055
struct ixgbe_hw *hw = &adapter->hw;
40524056
int i;
4053-
for (i = 0; i < hw->mac.num_rar_entries; i++) {
4054-
if (adapter->mac_table[i].state & IXGBE_MAC_STATE_MODIFIED) {
4055-
if (adapter->mac_table[i].state &
4056-
IXGBE_MAC_STATE_IN_USE)
4057-
hw->mac.ops.set_rar(hw, i,
4058-
adapter->mac_table[i].addr,
4059-
adapter->mac_table[i].queue,
4060-
IXGBE_RAH_AV);
4061-
else
4062-
hw->mac.ops.clear_rar(hw, i);
40634057

4064-
adapter->mac_table[i].state &=
4065-
~(IXGBE_MAC_STATE_MODIFIED);
4066-
}
4058+
for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) {
4059+
if (!(mac_table->state & IXGBE_MAC_STATE_MODIFIED))
4060+
continue;
4061+
4062+
mac_table->state &= ~IXGBE_MAC_STATE_MODIFIED;
4063+
4064+
if (mac_table->state & IXGBE_MAC_STATE_IN_USE)
4065+
hw->mac.ops.set_rar(hw, i,
4066+
mac_table->addr,
4067+
mac_table->pool,
4068+
IXGBE_RAH_AV);
4069+
else
4070+
hw->mac.ops.clear_rar(hw, i);
40674071
}
40684072
}
40694073

40704074
static void ixgbe_flush_sw_mac_table(struct ixgbe_adapter *adapter)
40714075
{
4072-
int i;
4076+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
40734077
struct ixgbe_hw *hw = &adapter->hw;
4078+
int i;
40744079

4075-
for (i = 0; i < hw->mac.num_rar_entries; i++) {
4076-
adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED;
4077-
adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE;
4078-
eth_zero_addr(adapter->mac_table[i].addr);
4079-
adapter->mac_table[i].queue = 0;
4080+
for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) {
4081+
mac_table->state |= IXGBE_MAC_STATE_MODIFIED;
4082+
mac_table->state &= ~IXGBE_MAC_STATE_IN_USE;
40804083
}
4084+
40814085
ixgbe_sync_mac_table(adapter);
40824086
}
40834087

4084-
static int ixgbe_available_rars(struct ixgbe_adapter *adapter)
4088+
static int ixgbe_available_rars(struct ixgbe_adapter *adapter, u16 pool)
40854089
{
4090+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
40864091
struct ixgbe_hw *hw = &adapter->hw;
40874092
int i, count = 0;
40884093

4089-
for (i = 0; i < hw->mac.num_rar_entries; i++) {
4090-
if (adapter->mac_table[i].state == 0)
4091-
count++;
4094+
for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) {
4095+
/* do not count default RAR as available */
4096+
if (mac_table->state & IXGBE_MAC_STATE_DEFAULT)
4097+
continue;
4098+
4099+
/* only count unused and addresses that belong to us */
4100+
if (mac_table->state & IXGBE_MAC_STATE_IN_USE) {
4101+
if (mac_table->pool != pool)
4102+
continue;
4103+
}
4104+
4105+
count++;
40924106
}
4107+
40934108
return count;
40944109
}
40954110

40964111
/* this function destroys the first RAR entry */
4097-
static void ixgbe_mac_set_default_filter(struct ixgbe_adapter *adapter,
4098-
u8 *addr)
4112+
static void ixgbe_mac_set_default_filter(struct ixgbe_adapter *adapter)
40994113
{
4114+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
41004115
struct ixgbe_hw *hw = &adapter->hw;
41014116

4102-
memcpy(&adapter->mac_table[0].addr, addr, ETH_ALEN);
4103-
adapter->mac_table[0].queue = VMDQ_P(0);
4104-
adapter->mac_table[0].state = (IXGBE_MAC_STATE_DEFAULT |
4105-
IXGBE_MAC_STATE_IN_USE);
4106-
hw->mac.ops.set_rar(hw, 0, adapter->mac_table[0].addr,
4107-
adapter->mac_table[0].queue,
4117+
memcpy(&mac_table->addr, hw->mac.addr, ETH_ALEN);
4118+
mac_table->pool = VMDQ_P(0);
4119+
4120+
mac_table->state = IXGBE_MAC_STATE_DEFAULT | IXGBE_MAC_STATE_IN_USE;
4121+
4122+
hw->mac.ops.set_rar(hw, 0, mac_table->addr, mac_table->pool,
41084123
IXGBE_RAH_AV);
41094124
}
41104125

4111-
int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue)
4126+
int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter,
4127+
const u8 *addr, u16 pool)
41124128
{
4129+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
41134130
struct ixgbe_hw *hw = &adapter->hw;
41144131
int i;
41154132

41164133
if (is_zero_ether_addr(addr))
41174134
return -EINVAL;
41184135

4119-
for (i = 0; i < hw->mac.num_rar_entries; i++) {
4120-
if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE)
4136+
for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) {
4137+
if (mac_table->state & IXGBE_MAC_STATE_IN_USE)
41214138
continue;
4122-
adapter->mac_table[i].state |= (IXGBE_MAC_STATE_MODIFIED |
4123-
IXGBE_MAC_STATE_IN_USE);
4124-
ether_addr_copy(adapter->mac_table[i].addr, addr);
4125-
adapter->mac_table[i].queue = queue;
4139+
4140+
ether_addr_copy(mac_table->addr, addr);
4141+
mac_table->pool = pool;
4142+
4143+
mac_table->state |= IXGBE_MAC_STATE_MODIFIED |
4144+
IXGBE_MAC_STATE_IN_USE;
4145+
41264146
ixgbe_sync_mac_table(adapter);
4147+
41274148
return i;
41284149
}
4150+
41294151
return -ENOMEM;
41304152
}
41314153

4132-
int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue)
4154+
int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter,
4155+
const u8 *addr, u16 pool)
41334156
{
4134-
/* search table for addr, if found, set to 0 and sync */
4135-
int i;
4157+
struct ixgbe_mac_addr *mac_table = &adapter->mac_table[0];
41364158
struct ixgbe_hw *hw = &adapter->hw;
4159+
int i;
41374160

41384161
if (is_zero_ether_addr(addr))
41394162
return -EINVAL;
41404163

4141-
for (i = 0; i < hw->mac.num_rar_entries; i++) {
4142-
if (ether_addr_equal(addr, adapter->mac_table[i].addr) &&
4143-
adapter->mac_table[i].queue == queue) {
4144-
adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED;
4145-
adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE;
4146-
eth_zero_addr(adapter->mac_table[i].addr);
4147-
adapter->mac_table[i].queue = 0;
4148-
ixgbe_sync_mac_table(adapter);
4149-
return 0;
4150-
}
4164+
/* search table for addr, if found clear IN_USE flag and sync */
4165+
for (i = 0; i < hw->mac.num_rar_entries; i++, mac_table++) {
4166+
/* we can only delete an entry if it is in use */
4167+
if (!(mac_table->state & IXGBE_MAC_STATE_IN_USE))
4168+
continue;
4169+
/* we only care about entries that belong to the given pool */
4170+
if (mac_table->pool != pool)
4171+
continue;
4172+
/* we only care about a specific MAC address */
4173+
if (!ether_addr_equal(addr, mac_table->addr))
4174+
continue;
4175+
4176+
mac_table->state |= IXGBE_MAC_STATE_MODIFIED;
4177+
mac_table->state &= ~IXGBE_MAC_STATE_IN_USE;
4178+
4179+
ixgbe_sync_mac_table(adapter);
4180+
4181+
return 0;
41514182
}
4183+
41524184
return -ENOMEM;
41534185
}
41544186
/**
@@ -4166,7 +4198,7 @@ static int ixgbe_write_uc_addr_list(struct net_device *netdev, int vfn)
41664198
int count = 0;
41674199

41684200
/* return ENOMEM indicating insufficient memory for addresses */
4169-
if (netdev_uc_count(netdev) > ixgbe_available_rars(adapter))
4201+
if (netdev_uc_count(netdev) > ixgbe_available_rars(adapter, vfn))
41704202
return -ENOMEM;
41714203

41724204
if (!netdev_uc_empty(netdev)) {
@@ -5039,7 +5071,6 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
50395071
struct ixgbe_hw *hw = &adapter->hw;
50405072
struct net_device *netdev = adapter->netdev;
50415073
int err;
5042-
u8 old_addr[ETH_ALEN];
50435074

50445075
if (ixgbe_removed(hw->hw_addr))
50455076
return;
@@ -5076,9 +5107,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
50765107

50775108
clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
50785109
/* do not flush user set addresses */
5079-
memcpy(old_addr, &adapter->mac_table[0].addr, netdev->addr_len);
50805110
ixgbe_flush_sw_mac_table(adapter);
5081-
ixgbe_mac_set_default_filter(adapter, old_addr);
5111+
ixgbe_mac_set_default_filter(adapter);
50825112

50835113
/* update SAN MAC vmdq pool selection */
50845114
if (hw->mac.san_mac_rar_index)
@@ -7656,17 +7686,16 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p)
76567686
struct ixgbe_adapter *adapter = netdev_priv(netdev);
76577687
struct ixgbe_hw *hw = &adapter->hw;
76587688
struct sockaddr *addr = p;
7659-
int ret;
76607689

76617690
if (!is_valid_ether_addr(addr->sa_data))
76627691
return -EADDRNOTAVAIL;
76637692

7664-
ixgbe_del_mac_filter(adapter, hw->mac.addr, VMDQ_P(0));
76657693
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
76667694
memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
76677695

7668-
ret = ixgbe_add_mac_filter(adapter, hw->mac.addr, VMDQ_P(0));
7669-
return ret > 0 ? 0 : ret;
7696+
ixgbe_mac_set_default_filter(adapter);
7697+
7698+
return 0;
76707699
}
76717700

76727701
static int
@@ -8867,7 +8896,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
88678896
goto err_sw_init;
88688897
}
88698898

8870-
ixgbe_mac_set_default_filter(adapter, hw->mac.perm_addr);
8899+
ixgbe_mac_set_default_filter(adapter);
88718900

88728901
setup_timer(&adapter->service_timer, &ixgbe_service_timer,
88738902
(unsigned long) adapter);

0 commit comments

Comments
 (0)