Commit 5d6201e1 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2014-12-09

This series contains updates to i40e and i40evf.

Jeff (me) provides a single patch to convert a macro to a static inline
function based on feedback from Joe Perches on a previous patch.

Shannon provides the remaining twelve patches against i40e.  Almost all
of Shannon's patches cleanup/fix NVM issues varying in range from
adding more detail to debug messages, to removing dead code, to fixing
NVM state transitions after an error.  Change the handy decoder interface
for admin queue return code to help catch and properly report the condition
as a useful errno rather than returning a misleading '0'.  Added a range
check to avoid any possible array index-out-of-bound issues.

v2:
 - fixed up patch 05 in the series to use the ARRAY_SIZE() macro as suggested
   by Sergei Shtylyov
 - fix up patch 13 to remove unnecessary parens in the return statement
   as suggested by Sergei Shtylyov
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 602de7ea 4bd145be
...@@ -617,7 +617,8 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) ...@@ -617,7 +617,8 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
/* pre-emptive resource lock release */ /* pre-emptive resource lock release */
i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
hw->aq.nvm_busy = false; hw->aq.nvm_release_on_done = false;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
ret_code = i40e_aq_set_hmc_resource_profile(hw, ret_code = i40e_aq_set_hmc_resource_profile(hw,
I40E_HMC_PROFILE_DEFAULT, I40E_HMC_PROFILE_DEFAULT,
...@@ -754,12 +755,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, ...@@ -754,12 +755,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
goto asq_send_command_exit; goto asq_send_command_exit;
} }
if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
status = I40E_ERR_NVM;
goto asq_send_command_exit;
}
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
if (cmd_details) { if (cmd_details) {
*details = *cmd_details; *details = *cmd_details;
...@@ -901,9 +896,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, ...@@ -901,9 +896,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
status = I40E_ERR_ADMIN_QUEUE_TIMEOUT; status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
} }
if (!status && i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
asq_send_command_error: asq_send_command_error:
mutex_unlock(&hw->aq.asq_mutex); mutex_unlock(&hw->aq.asq_mutex);
asq_send_command_exit: asq_send_command_exit:
...@@ -1016,7 +1008,6 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, ...@@ -1016,7 +1008,6 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
mutex_unlock(&hw->aq.arq_mutex); mutex_unlock(&hw->aq.arq_mutex);
if (i40e_is_nvm_update_op(&e->desc)) { if (i40e_is_nvm_update_op(&e->desc)) {
hw->aq.nvm_busy = false;
if (hw->aq.nvm_release_on_done) { if (hw->aq.nvm_release_on_done) {
i40e_release_nvm(hw); i40e_release_nvm(hw);
hw->aq.nvm_release_on_done = false; hw->aq.nvm_release_on_done = false;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define _I40E_ADMINQ_H_ #define _I40E_ADMINQ_H_
#include "i40e_osdep.h" #include "i40e_osdep.h"
#include "i40e_status.h"
#include "i40e_adminq_cmd.h" #include "i40e_adminq_cmd.h"
#define I40E_ADMINQ_DESC(R, i) \ #define I40E_ADMINQ_DESC(R, i) \
...@@ -94,7 +95,6 @@ struct i40e_adminq_info { ...@@ -94,7 +95,6 @@ struct i40e_adminq_info {
u16 fw_min_ver; /* firmware minor version */ u16 fw_min_ver; /* firmware minor version */
u16 api_maj_ver; /* api major version */ u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */ u16 api_min_ver; /* api minor version */
bool nvm_busy;
bool nvm_release_on_done; bool nvm_release_on_done;
struct mutex asq_mutex; /* Send queue lock */ struct mutex asq_mutex; /* Send queue lock */
...@@ -109,7 +109,7 @@ struct i40e_adminq_info { ...@@ -109,7 +109,7 @@ struct i40e_adminq_info {
* i40e_aq_rc_to_posix - convert errors to user-land codes * i40e_aq_rc_to_posix - convert errors to user-land codes
* aq_rc: AdminQ error code to convert * aq_rc: AdminQ error code to convert
**/ **/
static inline int i40e_aq_rc_to_posix(u16 aq_rc) static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc)
{ {
int aq_to_posix[] = { int aq_to_posix[] = {
0, /* I40E_AQ_RC_OK */ 0, /* I40E_AQ_RC_OK */
...@@ -137,6 +137,12 @@ static inline int i40e_aq_rc_to_posix(u16 aq_rc) ...@@ -137,6 +137,12 @@ static inline int i40e_aq_rc_to_posix(u16 aq_rc)
-EFBIG, /* I40E_AQ_RC_EFBIG */ -EFBIG, /* I40E_AQ_RC_EFBIG */
}; };
/* aq_rc is invalid if AQ timed out */
if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
return -EAGAIN;
if (aq_rc >= ARRAY_SIZE(aq_to_posix))
return -ERANGE;
return aq_to_posix[aq_rc]; return aq_to_posix[aq_rc];
} }
......
...@@ -822,7 +822,7 @@ static int i40e_get_eeprom(struct net_device *netdev, ...@@ -822,7 +822,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_hw *hw = &np->vsi->back->hw; struct i40e_hw *hw = &np->vsi->back->hw;
struct i40e_pf *pf = np->vsi->back; struct i40e_pf *pf = np->vsi->back;
int ret_val = 0, len; int ret_val = 0, len, offset;
u8 *eeprom_buff; u8 *eeprom_buff;
u16 i, sectors; u16 i, sectors;
bool last; bool last;
...@@ -835,19 +835,21 @@ static int i40e_get_eeprom(struct net_device *netdev, ...@@ -835,19 +835,21 @@ static int i40e_get_eeprom(struct net_device *netdev,
/* check for NVMUpdate access method */ /* check for NVMUpdate access method */
magic = hw->vendor_id | (hw->device_id << 16); magic = hw->vendor_id | (hw->device_id << 16);
if (eeprom->magic && eeprom->magic != magic) { if (eeprom->magic && eeprom->magic != magic) {
struct i40e_nvm_access *cmd;
int errno; int errno;
/* make sure it is the right magic for NVMUpdate */ /* make sure it is the right magic for NVMUpdate */
if ((eeprom->magic >> 16) != hw->device_id) if ((eeprom->magic >> 16) != hw->device_id)
return -EINVAL; return -EINVAL;
ret_val = i40e_nvmupd_command(hw, cmd = (struct i40e_nvm_access *)eeprom;
(struct i40e_nvm_access *)eeprom, ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno);
bytes, &errno);
if (ret_val) if (ret_val)
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"NVMUpdate read failed err=%d status=0x%x\n", "NVMUpdate read failed err=%d status=0x%x errno=%d module=%d offset=0x%x size=%d\n",
ret_val, hw->aq.asq_last_status); ret_val, hw->aq.asq_last_status, errno,
(u8)(cmd->config & I40E_NVM_MOD_PNT_MASK),
cmd->offset, cmd->data_size);
return errno; return errno;
} }
...@@ -876,20 +878,29 @@ static int i40e_get_eeprom(struct net_device *netdev, ...@@ -876,20 +878,29 @@ static int i40e_get_eeprom(struct net_device *netdev,
len = eeprom->len - (I40E_NVM_SECTOR_SIZE * i); len = eeprom->len - (I40E_NVM_SECTOR_SIZE * i);
last = true; last = true;
} }
ret_val = i40e_aq_read_nvm(hw, 0x0, offset = eeprom->offset + (I40E_NVM_SECTOR_SIZE * i),
eeprom->offset + (I40E_NVM_SECTOR_SIZE * i), ret_val = i40e_aq_read_nvm(hw, 0x0, offset, len,
len,
(u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i), (u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
last, NULL); last, NULL);
if (ret_val) { if (ret_val && hw->aq.asq_last_status == I40E_AQ_RC_EPERM) {
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"read NVM failed err=%d status=0x%x\n", "read NVM failed, invalid offset 0x%x\n",
ret_val, hw->aq.asq_last_status); offset);
goto release_nvm; break;
} else if (ret_val &&
hw->aq.asq_last_status == I40E_AQ_RC_EACCES) {
dev_info(&pf->pdev->dev,
"read NVM failed, access, offset 0x%x\n",
offset);
break;
} else if (ret_val) {
dev_info(&pf->pdev->dev,
"read NVM failed offset %d err=%d status=0x%x\n",
offset, ret_val, hw->aq.asq_last_status);
break;
} }
} }
release_nvm:
i40e_release_nvm(hw); i40e_release_nvm(hw);
memcpy(bytes, (u8 *)eeprom_buff, eeprom->len); memcpy(bytes, (u8 *)eeprom_buff, eeprom->len);
free_buff: free_buff:
...@@ -917,6 +928,7 @@ static int i40e_set_eeprom(struct net_device *netdev, ...@@ -917,6 +928,7 @@ static int i40e_set_eeprom(struct net_device *netdev,
struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_hw *hw = &np->vsi->back->hw; struct i40e_hw *hw = &np->vsi->back->hw;
struct i40e_pf *pf = np->vsi->back; struct i40e_pf *pf = np->vsi->back;
struct i40e_nvm_access *cmd;
int ret_val = 0; int ret_val = 0;
int errno; int errno;
u32 magic; u32 magic;
...@@ -934,12 +946,14 @@ static int i40e_set_eeprom(struct net_device *netdev, ...@@ -934,12 +946,14 @@ static int i40e_set_eeprom(struct net_device *netdev,
test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state)) test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
return -EBUSY; return -EBUSY;
ret_val = i40e_nvmupd_command(hw, (struct i40e_nvm_access *)eeprom, cmd = (struct i40e_nvm_access *)eeprom;
bytes, &errno); ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno);
if (ret_val) if (ret_val && hw->aq.asq_last_status != I40E_AQ_RC_EBUSY)
dev_info(&pf->pdev->dev, dev_info(&pf->pdev->dev,
"NVMUpdate write failed err=%d status=0x%x\n", "NVMUpdate write failed err=%d status=0x%x errno=%d module=%d offset=0x%x size=%d\n",
ret_val, hw->aq.asq_last_status); ret_val, hw->aq.asq_last_status, errno,
(u8)(cmd->config & I40E_NVM_MOD_PNT_MASK),
cmd->offset, cmd->data_size);
return errno; return errno;
} }
...@@ -1393,6 +1407,9 @@ static int i40e_eeprom_test(struct net_device *netdev, u64 *data) ...@@ -1393,6 +1407,9 @@ static int i40e_eeprom_test(struct net_device *netdev, u64 *data)
netif_info(pf, hw, netdev, "eeprom test\n"); netif_info(pf, hw, netdev, "eeprom test\n");
*data = i40e_diag_eeprom_test(&pf->hw); *data = i40e_diag_eeprom_test(&pf->hw);
/* forcebly clear the NVM Update state machine */
pf->hw.nvmupd_state = I40E_NVMUPD_STATE_INIT;
return *data; return *data;
} }
......
...@@ -61,7 +61,7 @@ i40e_status i40e_init_nvm(struct i40e_hw *hw) ...@@ -61,7 +61,7 @@ i40e_status i40e_init_nvm(struct i40e_hw *hw)
} else { /* Blank programming mode */ } else { /* Blank programming mode */
nvm->blank_nvm_mode = true; nvm->blank_nvm_mode = true;
ret_code = I40E_ERR_NVM_BLANK_MODE; ret_code = I40E_ERR_NVM_BLANK_MODE;
hw_dbg(hw, "NVM init error: unsupported blank mode.\n"); i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n");
} }
return ret_code; return ret_code;
...@@ -80,46 +80,45 @@ i40e_status i40e_acquire_nvm(struct i40e_hw *hw, ...@@ -80,46 +80,45 @@ i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
{ {
i40e_status ret_code = 0; i40e_status ret_code = 0;
u64 gtime, timeout; u64 gtime, timeout;
u64 time = 0; u64 time_left = 0;
if (hw->nvm.blank_nvm_mode) if (hw->nvm.blank_nvm_mode)
goto i40e_i40e_acquire_nvm_exit; goto i40e_i40e_acquire_nvm_exit;
ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
0, &time, NULL); 0, &time_left, NULL);
/* Reading the Global Device Timer */ /* Reading the Global Device Timer */
gtime = rd32(hw, I40E_GLVFGEN_TIMER); gtime = rd32(hw, I40E_GLVFGEN_TIMER);
/* Store the timeout */ /* Store the timeout */
hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime; hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime;
if (ret_code) { if (ret_code)
/* Set the polling timeout */ i40e_debug(hw, I40E_DEBUG_NVM,
if (time > I40E_MAX_NVM_TIMEOUT) "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n",
timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) access, time_left, ret_code, hw->aq.asq_last_status);
+ gtime;
else if (ret_code && time_left) {
timeout = hw->nvm.hw_semaphore_timeout;
/* Poll until the current NVM owner timeouts */ /* Poll until the current NVM owner timeouts */
while (gtime < timeout) { timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime;
while ((gtime < timeout) && time_left) {
usleep_range(10000, 20000); usleep_range(10000, 20000);
gtime = rd32(hw, I40E_GLVFGEN_TIMER);
ret_code = i40e_aq_request_resource(hw, ret_code = i40e_aq_request_resource(hw,
I40E_NVM_RESOURCE_ID, I40E_NVM_RESOURCE_ID,
access, 0, &time, access, 0, &time_left,
NULL); NULL);
if (!ret_code) { if (!ret_code) {
hw->nvm.hw_semaphore_timeout = hw->nvm.hw_semaphore_timeout =
I40E_MS_TO_GTIME(time) + gtime; I40E_MS_TO_GTIME(time_left) + gtime;
break; break;
} }
gtime = rd32(hw, I40E_GLVFGEN_TIMER);
} }
if (ret_code) { if (ret_code) {
hw->nvm.hw_semaphore_timeout = 0; hw->nvm.hw_semaphore_timeout = 0;
hw->nvm.hw_semaphore_wait = i40e_debug(hw, I40E_DEBUG_NVM,
I40E_MS_TO_GTIME(time) + gtime; "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n",
hw_dbg(hw, "NVM acquire timed out, wait %llu ms before trying again.\n", time_left, ret_code, hw->aq.asq_last_status);
time);
} }
} }
...@@ -160,7 +159,7 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) ...@@ -160,7 +159,7 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
udelay(5); udelay(5);
} }
if (ret_code == I40E_ERR_TIMEOUT) if (ret_code == I40E_ERR_TIMEOUT)
hw_dbg(hw, "Done bit in GLNVM_SRCTL not set\n"); i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set");
return ret_code; return ret_code;
} }
...@@ -179,7 +178,9 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, ...@@ -179,7 +178,9 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
u32 sr_reg; u32 sr_reg;
if (offset >= hw->nvm.sr_size) { if (offset >= hw->nvm.sr_size) {
hw_dbg(hw, "NVM read error: Offset beyond Shadow RAM limit.\n"); i40e_debug(hw, I40E_DEBUG_NVM,
"NVM read error: offset %d beyond Shadow RAM limit %d\n",
offset, hw->nvm.sr_size);
ret_code = I40E_ERR_PARAM; ret_code = I40E_ERR_PARAM;
goto read_nvm_exit; goto read_nvm_exit;
} }
...@@ -202,7 +203,8 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, ...@@ -202,7 +203,8 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
} }
} }
if (ret_code) if (ret_code)
hw_dbg(hw, "NVM read error: Couldn't access Shadow RAM address: 0x%x\n", i40e_debug(hw, I40E_DEBUG_NVM,
"NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
offset); offset);
read_nvm_exit: read_nvm_exit:
...@@ -263,14 +265,20 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, ...@@ -263,14 +265,20 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
* Firmware will check the module-based model. * Firmware will check the module-based model.
*/ */
if ((offset + words) > hw->nvm.sr_size) if ((offset + words) > hw->nvm.sr_size)
hw_dbg(hw, "NVM write error: offset beyond Shadow RAM limit.\n"); i40e_debug(hw, I40E_DEBUG_NVM,
"NVM write error: offset %d beyond Shadow RAM limit %d\n",
(offset + words), hw->nvm.sr_size);
else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
/* We can write only up to 4KB (one sector), in one AQ write */ /* We can write only up to 4KB (one sector), in one AQ write */
hw_dbg(hw, "NVM write fail error: cannot write more than 4KB in a single write.\n"); i40e_debug(hw, I40E_DEBUG_NVM,
"NVM write fail error: tried to write %d words, limit is %d.\n",
words, I40E_SR_SECTOR_SIZE_IN_WORDS);
else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
!= (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
/* A single write cannot spread over two sectors */ /* A single write cannot spread over two sectors */
hw_dbg(hw, "NVM write error: cannot spread over two sectors in a single write.\n"); i40e_debug(hw, I40E_DEBUG_NVM,
"NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
offset, words);
else else
ret_code = i40e_aq_update_nvm(hw, module_pointer, ret_code = i40e_aq_update_nvm(hw, module_pointer,
2 * offset, /*bytes*/ 2 * offset, /*bytes*/
...@@ -438,6 +446,22 @@ static inline u8 i40e_nvmupd_get_transaction(u32 val) ...@@ -438,6 +446,22 @@ static inline u8 i40e_nvmupd_get_transaction(u32 val)
return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT); return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
} }
static char *i40e_nvm_update_state_str[] = {
"I40E_NVMUPD_INVALID",
"I40E_NVMUPD_READ_CON",
"I40E_NVMUPD_READ_SNT",
"I40E_NVMUPD_READ_LCB",
"I40E_NVMUPD_READ_SA",
"I40E_NVMUPD_WRITE_ERA",
"I40E_NVMUPD_WRITE_CON",
"I40E_NVMUPD_WRITE_SNT",
"I40E_NVMUPD_WRITE_LCB",
"I40E_NVMUPD_WRITE_SA",
"I40E_NVMUPD_CSUM_CON",
"I40E_NVMUPD_CSUM_SA",
"I40E_NVMUPD_CSUM_LCB",
};
/** /**
* i40e_nvmupd_command - Process an NVM update command * i40e_nvmupd_command - Process an NVM update command
* @hw: pointer to hardware structure * @hw: pointer to hardware structure
...@@ -471,6 +495,8 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, ...@@ -471,6 +495,8 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
default: default:
/* invalid state, should never happen */ /* invalid state, should never happen */
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: no such state %d\n", hw->nvmupd_state);
status = I40E_NOT_SUPPORTED; status = I40E_NOT_SUPPORTED;
*errno = -ESRCH; *errno = -ESRCH;
break; break;
...@@ -501,7 +527,8 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -501,7 +527,8 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_READ_SA: case I40E_NVMUPD_READ_SA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
if (status) { if (status) {
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); *errno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else { } else {
status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
i40e_release_nvm(hw); i40e_release_nvm(hw);
...@@ -511,9 +538,13 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -511,9 +538,13 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_READ_SNT: case I40E_NVMUPD_READ_SNT:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
if (status) { if (status) {
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); *errno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else { } else {
status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
if (status)
i40e_release_nvm(hw);
else
hw->nvmupd_state = I40E_NVMUPD_STATE_READING; hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
} }
break; break;
...@@ -521,7 +552,8 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -521,7 +552,8 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_WRITE_ERA: case I40E_NVMUPD_WRITE_ERA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) { if (status) {
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); *errno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else { } else {
status = i40e_nvmupd_nvm_erase(hw, cmd, errno); status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
if (status) if (status)
...@@ -534,7 +566,8 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -534,7 +566,8 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_WRITE_SA: case I40E_NVMUPD_WRITE_SA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) { if (status) {
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); *errno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else { } else {
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
if (status) if (status)
...@@ -547,9 +580,13 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -547,9 +580,13 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_WRITE_SNT: case I40E_NVMUPD_WRITE_SNT:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) { if (status) {
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); *errno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else { } else {
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
if (status)
i40e_release_nvm(hw);
else
hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
} }
break; break;
...@@ -557,12 +594,14 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -557,12 +594,14 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
case I40E_NVMUPD_CSUM_SA: case I40E_NVMUPD_CSUM_SA:
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
if (status) { if (status) {
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); *errno = i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status);
} else { } else {
status = i40e_update_nvm_checksum(hw); status = i40e_update_nvm_checksum(hw);
if (status) { if (status) {
*errno = hw->aq.asq_last_status ? *errno = hw->aq.asq_last_status ?
i40e_aq_rc_to_posix(hw->aq.asq_last_status) : i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status) :
-EIO; -EIO;
i40e_release_nvm(hw); i40e_release_nvm(hw);
} else { } else {
...@@ -572,6 +611,9 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, ...@@ -572,6 +611,9 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
break; break;
default: default:
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: bad cmd %s in init state\n",
i40e_nvm_update_state_str[upd_cmd]);
status = I40E_ERR_NVM; status = I40E_ERR_NVM;
*errno = -ESRCH; *errno = -ESRCH;
break; break;
...@@ -611,6 +653,9 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, ...@@ -611,6 +653,9 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
break; break;
default: default:
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: bad cmd %s in reading state.\n",
i40e_nvm_update_state_str[upd_cmd]);
status = I40E_NOT_SUPPORTED; status = I40E_NOT_SUPPORTED;
*errno = -ESRCH; *errno = -ESRCH;
break; break;
...@@ -644,33 +689,38 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, ...@@ -644,33 +689,38 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
case I40E_NVMUPD_WRITE_LCB: case I40E_NVMUPD_WRITE_LCB:
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
if (!status) { if (!status)
hw->aq.nvm_release_on_done = true; hw->aq.nvm_release_on_done = true;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
}
break; break;
case I40E_NVMUPD_CSUM_CON: case I40E_NVMUPD_CSUM_CON:
status = i40e_update_nvm_checksum(hw); status = i40e_update_nvm_checksum(hw);
if (status) if (status) {
*errno = hw->aq.asq_last_status ? *errno = hw->aq.asq_last_status ?
i40e_aq_rc_to_posix(hw->aq.asq_last_status) : i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status) :
-EIO; -EIO;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
}
break; break;
case I40E_NVMUPD_CSUM_LCB: case I40E_NVMUPD_CSUM_LCB:
status = i40e_update_nvm_checksum(hw); status = i40e_update_nvm_checksum(hw);
if (status) { if (status)
*errno = hw->aq.asq_last_status ? *errno = hw->aq.asq_last_status ?
i40e_aq_rc_to_posix(hw->aq.asq_last_status) : i40e_aq_rc_to_posix(status,
hw->aq.asq_last_status) :
-EIO; -EIO;
} else { else
hw->aq.nvm_release_on_done = true; hw->aq.nvm_release_on_done = true;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
}
break; break;
default: default:
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: bad cmd %s in writing state.\n",
i40e_nvm_update_state_str[upd_cmd]);
status = I40E_NOT_SUPPORTED; status = I40E_NOT_SUPPORTED;
*errno = -ESRCH; *errno = -ESRCH;
break; break;
...@@ -702,7 +752,8 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, ...@@ -702,7 +752,8 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
/* limits on data size */ /* limits on data size */
if ((cmd->data_size < 1) || if ((cmd->data_size < 1) ||
(cmd->data_size > I40E_NVMUPD_MAX_DATA)) { (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
hw_dbg(hw, "i40e_nvmupd_validate_command data_size %d\n", i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_validate_command data_size %d\n",
cmd->data_size); cmd->data_size);
*errno = -EFAULT; *errno = -EFAULT;
return I40E_NVMUPD_INVALID; return I40E_NVMUPD_INVALID;
...@@ -755,11 +806,15 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, ...@@ -755,11 +806,15 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
} }
break; break;
} }
i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n",
i40e_nvm_update_state_str[upd_cmd],
hw->nvmupd_state,
hw->aq.nvm_release_on_done);
if (upd_cmd == I40E_NVMUPD_INVALID) { if (upd_cmd == I40E_NVMUPD_INVALID) {
*errno = -EFAULT; *errno = -EFAULT;
hw_dbg(hw, i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_validate_command returns %d errno: %d\n", "i40e_nvmupd_validate_command returns %d errno %d\n",
upd_cmd, *errno); upd_cmd, *errno);
} }
return upd_cmd; return upd_cmd;
...@@ -785,14 +840,18 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, ...@@ -785,14 +840,18 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
transaction = i40e_nvmupd_get_transaction(cmd->config); transaction = i40e_nvmupd_get_transaction(cmd->config);
module = i40e_nvmupd_get_module(cmd->config); module = i40e_nvmupd_get_module(cmd->config);
last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA); last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
hw_dbg(hw, "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
module, cmd->offset, cmd->data_size);
status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size, status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
bytes, last, NULL); bytes, last, NULL);
hw_dbg(hw, "i40e_nvmupd_nvm_read status %d\n", status); if (status) {
if (status) i40e_debug(hw, I40E_DEBUG_NVM,
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
module, cmd->offset, cmd->data_size);
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_read status %d aq %d\n",
status, hw->aq.asq_last_status);
*errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
return status; return status;
} }
...@@ -816,13 +875,17 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, ...@@ -816,13 +875,17 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
transaction = i40e_nvmupd_get_transaction(cmd->config); transaction = i40e_nvmupd_get_transaction(cmd->config);
module = i40e_nvmupd_get_module(cmd->config); module = i40e_nvmupd_get_module(cmd->config);
last = (transaction & I40E_NVM_LCB); last = (transaction & I40E_NVM_LCB);
hw_dbg(hw, "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
module, cmd->offset, cmd->data_size);
status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size, status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
last, NULL); last, NULL);
hw_dbg(hw, "i40e_nvmupd_nvm_erase status %d\n", status); if (status) {
if (status) i40e_debug(hw, I40E_DEBUG_NVM,
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
module, cmd->offset, cmd->data_size);
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_erase status %d aq %d\n",
status, hw->aq.asq_last_status);
*errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
return status; return status;
} }
...@@ -847,13 +910,18 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, ...@@ -847,13 +910,18 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
transaction = i40e_nvmupd_get_transaction(cmd->config); transaction = i40e_nvmupd_get_transaction(cmd->config);
module = i40e_nvmupd_get_module(cmd->config); module = i40e_nvmupd_get_module(cmd->config);
last = (transaction & I40E_NVM_LCB); last = (transaction & I40E_NVM_LCB);
hw_dbg(hw, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
module, cmd->offset, cmd->data_size);
status = i40e_aq_update_nvm(hw, module, cmd->offset, status = i40e_aq_update_nvm(hw, module, cmd->offset,
(u16)cmd->data_size, bytes, last, NULL); (u16)cmd->data_size, bytes, last, NULL);
hw_dbg(hw, "i40e_nvmupd_nvm_write status %d\n", status); if (status) {
if (status) i40e_debug(hw, I40E_DEBUG_NVM,
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status); "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
module, cmd->offset, cmd->data_size);
i40e_debug(hw, I40E_DEBUG_NVM,
"i40e_nvmupd_nvm_write status %d aq %d\n",
status, hw->aq.asq_last_status);
*errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
return status; return status;
} }
...@@ -261,8 +261,7 @@ enum i40e_aq_resource_access_type { ...@@ -261,8 +261,7 @@ enum i40e_aq_resource_access_type {
}; };
struct i40e_nvm_info { struct i40e_nvm_info {
u64 hw_semaphore_timeout; /* 2usec global time (GTIME resolution) */ u64 hw_semaphore_timeout; /* usec global time (GTIME resolution) */
u64 hw_semaphore_wait; /* - || - */
u32 timeout; /* [ms] */ u32 timeout; /* [ms] */
u16 sr_size; /* Shadow RAM size in words */ u16 sr_size; /* Shadow RAM size in words */
bool blank_nvm_mode; /* is NVM empty (no FW present)*/ bool blank_nvm_mode; /* is NVM empty (no FW present)*/
...@@ -482,7 +481,10 @@ struct i40e_hw { ...@@ -482,7 +481,10 @@ struct i40e_hw {
u32 debug_mask; u32 debug_mask;
}; };
#define i40e_is_vf(_hw) ((_hw)->mac.type == I40E_MAC_VF) static inline bool i40e_is_vf(struct i40e_hw *hw)
{
return hw->mac.type == I40E_MAC_VF;
}
struct i40e_driver_version { struct i40e_driver_version {
u8 major_version; u8 major_version;
......
...@@ -836,9 +836,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, ...@@ -836,9 +836,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval; hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
} }
if (i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
"AQTX: desc and buffer writeback:\n"); "AQTX: desc and buffer writeback:\n");
i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff,
...@@ -931,9 +928,6 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw, ...@@ -931,9 +928,6 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va, memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
e->msg_len); e->msg_len);
if (i40e_is_nvm_update_op(&e->desc))
hw->aq.nvm_busy = false;
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n"); i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf, i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf,
hw->aq.arq_buf_size); hw->aq.arq_buf_size);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define _I40E_ADMINQ_H_ #define _I40E_ADMINQ_H_
#include "i40e_osdep.h" #include "i40e_osdep.h"
#include "i40e_status.h"
#include "i40e_adminq_cmd.h" #include "i40e_adminq_cmd.h"
#define I40E_ADMINQ_DESC(R, i) \ #define I40E_ADMINQ_DESC(R, i) \
...@@ -94,7 +95,6 @@ struct i40e_adminq_info { ...@@ -94,7 +95,6 @@ struct i40e_adminq_info {
u16 fw_min_ver; /* firmware minor version */ u16 fw_min_ver; /* firmware minor version */
u16 api_maj_ver; /* api major version */ u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */ u16 api_min_ver; /* api minor version */
bool nvm_busy;
bool nvm_release_on_done; bool nvm_release_on_done;
struct mutex asq_mutex; /* Send queue lock */ struct mutex asq_mutex; /* Send queue lock */
...@@ -109,7 +109,7 @@ struct i40e_adminq_info { ...@@ -109,7 +109,7 @@ struct i40e_adminq_info {
* i40e_aq_rc_to_posix - convert errors to user-land codes * i40e_aq_rc_to_posix - convert errors to user-land codes
* aq_rc: AdminQ error code to convert * aq_rc: AdminQ error code to convert
**/ **/
static inline int i40e_aq_rc_to_posix(u16 aq_rc) static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc)
{ {
int aq_to_posix[] = { int aq_to_posix[] = {
0, /* I40E_AQ_RC_OK */ 0, /* I40E_AQ_RC_OK */
...@@ -137,6 +137,12 @@ static inline int i40e_aq_rc_to_posix(u16 aq_rc) ...@@ -137,6 +137,12 @@ static inline int i40e_aq_rc_to_posix(u16 aq_rc)
-EFBIG, /* I40E_AQ_RC_EFBIG */ -EFBIG, /* I40E_AQ_RC_EFBIG */
}; };
/* aq_rc is invalid if AQ timed out */
if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT)
return -EAGAIN;
if (aq_rc >= ARRAY_SIZE(aq_to_posix))
return -ERANGE;
return aq_to_posix[aq_rc]; return aq_to_posix[aq_rc];
} }
......
...@@ -260,8 +260,7 @@ enum i40e_aq_resource_access_type { ...@@ -260,8 +260,7 @@ enum i40e_aq_resource_access_type {
}; };
struct i40e_nvm_info { struct i40e_nvm_info {
u64 hw_semaphore_timeout; /* 2usec global time (GTIME resolution) */ u64 hw_semaphore_timeout; /* usec global time (GTIME resolution) */
u64 hw_semaphore_wait; /* - || - */
u32 timeout; /* [ms] */ u32 timeout; /* [ms] */
u16 sr_size; /* Shadow RAM size in words */ u16 sr_size; /* Shadow RAM size in words */
bool blank_nvm_mode; /* is NVM empty (no FW present)*/ bool blank_nvm_mode; /* is NVM empty (no FW present)*/
...@@ -476,7 +475,10 @@ struct i40e_hw { ...@@ -476,7 +475,10 @@ struct i40e_hw {
u32 debug_mask; u32 debug_mask;
}; };
#define i40e_is_vf(_hw) ((_hw)->mac.type == I40E_MAC_VF) static inline bool i40e_is_vf(struct i40e_hw *hw)
{
return hw->mac.type == I40E_MAC_VF;
}
struct i40e_driver_version { struct i40e_driver_version {
u8 major_version; u8 major_version;
......
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