Commit d5e7f827 authored by David S. Miller's avatar David S. Miller

Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
1GbE Intel Wired LAN Driver Updates 2017-08-08

This series contains updates to e1000e and igb/igbvf.

Gangfeng Huang fixes an issue with receive network flow classification,
where igb_nfc_filter_exit() was not being called in igb_down() which
would cause the filter tables to "fill up" if a user where to change
the adapter settings (such as speed) which requires a reset of the
adapter.

Cliff Spradlin fixes a timestamping issue, where igb was allowing requests
for hardware timestamping even if it was not configured for hardware
transmit timestamping.

Corinna Vinschen removes the error message that there was an "unexpected
SYS WRAP", when it is actually expected.  So remove the message to not
confuse users.

Greg Edwards provides several patches for the mailbox interface between
the PF and VF drivers.  Added a mailbox unlock method to be used to unlock
the PF/VF mailbox by the PF.  Added a lock around the VF mailbox ops to
prevent the VF from sending another message while the PF is still
processing the previous message.  Fixed a "scheduling while atomic" issue
by changing msleep() to mdelay().

Sasha adds support for the next LOM generations i219 (v8 & v9) which
will be available in the next Intel client platform IceLake.

John Linville adds support for a Broadcom PHY to the igb driver, since
there are designs out in the world which use the igb MAC and a third
party PHY.  This allows the driver to load and function as expected on
these designs.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3118e6e1 eeb01496
...@@ -100,6 +100,10 @@ struct e1000_hw; ...@@ -100,6 +100,10 @@ struct e1000_hw;
#define E1000_DEV_ID_PCH_CNP_I219_V6 0x15BE #define E1000_DEV_ID_PCH_CNP_I219_V6 0x15BE
#define E1000_DEV_ID_PCH_CNP_I219_LM7 0x15BB #define E1000_DEV_ID_PCH_CNP_I219_LM7 0x15BB
#define E1000_DEV_ID_PCH_CNP_I219_V7 0x15BC #define E1000_DEV_ID_PCH_CNP_I219_V7 0x15BC
#define E1000_DEV_ID_PCH_ICP_I219_LM8 0x15DF
#define E1000_DEV_ID_PCH_ICP_I219_V8 0x15E0
#define E1000_DEV_ID_PCH_ICP_I219_LM9 0x15E1
#define E1000_DEV_ID_PCH_ICP_I219_V9 0x15E2
#define E1000_REVISION_4 4 #define E1000_REVISION_4 4
......
...@@ -2437,6 +2437,8 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ...@@ -2437,6 +2437,8 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
if (hw->phy.revision < 2) { if (hw->phy.revision < 2) {
e1000e_phy_sw_reset(hw); e1000e_phy_sw_reset(hw);
ret_val = e1e_wphy(hw, MII_BMCR, 0x3140); ret_val = e1e_wphy(hw, MII_BMCR, 0x3140);
if (ret_val)
return ret_val;
} }
} }
......
...@@ -7544,6 +7544,10 @@ static const struct pci_device_id e1000_pci_tbl[] = { ...@@ -7544,6 +7544,10 @@ static const struct pci_device_id e1000_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CNP_I219_V6), board_pch_cnp }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CNP_I219_V6), board_pch_cnp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CNP_I219_LM7), board_pch_cnp }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CNP_I219_LM7), board_pch_cnp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CNP_I219_V7), board_pch_cnp }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CNP_I219_V7), board_pch_cnp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_LM8), board_pch_cnp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_V8), board_pch_cnp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_LM9), board_pch_cnp },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_V9), board_pch_cnp },
{ 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
}; };
......
...@@ -340,6 +340,9 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) ...@@ -340,6 +340,9 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw)
phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580; phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break; break;
case BCM54616_E_PHY_ID:
phy->type = e1000_phy_bcm54616;
break;
default: default:
ret_val = -E1000_ERR_PHY; ret_val = -E1000_ERR_PHY;
goto out; goto out;
...@@ -1659,6 +1662,9 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) ...@@ -1659,6 +1662,9 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
case e1000_phy_82580: case e1000_phy_82580:
ret_val = igb_copper_link_setup_82580(hw); ret_val = igb_copper_link_setup_82580(hw);
break; break;
case e1000_phy_bcm54616:
ret_val = 0;
break;
default: default:
ret_val = -E1000_ERR_PHY; ret_val = -E1000_ERR_PHY;
break; break;
......
...@@ -889,6 +889,7 @@ ...@@ -889,6 +889,7 @@
#define I210_I_PHY_ID 0x01410C00 #define I210_I_PHY_ID 0x01410C00
#define M88E1543_E_PHY_ID 0x01410EA0 #define M88E1543_E_PHY_ID 0x01410EA0
#define M88E1512_E_PHY_ID 0x01410DD0 #define M88E1512_E_PHY_ID 0x01410DD0
#define BCM54616_E_PHY_ID 0x03625D10
/* M88E1000 Specific Registers */ /* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
......
...@@ -128,6 +128,7 @@ enum e1000_phy_type { ...@@ -128,6 +128,7 @@ enum e1000_phy_type {
e1000_phy_ife, e1000_phy_ife,
e1000_phy_82580, e1000_phy_82580,
e1000_phy_i210, e1000_phy_i210,
e1000_phy_bcm54616,
}; };
enum e1000_bus_type { enum e1000_bus_type {
...@@ -491,13 +492,16 @@ struct e1000_fc_info { ...@@ -491,13 +492,16 @@ struct e1000_fc_info {
struct e1000_mbx_operations { struct e1000_mbx_operations {
s32 (*init_params)(struct e1000_hw *hw); s32 (*init_params)(struct e1000_hw *hw);
s32 (*read)(struct e1000_hw *, u32 *, u16, u16); s32 (*read)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
s32 (*write)(struct e1000_hw *, u32 *, u16, u16); bool unlock);
s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*write)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*read_posted)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
s32 (*check_for_msg)(struct e1000_hw *, u16); s32 (*write_posted)(struct e1000_hw *hw, u32 *msg, u16 size,
s32 (*check_for_ack)(struct e1000_hw *, u16); u16 mbx_id);
s32 (*check_for_rst)(struct e1000_hw *, u16); s32 (*check_for_msg)(struct e1000_hw *hw, u16 mbx_id);
s32 (*check_for_ack)(struct e1000_hw *hw, u16 mbx_id);
s32 (*check_for_rst)(struct e1000_hw *hw, u16 mbx_id);
s32 (*unlock)(struct e1000_hw *hw, u16 mbx_id);
}; };
struct e1000_mbx_stats { struct e1000_mbx_stats {
......
...@@ -32,7 +32,8 @@ ...@@ -32,7 +32,8 @@
* *
* returns SUCCESS if it successfully read message from buffer * returns SUCCESS if it successfully read message from buffer
**/ **/
s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
bool unlock)
{ {
struct e1000_mbx_info *mbx = &hw->mbx; struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX; s32 ret_val = -E1000_ERR_MBX;
...@@ -42,7 +43,7 @@ s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) ...@@ -42,7 +43,7 @@ s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
size = mbx->size; size = mbx->size;
if (mbx->ops.read) if (mbx->ops.read)
ret_val = mbx->ops.read(hw, msg, size, mbx_id); ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock);
return ret_val; return ret_val;
} }
...@@ -124,6 +125,24 @@ s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id) ...@@ -124,6 +125,24 @@ s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
return ret_val; return ret_val;
} }
/**
* igb_unlock_mbx - unlock the mailbox
* @hw: pointer to the HW structure
* @mbx_id: id of mailbox to check
*
* returns SUCCESS if the mailbox was unlocked or else ERR_MBX
**/
s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
if (mbx->ops.unlock)
ret_val = mbx->ops.unlock(hw, mbx_id);
return ret_val;
}
/** /**
* igb_poll_for_msg - Wait for message notification * igb_poll_for_msg - Wait for message notification
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -204,7 +223,7 @@ static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, ...@@ -204,7 +223,7 @@ static s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
ret_val = igb_poll_for_msg(hw, mbx_id); ret_val = igb_poll_for_msg(hw, mbx_id);
if (!ret_val) if (!ret_val)
ret_val = mbx->ops.read(hw, msg, size, mbx_id); ret_val = mbx->ops.read(hw, msg, size, mbx_id, true);
out: out:
return ret_val; return ret_val;
} }
...@@ -340,6 +359,26 @@ static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) ...@@ -340,6 +359,26 @@ static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
return ret_val; return ret_val;
} }
/**
* igb_release_mbx_lock_pf - release mailbox lock
* @hw: pointer to the HW structure
* @vf_number: the VF index
*
* return SUCCESS if we released the mailbox lock
**/
static s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
{
u32 p2v_mailbox;
/* drop PF lock of mailbox, if set */
p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
wr32(E1000_P2VMAILBOX(vf_number),
p2v_mailbox & ~E1000_P2VMAILBOX_PFU);
return 0;
}
/** /**
* igb_write_mbx_pf - Places a message in the mailbox * igb_write_mbx_pf - Places a message in the mailbox
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -385,13 +424,14 @@ static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, ...@@ -385,13 +424,14 @@ static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
* @msg: The message buffer * @msg: The message buffer
* @size: Length of buffer * @size: Length of buffer
* @vf_number: the VF index * @vf_number: the VF index
* @unlock: unlock the mailbox when done?
* *
* This function copies a message from the mailbox buffer to the caller's * This function copies a message from the mailbox buffer to the caller's
* memory buffer. The presumption is that the caller knows that there was * memory buffer. The presumption is that the caller knows that there was
* a message due to a VF request so no polling for message is needed. * a message due to a VF request so no polling for message is needed.
**/ **/
static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
u16 vf_number) u16 vf_number, bool unlock)
{ {
s32 ret_val; s32 ret_val;
u16 i; u16 i;
...@@ -405,8 +445,12 @@ static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, ...@@ -405,8 +445,12 @@ static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
msg[i] = array_rd32(E1000_VMBMEM(vf_number), i); msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
/* Acknowledge the message and release buffer */ /* Acknowledge the message and release mailbox lock (or not) */
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); if (unlock)
wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
else
wr32(E1000_P2VMAILBOX(vf_number),
E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU);
/* update stats */ /* update stats */
hw->mbx.stats.msgs_rx++; hw->mbx.stats.msgs_rx++;
...@@ -437,6 +481,7 @@ s32 igb_init_mbx_params_pf(struct e1000_hw *hw) ...@@ -437,6 +481,7 @@ s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
mbx->ops.check_for_msg = igb_check_for_msg_pf; mbx->ops.check_for_msg = igb_check_for_msg_pf;
mbx->ops.check_for_ack = igb_check_for_ack_pf; mbx->ops.check_for_ack = igb_check_for_ack_pf;
mbx->ops.check_for_rst = igb_check_for_rst_pf; mbx->ops.check_for_rst = igb_check_for_rst_pf;
mbx->ops.unlock = igb_release_mbx_lock_pf;
mbx->stats.msgs_tx = 0; mbx->stats.msgs_tx = 0;
mbx->stats.msgs_rx = 0; mbx->stats.msgs_rx = 0;
......
...@@ -67,11 +67,13 @@ ...@@ -67,11 +67,13 @@
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ #define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
s32 igb_read_mbx(struct e1000_hw *, u32 *, u16, u16); s32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
s32 igb_write_mbx(struct e1000_hw *, u32 *, u16, u16); bool unlock);
s32 igb_check_for_msg(struct e1000_hw *, u16); s32 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
s32 igb_check_for_ack(struct e1000_hw *, u16); s32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id);
s32 igb_check_for_rst(struct e1000_hw *, u16); s32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id);
s32 igb_init_mbx_params_pf(struct e1000_hw *); s32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id);
s32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id);
s32 igb_init_mbx_params_pf(struct e1000_hw *hw);
#endif /* _E1000_MBX_H_ */ #endif /* _E1000_MBX_H_ */
...@@ -1791,6 +1791,8 @@ void igb_down(struct igb_adapter *adapter) ...@@ -1791,6 +1791,8 @@ void igb_down(struct igb_adapter *adapter)
wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN); wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
/* flush and sleep below */ /* flush and sleep below */
igb_nfc_filter_exit(adapter);
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev); netif_tx_stop_all_queues(netdev);
...@@ -3317,8 +3319,6 @@ static int __igb_close(struct net_device *netdev, bool suspending) ...@@ -3317,8 +3319,6 @@ static int __igb_close(struct net_device *netdev, bool suspending)
igb_down(adapter); igb_down(adapter);
igb_free_irq(adapter); igb_free_irq(adapter);
igb_nfc_filter_exit(adapter);
igb_free_all_tx_resources(adapter); igb_free_all_tx_resources(adapter);
igb_free_all_rx_resources(adapter); igb_free_all_rx_resources(adapter);
...@@ -5380,7 +5380,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, ...@@ -5380,7 +5380,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
if (!test_and_set_bit_lock(__IGB_PTP_TX_IN_PROGRESS, if (adapter->tstamp_config.tx_type & HWTSTAMP_TX_ON &&
!test_and_set_bit_lock(__IGB_PTP_TX_IN_PROGRESS,
&adapter->state)) { &adapter->state)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IGB_TX_FLAGS_TSTAMP; tx_flags |= IGB_TX_FLAGS_TSTAMP;
...@@ -5745,8 +5746,6 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) ...@@ -5745,8 +5746,6 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter)
event.type = PTP_CLOCK_PPS; event.type = PTP_CLOCK_PPS;
if (adapter->ptp_caps.pps) if (adapter->ptp_caps.pps)
ptp_clock_event(adapter->ptp_clock, &event); ptp_clock_event(adapter->ptp_clock, &event);
else
dev_err(&adapter->pdev->dev, "unexpected SYS WRAP");
ack |= TSINTR_SYS_WRAP; ack |= TSINTR_SYS_WRAP;
} }
...@@ -6676,32 +6675,33 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) ...@@ -6676,32 +6675,33 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf)
struct vf_data_storage *vf_data = &adapter->vf_data[vf]; struct vf_data_storage *vf_data = &adapter->vf_data[vf];
s32 retval; s32 retval;
retval = igb_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf); retval = igb_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf, false);
if (retval) { if (retval) {
/* if receive failed revoke VF CTS stats and restart init */ /* if receive failed revoke VF CTS stats and restart init */
dev_err(&pdev->dev, "Error receiving message from VF\n"); dev_err(&pdev->dev, "Error receiving message from VF\n");
vf_data->flags &= ~IGB_VF_FLAG_CTS; vf_data->flags &= ~IGB_VF_FLAG_CTS;
if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) if (!time_after(jiffies, vf_data->last_nack + (2 * HZ)))
return; goto unlock;
goto out; goto out;
} }
/* this is a message we already processed, do nothing */ /* this is a message we already processed, do nothing */
if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK))
return; goto unlock;
/* until the vf completes a reset it should not be /* until the vf completes a reset it should not be
* allowed to start any configuration. * allowed to start any configuration.
*/ */
if (msgbuf[0] == E1000_VF_RESET) { if (msgbuf[0] == E1000_VF_RESET) {
/* unlocks mailbox */
igb_vf_reset_msg(adapter, vf); igb_vf_reset_msg(adapter, vf);
return; return;
} }
if (!(vf_data->flags & IGB_VF_FLAG_CTS)) { if (!(vf_data->flags & IGB_VF_FLAG_CTS)) {
if (!time_after(jiffies, vf_data->last_nack + (2 * HZ))) if (!time_after(jiffies, vf_data->last_nack + (2 * HZ)))
return; goto unlock;
retval = -1; retval = -1;
goto out; goto out;
} }
...@@ -6742,7 +6742,12 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) ...@@ -6742,7 +6742,12 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf)
else else
msgbuf[0] |= E1000_VT_MSGTYPE_ACK; msgbuf[0] |= E1000_VT_MSGTYPE_ACK;
/* unlocks mailbox */
igb_write_mbx(hw, msgbuf, 1, vf); igb_write_mbx(hw, msgbuf, 1, vf);
return;
unlock:
igb_unlock_mbx(hw, vf);
} }
static void igb_msg_task(struct igb_adapter *adapter) static void igb_msg_task(struct igb_adapter *adapter)
......
...@@ -296,8 +296,12 @@ static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data) ...@@ -296,8 +296,12 @@ static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
*data = 0; *data = 0;
spin_lock_bh(&hw->mbx_lock);
hw->mac.ops.check_for_link(hw); hw->mac.ops.check_for_link(hw);
spin_unlock_bh(&hw->mbx_lock);
if (!(er32(STATUS) & E1000_STATUS_LU)) if (!(er32(STATUS) & E1000_STATUS_LU))
*data = 1; *data = 1;
......
...@@ -264,6 +264,8 @@ static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size) ...@@ -264,6 +264,8 @@ static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
s32 err; s32 err;
u16 i; u16 i;
WARN_ON_ONCE(!spin_is_locked(&hw->mbx_lock));
/* lock the mailbox to prevent pf/vf race condition */ /* lock the mailbox to prevent pf/vf race condition */
err = e1000_obtain_mbx_lock_vf(hw); err = e1000_obtain_mbx_lock_vf(hw);
if (err) if (err)
...@@ -300,6 +302,8 @@ static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size) ...@@ -300,6 +302,8 @@ static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
s32 err; s32 err;
u16 i; u16 i;
WARN_ON_ONCE(!spin_is_locked(&hw->mbx_lock));
/* lock the mailbox to prevent pf/vf race condition */ /* lock the mailbox to prevent pf/vf race condition */
err = e1000_obtain_mbx_lock_vf(hw); err = e1000_obtain_mbx_lock_vf(hw);
if (err) if (err)
......
...@@ -1235,7 +1235,12 @@ static void igbvf_set_rlpml(struct igbvf_adapter *adapter) ...@@ -1235,7 +1235,12 @@ static void igbvf_set_rlpml(struct igbvf_adapter *adapter)
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE; max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
spin_lock_bh(&hw->mbx_lock);
e1000_rlpml_set_vf(hw, max_frame_size); e1000_rlpml_set_vf(hw, max_frame_size);
spin_unlock_bh(&hw->mbx_lock);
} }
static int igbvf_vlan_rx_add_vid(struct net_device *netdev, static int igbvf_vlan_rx_add_vid(struct net_device *netdev,
...@@ -1244,10 +1249,16 @@ static int igbvf_vlan_rx_add_vid(struct net_device *netdev, ...@@ -1244,10 +1249,16 @@ static int igbvf_vlan_rx_add_vid(struct net_device *netdev,
struct igbvf_adapter *adapter = netdev_priv(netdev); struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
spin_lock_bh(&hw->mbx_lock);
if (hw->mac.ops.set_vfta(hw, vid, true)) { if (hw->mac.ops.set_vfta(hw, vid, true)) {
dev_err(&adapter->pdev->dev, "Failed to add vlan id %d\n", vid); dev_err(&adapter->pdev->dev, "Failed to add vlan id %d\n", vid);
spin_unlock_bh(&hw->mbx_lock);
return -EINVAL; return -EINVAL;
} }
spin_unlock_bh(&hw->mbx_lock);
set_bit(vid, adapter->active_vlans); set_bit(vid, adapter->active_vlans);
return 0; return 0;
} }
...@@ -1258,11 +1269,17 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, ...@@ -1258,11 +1269,17 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev,
struct igbvf_adapter *adapter = netdev_priv(netdev); struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
spin_lock_bh(&hw->mbx_lock);
if (hw->mac.ops.set_vfta(hw, vid, false)) { if (hw->mac.ops.set_vfta(hw, vid, false)) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to remove vlan id %d\n", vid); "Failed to remove vlan id %d\n", vid);
spin_unlock_bh(&hw->mbx_lock);
return -EINVAL; return -EINVAL;
} }
spin_unlock_bh(&hw->mbx_lock);
clear_bit(vid, adapter->active_vlans); clear_bit(vid, adapter->active_vlans);
return 0; return 0;
} }
...@@ -1428,7 +1445,11 @@ static void igbvf_set_multi(struct net_device *netdev) ...@@ -1428,7 +1445,11 @@ static void igbvf_set_multi(struct net_device *netdev)
netdev_for_each_mc_addr(ha, netdev) netdev_for_each_mc_addr(ha, netdev)
memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
spin_lock_bh(&hw->mbx_lock);
hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0); hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0);
spin_unlock_bh(&hw->mbx_lock);
kfree(mta_list); kfree(mta_list);
} }
...@@ -1449,16 +1470,24 @@ static int igbvf_set_uni(struct net_device *netdev) ...@@ -1449,16 +1470,24 @@ static int igbvf_set_uni(struct net_device *netdev)
return -ENOSPC; return -ENOSPC;
} }
spin_lock_bh(&hw->mbx_lock);
/* Clear all unicast MAC filters */ /* Clear all unicast MAC filters */
hw->mac.ops.set_uc_addr(hw, E1000_VF_MAC_FILTER_CLR, NULL); hw->mac.ops.set_uc_addr(hw, E1000_VF_MAC_FILTER_CLR, NULL);
spin_unlock_bh(&hw->mbx_lock);
if (!netdev_uc_empty(netdev)) { if (!netdev_uc_empty(netdev)) {
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
/* Add MAC filters one by one */ /* Add MAC filters one by one */
netdev_for_each_uc_addr(ha, netdev) { netdev_for_each_uc_addr(ha, netdev) {
spin_lock_bh(&hw->mbx_lock);
hw->mac.ops.set_uc_addr(hw, E1000_VF_MAC_FILTER_ADD, hw->mac.ops.set_uc_addr(hw, E1000_VF_MAC_FILTER_ADD,
ha->addr); ha->addr);
spin_unlock_bh(&hw->mbx_lock);
udelay(200); udelay(200);
} }
} }
...@@ -1503,12 +1532,16 @@ static void igbvf_reset(struct igbvf_adapter *adapter) ...@@ -1503,12 +1532,16 @@ static void igbvf_reset(struct igbvf_adapter *adapter)
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
spin_lock_bh(&hw->mbx_lock);
/* Allow time for pending master requests to run */ /* Allow time for pending master requests to run */
if (mac->ops.reset_hw(hw)) if (mac->ops.reset_hw(hw))
dev_err(&adapter->pdev->dev, "PF still resetting\n"); dev_err(&adapter->pdev->dev, "PF still resetting\n");
mac->ops.init_hw(hw); mac->ops.init_hw(hw);
spin_unlock_bh(&hw->mbx_lock);
if (is_valid_ether_addr(adapter->hw.mac.addr)) { if (is_valid_ether_addr(adapter->hw.mac.addr)) {
memcpy(netdev->dev_addr, adapter->hw.mac.addr, memcpy(netdev->dev_addr, adapter->hw.mac.addr,
netdev->addr_len); netdev->addr_len);
...@@ -1643,6 +1676,7 @@ static int igbvf_sw_init(struct igbvf_adapter *adapter) ...@@ -1643,6 +1676,7 @@ static int igbvf_sw_init(struct igbvf_adapter *adapter)
igbvf_irq_disable(adapter); igbvf_irq_disable(adapter);
spin_lock_init(&adapter->stats_lock); spin_lock_init(&adapter->stats_lock);
spin_lock_init(&adapter->hw.mbx_lock);
set_bit(__IGBVF_DOWN, &adapter->state); set_bit(__IGBVF_DOWN, &adapter->state);
return 0; return 0;
...@@ -1786,8 +1820,12 @@ static int igbvf_set_mac(struct net_device *netdev, void *p) ...@@ -1786,8 +1820,12 @@ static int igbvf_set_mac(struct net_device *netdev, void *p)
memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
spin_lock_bh(&hw->mbx_lock);
hw->mac.ops.rar_set(hw, hw->mac.addr, 0); hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
spin_unlock_bh(&hw->mbx_lock);
if (!ether_addr_equal(addr->sa_data, hw->mac.addr)) if (!ether_addr_equal(addr->sa_data, hw->mac.addr))
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
...@@ -1858,7 +1896,12 @@ static bool igbvf_has_link(struct igbvf_adapter *adapter) ...@@ -1858,7 +1896,12 @@ static bool igbvf_has_link(struct igbvf_adapter *adapter)
if (test_bit(__IGBVF_DOWN, &adapter->state)) if (test_bit(__IGBVF_DOWN, &adapter->state))
return false; return false;
spin_lock_bh(&hw->mbx_lock);
ret_val = hw->mac.ops.check_for_link(hw); ret_val = hw->mac.ops.check_for_link(hw);
spin_unlock_bh(&hw->mbx_lock);
link_active = !hw->mac.get_link_status; link_active = !hw->mac.get_link_status;
/* if check for link returns error we will need to reset */ /* if check for link returns error we will need to reset */
...@@ -2808,6 +2851,8 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2808,6 +2851,8 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->min_mtu = ETH_MIN_MTU; netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
spin_lock_bh(&hw->mbx_lock);
/*reset the controller to put the device in a known good state */ /*reset the controller to put the device in a known good state */
err = hw->mac.ops.reset_hw(hw); err = hw->mac.ops.reset_hw(hw);
if (err) { if (err) {
...@@ -2824,6 +2869,8 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2824,6 +2869,8 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->addr_len); netdev->addr_len);
} }
spin_unlock_bh(&hw->mbx_lock);
if (!is_valid_ether_addr(netdev->dev_addr)) { if (!is_valid_ether_addr(netdev->dev_addr)) {
dev_info(&pdev->dev, "Assigning random MAC address.\n"); dev_info(&pdev->dev, "Assigning random MAC address.\n");
eth_hw_addr_random(netdev); eth_hw_addr_random(netdev);
......
...@@ -149,7 +149,7 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw) ...@@ -149,7 +149,7 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
msgbuf[0] = E1000_VF_RESET; msgbuf[0] = E1000_VF_RESET;
mbx->ops.write_posted(hw, msgbuf, 1); mbx->ops.write_posted(hw, msgbuf, 1);
msleep(10); mdelay(10);
/* set our "perm_addr" based on info provided by PF */ /* set our "perm_addr" based on info provided by PF */
ret_val = mbx->ops.read_posted(hw, msgbuf, 3); ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
...@@ -230,6 +230,7 @@ static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, ...@@ -230,6 +230,7 @@ static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
u16 *hash_list = (u16 *)&msgbuf[1]; u16 *hash_list = (u16 *)&msgbuf[1];
u32 hash_value; u32 hash_value;
u32 cnt, i; u32 cnt, i;
s32 ret_val;
/* Each entry in the list uses 1 16 bit word. We have 30 /* Each entry in the list uses 1 16 bit word. We have 30
* 16 bit words available in our HW msg buffer (minus 1 for the * 16 bit words available in our HW msg buffer (minus 1 for the
...@@ -250,7 +251,9 @@ static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, ...@@ -250,7 +251,9 @@ static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
mc_addr_list += ETH_ALEN; mc_addr_list += ETH_ALEN;
} }
mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE); ret_val = mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE);
if (!ret_val)
mbx->ops.read_posted(hw, msgbuf, 1);
} }
/** /**
...@@ -293,11 +296,14 @@ void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size) ...@@ -293,11 +296,14 @@ void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
{ {
struct e1000_mbx_info *mbx = &hw->mbx; struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2]; u32 msgbuf[2];
s32 ret_val;
msgbuf[0] = E1000_VF_SET_LPE; msgbuf[0] = E1000_VF_SET_LPE;
msgbuf[1] = max_size; msgbuf[1] = max_size;
mbx->ops.write_posted(hw, msgbuf, 2); ret_val = mbx->ops.write_posted(hw, msgbuf, 2);
if (!ret_val)
mbx->ops.read_posted(hw, msgbuf, 1);
} }
/** /**
......
...@@ -245,6 +245,7 @@ struct e1000_hw { ...@@ -245,6 +245,7 @@ struct e1000_hw {
struct e1000_mac_info mac; struct e1000_mac_info mac;
struct e1000_mbx_info mbx; struct e1000_mbx_info mbx;
spinlock_t mbx_lock; /* serializes mailbox ops */
union { union {
struct e1000_dev_spec_vf vf; struct e1000_dev_spec_vf vf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment