Skip to content

Commit 81f0749

Browse files
jacob-kellerJeff Kirsher
authored andcommitted
ice: discover and store size of available flash
When reading from the NVM using a flat address, it is useful to know the upper bound on the size of the flash contents. This value is not stored within the NVM. We can determine the size by performing a bisection between upper and lower bounds. It is known that the size cannot exceed 16 MB (offset of 0xFFFFFF). Use a while loop to bisect the upper and lower bounds by reading one byte at a time. On a failed read, lower the maximum bound. On a successful read, increase the lower bound. Save this as the flash_size in the ice_nvm_info structure that contains data related to the NVM. The size will be used in a future patch for implementing full NVM read via ethtool's GEEPROM command. The maximum possible size for the flash is bounded by the size limit for the NVM AdminQ commands. Add a new macro, ICE_AQC_NVM_MAX_OFFSET, which can be used to represent this upper bound. Signed-off-by: Jacob Keller <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent d4e8744 commit 81f0749

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

drivers/net/ethernet/intel/ice/ice_adminq_cmd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,7 @@ struct ice_aqc_sff_eeprom {
12321232
* NVM Update commands (indirect 0x0703)
12331233
*/
12341234
struct ice_aqc_nvm {
1235+
#define ICE_AQC_NVM_MAX_OFFSET 0xFFFFFF
12351236
__le16 offset_low;
12361237
u8 offset_high;
12371238
u8 cmd_flags;
@@ -1766,6 +1767,7 @@ enum ice_aq_err {
17661767
ICE_AQ_RC_ENOMEM = 9, /* Out of memory */
17671768
ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */
17681769
ICE_AQ_RC_EEXIST = 13, /* Object already exists */
1770+
ICE_AQ_RC_EINVAL = 14, /* Invalid argument */
17691771
ICE_AQ_RC_ENOSPC = 16, /* No space left or allocation failure */
17701772
ICE_AQ_RC_ENOSYS = 17, /* Function not implemented */
17711773
ICE_AQ_RC_ENOSEC = 24, /* Missing security manifest */

drivers/net/ethernet/intel/ice/ice_nvm.c

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length,
2626

2727
cmd = &desc.params.nvm;
2828

29-
/* In offset the highest byte must be zeroed. */
30-
if (offset & 0xFF000000)
29+
if (offset > ICE_AQC_NVM_MAX_OFFSET)
3130
return ICE_ERR_PARAM;
3231

3332
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read);
@@ -363,6 +362,58 @@ static enum ice_status ice_get_orom_ver_info(struct ice_hw *hw)
363362
return 0;
364363
}
365364

365+
/**
366+
* ice_discover_flash_size - Discover the available flash size.
367+
* @hw: pointer to the HW struct
368+
*
369+
* The device flash could be up to 16MB in size. However, it is possible that
370+
* the actual size is smaller. Use bisection to determine the accessible size
371+
* of flash memory.
372+
*/
373+
static enum ice_status ice_discover_flash_size(struct ice_hw *hw)
374+
{
375+
u32 min_size = 0, max_size = ICE_AQC_NVM_MAX_OFFSET + 1;
376+
enum ice_status status;
377+
378+
status = ice_acquire_nvm(hw, ICE_RES_READ);
379+
if (status)
380+
return status;
381+
382+
while ((max_size - min_size) > 1) {
383+
u32 offset = (max_size + min_size) / 2;
384+
u32 len = 1;
385+
u8 data;
386+
387+
status = ice_read_flat_nvm(hw, offset, &len, &data, false);
388+
if (status == ICE_ERR_AQ_ERROR &&
389+
hw->adminq.sq_last_status == ICE_AQ_RC_EINVAL) {
390+
ice_debug(hw, ICE_DBG_NVM,
391+
"%s: New upper bound of %u bytes\n",
392+
__func__, offset);
393+
status = 0;
394+
max_size = offset;
395+
} else if (!status) {
396+
ice_debug(hw, ICE_DBG_NVM,
397+
"%s: New lower bound of %u bytes\n",
398+
__func__, offset);
399+
min_size = offset;
400+
} else {
401+
/* an unexpected error occurred */
402+
goto err_read_flat_nvm;
403+
}
404+
}
405+
406+
ice_debug(hw, ICE_DBG_NVM,
407+
"Predicted flash size is %u bytes\n", max_size);
408+
409+
hw->nvm.flash_size = max_size;
410+
411+
err_read_flat_nvm:
412+
ice_release_nvm(hw);
413+
414+
return status;
415+
}
416+
366417
/**
367418
* ice_init_nvm - initializes NVM setting
368419
* @hw: pointer to the HW struct
@@ -421,6 +472,13 @@ enum ice_status ice_init_nvm(struct ice_hw *hw)
421472

422473
nvm->eetrack = (eetrack_hi << 16) | eetrack_lo;
423474

475+
status = ice_discover_flash_size(hw);
476+
if (status) {
477+
ice_debug(hw, ICE_DBG_NVM,
478+
"NVM init error: failed to discover flash size.\n");
479+
return status;
480+
}
481+
424482
switch (hw->device_id) {
425483
/* the following devices do not have boot_cfg_tlv yet */
426484
case ICE_DEV_ID_E823C_BACKPLANE:

drivers/net/ethernet/intel/ice/ice_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ struct ice_nvm_info {
251251
struct ice_orom_info orom; /* Option ROM version info */
252252
u32 eetrack; /* NVM data version */
253253
u16 sr_words; /* Shadow RAM size in words */
254+
u32 flash_size; /* Size of available flash in bytes */
254255
u8 major_ver; /* major version of NVM package */
255256
u8 minor_ver; /* minor version of dev starter */
256257
u8 blank_nvm_mode; /* is NVM empty (no FW present) */

0 commit comments

Comments
 (0)