diff options
Diffstat (limited to 'drivers/net/igb/igb_main.c')
-rw-r--r-- | drivers/net/igb/igb_main.c | 74 |
1 files changed, 67 insertions, 7 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 62348fc60e53..58c665b7513d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -73,6 +73,8 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { | |||
73 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, | 73 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 }, |
74 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 }, | 74 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 }, |
75 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 }, | 75 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 }, |
76 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE), board_82575 }, | ||
77 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP), board_82575 }, | ||
76 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, | 78 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, |
77 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, | 79 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 }, |
78 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 }, | 80 | { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 }, |
@@ -1654,7 +1656,7 @@ void igb_reset(struct igb_adapter *adapter) | |||
1654 | if (adapter->vfs_allocated_count) { | 1656 | if (adapter->vfs_allocated_count) { |
1655 | int i; | 1657 | int i; |
1656 | for (i = 0 ; i < adapter->vfs_allocated_count; i++) | 1658 | for (i = 0 ; i < adapter->vfs_allocated_count; i++) |
1657 | adapter->vf_data[i].flags = 0; | 1659 | adapter->vf_data[i].flags &= IGB_VF_FLAG_PF_SET_MAC; |
1658 | 1660 | ||
1659 | /* ping all the active vfs to let them know we are going down */ | 1661 | /* ping all the active vfs to let them know we are going down */ |
1660 | igb_ping_all_vfs(adapter); | 1662 | igb_ping_all_vfs(adapter); |
@@ -3364,6 +3366,45 @@ static void igb_set_rx_mode(struct net_device *netdev) | |||
3364 | igb_restore_vf_multicasts(adapter); | 3366 | igb_restore_vf_multicasts(adapter); |
3365 | } | 3367 | } |
3366 | 3368 | ||
3369 | static void igb_check_wvbr(struct igb_adapter *adapter) | ||
3370 | { | ||
3371 | struct e1000_hw *hw = &adapter->hw; | ||
3372 | u32 wvbr = 0; | ||
3373 | |||
3374 | switch (hw->mac.type) { | ||
3375 | case e1000_82576: | ||
3376 | case e1000_i350: | ||
3377 | if (!(wvbr = rd32(E1000_WVBR))) | ||
3378 | return; | ||
3379 | break; | ||
3380 | default: | ||
3381 | break; | ||
3382 | } | ||
3383 | |||
3384 | adapter->wvbr |= wvbr; | ||
3385 | } | ||
3386 | |||
3387 | #define IGB_STAGGERED_QUEUE_OFFSET 8 | ||
3388 | |||
3389 | static void igb_spoof_check(struct igb_adapter *adapter) | ||
3390 | { | ||
3391 | int j; | ||
3392 | |||
3393 | if (!adapter->wvbr) | ||
3394 | return; | ||
3395 | |||
3396 | for(j = 0; j < adapter->vfs_allocated_count; j++) { | ||
3397 | if (adapter->wvbr & (1 << j) || | ||
3398 | adapter->wvbr & (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))) { | ||
3399 | dev_warn(&adapter->pdev->dev, | ||
3400 | "Spoof event(s) detected on VF %d\n", j); | ||
3401 | adapter->wvbr &= | ||
3402 | ~((1 << j) | | ||
3403 | (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))); | ||
3404 | } | ||
3405 | } | ||
3406 | } | ||
3407 | |||
3367 | /* Need to wait a few seconds after link up to get diagnostic information from | 3408 | /* Need to wait a few seconds after link up to get diagnostic information from |
3368 | * the phy */ | 3409 | * the phy */ |
3369 | static void igb_update_phy_info(unsigned long data) | 3410 | static void igb_update_phy_info(unsigned long data) |
@@ -3523,6 +3564,8 @@ static void igb_watchdog_task(struct work_struct *work) | |||
3523 | wr32(E1000_ICS, E1000_ICS_RXDMT0); | 3564 | wr32(E1000_ICS, E1000_ICS_RXDMT0); |
3524 | } | 3565 | } |
3525 | 3566 | ||
3567 | igb_spoof_check(adapter); | ||
3568 | |||
3526 | /* Reset the timer */ | 3569 | /* Reset the timer */ |
3527 | if (!test_bit(__IGB_DOWN, &adapter->state)) | 3570 | if (!test_bit(__IGB_DOWN, &adapter->state)) |
3528 | mod_timer(&adapter->watchdog_timer, | 3571 | mod_timer(&adapter->watchdog_timer, |
@@ -4519,6 +4562,10 @@ static irqreturn_t igb_msix_other(int irq, void *data) | |||
4519 | if (icr & E1000_ICR_DOUTSYNC) { | 4562 | if (icr & E1000_ICR_DOUTSYNC) { |
4520 | /* HW is reporting DMA is out of sync */ | 4563 | /* HW is reporting DMA is out of sync */ |
4521 | adapter->stats.doosync++; | 4564 | adapter->stats.doosync++; |
4565 | /* The DMA Out of Sync is also indication of a spoof event | ||
4566 | * in IOV mode. Check the Wrong VM Behavior register to | ||
4567 | * see if it is really a spoof event. */ | ||
4568 | igb_check_wvbr(adapter); | ||
4522 | } | 4569 | } |
4523 | 4570 | ||
4524 | /* Check for a mailbox event */ | 4571 | /* Check for a mailbox event */ |
@@ -4971,8 +5018,8 @@ static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) | |||
4971 | 5018 | ||
4972 | static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) | 5019 | static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) |
4973 | { | 5020 | { |
4974 | /* clear flags */ | 5021 | /* clear flags - except flag that indicates PF has set the MAC */ |
4975 | adapter->vf_data[vf].flags &= ~(IGB_VF_FLAG_PF_SET_MAC); | 5022 | adapter->vf_data[vf].flags &= IGB_VF_FLAG_PF_SET_MAC; |
4976 | adapter->vf_data[vf].last_nack = jiffies; | 5023 | adapter->vf_data[vf].last_nack = jiffies; |
4977 | 5024 | ||
4978 | /* reset offloads to defaults */ | 5025 | /* reset offloads to defaults */ |
@@ -5026,7 +5073,7 @@ static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) | |||
5026 | reg = rd32(E1000_VFRE); | 5073 | reg = rd32(E1000_VFRE); |
5027 | wr32(E1000_VFRE, reg | (1 << vf)); | 5074 | wr32(E1000_VFRE, reg | (1 << vf)); |
5028 | 5075 | ||
5029 | adapter->vf_data[vf].flags = IGB_VF_FLAG_CTS; | 5076 | adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS; |
5030 | 5077 | ||
5031 | /* reply to reset with ack and vf mac address */ | 5078 | /* reply to reset with ack and vf mac address */ |
5032 | msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; | 5079 | msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; |
@@ -5105,7 +5152,14 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) | |||
5105 | 5152 | ||
5106 | switch ((msgbuf[0] & 0xFFFF)) { | 5153 | switch ((msgbuf[0] & 0xFFFF)) { |
5107 | case E1000_VF_SET_MAC_ADDR: | 5154 | case E1000_VF_SET_MAC_ADDR: |
5108 | retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); | 5155 | retval = -EINVAL; |
5156 | if (!(vf_data->flags & IGB_VF_FLAG_PF_SET_MAC)) | ||
5157 | retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); | ||
5158 | else | ||
5159 | dev_warn(&pdev->dev, | ||
5160 | "VF %d attempted to override administratively " | ||
5161 | "set MAC address\nReload the VF driver to " | ||
5162 | "resume operations\n", vf); | ||
5109 | break; | 5163 | break; |
5110 | case E1000_VF_SET_PROMISC: | 5164 | case E1000_VF_SET_PROMISC: |
5111 | retval = igb_set_vf_promisc(adapter, msgbuf, vf); | 5165 | retval = igb_set_vf_promisc(adapter, msgbuf, vf); |
@@ -5117,8 +5171,12 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) | |||
5117 | retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); | 5171 | retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); |
5118 | break; | 5172 | break; |
5119 | case E1000_VF_SET_VLAN: | 5173 | case E1000_VF_SET_VLAN: |
5120 | if (adapter->vf_data[vf].pf_vlan) | 5174 | retval = -1; |
5121 | retval = -1; | 5175 | if (vf_data->pf_vlan) |
5176 | dev_warn(&pdev->dev, | ||
5177 | "VF %d attempted to override administratively " | ||
5178 | "set VLAN tag\nReload the VF driver to " | ||
5179 | "resume operations\n", vf); | ||
5122 | else | 5180 | else |
5123 | retval = igb_set_vf_vlan(adapter, msgbuf, vf); | 5181 | retval = igb_set_vf_vlan(adapter, msgbuf, vf); |
5124 | break; | 5182 | break; |
@@ -6582,6 +6640,8 @@ static void igb_vmm_control(struct igb_adapter *adapter) | |||
6582 | if (adapter->vfs_allocated_count) { | 6640 | if (adapter->vfs_allocated_count) { |
6583 | igb_vmdq_set_loopback_pf(hw, true); | 6641 | igb_vmdq_set_loopback_pf(hw, true); |
6584 | igb_vmdq_set_replication_pf(hw, true); | 6642 | igb_vmdq_set_replication_pf(hw, true); |
6643 | igb_vmdq_set_anti_spoofing_pf(hw, true, | ||
6644 | adapter->vfs_allocated_count); | ||
6585 | } else { | 6645 | } else { |
6586 | igb_vmdq_set_loopback_pf(hw, false); | 6646 | igb_vmdq_set_loopback_pf(hw, false); |
6587 | igb_vmdq_set_replication_pf(hw, false); | 6647 | igb_vmdq_set_replication_pf(hw, false); |