igb: add PF to pool
authorAlexander Duyck <alexander.h.duyck@intel.com>
Fri, 13 Mar 2009 20:41:37 +0000 (20:41 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 14 Mar 2009 19:41:03 +0000 (12:41 -0700)
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>
drivers/net/igb/e1000_mac.c
drivers/net/igb/e1000_mac.h
drivers/net/igb/igb_main.c

index 2804db03e9d934eba256d964cd0fde3bb4dbf11e..f11592fe1371306d859634cf50ff063722bd203d 100644 (file)
@@ -126,19 +126,26 @@ void igb_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
  *  Sets or clears a bit in the VLAN filter table array based on VLAN id
  *  and if we are adding or removing the filter
  **/
-void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add)
+s32 igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add)
 {
        u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
        u32 mask = 1 < (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
-       u32 vfta;
+       u32 vfta = array_rd32(E1000_VFTA, index);
+       s32 ret_val = 0;
 
-       vfta = array_rd32(E1000_VFTA, index);
-       if (add)
-               vfta |= mask;
-       else
-               vfta &= ~mask;
+       /* bit was set/cleared before we started */
+       if ((!!(vfta & mask)) == add) {
+               ret_val = -E1000_ERR_CONFIG;
+       } else {
+               if (add)
+                       vfta |= mask;
+               else
+                       vfta &= ~mask;
+       }
 
        igb_write_vfta(hw, index, vfta);
+
+       return ret_val;
 }
 
 /**
index eccc3536a5687550dc51febe0568533b62fbe5cc..a34de52696377c292ea31a4b357ea3dd71de143b 100644 (file)
@@ -58,7 +58,7 @@ s32  igb_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg,
 
 void igb_clear_hw_cntrs_base(struct e1000_hw *hw);
 void igb_clear_vfta(struct e1000_hw *hw);
-void igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
+s32  igb_vfta_set(struct e1000_hw *hw, u32 vid, bool add);
 void igb_config_collision_dist(struct e1000_hw *hw);
 void igb_mta_set(struct e1000_hw *hw, u32 hash_value);
 void igb_put_hw_semaphore(struct e1000_hw *hw);
index f0c3a01452c81c080ae78bd3861f8ea2c3898937..a3c2f83fb495307558d566c3c71be7c8b14e1398 100644 (file)
@@ -3895,10 +3895,15 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
 
                        /* if !enabled we need to set this up in vfta */
                        if (!(reg & E1000_VLVF_VLANID_ENABLE)) {
-                               /* add VID to filter table */
-                               igb_vfta_set(hw, vid, true);
+                               /* add VID to filter table, if bit already set
+                                * PF must have added it outside of table */
+                               if (igb_vfta_set(hw, vid, true))
+                                       reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT +
+                                               adapter->vfs_allocated_count);
                                reg |= E1000_VLVF_VLANID_ENABLE;
                        }
+                       reg &= ~E1000_VLVF_VLANID_MASK;
+                       reg |= vid;
 
                        wr32(E1000_VLVF(i), reg);
                        return 0;