igb: set vf rlpml wasn't taking vlan tag into account
authorAlexander Duyck <alexander.h.duyck@intel.com>
Thu, 3 Sep 2009 14:49:33 +0000 (14:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 4 Sep 2009 03:01:50 +0000 (20:01 -0700)
This patch updates things so that vlan tags are taken into account when
setting the receive large packet maximum length.  This allows the VF driver
to correctly receive full sized frames when vlans are enabled.

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/igb.h
drivers/net/igb/igb_main.c

index b2c98dea9eed4c01bd0bbfbdf750d1231b53c66e..7126fea26fec5a0dc873daa9cf5029b5f04b7931 100644 (file)
@@ -70,6 +70,7 @@ struct vf_data_storage {
        unsigned char vf_mac_addresses[ETH_ALEN];
        u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
        u16 num_vf_mc_hashes;
+       u16 vlans_enabled;
        bool clear_to_send;
 };
 
index 1d03fcb0bd6c000ad5001021cc7cad2f8437d5ca..90b0b1b91730bfec62af4e589c5ff4ff8fceef37 100644 (file)
@@ -154,6 +154,12 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
        struct e1000_hw *hw = &adapter->hw;
        u32 vmolr;
 
+       /* if it isn't the PF check to see if VFs are enabled and
+        * increase the size to support vlan tags */
+       if (vfn < adapter->vfs_allocated_count &&
+           adapter->vf_data[vfn].vlans_enabled)
+               size += VLAN_TAG_SIZE;
+
        vmolr = rd32(E1000_VMOLR(vfn));
        vmolr &= ~E1000_VMOLR_RLPML_MASK;
        vmolr |= size | E1000_VMOLR_LPE;
@@ -4006,6 +4012,8 @@ static void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf)
 
                wr32(E1000_VLVF(i), reg);
        }
+
+       adapter->vf_data[vf].vlans_enabled = 0;
 }
 
 static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
@@ -4054,6 +4062,22 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
                        reg |= vid;
 
                        wr32(E1000_VLVF(i), reg);
+
+                       /* do not modify RLPML for PF devices */
+                       if (vf >= adapter->vfs_allocated_count)
+                               return 0;
+
+                       if (!adapter->vf_data[vf].vlans_enabled) {
+                               u32 size;
+                               reg = rd32(E1000_VMOLR(vf));
+                               size = reg & E1000_VMOLR_RLPML_MASK;
+                               size += 4;
+                               reg &= ~E1000_VMOLR_RLPML_MASK;
+                               reg |= size;
+                               wr32(E1000_VMOLR(vf), reg);
+                       }
+                       adapter->vf_data[vf].vlans_enabled++;
+
                        return 0;
                }
        } else {
@@ -4066,6 +4090,21 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf)
                                igb_vfta_set(hw, vid, false);
                        }
                        wr32(E1000_VLVF(i), reg);
+
+                       /* do not modify RLPML for PF devices */
+                       if (vf >= adapter->vfs_allocated_count)
+                               return 0;
+
+                       adapter->vf_data[vf].vlans_enabled--;
+                       if (!adapter->vf_data[vf].vlans_enabled) {
+                               u32 size;
+                               reg = rd32(E1000_VMOLR(vf));
+                               size = reg & E1000_VMOLR_RLPML_MASK;
+                               size -= 4;
+                               reg &= ~E1000_VMOLR_RLPML_MASK;
+                               reg |= size;
+                               wr32(E1000_VMOLR(vf), reg);
+                       }
                        return 0;
                }
        }