Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ice: create function to read a section of the NVM and Shadow RAM

The NVM contents are read via firmware by using the ice_aq_read_nvm
function. This function has a couple of limits:

1) The AdminQ commands can only take buffers sized up to 4Kb. Thus, any
larger read must be split into multiple reads.
2) when reading from the Shadow RAM, reads must not cross sector
boundaries. The sectors are also 4Kb in size.

Implement the ice_read_flat_nvm function to read portions of the NVM by
flat offset. That is, to read using offsets from the start of the NVM
rather than from a specific module.

This function will be able to read both from the NVM and from the Shadow
RAM. For simplicity NVM reads will always be broken up to not cross 4Kb
page boundaries, even though this is not required unless reading from
the Shadow RAM.

Use this new function as the implementation of ice_read_sr_word_aq.

The ice_read_sr_buf_aq function is not modified here. This is because
a following change will remove the only caller of that function in favor
of directly using ice_read_flat_nvm. Thus, there is little benefit to
changing it now only to remove it momentarily. At the same time, the
ice_read_sr_aq function will also be removed.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Jacob Keller and committed by
Jeff Kirsher
e9450990 2efefb56

+85 -7
+2
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 1250 1250 __le32 addr_low; 1251 1251 }; 1252 1252 1253 + #define ICE_AQC_NVM_START_POINT 0 1254 + 1253 1255 /* NVM Checksum Command (direct, 0x0706) */ 1254 1256 struct ice_aqc_nvm_checksum { 1255 1257 u8 flags;
+80 -7
drivers/net/ethernet/intel/ice/ice_nvm.c
··· 11 11 * @length: length of the section to be read (in bytes from the offset) 12 12 * @data: command buffer (size [bytes] = length) 13 13 * @last_command: tells if this is the last command in a series 14 + * @read_shadow_ram: tell if this is a shadow RAM read 14 15 * @cd: pointer to command details structure or NULL 15 16 * 16 17 * Read the NVM using the admin queue commands (0x0701) 17 18 */ 18 19 static enum ice_status 19 20 ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length, 20 - void *data, bool last_command, struct ice_sq_cd *cd) 21 + void *data, bool last_command, bool read_shadow_ram, 22 + struct ice_sq_cd *cd) 21 23 { 22 24 struct ice_aq_desc desc; 23 25 struct ice_aqc_nvm *cmd; ··· 32 30 33 31 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read); 34 32 33 + if (!read_shadow_ram && module_typeid == ICE_AQC_NVM_START_POINT) 34 + cmd->cmd_flags |= ICE_AQC_NVM_FLASH_ONLY; 35 + 35 36 /* If this is the last command in a series, set the proper flag. */ 36 37 if (last_command) 37 38 cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD; ··· 44 39 cmd->length = cpu_to_le16(length); 45 40 46 41 return ice_aq_send_cmd(hw, &desc, data, length, cd); 42 + } 43 + 44 + /** 45 + * ice_read_flat_nvm - Read portion of NVM by flat offset 46 + * @hw: pointer to the HW struct 47 + * @offset: offset from beginning of NVM 48 + * @length: (in) number of bytes to read; (out) number of bytes actually read 49 + * @data: buffer to return data in (sized to fit the specified length) 50 + * @read_shadow_ram: if true, read from shadow RAM instead of NVM 51 + * 52 + * Reads a portion of the NVM, as a flat memory space. This function correctly 53 + * breaks read requests across Shadow RAM sectors and ensures that no single 54 + * read request exceeds the maximum 4Kb read for a single AdminQ command. 55 + * 56 + * Returns a status code on failure. Note that the data pointer may be 57 + * partially updated if some reads succeed before a failure. 58 + */ 59 + enum ice_status 60 + ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, 61 + bool read_shadow_ram) 62 + { 63 + enum ice_status status; 64 + u32 inlen = *length; 65 + u32 bytes_read = 0; 66 + bool last_cmd; 67 + 68 + *length = 0; 69 + 70 + /* Verify the length of the read if this is for the Shadow RAM */ 71 + if (read_shadow_ram && ((offset + inlen) > (hw->nvm.sr_words * 2u))) { 72 + ice_debug(hw, ICE_DBG_NVM, 73 + "NVM error: requested offset is beyond Shadow RAM limit\n"); 74 + return ICE_ERR_PARAM; 75 + } 76 + 77 + do { 78 + u32 read_size, sector_offset; 79 + 80 + /* ice_aq_read_nvm cannot read more than 4Kb at a time. 81 + * Additionally, a read from the Shadow RAM may not cross over 82 + * a sector boundary. Conveniently, the sector size is also 83 + * 4Kb. 84 + */ 85 + sector_offset = offset % ICE_AQ_MAX_BUF_LEN; 86 + read_size = min_t(u32, ICE_AQ_MAX_BUF_LEN - sector_offset, 87 + inlen - bytes_read); 88 + 89 + last_cmd = !(bytes_read + read_size < inlen); 90 + 91 + status = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, 92 + offset, read_size, 93 + data + bytes_read, last_cmd, 94 + read_shadow_ram, NULL); 95 + if (status) 96 + break; 97 + 98 + bytes_read += read_size; 99 + offset += read_size; 100 + } while (!last_cmd); 101 + 102 + *length = bytes_read; 103 + return status; 47 104 } 48 105 49 106 /** ··· 167 100 */ 168 101 if (!status) 169 102 status = ice_aq_read_nvm(hw, 0, 2 * offset, 2 * words, data, 170 - last_command, NULL); 103 + last_command, true, NULL); 171 104 172 105 return status; 173 106 } ··· 178 111 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) 179 112 * @data: word read from the Shadow RAM 180 113 * 181 - * Reads one 16 bit word from the Shadow RAM using the ice_read_sr_aq method. 114 + * Reads one 16 bit word from the Shadow RAM using ice_read_flat_nvm. 182 115 */ 183 116 static enum ice_status 184 117 ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) 185 118 { 119 + u32 bytes = sizeof(u16); 186 120 enum ice_status status; 187 121 __le16 data_local; 188 122 189 - status = ice_read_sr_aq(hw, offset, 1, &data_local, true); 190 - if (!status) 191 - *data = le16_to_cpu(data_local); 123 + /* Note that ice_read_flat_nvm takes into account the 4Kb AdminQ and 124 + * Shadow RAM sector restrictions necessary when reading from the NVM. 125 + */ 126 + status = ice_read_flat_nvm(hw, offset * sizeof(u16), &bytes, 127 + (u8 *)&data_local, true); 128 + if (status) 129 + return status; 192 130 193 - return status; 131 + *data = le16_to_cpu(data_local); 132 + return 0; 194 133 } 195 134 196 135 /**
+3
drivers/net/ethernet/intel/ice/ice_nvm.h
··· 4 4 #ifndef _ICE_NVM_H_ 5 5 #define _ICE_NVM_H_ 6 6 7 + enum ice_status 8 + ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, 9 + bool read_shadow_ram); 7 10 enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data); 8 11 #endif /* _ICE_NVM_H_ */