aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel
diff options
context:
space:
mode:
authorShannon Nelson <shannon.nelson@intel.com>2014-07-09 03:46:09 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-07-24 06:32:40 -0400
commitcd552cb49e9ad5fd8748fb6b38a8bd38e9e4d86c (patch)
treef83278a853151b9370e542d5092df9c2862982b8 /drivers/net/ethernet/intel
parentefe1ac25d084fd56c5b809634a0444606c2a5cd3 (diff)
i40e/i40evf: Add nvmupdate support
This implements a state machine intended to support the userland tool for updating the device eeprom. The state machine implements one-shot reads, writes, multi-step write sessions, and checksum requests. If we're in the middle of a multi-step write session, no one should fire off other writes, however, one shot reads are valid. The userland tool is expected to keep track of its session status, arrange the placement and ordering of the writes, and deal with the checksum requirement. This patch also adds nvmupdate support to ethtool callbacks. The get_eeprom() and set_eeprom() services in ethtool are used here to facilitate the userland NVMUpdate tool. The 'magic' value in the get and set commands is used to pass additional control information for managing the read and write steps. The read operation works both as normally expected in the standard ethtool method, as well as with the extra NVM controls. The write operation works only for the expanded NVM functions - the normal ethtool method is not allowed because of the NVM semaphore management needed for multipart writes, as well as the checksum requirement. Change-ID: I1d84a170153a9f437906744e2e350fd68fe7563d Signed-off-by: Shannon Nelson <shannon.nelson@intel.com> Tested-by: Jim Young <jamesx.m.young@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.c21
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.h36
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c88
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c61
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c511
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_prototype.h7
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_type.h58
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.c6
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.h36
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_type.h58
10 files changed, 866 insertions, 16 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 0e551f281d59..1e21fbb1359c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -38,8 +38,8 @@ static void i40e_resume_aq(struct i40e_hw *hw);
38 **/ 38 **/
39static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc) 39static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
40{ 40{
41 return (desc->opcode == i40e_aqc_opc_nvm_erase) || 41 return (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_erase)) ||
42 (desc->opcode == i40e_aqc_opc_nvm_update); 42 (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_update));
43} 43}
44 44
45/** 45/**
@@ -889,9 +889,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
889 hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval; 889 hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
890 } 890 }
891 891
892 if (i40e_is_nvm_update_op(desc))
893 hw->aq.nvm_busy = true;
894
895 if (le16_to_cpu(desc->datalen) == buff_size) { 892 if (le16_to_cpu(desc->datalen) == buff_size) {
896 i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, 893 i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
897 "AQTX: desc and buffer writeback:\n"); 894 "AQTX: desc and buffer writeback:\n");
@@ -907,6 +904,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
907 status = I40E_ERR_ADMIN_QUEUE_TIMEOUT; 904 status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
908 } 905 }
909 906
907 if (!status && i40e_is_nvm_update_op(desc))
908 hw->aq.nvm_busy = true;
909
910asq_send_command_error: 910asq_send_command_error:
911 mutex_unlock(&hw->aq.asq_mutex); 911 mutex_unlock(&hw->aq.asq_mutex);
912asq_send_command_exit: 912asq_send_command_exit:
@@ -988,9 +988,6 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
988 e->msg_size); 988 e->msg_size);
989 } 989 }
990 990
991 if (i40e_is_nvm_update_op(&e->desc))
992 hw->aq.nvm_busy = false;
993
994 i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n"); 991 i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
995 i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf); 992 i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf);
996 993
@@ -1023,6 +1020,14 @@ clean_arq_element_out:
1023 *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc); 1020 *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
1024 mutex_unlock(&hw->aq.arq_mutex); 1021 mutex_unlock(&hw->aq.arq_mutex);
1025 1022
1023 if (i40e_is_nvm_update_op(&e->desc)) {
1024 hw->aq.nvm_busy = false;
1025 if (hw->aq.nvm_release_on_done) {
1026 i40e_release_nvm(hw);
1027 hw->aq.nvm_release_on_done = false;
1028 }
1029 }
1030
1026 return ret_code; 1031 return ret_code;
1027} 1032}
1028 1033
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
index bb76be1d38f7..ba38a89c79d6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
@@ -94,6 +94,7 @@ struct i40e_adminq_info {
94 u16 api_maj_ver; /* api major version */ 94 u16 api_maj_ver; /* api major version */
95 u16 api_min_ver; /* api minor version */ 95 u16 api_min_ver; /* api minor version */
96 bool nvm_busy; 96 bool nvm_busy;
97 bool nvm_release_on_done;
97 98
98 struct mutex asq_mutex; /* Send queue lock */ 99 struct mutex asq_mutex; /* Send queue lock */
99 struct mutex arq_mutex; /* Receive queue lock */ 100 struct mutex arq_mutex; /* Receive queue lock */
@@ -103,6 +104,41 @@ struct i40e_adminq_info {
103 enum i40e_admin_queue_err arq_last_status; 104 enum i40e_admin_queue_err arq_last_status;
104}; 105};
105 106
107/**
108 * i40e_aq_rc_to_posix - convert errors to user-land codes
109 * aq_rc: AdminQ error code to convert
110 **/
111static inline int i40e_aq_rc_to_posix(u16 aq_rc)
112{
113 int aq_to_posix[] = {
114 0, /* I40E_AQ_RC_OK */
115 -EPERM, /* I40E_AQ_RC_EPERM */
116 -ENOENT, /* I40E_AQ_RC_ENOENT */
117 -ESRCH, /* I40E_AQ_RC_ESRCH */
118 -EINTR, /* I40E_AQ_RC_EINTR */
119 -EIO, /* I40E_AQ_RC_EIO */
120 -ENXIO, /* I40E_AQ_RC_ENXIO */
121 -E2BIG, /* I40E_AQ_RC_E2BIG */
122 -EAGAIN, /* I40E_AQ_RC_EAGAIN */
123 -ENOMEM, /* I40E_AQ_RC_ENOMEM */
124 -EACCES, /* I40E_AQ_RC_EACCES */
125 -EFAULT, /* I40E_AQ_RC_EFAULT */
126 -EBUSY, /* I40E_AQ_RC_EBUSY */
127 -EEXIST, /* I40E_AQ_RC_EEXIST */
128 -EINVAL, /* I40E_AQ_RC_EINVAL */
129 -ENOTTY, /* I40E_AQ_RC_ENOTTY */
130 -ENOSPC, /* I40E_AQ_RC_ENOSPC */
131 -ENOSYS, /* I40E_AQ_RC_ENOSYS */
132 -ERANGE, /* I40E_AQ_RC_ERANGE */
133 -EPIPE, /* I40E_AQ_RC_EFLUSHED */
134 -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
135 -EROFS, /* I40E_AQ_RC_EMODE */
136 -EFBIG, /* I40E_AQ_RC_EFBIG */
137 };
138
139 return aq_to_posix[aq_rc];
140}
141
106/* general information */ 142/* general information */
107#define I40E_AQ_LARGE_BUF 512 143#define I40E_AQ_LARGE_BUF 512
108#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */ 144#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index c65f4e8e6cee..f4e502a305ff 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -2121,6 +2121,47 @@ i40e_aq_read_nvm_exit:
2121 return status; 2121 return status;
2122} 2122}
2123 2123
2124/**
2125 * i40e_aq_erase_nvm
2126 * @hw: pointer to the hw struct
2127 * @module_pointer: module pointer location in words from the NVM beginning
2128 * @offset: offset in the module (expressed in 4 KB from module's beginning)
2129 * @length: length of the section to be erased (expressed in 4 KB)
2130 * @last_command: tells if this is the last command in a series
2131 * @cmd_details: pointer to command details structure or NULL
2132 *
2133 * Erase the NVM sector using the admin queue commands
2134 **/
2135i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
2136 u32 offset, u16 length, bool last_command,
2137 struct i40e_asq_cmd_details *cmd_details)
2138{
2139 struct i40e_aq_desc desc;
2140 struct i40e_aqc_nvm_update *cmd =
2141 (struct i40e_aqc_nvm_update *)&desc.params.raw;
2142 i40e_status status;
2143
2144 /* In offset the highest byte must be zeroed. */
2145 if (offset & 0xFF000000) {
2146 status = I40E_ERR_PARAM;
2147 goto i40e_aq_erase_nvm_exit;
2148 }
2149
2150 i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_erase);
2151
2152 /* If this is the last command in a series, set the proper flag. */
2153 if (last_command)
2154 cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
2155 cmd->module_pointer = module_pointer;
2156 cmd->offset = cpu_to_le32(offset);
2157 cmd->length = cpu_to_le16(length);
2158
2159 status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
2160
2161i40e_aq_erase_nvm_exit:
2162 return status;
2163}
2164
2124#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01 2165#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01
2125#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02 2166#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02
2126#define I40E_DEV_FUNC_CAP_NPAR 0x03 2167#define I40E_DEV_FUNC_CAP_NPAR 0x03
@@ -2351,6 +2392,53 @@ exit:
2351} 2392}
2352 2393
2353/** 2394/**
2395 * i40e_aq_update_nvm
2396 * @hw: pointer to the hw struct
2397 * @module_pointer: module pointer location in words from the NVM beginning
2398 * @offset: byte offset from the module beginning
2399 * @length: length of the section to be written (in bytes from the offset)
2400 * @data: command buffer (size [bytes] = length)
2401 * @last_command: tells if this is the last command in a series
2402 * @cmd_details: pointer to command details structure or NULL
2403 *
2404 * Update the NVM using the admin queue commands
2405 **/
2406i40e_status i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
2407 u32 offset, u16 length, void *data,
2408 bool last_command,
2409 struct i40e_asq_cmd_details *cmd_details)
2410{
2411 struct i40e_aq_desc desc;
2412 struct i40e_aqc_nvm_update *cmd =
2413 (struct i40e_aqc_nvm_update *)&desc.params.raw;
2414 i40e_status status;
2415
2416 /* In offset the highest byte must be zeroed. */
2417 if (offset & 0xFF000000) {
2418 status = I40E_ERR_PARAM;
2419 goto i40e_aq_update_nvm_exit;
2420 }
2421
2422 i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update);
2423
2424 /* If this is the last command in a series, set the proper flag. */
2425 if (last_command)
2426 cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
2427 cmd->module_pointer = module_pointer;
2428 cmd->offset = cpu_to_le32(offset);
2429 cmd->length = cpu_to_le16(length);
2430
2431 desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
2432 if (length > I40E_AQ_LARGE_BUF)
2433 desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
2434
2435 status = i40e_asq_send_command(hw, &desc, data, length, cmd_details);
2436
2437i40e_aq_update_nvm_exit:
2438 return status;
2439}
2440
2441/**
2354 * i40e_aq_get_lldp_mib 2442 * i40e_aq_get_lldp_mib
2355 * @hw: pointer to the hw struct 2443 * @hw: pointer to the hw struct
2356 * @bridge_type: type of bridge requested 2444 * @bridge_type: type of bridge requested
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 3abd3cbab75f..f1d241ec1fc3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -759,10 +759,33 @@ static int i40e_get_eeprom(struct net_device *netdev,
759 u8 *eeprom_buff; 759 u8 *eeprom_buff;
760 u16 i, sectors; 760 u16 i, sectors;
761 bool last; 761 bool last;
762 u32 magic;
763
762#define I40E_NVM_SECTOR_SIZE 4096 764#define I40E_NVM_SECTOR_SIZE 4096
763 if (eeprom->len == 0) 765 if (eeprom->len == 0)
764 return -EINVAL; 766 return -EINVAL;
765 767
768 /* check for NVMUpdate access method */
769 magic = hw->vendor_id | (hw->device_id << 16);
770 if (eeprom->magic && eeprom->magic != magic) {
771 int errno;
772
773 /* make sure it is the right magic for NVMUpdate */
774 if ((eeprom->magic >> 16) != hw->device_id)
775 return -EINVAL;
776
777 ret_val = i40e_nvmupd_command(hw,
778 (struct i40e_nvm_access *)eeprom,
779 bytes, &errno);
780 if (ret_val)
781 dev_info(&pf->pdev->dev,
782 "NVMUpdate read failed err=%d status=0x%x\n",
783 ret_val, hw->aq.asq_last_status);
784
785 return errno;
786 }
787
788 /* normal ethtool get_eeprom support */
766 eeprom->magic = hw->vendor_id | (hw->device_id << 16); 789 eeprom->magic = hw->vendor_id | (hw->device_id << 16);
767 790
768 eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL); 791 eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL);
@@ -789,7 +812,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
789 ret_val = i40e_aq_read_nvm(hw, 0x0, 812 ret_val = i40e_aq_read_nvm(hw, 0x0,
790 eeprom->offset + (I40E_NVM_SECTOR_SIZE * i), 813 eeprom->offset + (I40E_NVM_SECTOR_SIZE * i),
791 len, 814 len,
792 eeprom_buff + (I40E_NVM_SECTOR_SIZE * i), 815 (u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
793 last, NULL); 816 last, NULL);
794 if (ret_val) { 817 if (ret_val) {
795 dev_info(&pf->pdev->dev, 818 dev_info(&pf->pdev->dev,
@@ -801,7 +824,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
801 824
802release_nvm: 825release_nvm:
803 i40e_release_nvm(hw); 826 i40e_release_nvm(hw);
804 memcpy(bytes, eeprom_buff, eeprom->len); 827 memcpy(bytes, (u8 *)eeprom_buff, eeprom->len);
805free_buff: 828free_buff:
806 kfree(eeprom_buff); 829 kfree(eeprom_buff);
807 return ret_val; 830 return ret_val;
@@ -821,6 +844,39 @@ static int i40e_get_eeprom_len(struct net_device *netdev)
821 return val; 844 return val;
822} 845}
823 846
847static int i40e_set_eeprom(struct net_device *netdev,
848 struct ethtool_eeprom *eeprom, u8 *bytes)
849{
850 struct i40e_netdev_priv *np = netdev_priv(netdev);
851 struct i40e_hw *hw = &np->vsi->back->hw;
852 struct i40e_pf *pf = np->vsi->back;
853 int ret_val = 0;
854 int errno;
855 u32 magic;
856
857 /* normal ethtool set_eeprom is not supported */
858 magic = hw->vendor_id | (hw->device_id << 16);
859 if (eeprom->magic == magic)
860 return -EOPNOTSUPP;
861
862 /* check for NVMUpdate access method */
863 if (!eeprom->magic || (eeprom->magic >> 16) != hw->device_id)
864 return -EINVAL;
865
866 if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
867 test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
868 return -EBUSY;
869
870 ret_val = i40e_nvmupd_command(hw, (struct i40e_nvm_access *)eeprom,
871 bytes, &errno);
872 if (ret_val)
873 dev_info(&pf->pdev->dev,
874 "NVMUpdate write failed err=%d status=0x%x\n",
875 ret_val, hw->aq.asq_last_status);
876
877 return errno;
878}
879
824static void i40e_get_drvinfo(struct net_device *netdev, 880static void i40e_get_drvinfo(struct net_device *netdev,
825 struct ethtool_drvinfo *drvinfo) 881 struct ethtool_drvinfo *drvinfo)
826{ 882{
@@ -2094,6 +2150,7 @@ static const struct ethtool_ops i40e_ethtool_ops = {
2094 .get_link = ethtool_op_get_link, 2150 .get_link = ethtool_op_get_link,
2095 .get_wol = i40e_get_wol, 2151 .get_wol = i40e_get_wol,
2096 .set_wol = i40e_set_wol, 2152 .set_wol = i40e_set_wol,
2153 .set_eeprom = i40e_set_eeprom,
2097 .get_eeprom_len = i40e_get_eeprom_len, 2154 .get_eeprom_len = i40e_get_eeprom_len,
2098 .get_eeprom = i40e_get_eeprom, 2155 .get_eeprom = i40e_get_eeprom,
2099 .get_ringparam = i40e_get_ringparam, 2156 .get_ringparam = i40e_get_ringparam,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 66bcb15422da..97bda3dffd49 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -241,6 +241,46 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
241} 241}
242 242
243/** 243/**
244 * i40e_write_nvm_aq - Writes Shadow RAM.
245 * @hw: pointer to the HW structure.
246 * @module_pointer: module pointer location in words from the NVM beginning
247 * @offset: offset in words from module start
248 * @words: number of words to write
249 * @data: buffer with words to write to the Shadow RAM
250 * @last_command: tells the AdminQ that this is the last command
251 *
252 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
253 **/
254i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
255 u32 offset, u16 words, void *data,
256 bool last_command)
257{
258 i40e_status ret_code = I40E_ERR_NVM;
259
260 /* Here we are checking the SR limit only for the flat memory model.
261 * We cannot do it for the module-based model, as we did not acquire
262 * the NVM resource yet (we cannot get the module pointer value).
263 * Firmware will check the module-based model.
264 */
265 if ((offset + words) > hw->nvm.sr_size)
266 hw_dbg(hw, "NVM write error: offset beyond Shadow RAM limit.\n");
267 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
268 /* We can write only up to 4KB (one sector), in one AQ write */
269 hw_dbg(hw, "NVM write fail error: cannot write more than 4KB in a single write.\n");
270 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
271 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
272 /* A single write cannot spread over two sectors */
273 hw_dbg(hw, "NVM write error: cannot spread over two sectors in a single write.\n");
274 else
275 ret_code = i40e_aq_update_nvm(hw, module_pointer,
276 2 * offset, /*bytes*/
277 2 * words, /*bytes*/
278 data, last_command, NULL);
279
280 return ret_code;
281}
282
283/**
244 * i40e_calc_nvm_checksum - Calculates and returns the checksum 284 * i40e_calc_nvm_checksum - Calculates and returns the checksum
245 * @hw: pointer to hardware structure 285 * @hw: pointer to hardware structure
246 * @checksum: pointer to the checksum 286 * @checksum: pointer to the checksum
@@ -310,6 +350,27 @@ i40e_calc_nvm_checksum_exit:
310} 350}
311 351
312/** 352/**
353 * i40e_update_nvm_checksum - Updates the NVM checksum
354 * @hw: pointer to hardware structure
355 *
356 * NVM ownership must be acquired before calling this function and released
357 * on ARQ completion event reception by caller.
358 * This function will commit SR to NVM.
359 **/
360i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
361{
362 i40e_status ret_code = 0;
363 u16 checksum;
364
365 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
366 if (!ret_code)
367 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
368 1, &checksum, true);
369
370 return ret_code;
371}
372
373/**
313 * i40e_validate_nvm_checksum - Validate EEPROM checksum 374 * i40e_validate_nvm_checksum - Validate EEPROM checksum
314 * @hw: pointer to hardware structure 375 * @hw: pointer to hardware structure
315 * @checksum: calculated checksum 376 * @checksum: calculated checksum
@@ -346,3 +407,453 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
346i40e_validate_nvm_checksum_exit: 407i40e_validate_nvm_checksum_exit:
347 return ret_code; 408 return ret_code;
348} 409}
410
411static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
412 struct i40e_nvm_access *cmd,
413 u8 *bytes, int *errno);
414static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
415 struct i40e_nvm_access *cmd,
416 u8 *bytes, int *errno);
417static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
418 struct i40e_nvm_access *cmd,
419 u8 *bytes, int *errno);
420static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
421 struct i40e_nvm_access *cmd,
422 int *errno);
423static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
424 struct i40e_nvm_access *cmd,
425 int *errno);
426static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
427 struct i40e_nvm_access *cmd,
428 u8 *bytes, int *errno);
429static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
430 struct i40e_nvm_access *cmd,
431 u8 *bytes, int *errno);
432static inline u8 i40e_nvmupd_get_module(u32 val)
433{
434 return (u8)(val & I40E_NVM_MOD_PNT_MASK);
435}
436static inline u8 i40e_nvmupd_get_transaction(u32 val)
437{
438 return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
439}
440
441/**
442 * i40e_nvmupd_command - Process an NVM update command
443 * @hw: pointer to hardware structure
444 * @cmd: pointer to nvm update command
445 * @bytes: pointer to the data buffer
446 * @errno: pointer to return error code
447 *
448 * Dispatches command depending on what update state is current
449 **/
450i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
451 struct i40e_nvm_access *cmd,
452 u8 *bytes, int *errno)
453{
454 i40e_status status;
455
456 /* assume success */
457 *errno = 0;
458
459 switch (hw->nvmupd_state) {
460 case I40E_NVMUPD_STATE_INIT:
461 status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
462 break;
463
464 case I40E_NVMUPD_STATE_READING:
465 status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
466 break;
467
468 case I40E_NVMUPD_STATE_WRITING:
469 status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
470 break;
471
472 default:
473 /* invalid state, should never happen */
474 status = I40E_NOT_SUPPORTED;
475 *errno = -ESRCH;
476 break;
477 }
478 return status;
479}
480
481/**
482 * i40e_nvmupd_state_init - Handle NVM update state Init
483 * @hw: pointer to hardware structure
484 * @cmd: pointer to nvm update command buffer
485 * @bytes: pointer to the data buffer
486 * @errno: pointer to return error code
487 *
488 * Process legitimate commands of the Init state and conditionally set next
489 * state. Reject all other commands.
490 **/
491static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
492 struct i40e_nvm_access *cmd,
493 u8 *bytes, int *errno)
494{
495 i40e_status status = 0;
496 enum i40e_nvmupd_cmd upd_cmd;
497
498 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
499
500 switch (upd_cmd) {
501 case I40E_NVMUPD_READ_SA:
502 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
503 if (status) {
504 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
505 } else {
506 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
507 i40e_release_nvm(hw);
508 }
509 break;
510
511 case I40E_NVMUPD_READ_SNT:
512 status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
513 if (status) {
514 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
515 } else {
516 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
517 hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
518 }
519 break;
520
521 case I40E_NVMUPD_WRITE_ERA:
522 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
523 if (status) {
524 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
525 } else {
526 status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
527 if (status)
528 i40e_release_nvm(hw);
529 else
530 hw->aq.nvm_release_on_done = true;
531 }
532 break;
533
534 case I40E_NVMUPD_WRITE_SA:
535 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
536 if (status) {
537 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
538 } else {
539 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
540 if (status)
541 i40e_release_nvm(hw);
542 else
543 hw->aq.nvm_release_on_done = true;
544 }
545 break;
546
547 case I40E_NVMUPD_WRITE_SNT:
548 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
549 if (status) {
550 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
551 } else {
552 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
553 hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
554 }
555 break;
556
557 case I40E_NVMUPD_CSUM_SA:
558 status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
559 if (status) {
560 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
561 } else {
562 status = i40e_update_nvm_checksum(hw);
563 if (status) {
564 *errno = hw->aq.asq_last_status ?
565 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
566 -EIO;
567 i40e_release_nvm(hw);
568 } else {
569 hw->aq.nvm_release_on_done = true;
570 }
571 }
572 break;
573
574 default:
575 status = I40E_ERR_NVM;
576 *errno = -ESRCH;
577 break;
578 }
579 return status;
580}
581
582/**
583 * i40e_nvmupd_state_reading - Handle NVM update state Reading
584 * @hw: pointer to hardware structure
585 * @cmd: pointer to nvm update command buffer
586 * @bytes: pointer to the data buffer
587 * @errno: pointer to return error code
588 *
589 * NVM ownership is already held. Process legitimate commands and set any
590 * change in state; reject all other commands.
591 **/
592static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
593 struct i40e_nvm_access *cmd,
594 u8 *bytes, int *errno)
595{
596 i40e_status status;
597 enum i40e_nvmupd_cmd upd_cmd;
598
599 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
600
601 switch (upd_cmd) {
602 case I40E_NVMUPD_READ_SA:
603 case I40E_NVMUPD_READ_CON:
604 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
605 break;
606
607 case I40E_NVMUPD_READ_LCB:
608 status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
609 i40e_release_nvm(hw);
610 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
611 break;
612
613 default:
614 status = I40E_NOT_SUPPORTED;
615 *errno = -ESRCH;
616 break;
617 }
618 return status;
619}
620
621/**
622 * i40e_nvmupd_state_writing - Handle NVM update state Writing
623 * @hw: pointer to hardware structure
624 * @cmd: pointer to nvm update command buffer
625 * @bytes: pointer to the data buffer
626 * @errno: pointer to return error code
627 *
628 * NVM ownership is already held. Process legitimate commands and set any
629 * change in state; reject all other commands
630 **/
631static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
632 struct i40e_nvm_access *cmd,
633 u8 *bytes, int *errno)
634{
635 i40e_status status;
636 enum i40e_nvmupd_cmd upd_cmd;
637
638 upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
639
640 switch (upd_cmd) {
641 case I40E_NVMUPD_WRITE_CON:
642 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
643 break;
644
645 case I40E_NVMUPD_WRITE_LCB:
646 status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
647 if (!status) {
648 hw->aq.nvm_release_on_done = true;
649 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
650 }
651 break;
652
653 case I40E_NVMUPD_CSUM_CON:
654 status = i40e_update_nvm_checksum(hw);
655 if (status)
656 *errno = hw->aq.asq_last_status ?
657 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
658 -EIO;
659 break;
660
661 case I40E_NVMUPD_CSUM_LCB:
662 status = i40e_update_nvm_checksum(hw);
663 if (status) {
664 *errno = hw->aq.asq_last_status ?
665 i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
666 -EIO;
667 } else {
668 hw->aq.nvm_release_on_done = true;
669 hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
670 }
671 break;
672
673 default:
674 status = I40E_NOT_SUPPORTED;
675 *errno = -ESRCH;
676 break;
677 }
678 return status;
679}
680
681/**
682 * i40e_nvmupd_validate_command - Validate given command
683 * @hw: pointer to hardware structure
684 * @cmd: pointer to nvm update command buffer
685 * @errno: pointer to return error code
686 *
687 * Return one of the valid command types or I40E_NVMUPD_INVALID
688 **/
689static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
690 struct i40e_nvm_access *cmd,
691 int *errno)
692{
693 enum i40e_nvmupd_cmd upd_cmd;
694 u8 transaction, module;
695
696 /* anything that doesn't match a recognized case is an error */
697 upd_cmd = I40E_NVMUPD_INVALID;
698
699 transaction = i40e_nvmupd_get_transaction(cmd->config);
700 module = i40e_nvmupd_get_module(cmd->config);
701
702 /* limits on data size */
703 if ((cmd->data_size < 1) ||
704 (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
705 hw_dbg(hw, "i40e_nvmupd_validate_command data_size %d\n",
706 cmd->data_size);
707 *errno = -EFAULT;
708 return I40E_NVMUPD_INVALID;
709 }
710
711 switch (cmd->command) {
712 case I40E_NVM_READ:
713 switch (transaction) {
714 case I40E_NVM_CON:
715 upd_cmd = I40E_NVMUPD_READ_CON;
716 break;
717 case I40E_NVM_SNT:
718 upd_cmd = I40E_NVMUPD_READ_SNT;
719 break;
720 case I40E_NVM_LCB:
721 upd_cmd = I40E_NVMUPD_READ_LCB;
722 break;
723 case I40E_NVM_SA:
724 upd_cmd = I40E_NVMUPD_READ_SA;
725 break;
726 }
727 break;
728
729 case I40E_NVM_WRITE:
730 switch (transaction) {
731 case I40E_NVM_CON:
732 upd_cmd = I40E_NVMUPD_WRITE_CON;
733 break;
734 case I40E_NVM_SNT:
735 upd_cmd = I40E_NVMUPD_WRITE_SNT;
736 break;
737 case I40E_NVM_LCB:
738 upd_cmd = I40E_NVMUPD_WRITE_LCB;
739 break;
740 case I40E_NVM_SA:
741 upd_cmd = I40E_NVMUPD_WRITE_SA;
742 break;
743 case I40E_NVM_ERA:
744 upd_cmd = I40E_NVMUPD_WRITE_ERA;
745 break;
746 case I40E_NVM_CSUM:
747 upd_cmd = I40E_NVMUPD_CSUM_CON;
748 break;
749 case (I40E_NVM_CSUM|I40E_NVM_SA):
750 upd_cmd = I40E_NVMUPD_CSUM_SA;
751 break;
752 case (I40E_NVM_CSUM|I40E_NVM_LCB):
753 upd_cmd = I40E_NVMUPD_CSUM_LCB;
754 break;
755 }
756 break;
757 }
758
759 if (upd_cmd == I40E_NVMUPD_INVALID) {
760 *errno = -EFAULT;
761 hw_dbg(hw,
762 "i40e_nvmupd_validate_command returns %d errno: %d\n",
763 upd_cmd, *errno);
764 }
765 return upd_cmd;
766}
767
768/**
769 * i40e_nvmupd_nvm_read - Read NVM
770 * @hw: pointer to hardware structure
771 * @cmd: pointer to nvm update command buffer
772 * @bytes: pointer to the data buffer
773 * @errno: pointer to return error code
774 *
775 * cmd structure contains identifiers and data buffer
776 **/
777static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
778 struct i40e_nvm_access *cmd,
779 u8 *bytes, int *errno)
780{
781 i40e_status status;
782 u8 module, transaction;
783 bool last;
784
785 transaction = i40e_nvmupd_get_transaction(cmd->config);
786 module = i40e_nvmupd_get_module(cmd->config);
787 last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
788 hw_dbg(hw, "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
789 module, cmd->offset, cmd->data_size);
790
791 status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
792 bytes, last, NULL);
793 hw_dbg(hw, "i40e_nvmupd_nvm_read status %d\n", status);
794 if (status)
795 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
796
797 return status;
798}
799
800/**
801 * i40e_nvmupd_nvm_erase - Erase an NVM module
802 * @hw: pointer to hardware structure
803 * @cmd: pointer to nvm update command buffer
804 * @errno: pointer to return error code
805 *
806 * module, offset, data_size and data are in cmd structure
807 **/
808static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
809 struct i40e_nvm_access *cmd,
810 int *errno)
811{
812 i40e_status status = 0;
813 u8 module, transaction;
814 bool last;
815
816 transaction = i40e_nvmupd_get_transaction(cmd->config);
817 module = i40e_nvmupd_get_module(cmd->config);
818 last = (transaction & I40E_NVM_LCB);
819 hw_dbg(hw, "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
820 module, cmd->offset, cmd->data_size);
821 status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
822 last, NULL);
823 hw_dbg(hw, "i40e_nvmupd_nvm_erase status %d\n", status);
824 if (status)
825 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
826
827 return status;
828}
829
830/**
831 * i40e_nvmupd_nvm_write - Write NVM
832 * @hw: pointer to hardware structure
833 * @cmd: pointer to nvm update command buffer
834 * @bytes: pointer to the data buffer
835 * @errno: pointer to return error code
836 *
837 * module, offset, data_size and data are in cmd structure
838 **/
839static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
840 struct i40e_nvm_access *cmd,
841 u8 *bytes, int *errno)
842{
843 i40e_status status = 0;
844 u8 module, transaction;
845 bool last;
846
847 transaction = i40e_nvmupd_get_transaction(cmd->config);
848 module = i40e_nvmupd_get_module(cmd->config);
849 last = (transaction & I40E_NVM_LCB);
850 hw_dbg(hw, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
851 module, cmd->offset, cmd->data_size);
852 status = i40e_aq_update_nvm(hw, module, cmd->offset,
853 (u16)cmd->data_size, bytes, last, NULL);
854 hw_dbg(hw, "i40e_nvmupd_nvm_write status %d\n", status);
855 if (status)
856 *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
857
858 return status;
859}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index 9383f08ff4e3..a91d7e1a5b5b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -150,6 +150,9 @@ i40e_status i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer,
150 u32 offset, u16 length, void *data, 150 u32 offset, u16 length, void *data,
151 bool last_command, 151 bool last_command,
152 struct i40e_asq_cmd_details *cmd_details); 152 struct i40e_asq_cmd_details *cmd_details);
153i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
154 u32 offset, u16 length, bool last_command,
155 struct i40e_asq_cmd_details *cmd_details);
153i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw, 156i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
154 void *buff, u16 buff_size, u16 *data_size, 157 void *buff, u16 buff_size, u16 *data_size,
155 enum i40e_admin_queue_opc list_type_opc, 158 enum i40e_admin_queue_opc list_type_opc,
@@ -245,8 +248,12 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
245 u16 *data); 248 u16 *data);
246i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, 249i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
247 u16 *words, u16 *data); 250 u16 *words, u16 *data);
251i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
248i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, 252i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
249 u16 *checksum); 253 u16 *checksum);
254i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
255 struct i40e_nvm_access *cmd,
256 u8 *bytes, int *);
250void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status); 257void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
251 258
252extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[]; 259extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index 1fcf2205ffe6..8bb9049191cb 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -269,6 +269,61 @@ struct i40e_nvm_info {
269 u32 eetrack; /* NVM data version */ 269 u32 eetrack; /* NVM data version */
270}; 270};
271 271
272/* definitions used in NVM update support */
273
274enum i40e_nvmupd_cmd {
275 I40E_NVMUPD_INVALID,
276 I40E_NVMUPD_READ_CON,
277 I40E_NVMUPD_READ_SNT,
278 I40E_NVMUPD_READ_LCB,
279 I40E_NVMUPD_READ_SA,
280 I40E_NVMUPD_WRITE_ERA,
281 I40E_NVMUPD_WRITE_CON,
282 I40E_NVMUPD_WRITE_SNT,
283 I40E_NVMUPD_WRITE_LCB,
284 I40E_NVMUPD_WRITE_SA,
285 I40E_NVMUPD_CSUM_CON,
286 I40E_NVMUPD_CSUM_SA,
287 I40E_NVMUPD_CSUM_LCB,
288};
289
290enum i40e_nvmupd_state {
291 I40E_NVMUPD_STATE_INIT,
292 I40E_NVMUPD_STATE_READING,
293 I40E_NVMUPD_STATE_WRITING
294};
295
296/* nvm_access definition and its masks/shifts need to be accessible to
297 * application, core driver, and shared code. Where is the right file?
298 */
299#define I40E_NVM_READ 0xB
300#define I40E_NVM_WRITE 0xC
301
302#define I40E_NVM_MOD_PNT_MASK 0xFF
303
304#define I40E_NVM_TRANS_SHIFT 8
305#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
306#define I40E_NVM_CON 0x0
307#define I40E_NVM_SNT 0x1
308#define I40E_NVM_LCB 0x2
309#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
310#define I40E_NVM_ERA 0x4
311#define I40E_NVM_CSUM 0x8
312
313#define I40E_NVM_ADAPT_SHIFT 16
314#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
315
316#define I40E_NVMUPD_MAX_DATA 4096
317#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
318
319struct i40e_nvm_access {
320 u32 command;
321 u32 config;
322 u32 offset; /* in bytes */
323 u32 data_size; /* in bytes */
324 u8 data[1];
325};
326
272/* PCI bus types */ 327/* PCI bus types */
273enum i40e_bus_type { 328enum i40e_bus_type {
274 i40e_bus_type_unknown = 0, 329 i40e_bus_type_unknown = 0,
@@ -404,6 +459,9 @@ struct i40e_hw {
404 /* Admin Queue info */ 459 /* Admin Queue info */
405 struct i40e_adminq_info aq; 460 struct i40e_adminq_info aq;
406 461
462 /* state of nvm update process */
463 enum i40e_nvmupd_state nvmupd_state;
464
407 /* HMC info */ 465 /* HMC info */
408 struct i40e_hmc_info hmc; /* HMC info struct */ 466 struct i40e_hmc_info hmc; /* HMC info struct */
409 467
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
index 8330744b02f1..ee3a934043bb 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
@@ -708,12 +708,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
708 goto asq_send_command_exit; 708 goto asq_send_command_exit;
709 } 709 }
710 710
711 if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
712 i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
713 status = I40E_ERR_NVM;
714 goto asq_send_command_exit;
715 }
716
717 details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); 711 details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
718 if (cmd_details) { 712 if (cmd_details) {
719 *details = *cmd_details; 713 *details = *cmd_details;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
index 162845589bf7..91a5c5bd80f3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
@@ -94,6 +94,7 @@ struct i40e_adminq_info {
94 u16 api_maj_ver; /* api major version */ 94 u16 api_maj_ver; /* api major version */
95 u16 api_min_ver; /* api minor version */ 95 u16 api_min_ver; /* api minor version */
96 bool nvm_busy; 96 bool nvm_busy;
97 bool nvm_release_on_done;
97 98
98 struct mutex asq_mutex; /* Send queue lock */ 99 struct mutex asq_mutex; /* Send queue lock */
99 struct mutex arq_mutex; /* Receive queue lock */ 100 struct mutex arq_mutex; /* Receive queue lock */
@@ -103,6 +104,41 @@ struct i40e_adminq_info {
103 enum i40e_admin_queue_err arq_last_status; 104 enum i40e_admin_queue_err arq_last_status;
104}; 105};
105 106
107/**
108 * i40e_aq_rc_to_posix - convert errors to user-land codes
109 * aq_rc: AdminQ error code to convert
110 **/
111static inline int i40e_aq_rc_to_posix(u16 aq_rc)
112{
113 int aq_to_posix[] = {
114 0, /* I40E_AQ_RC_OK */
115 -EPERM, /* I40E_AQ_RC_EPERM */
116 -ENOENT, /* I40E_AQ_RC_ENOENT */
117 -ESRCH, /* I40E_AQ_RC_ESRCH */
118 -EINTR, /* I40E_AQ_RC_EINTR */
119 -EIO, /* I40E_AQ_RC_EIO */
120 -ENXIO, /* I40E_AQ_RC_ENXIO */
121 -E2BIG, /* I40E_AQ_RC_E2BIG */
122 -EAGAIN, /* I40E_AQ_RC_EAGAIN */
123 -ENOMEM, /* I40E_AQ_RC_ENOMEM */
124 -EACCES, /* I40E_AQ_RC_EACCES */
125 -EFAULT, /* I40E_AQ_RC_EFAULT */
126 -EBUSY, /* I40E_AQ_RC_EBUSY */
127 -EEXIST, /* I40E_AQ_RC_EEXIST */
128 -EINVAL, /* I40E_AQ_RC_EINVAL */
129 -ENOTTY, /* I40E_AQ_RC_ENOTTY */
130 -ENOSPC, /* I40E_AQ_RC_ENOSPC */
131 -ENOSYS, /* I40E_AQ_RC_ENOSYS */
132 -ERANGE, /* I40E_AQ_RC_ERANGE */
133 -EPIPE, /* I40E_AQ_RC_EFLUSHED */
134 -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
135 -EROFS, /* I40E_AQ_RC_EMODE */
136 -EFBIG, /* I40E_AQ_RC_EFBIG */
137 };
138
139 return aq_to_posix[aq_rc];
140}
141
106/* general information */ 142/* general information */
107#define I40E_AQ_LARGE_BUF 512 143#define I40E_AQ_LARGE_BUF 512
108#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */ 144#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 6dd72ad58e7d..15376436cead 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -268,6 +268,61 @@ struct i40e_nvm_info {
268 u32 eetrack; /* NVM data version */ 268 u32 eetrack; /* NVM data version */
269}; 269};
270 270
271/* definitions used in NVM update support */
272
273enum i40e_nvmupd_cmd {
274 I40E_NVMUPD_INVALID,
275 I40E_NVMUPD_READ_CON,
276 I40E_NVMUPD_READ_SNT,
277 I40E_NVMUPD_READ_LCB,
278 I40E_NVMUPD_READ_SA,
279 I40E_NVMUPD_WRITE_ERA,
280 I40E_NVMUPD_WRITE_CON,
281 I40E_NVMUPD_WRITE_SNT,
282 I40E_NVMUPD_WRITE_LCB,
283 I40E_NVMUPD_WRITE_SA,
284 I40E_NVMUPD_CSUM_CON,
285 I40E_NVMUPD_CSUM_SA,
286 I40E_NVMUPD_CSUM_LCB,
287};
288
289enum i40e_nvmupd_state {
290 I40E_NVMUPD_STATE_INIT,
291 I40E_NVMUPD_STATE_READING,
292 I40E_NVMUPD_STATE_WRITING
293};
294
295/* nvm_access definition and its masks/shifts need to be accessible to
296 * application, core driver, and shared code. Where is the right file?
297 */
298#define I40E_NVM_READ 0xB
299#define I40E_NVM_WRITE 0xC
300
301#define I40E_NVM_MOD_PNT_MASK 0xFF
302
303#define I40E_NVM_TRANS_SHIFT 8
304#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
305#define I40E_NVM_CON 0x0
306#define I40E_NVM_SNT 0x1
307#define I40E_NVM_LCB 0x2
308#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
309#define I40E_NVM_ERA 0x4
310#define I40E_NVM_CSUM 0x8
311
312#define I40E_NVM_ADAPT_SHIFT 16
313#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
314
315#define I40E_NVMUPD_MAX_DATA 4096
316#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
317
318struct i40e_nvm_access {
319 u32 command;
320 u32 config;
321 u32 offset; /* in bytes */
322 u32 data_size; /* in bytes */
323 u8 data[1];
324};
325
271/* PCI bus types */ 326/* PCI bus types */
272enum i40e_bus_type { 327enum i40e_bus_type {
273 i40e_bus_type_unknown = 0, 328 i40e_bus_type_unknown = 0,
@@ -403,6 +458,9 @@ struct i40e_hw {
403 /* Admin Queue info */ 458 /* Admin Queue info */
404 struct i40e_adminq_info aq; 459 struct i40e_adminq_info aq;
405 460
461 /* state of nvm update process */
462 enum i40e_nvmupd_state nvmupd_state;
463
406 /* HMC info */ 464 /* HMC info */
407 struct i40e_hmc_info hmc; /* HMC info struct */ 465 struct i40e_hmc_info hmc; /* HMC info struct */
408 466