Commit 13acb546 authored by Mitch Williams's avatar Mitch Williams Committed by Jeff Kirsher

i40evf: protect VLAN filter list

The MAC filter list is protected by a critical task bit, and the VLAN
list should be protected as well. This prevents list corruption if the
watchdog happens to run at the same time as a VLAN filter is being added
or deleted.

Change-ID: Ia4867cebbbb046a1f38012771b288a634ca5882b
Signed-off-by: default avatarMitch Williams <mitch.a.williams@intel.com>
Tested-by: default avatarJim Young <james.m.young@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent fdf0e0bf
...@@ -664,13 +664,21 @@ i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan) ...@@ -664,13 +664,21 @@ i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan)
static struct static struct
i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
{ {
struct i40evf_vlan_filter *f; struct i40evf_vlan_filter *f = NULL;
int count = 50;
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section)) {
udelay(1);
if (--count == 0)
goto out;
}
f = i40evf_find_vlan(adapter, vlan); f = i40evf_find_vlan(adapter, vlan);
if (!f) { if (!f) {
f = kzalloc(sizeof(*f), GFP_ATOMIC); f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f) if (!f)
return NULL; goto clearout;
f->vlan = vlan; f->vlan = vlan;
...@@ -680,6 +688,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) ...@@ -680,6 +688,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER; adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
} }
clearout:
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
out:
return f; return f;
} }
...@@ -691,12 +702,21 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) ...@@ -691,12 +702,21 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan)
static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan)
{ {
struct i40evf_vlan_filter *f; struct i40evf_vlan_filter *f;
int count = 50;
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section)) {
udelay(1);
if (--count == 0)
return;
}
f = i40evf_find_vlan(adapter, vlan); f = i40evf_find_vlan(adapter, vlan);
if (f) { if (f) {
f->remove = true; f->remove = true;
adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
} }
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
} }
/** /**
......
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