Skip to content

Commit

Permalink
fm10k: request reset when mbx->state changes
Browse files Browse the repository at this point in the history
Multiple IES API resets can cause a race condition where the mailbox
interrupt request bits can be cleared before being handled. This can
leave certain mailbox messages from the PF to be untreated and the PF
will enter in some inactive state. If this situation occurs, the IES API
will initiate a mailbox version reset which, then, trigger a mailbox
state change. Once this mailbox transition occurs (from OPEN to CONNECT
state), a request for reset will be returned.

This ensures that PF will undergo a reset whenever IES API encounters an
unknown global mailbox interrupt event or whenever the IES API
terminates.

Signed-off-by: Ngai-Mint Kwan <ngai-mint.kwan@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Ngai-Mint Kwan authored and Jeff Kirsher committed Jan 8, 2017
1 parent aee2433 commit 2f3fc1e
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
10 changes: 7 additions & 3 deletions drivers/net/ethernet/intel/fm10k/fm10k_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2011,9 +2011,10 @@ static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
* function can also be used to respond to an error as the connection
* resetting would also be a means of dealing with errors.
**/
static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
struct fm10k_mbx_info *mbx)
static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
struct fm10k_mbx_info *mbx)
{
s32 err = 0;
const enum fm10k_mbx_state state = mbx->state;

switch (state) {
Expand All @@ -2026,6 +2027,7 @@ static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
case FM10K_STATE_OPEN:
/* flush any incomplete work */
fm10k_sm_mbx_connect_reset(mbx);
err = FM10K_ERR_RESET_REQUESTED;
break;
case FM10K_STATE_CONNECT:
/* Update remote value to match local value */
Expand All @@ -2035,6 +2037,8 @@ static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
}

fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);

return err;
}

/**
Expand Down Expand Up @@ -2115,7 +2119,7 @@ static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,

switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
case 0:
fm10k_sm_mbx_process_reset(hw, mbx);
err = fm10k_sm_mbx_process_reset(hw, mbx);
break;
case FM10K_SM_MBX_VERSION:
err = fm10k_sm_mbx_process_version_1(hw, mbx);
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/ethernet/intel/fm10k/fm10k_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,7 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data)
struct fm10k_hw *hw = &interface->hw;
struct fm10k_mbx_info *mbx = &hw->mbx;
u32 eicr;
s32 err = 0;

/* unmask any set bits related to this interrupt */
eicr = fm10k_read_reg(hw, FM10K_EICR);
Expand All @@ -1159,12 +1160,15 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data)

/* service mailboxes */
if (fm10k_mbx_trylock(interface)) {
mbx->ops.process(hw, mbx);
err = mbx->ops.process(hw, mbx);
/* handle VFLRE events */
fm10k_iov_event(interface);
fm10k_mbx_unlock(interface);
}

if (err == FM10K_ERR_RESET_REQUESTED)
interface->flags |= FM10K_FLAG_RESET_REQUESTED;

/* if switch toggled state we should reset GLORTs */
if (eicr & FM10K_EICR_SWITCHNOTREADY) {
/* force link down for at least 4 seconds */
Expand Down

0 comments on commit 2f3fc1e

Please sign in to comment.