aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2009-03-13 16:41:37 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-14 15:41:03 -0400
commitcad6d05f5676d879bb2a48154aea26cd81ebf1bb (patch)
treed44c60b143798c799a61bee96e9cf495f1e28b34
parenta2cf8b6ce17415fc84f51300fd6be372d95bfcea (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.c21
-rw-r--r--drivers/net/igb/e1000_mac.h2
-rw-r--r--drivers/net/igb/igb_main.c9
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 **/
129void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add) 129s32 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
59void igb_clear_hw_cntrs_base(struct e1000_hw *hw); 59void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
60void igb_clear_vfta(struct e1000_hw *hw); 60void igb_clear_vfta(struct e1000_hw *hw);
61void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add); 61s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
62void igb_config_collision_dist(struct e1000_hw *hw); 62void igb_config_collision_dist(struct e1000_hw *hw);
63void igb_mta_set(struct e1000_hw *hw, u32 hash_value); 63void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
64void igb_put_hw_semaphore(struct e1000_hw *hw); 64void 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;