Commit 4b2cd27f authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher

ixgbevf: Fix code for handling timeout

The VF driver was not designed to correctly handle a message timeout.  As
a result it is possible for one bad message to invalidate all messages
following it until the part is reset.  Instead we should copy the example
in igbvf of how to handle a mailbox event and message timeout.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent c9d2ea96
......@@ -716,40 +716,15 @@ static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector)
}
}
static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
static irqreturn_t ixgbevf_msix_other(int irq, void *data)
{
struct ixgbevf_adapter *adapter = data;
struct ixgbe_hw *hw = &adapter->hw;
u32 msg;
bool got_ack = false;
if (!hw->mbx.ops.check_for_ack(hw))
got_ack = true;
hw->mac.get_link_status = 1;
if (!hw->mbx.ops.check_for_msg(hw)) {
hw->mbx.ops.read(hw, &msg, 1);
if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
mod_timer(&adapter->watchdog_timer,
round_jiffies(jiffies + 1));
if (msg & IXGBE_VT_MSGTYPE_NACK)
pr_warn("Last Request of type %2.2x to PF Nacked\n",
msg & 0xFF);
/*
* Restore the PFSTS bit in case someone is polling for a
* return message from the PF
*/
hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFSTS;
}
/*
* checking for the ack clears the PFACK bit. Place
* it back in the v2p_mailbox cache so that anyone
* polling for an ack will not miss it
*/
if (got_ack)
hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
mod_timer(&adapter->watchdog_timer, jiffies);
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other);
......@@ -899,10 +874,10 @@ static int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter)
}
err = request_irq(adapter->msix_entries[vector].vector,
&ixgbevf_msix_mbx, 0, netdev->name, adapter);
&ixgbevf_msix_other, 0, netdev->name, adapter);
if (err) {
hw_dbg(&adapter->hw,
"request_irq for msix_mbx failed: %d\n", err);
"request_irq for msix_other failed: %d\n", err);
goto free_queue_irqs;
}
......@@ -1411,6 +1386,7 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
ixgbevf_save_reset_stats(adapter);
ixgbevf_init_last_counter_stats(adapter);
hw->mac.get_link_status = 1;
mod_timer(&adapter->watchdog_timer, jiffies);
}
......@@ -1589,8 +1565,6 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter)
void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
WARN_ON(in_interrupt());
while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
......@@ -1603,10 +1577,8 @@ void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
* watchdog task will continue to schedule reset tasks until
* the PF is up and running.
*/
if (!hw->mac.ops.reset_hw(hw)) {
ixgbevf_down(adapter);
ixgbevf_up(adapter);
}
clear_bit(__IXGBEVF_RESETTING, &adapter->state);
}
......
......@@ -86,14 +86,17 @@ static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw)
static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
s32 ret_val = IXGBE_ERR_MBX;
s32 ret_val = -IXGBE_ERR_MBX;
if (!mbx->ops.read)
goto out;
ret_val = ixgbevf_poll_for_msg(hw);
/* if ack received read message, otherwise we timed out */
if (!ret_val)
ret_val = mbx->ops.read(hw, msg, size);
out:
return ret_val;
}
......@@ -109,7 +112,11 @@ static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size)
static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
s32 ret_val;
s32 ret_val = -IXGBE_ERR_MBX;
/* exit if either we can't write or there isn't a defined timeout */
if (!mbx->ops.write || !mbx->timeout)
goto out;
/* send msg */
ret_val = mbx->ops.write(hw, msg, size);
......@@ -117,7 +124,7 @@ static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size)
/* if msg sent wait until we receive an ack */
if (!ret_val)
ret_val = ixgbevf_poll_for_ack(hw);
out:
return ret_val;
}
......
......@@ -392,20 +392,23 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
bool *link_up,
bool autoneg_wait_to_complete)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
struct ixgbe_mac_info *mac = &hw->mac;
s32 ret_val = 0;
u32 links_reg;
u32 in_msg = 0;
if (!(hw->mbx.ops.check_for_rst(hw))) {
*link_up = false;
*speed = 0;
return -1;
}
/* If we were hit with a reset drop the link */
if (!mbx->ops.check_for_rst(hw) || !mbx->timeout)
mac->get_link_status = true;
links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
if (!mac->get_link_status)
goto out;
if (links_reg & IXGBE_LINKS_UP)
*link_up = true;
else
*link_up = false;
/* if link status is down no point in checking to see if pf is up */
links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
if (!(links_reg & IXGBE_LINKS_UP))
goto out;
switch (links_reg & IXGBE_LINKS_SPEED_82599) {
case IXGBE_LINKS_SPEED_10G_82599:
......@@ -419,7 +422,31 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
break;
}
return 0;
/* if the read failed it could just be a mailbox collision, best wait
* until we are called again and don't report an error */
if (mbx->ops.read(hw, &in_msg, 1))
goto out;
if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) {
/* msg is not CTS and is NACK we must have lost CTS status */
if (in_msg & IXGBE_VT_MSGTYPE_NACK)
ret_val = -1;
goto out;
}
/* the pf is talking, if we timed out in the past we reinit */
if (!mbx->timeout) {
ret_val = -1;
goto out;
}
/* if we passed all the tests above then the link is up and we no
* longer need to check for link */
mac->get_link_status = false;
out:
*link_up = !mac->get_link_status;
return ret_val;
}
/**
......
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