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 | |
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>
-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 | /** |