diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/igb/igb.h | 1 | ||||
-rw-r--r-- | drivers/net/igb/igb_main.c | 39 |
2 files changed, 40 insertions, 0 deletions
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index b2c98dea9eed..7126fea26fec 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -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; }; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 1d03fcb0bd6c..90b0b1b91730 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -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; } } |