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

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 <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
81f07491 d4e87444

+63 -2
+2
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 1232 1232 * NVM Update commands (indirect 0x0703) 1233 1233 */ 1234 1234 struct ice_aqc_nvm { 1235 + #define ICE_AQC_NVM_MAX_OFFSET 0xFFFFFF 1235 1236 __le16 offset_low; 1236 1237 u8 offset_high; 1237 1238 u8 cmd_flags; ··· 1767 1766 ICE_AQ_RC_ENOMEM = 9, /* Out of memory */ 1768 1767 ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */ 1769 1768 ICE_AQ_RC_EEXIST = 13, /* Object already exists */ 1769 + ICE_AQ_RC_EINVAL = 14, /* Invalid argument */ 1770 1770 ICE_AQ_RC_ENOSPC = 16, /* No space left or allocation failure */ 1771 1771 ICE_AQ_RC_ENOSYS = 17, /* Function not implemented */ 1772 1772 ICE_AQ_RC_ENOSEC = 24, /* Missing security manifest */
+60 -2
drivers/net/ethernet/intel/ice/ice_nvm.c
··· 26 26 27 27 cmd = &desc.params.nvm; 28 28 29 - /* In offset the highest byte must be zeroed. */ 30 - if (offset & 0xFF000000) 29 + if (offset > ICE_AQC_NVM_MAX_OFFSET) 31 30 return ICE_ERR_PARAM; 32 31 33 32 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read); ··· 363 364 } 364 365 365 366 /** 367 + * ice_discover_flash_size - Discover the available flash size. 368 + * @hw: pointer to the HW struct 369 + * 370 + * The device flash could be up to 16MB in size. However, it is possible that 371 + * the actual size is smaller. Use bisection to determine the accessible size 372 + * of flash memory. 373 + */ 374 + static enum ice_status ice_discover_flash_size(struct ice_hw *hw) 375 + { 376 + u32 min_size = 0, max_size = ICE_AQC_NVM_MAX_OFFSET + 1; 377 + enum ice_status status; 378 + 379 + status = ice_acquire_nvm(hw, ICE_RES_READ); 380 + if (status) 381 + return status; 382 + 383 + while ((max_size - min_size) > 1) { 384 + u32 offset = (max_size + min_size) / 2; 385 + u32 len = 1; 386 + u8 data; 387 + 388 + status = ice_read_flat_nvm(hw, offset, &len, &data, false); 389 + if (status == ICE_ERR_AQ_ERROR && 390 + hw->adminq.sq_last_status == ICE_AQ_RC_EINVAL) { 391 + ice_debug(hw, ICE_DBG_NVM, 392 + "%s: New upper bound of %u bytes\n", 393 + __func__, offset); 394 + status = 0; 395 + max_size = offset; 396 + } else if (!status) { 397 + ice_debug(hw, ICE_DBG_NVM, 398 + "%s: New lower bound of %u bytes\n", 399 + __func__, offset); 400 + min_size = offset; 401 + } else { 402 + /* an unexpected error occurred */ 403 + goto err_read_flat_nvm; 404 + } 405 + } 406 + 407 + ice_debug(hw, ICE_DBG_NVM, 408 + "Predicted flash size is %u bytes\n", max_size); 409 + 410 + hw->nvm.flash_size = max_size; 411 + 412 + err_read_flat_nvm: 413 + ice_release_nvm(hw); 414 + 415 + return status; 416 + } 417 + 418 + /** 366 419 * ice_init_nvm - initializes NVM setting 367 420 * @hw: pointer to the HW struct 368 421 * ··· 471 420 } 472 421 473 422 nvm->eetrack = (eetrack_hi << 16) | eetrack_lo; 423 + 424 + status = ice_discover_flash_size(hw); 425 + if (status) { 426 + ice_debug(hw, ICE_DBG_NVM, 427 + "NVM init error: failed to discover flash size.\n"); 428 + return status; 429 + } 474 430 475 431 switch (hw->device_id) { 476 432 /* the following devices do not have boot_cfg_tlv yet */
+1
drivers/net/ethernet/intel/ice/ice_type.h
··· 251 251 struct ice_orom_info orom; /* Option ROM version info */ 252 252 u32 eetrack; /* NVM data version */ 253 253 u16 sr_words; /* Shadow RAM size in words */ 254 + u32 flash_size; /* Size of available flash in bytes */ 254 255 u8 major_ver; /* major version of NVM package */ 255 256 u8 minor_ver; /* minor version of dev starter */ 256 257 u8 blank_nvm_mode; /* is NVM empty (no FW present) */