Skip to content

Commit

Permalink
i40e: rtnl_lock in reset path fixes
Browse files Browse the repository at this point in the history
Any user-initiated path which eventually calls reset needs
to hold the rtnl_lock, so add functionality to do that.

Be careful not to use the safe reset when cleaning up
from the diagnostic tests, which avoids rtnl_lock
recursion from ethtool.

Protect the reset_task with rtnl_lock, since it runs from a work item.

Change-Id: Ib6e7a3fb2966809db2daf35fd5a123ccdf6f6f0f
Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Kavindya Deegala <kavindya.s.deegala@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Anjali Singhai Jain authored and Jeff Kirsher committed Dec 16, 2013
1 parent 4b7820c commit 2332618
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ int i40e_up(struct i40e_vsi *vsi);
void i40e_down(struct i40e_vsi *vsi);
extern const char i40e_driver_name[];
extern const char i40e_driver_version_str[];
void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags);
void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags);
void i40e_update_stats(struct i40e_vsi *vsi);
void i40e_update_eth_stats(struct i40e_vsi *vsi);
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/ethernet/intel/i40e/i40e_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1462,19 +1462,19 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
}
} else if (strncmp(cmd_buf, "pfr", 3) == 0) {
dev_info(&pf->pdev->dev, "forcing PFR\n");
i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED));
i40e_do_reset_safe(pf, (1 << __I40E_PF_RESET_REQUESTED));

} else if (strncmp(cmd_buf, "corer", 5) == 0) {
dev_info(&pf->pdev->dev, "forcing CoreR\n");
i40e_do_reset(pf, (1 << __I40E_CORE_RESET_REQUESTED));
i40e_do_reset_safe(pf, (1 << __I40E_CORE_RESET_REQUESTED));

} else if (strncmp(cmd_buf, "globr", 5) == 0) {
dev_info(&pf->pdev->dev, "forcing GlobR\n");
i40e_do_reset(pf, (1 << __I40E_GLOBAL_RESET_REQUESTED));
i40e_do_reset_safe(pf, (1 << __I40E_GLOBAL_RESET_REQUESTED));

} else if (strncmp(cmd_buf, "empr", 4) == 0) {
dev_info(&pf->pdev->dev, "forcing EMPR\n");
i40e_do_reset(pf, (1 << __I40E_EMP_RESET_REQUESTED));
i40e_do_reset_safe(pf, (1 << __I40E_EMP_RESET_REQUESTED));

} else if (strncmp(cmd_buf, "read", 4) == 0) {
u32 address;
Expand Down
19 changes: 18 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4131,6 +4131,19 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
}
}

/**
* i40e_do_reset_safe - Protected reset path for userland calls.
* @pf: board private structure
* @reset_flags: which reset is requested
*
**/
void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags)
{
rtnl_lock();
i40e_do_reset(pf, reset_flags);
rtnl_unlock();
}

/**
* i40e_handle_lan_overflow_event - Handler for LAN queue overflow event
* @pf: board private structure
Expand Down Expand Up @@ -4376,6 +4389,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
{
u32 reset_flags = 0;

rtnl_lock();
if (test_bit(__I40E_REINIT_REQUESTED, &pf->state)) {
reset_flags |= (1 << __I40E_REINIT_REQUESTED);
clear_bit(__I40E_REINIT_REQUESTED, &pf->state);
Expand All @@ -4398,14 +4412,17 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
*/
if (test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state)) {
i40e_handle_reset_warning(pf);
return;
goto unlock;
}

/* If we're already down or resetting, just bail */
if (reset_flags &&
!test_bit(__I40E_DOWN, &pf->state) &&
!test_bit(__I40E_CONFIG_BUSY, &pf->state))
i40e_do_reset(pf, reset_flags);

unlock:
rtnl_unlock();
}

/**
Expand Down

0 comments on commit 2332618

Please sign in to comment.