aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel
diff options
context:
space:
mode:
authorGreg Rose <gregory.v.rose@intel.com>2013-03-26 02:19:41 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-04-24 23:30:08 -0400
commit6f3dc319ec5c101e1e927e55d593ad6637648fe5 (patch)
treee66c72c059624720165ef22f8498fb0b0fcbdcb2 /drivers/net/ethernet/intel
parentc0ba477807191d04f95057a58e08c88ad27b284c (diff)
igb: Retain HW VLAN filtering while in promiscuous + VT mode
When using the new bridge FDB interface to allow SR-IOV virtual function network devices to communicate with SW bridged network devices the physical function is placed into promiscuous mode and hardware VLAN filtering is disabled. This defeats the ability to use VLAN tagging to isolate user networks. When the device is in promiscuous mode and VT mode simultaneously ensure that VLAN hardware filtering remains enabled. Signed-off-by: Greg Rose <gregory.v.rose@intel.com> Tested-by: Sibai Li <sibai.li@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 93be6eced2e3..59a28fec83e8 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3736,6 +3736,10 @@ static void igb_set_rx_mode(struct net_device *netdev)
3736 rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE); 3736 rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE);
3737 3737
3738 if (netdev->flags & IFF_PROMISC) { 3738 if (netdev->flags & IFF_PROMISC) {
3739 u32 mrqc = rd32(E1000_MRQC);
3740 /* retain VLAN HW filtering if in VT mode */
3741 if (mrqc & E1000_MRQC_ENABLE_VMDQ)
3742 rctl |= E1000_RCTL_VFE;
3739 rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); 3743 rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
3740 vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); 3744 vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME);
3741 } else { 3745 } else {
@@ -5520,12 +5524,75 @@ out:
5520 return err; 5524 return err;
5521} 5525}
5522 5526
5527static int igb_find_vlvf_entry(struct igb_adapter *adapter, int vid)
5528{
5529 struct e1000_hw *hw = &adapter->hw;
5530 int i;
5531 u32 reg;
5532
5533 /* Find the vlan filter for this id */
5534 for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {
5535 reg = rd32(E1000_VLVF(i));
5536 if ((reg & E1000_VLVF_VLANID_ENABLE) &&
5537 vid == (reg & E1000_VLVF_VLANID_MASK))
5538 break;
5539 }
5540
5541 if (i >= E1000_VLVF_ARRAY_SIZE)
5542 i = -1;
5543
5544 return i;
5545}
5546
5523static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) 5547static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf)
5524{ 5548{
5549 struct e1000_hw *hw = &adapter->hw;
5525 int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; 5550 int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT;
5526 int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); 5551 int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK);
5552 int err = 0;
5527 5553
5528 return igb_vlvf_set(adapter, vid, add, vf); 5554 /* If in promiscuous mode we need to make sure the PF also has
5555 * the VLAN filter set.
5556 */
5557 if (add && (adapter->netdev->flags & IFF_PROMISC))
5558 err = igb_vlvf_set(adapter, vid, add,
5559 adapter->vfs_allocated_count);
5560 if (err)
5561 goto out;
5562
5563 err = igb_vlvf_set(adapter, vid, add, vf);
5564
5565 if (err)
5566 goto out;
5567
5568 /* Go through all the checks to see if the VLAN filter should
5569 * be wiped completely.
5570 */
5571 if (!add && (adapter->netdev->flags & IFF_PROMISC)) {
5572 u32 vlvf, bits;
5573
5574 int regndx = igb_find_vlvf_entry(adapter, vid);
5575 if (regndx < 0)
5576 goto out;
5577 /* See if any other pools are set for this VLAN filter
5578 * entry other than the PF.
5579 */
5580 vlvf = bits = rd32(E1000_VLVF(regndx));
5581 bits &= 1 << (E1000_VLVF_POOLSEL_SHIFT +
5582 adapter->vfs_allocated_count);
5583 /* If the filter was removed then ensure PF pool bit
5584 * is cleared if the PF only added itself to the pool
5585 * because the PF is in promiscuous mode.
5586 */
5587 if ((vlvf & VLAN_VID_MASK) == vid &&
5588 !test_bit(vid, adapter->active_vlans) &&
5589 !bits)
5590 igb_vlvf_set(adapter, vid, add,
5591 adapter->vfs_allocated_count);
5592 }
5593
5594out:
5595 return err;
5529} 5596}
5530 5597
5531static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) 5598static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf)