diff options
| author | Mitch Williams <mitch.a.williams@intel.com> | 2015-03-31 03:45:05 -0400 |
|---|---|---|
| committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2015-04-03 06:54:31 -0400 |
| commit | 13acb54683f834cb16baf7ad7fd6e15a97b0762f (patch) | |
| tree | 4db1f132bff889917b421a5a99004b427567c35e /drivers/net/ethernet/intel/i40evf | |
| parent | fdf0e0bfc363a9b5380ecb5e9c46d6f5a39a9b75 (diff) | |
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: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/i40evf')
| -rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf_main.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index b08efafee1ae..46aef2a45cbf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c | |||
| @@ -664,13 +664,21 @@ i40evf_vlan_filter *i40evf_find_vlan(struct i40evf_adapter *adapter, u16 vlan) | |||
| 664 | static struct | 664 | static struct |
| 665 | i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) | 665 | i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) |
| 666 | { | 666 | { |
| 667 | struct i40evf_vlan_filter *f; | 667 | struct i40evf_vlan_filter *f = NULL; |
| 668 | int count = 50; | ||
| 669 | |||
| 670 | while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, | ||
| 671 | &adapter->crit_section)) { | ||
| 672 | udelay(1); | ||
| 673 | if (--count == 0) | ||
| 674 | goto out; | ||
| 675 | } | ||
| 668 | 676 | ||
| 669 | f = i40evf_find_vlan(adapter, vlan); | 677 | f = i40evf_find_vlan(adapter, vlan); |
| 670 | if (!f) { | 678 | if (!f) { |
| 671 | f = kzalloc(sizeof(*f), GFP_ATOMIC); | 679 | f = kzalloc(sizeof(*f), GFP_ATOMIC); |
| 672 | if (!f) | 680 | if (!f) |
| 673 | return NULL; | 681 | goto clearout; |
| 674 | 682 | ||
| 675 | f->vlan = vlan; | 683 | f->vlan = vlan; |
| 676 | 684 | ||
| @@ -680,6 +688,9 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) | |||
| 680 | adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER; | 688 | adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER; |
| 681 | } | 689 | } |
| 682 | 690 | ||
| 691 | clearout: | ||
| 692 | clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); | ||
| 693 | out: | ||
| 683 | return f; | 694 | return f; |
| 684 | } | 695 | } |
| 685 | 696 | ||
| @@ -691,12 +702,21 @@ i40evf_vlan_filter *i40evf_add_vlan(struct i40evf_adapter *adapter, u16 vlan) | |||
| 691 | static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) | 702 | static void i40evf_del_vlan(struct i40evf_adapter *adapter, u16 vlan) |
| 692 | { | 703 | { |
| 693 | struct i40evf_vlan_filter *f; | 704 | struct i40evf_vlan_filter *f; |
| 705 | int count = 50; | ||
| 706 | |||
| 707 | while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, | ||
| 708 | &adapter->crit_section)) { | ||
| 709 | udelay(1); | ||
| 710 | if (--count == 0) | ||
| 711 | return; | ||
| 712 | } | ||
| 694 | 713 | ||
| 695 | f = i40evf_find_vlan(adapter, vlan); | 714 | f = i40evf_find_vlan(adapter, vlan); |
| 696 | if (f) { | 715 | if (f) { |
| 697 | f->remove = true; | 716 | f->remove = true; |
| 698 | adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; | 717 | adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER; |
| 699 | } | 718 | } |
| 719 | clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); | ||
| 700 | } | 720 | } |
| 701 | 721 | ||
| 702 | /** | 722 | /** |
