diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-03-13 16:41:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-14 15:41:03 -0400 |
commit | cad6d05f5676d879bb2a48154aea26cd81ebf1bb (patch) | |
tree | d44c60b143798c799a61bee96e9cf495f1e28b34 | |
parent | a2cf8b6ce17415fc84f51300fd6be372d95bfcea (diff) |
igb: add PF to pool
Add Pf to pool if adding a VLVF register value and the VFTA bit is
already set.
This patch addresses the unlikely situation that the PF adds a vlan
entry when the vlvf is full, and a vf later adds the vlan to the vlvf.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/igb/e1000_mac.c | 21 | ||||
-rw-r--r-- | drivers/net/igb/e1000_mac.h | 2 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 9 |
3 files changed, 22 insertions, 10 deletions
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 2804db03e9d9..f11592fe1371 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c | |||
@@ -126,19 +126,26 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) | |||
126 | * Sets or clears a bit in the VLAN filter table array based on VLAN id | 126 | * Sets or clears a bit in the VLAN filter table array based on VLAN id |
127 | * and if we are adding or removing the filter | 127 | * and if we are adding or removing the filter |
128 | **/ | 128 | **/ |
129 | void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) | 129 | s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) |
130 | { | 130 | { |
131 | u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; | 131 | u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; |
132 | u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); | 132 | u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); |
133 | u32 vfta; | 133 | u32 vfta = array_rd32(E1000_VFTA, index); |
134 | s32 ret_val = 0; | ||
134 | 135 | ||
135 | vfta = array_rd32(E1000_VFTA, index); | 136 | /* bit was set/cleared before we started */ |
136 | if (add) | 137 | if ((!!(vfta & mask)) == add) { |
137 | vfta |= mask; | 138 | ret_val = -E1000_ERR_CONFIG; |
138 | else | 139 | } else { |
139 | vfta &= ~mask; | 140 | if (add) |
141 | vfta |= mask; | ||
142 | else | ||
143 | vfta &= ~mask; | ||
144 | } | ||
140 | 145 | ||
141 | igb_write_vfta(hw, index, vfta); | 146 | igb_write_vfta(hw, index, vfta); |
147 | |||
148 | return ret_val; | ||
142 | } | 149 | } |
143 | 150 | ||
144 | /** | 151 | /** |
diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index eccc3536a568..a34de5269637 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h | |||
@@ -58,7 +58,7 @@ s32 igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, | |||
58 | 58 | ||
59 | void igb_clear_hw_cntrs_base(struct e1000_hw *hw); | 59 | void igb_clear_hw_cntrs_base(struct e1000_hw *hw); |
60 | void igb_clear_vfta(struct e1000_hw *hw); | 60 | void igb_clear_vfta(struct e1000_hw *hw); |
61 | void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); | 61 | s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); |
62 | void igb_config_collision_dist(struct e1000_hw *hw); | 62 | void igb_config_collision_dist(struct e1000_hw *hw); |
63 | void igb_mta_set(struct e1000_hw *hw, u32 hash_value); | 63 | void igb_mta_set(struct e1000_hw *hw, u32 hash_value); |
64 | void igb_put_hw_semaphore(struct e1000_hw *hw); | 64 | void igb_put_hw_semaphore(struct e1000_hw *hw); |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f0c3a01452c8..a3c2f83fb495 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -3895,10 +3895,15 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) | |||
3895 | 3895 | ||
3896 | /* if !enabled we need to set this up in vfta */ | 3896 | /* if !enabled we need to set this up in vfta */ |
3897 | if (!(reg & E1000_VLVF_VLANID_ENABLE)) { | 3897 | if (!(reg & E1000_VLVF_VLANID_ENABLE)) { |
3898 | /* add VID to filter table */ | 3898 | /* add VID to filter table, if bit already set |
3899 | igb_vfta_set(hw, vid, true); | 3899 | * PF must have added it outside of table */ |
3900 | if (igb_vfta_set(hw, vid, true)) | ||
3901 | reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT + | ||
3902 | adapter->vfs_allocated_count); | ||
3900 | reg |= E1000_VLVF_VLANID_ENABLE; | 3903 | reg |= E1000_VLVF_VLANID_ENABLE; |
3901 | } | 3904 | } |
3905 | reg &= ~E1000_VLVF_VLANID_MASK; | ||
3906 | reg |= vid; | ||
3902 | 3907 | ||
3903 | wr32(E1000_VLVF(i), reg); | 3908 | wr32(E1000_VLVF(i), reg); |
3904 | return 0; | 3909 | return 0; |