Skip to content

Commit

Permalink
ice: Update request resource command to latest specification
Browse files Browse the repository at this point in the history
Align Request Resource Ownership AQ command (0x0008) to the latest
specification. This includes:

- Correcting the resource IDs for the Global Cfg and Change locks.
- new enum ICE_CHANGE_LOCK_RES_ID
- new enum ICE_GLOBAL_CFG_LOCK_RES_ID
- Altering the flow for Global Config Lock to allow only the first PF to
  download the package.

Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Tony Brelinski <tonyx.brelinski@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Dan Nowlin authored and Jeff Kirsher committed Aug 28, 2018
1 parent b36c598 commit ff2b132
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 21 deletions.
75 changes: 58 additions & 17 deletions drivers/net/ethernet/intel/ice/ice_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,22 @@ enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading)
* @timeout: the maximum time in ms that the driver may hold the resource
* @cd: pointer to command details structure or NULL
*
* requests common resource using the admin queue commands (0x0008)
* Requests common resource using the admin queue commands (0x0008).
* When attempting to acquire the Global Config Lock, the driver can
* learn of three states:
* 1) ICE_SUCCESS - acquired lock, and can perform download package
* 2) ICE_ERR_AQ_ERROR - did not get lock, driver should fail to load
* 3) ICE_ERR_AQ_NO_WORK - did not get lock, but another driver has
* successfully downloaded the package; the driver does
* not have to download the package and can continue
* loading
*
* Note that if the caller is in an acquire lock, perform action, release lock
* phase of operation, it is possible that the FW may detect a timeout and issue
* a CORER. In this case, the driver will receive a CORER interrupt and will
* have to determine its cause. The calling thread that is handling this flow
* will likely get an error propagated back to it indicating the Download
* Package, Update Package or the Release Resource AQ commands timed out.
*/
static enum ice_status
ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
Expand All @@ -985,13 +1000,43 @@ ice_aq_req_res(struct ice_hw *hw, enum ice_aq_res_ids res,
cmd_resp->res_id = cpu_to_le16(res);
cmd_resp->access_type = cpu_to_le16(access);
cmd_resp->res_number = cpu_to_le32(sdp_number);
cmd_resp->timeout = cpu_to_le32(*timeout);
*timeout = 0;

status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);

/* The completion specifies the maximum time in ms that the driver
* may hold the resource in the Timeout field.
* If the resource is held by someone else, the command completes with
* busy return value and the timeout field indicates the maximum time
* the current owner of the resource has to free it.
*/

/* Global config lock response utilizes an additional status field.
*
* If the Global config lock resource is held by some other driver, the
* command completes with ICE_AQ_RES_GLBL_IN_PROG in the status field
* and the timeout field indicates the maximum time the current owner
* of the resource has to free it.
*/
if (res == ICE_GLOBAL_CFG_LOCK_RES_ID) {
if (le16_to_cpu(cmd_resp->status) == ICE_AQ_RES_GLBL_SUCCESS) {
*timeout = le32_to_cpu(cmd_resp->timeout);
return 0;
} else if (le16_to_cpu(cmd_resp->status) ==
ICE_AQ_RES_GLBL_IN_PROG) {
*timeout = le32_to_cpu(cmd_resp->timeout);
return ICE_ERR_AQ_ERROR;
} else if (le16_to_cpu(cmd_resp->status) ==
ICE_AQ_RES_GLBL_DONE) {
return ICE_ERR_AQ_NO_WORK;
}

/* invalid FW response, force a timeout immediately */
*timeout = 0;
return ICE_ERR_AQ_ERROR;
}

/* If the resource is held by some other driver, the command completes
* with a busy return value and the timeout field indicates the maximum
* time the current owner of the resource has to free it.
*/
if (!status || hw->adminq.sq_last_status == ICE_AQ_RC_EBUSY)
*timeout = le32_to_cpu(cmd_resp->timeout);
Expand Down Expand Up @@ -1030,30 +1075,28 @@ ice_aq_release_res(struct ice_hw *hw, enum ice_aq_res_ids res, u8 sdp_number,
* @hw: pointer to the HW structure
* @res: resource id
* @access: access type (read or write)
* @timeout: timeout in milliseconds
*
* This function will attempt to acquire the ownership of a resource.
*/
enum ice_status
ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
enum ice_aq_res_access_type access)
enum ice_aq_res_access_type access, u32 timeout)
{
#define ICE_RES_POLLING_DELAY_MS 10
u32 delay = ICE_RES_POLLING_DELAY_MS;
u32 time_left = timeout;
enum ice_status status;
u32 time_left = 0;
u32 timeout;

status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);

/* An admin queue return code of ICE_AQ_RC_EEXIST means that another
* driver has previously acquired the resource and performed any
* necessary updates; in this case the caller does not obtain the
* resource and has no further work to do.
/* A return code of ICE_ERR_AQ_NO_WORK means that another driver has
* previously acquired the resource and performed any necessary updates;
* in this case the caller does not obtain the resource and has no
* further work to do.
*/
if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
status = ICE_ERR_AQ_NO_WORK;
if (status == ICE_ERR_AQ_NO_WORK)
goto ice_acquire_res_exit;
}

if (status)
ice_debug(hw, ICE_DBG_RES,
Expand All @@ -1066,11 +1109,9 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
timeout = (timeout > delay) ? timeout - delay : 0;
status = ice_aq_req_res(hw, res, access, 0, &time_left, NULL);

if (hw->adminq.sq_last_status == ICE_AQ_RC_EEXIST) {
if (status == ICE_ERR_AQ_NO_WORK)
/* lock free, but no work to do */
status = ICE_ERR_AQ_NO_WORK;
break;
}

if (!status)
/* lock acquired */
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/ice/ice_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ enum ice_status
ice_get_link_status(struct ice_port_info *pi, bool *link_up);
enum ice_status
ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
enum ice_aq_res_access_type access);
enum ice_aq_res_access_type access, u32 timeout);
void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/ice/ice_nvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access)
if (hw->nvm.blank_nvm_mode)
return 0;

return ice_acquire_res(hw, ICE_NVM_RES_ID, access);
return ice_acquire_res(hw, ICE_NVM_RES_ID, access, ICE_NVM_TIMEOUT);
}

/**
Expand Down
9 changes: 7 additions & 2 deletions drivers/net/ethernet/intel/ice/ice_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,15 @@ static inline bool ice_is_tc_ena(u8 bitmap, u8 tc)
enum ice_aq_res_ids {
ICE_NVM_RES_ID = 1,
ICE_SPD_RES_ID,
ICE_GLOBAL_CFG_LOCK_RES_ID,
ICE_CHANGE_LOCK_RES_ID
ICE_CHANGE_LOCK_RES_ID,
ICE_GLOBAL_CFG_LOCK_RES_ID
};

/* FW update timeout definitions are in milliseconds */
#define ICE_NVM_TIMEOUT 180000
#define ICE_CHANGE_LOCK_TIMEOUT 1000
#define ICE_GLOBAL_CFG_LOCK_TIMEOUT 3000

enum ice_aq_res_access_type {
ICE_RES_READ = 1,
ICE_RES_WRITE
Expand Down

0 comments on commit ff2b132

Please sign in to comment.