From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 346E7A0567 for ; Wed, 10 Mar 2021 10:18:39 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 154CB40687; Wed, 10 Mar 2021 10:18:39 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 7F49F40687 for ; Wed, 10 Mar 2021 10:18:37 +0100 (CET) IronPort-SDR: C4TRSSIu69K1v3u0OhhEggjElFeVAMK841LxXtMrKid85bD0fhSjL7Fw+4MU+6nrmKhIPcmD3F 69hyT+8wTNhw== X-IronPort-AV: E=McAfee;i="6000,8403,9917"; a="176021672" X-IronPort-AV: E=Sophos;i="5.81,237,1610438400"; d="scan'208";a="176021672" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Mar 2021 01:18:35 -0800 IronPort-SDR: 2xLMJww5Oj1CyQKJVLEctFGFGBsKAR1uNAa2zrmQpWv6S6uQg2iKLf+DReUrWum63Chh/5vPKe aODp4pqqbIaw== X-IronPort-AV: E=Sophos;i="5.81,237,1610438400"; d="scan'208";a="410115255" Received: from unknown (HELO intel-npg-odc-srv02.cd.intel.com) ([10.240.178.186]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Mar 2021 01:18:32 -0800 From: Murphy Yang To: stable@dpdk.org Cc: Murphy Yang , Jacob Keller , Paul M Stillwell Jr , Qi Zhang Date: Wed, 10 Mar 2021 09:11:38 +0000 Message-Id: <20210310091138.86061-1-murphyx.yang@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [dpdk-stable] [PATCH 19.11] net/ice/base: xtract logic of flat NVM read to function X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" [ upstream commit 2516684aed7a4ea93391caefe8e2cdc486955a83 ] The ice_read_sr_buf_aq function implements logic to correctly break apart NVM reads into 4Kb chunks. Additionally, it ensures that each read never crosses a Shadow RAM sector boundary. This logic is useful when reading the flat NVM as a byte-addressable stream. Extract that logic in terms of bytes and implement it as ice_read_flat_nvm. Use this new function to implement ice_read_sr_buf_aq function. Signed-off-by: Jacob Keller Signed-off-by: Paul M Stillwell Jr Signed-off-by: Qi Zhang --- drivers/net/ice/base/ice_nvm.c | 114 ++++++++++++++++++++++----------- drivers/net/ice/base/ice_nvm.h | 3 + 2 files changed, 81 insertions(+), 36 deletions(-) diff --git a/drivers/net/ice/base/ice_nvm.c b/drivers/net/ice/base/ice_nvm.c index 434258b14c..86194ca4f1 100644 --- a/drivers/net/ice/base/ice_nvm.c +++ b/drivers/net/ice/base/ice_nvm.c @@ -49,6 +49,74 @@ ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length, return ice_aq_send_cmd(hw, &desc, data, length, cd); } +/** + * ice_read_flat_nvm - Read portion of NVM by flat offset + * @hw: pointer to the HW struct + * @offset: offset from beginning of NVM + * @length: (in) number of bytes to read; (out) number of bytes actually read + * @data: buffer to return data in (sized to fit the specified length) + * @read_shadow_ram: if true, read from shadow RAM instead of NVM + * + * Reads a portion of the NVM, as a flat memory space. This function correctly + * breaks read requests across Shadow RAM sectors and ensures that no single + * read request exceeds the maximum 4Kb read for a single AdminQ command. + * + * Returns a status code on failure. Note that the data pointer may be + * partially updated if some reads succeed before a failure. + */ +enum ice_status +ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, + bool read_shadow_ram) +{ + enum ice_status status; + u32 inlen = *length; + u32 bytes_read = 0; + bool last_cmd; + + ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); + + *length = 0; + + /* Verify the length of the read if this is for the Shadow RAM */ + if (read_shadow_ram && ((offset + inlen) > (hw->nvm.sr_words * 2u))) { + ice_debug(hw, ICE_DBG_NVM, + "NVM error: requested data is beyond Shadow RAM limit\n"); + return ICE_ERR_PARAM; + } + + do { + u32 read_size, sector_offset; + + /* ice_aq_read_nvm cannot read more than 4Kb at a time. + * Additionally, a read from the Shadow RAM may not cross over + * a sector boundary. Conveniently, the sector size is also + * 4Kb. + */ + sector_offset = offset % ICE_AQ_MAX_BUF_LEN; + read_size = MIN_T(u32, ICE_AQ_MAX_BUF_LEN - sector_offset, + inlen - bytes_read); + + last_cmd = !(bytes_read + read_size < inlen); + + /* ice_aq_read_nvm takes the length as a u16. Our read_size is + * calculated using a u32, but the ICE_AQ_MAX_BUF_LEN maximum + * size guarantees that it will fit within the 2 bytes. + */ + status = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT, + offset, (u16)read_size, + data + bytes_read, last_cmd, + read_shadow_ram, NULL); + if (status) + break; + + bytes_read += read_size; + offset += read_size; + } while (!last_cmd); + + *length = bytes_read; + return status; +} + /** * ice_check_sr_access_params - verify params for Shadow RAM R/W operations. * @hw: pointer to the HW structure @@ -144,55 +212,29 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) * @words: (in) number of words to read; (out) number of words actually read * @data: words read from the Shadow RAM * - * Reads 16 bit words (data buf) from the SR using the ice_read_sr_aq - * method. Ownership of the NVM is taken before reading the buffer and later - * released. + * Reads 16 bit words (data buf) from the Shadow RAM. Ownership of the NVM is + * taken before reading the buffer and later released. */ static enum ice_status ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) { + u32 bytes = *words * 2, i; enum ice_status status; - bool last_cmd = false; - u16 words_read = 0; - u16 i = 0; ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__); - do { - u16 read_size, off_w; - - /* Calculate number of bytes we should read in this step. - * It's not allowed to read more than one page at a time or - * to cross page boundaries. - */ - off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS; - read_size = off_w ? - MIN_T(u16, *words, - (ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) : - MIN_T(u16, (*words - words_read), - ICE_SR_SECTOR_SIZE_IN_WORDS); - - /* Check if this is last command, if so set proper flag */ - if ((words_read + read_size) >= *words) - last_cmd = true; - - status = ice_read_sr_aq(hw, offset, read_size, - data + words_read, last_cmd); - if (status) - goto read_nvm_buf_aq_exit; + /* ice_read_flat_nvm takes into account the 4Kb AdminQ and Shadow RAM + * sector restrictions necessary when reading from the NVM. + */ + status = ice_read_flat_nvm(hw, offset * 2, &bytes, (u8 *)data, true); - /* Increment counter for words already read and move offset to - * new read location - */ - words_read += read_size; - offset += read_size; - } while (words_read < *words); + /* Report the number of words successfully read */ + *words = bytes / 2; + /* Byte swap the words up to the amount we actually read */ for (i = 0; i < *words; i++) data[i] = LE16_TO_CPU(((_FORCE_ __le16 *)data)[i]); -read_nvm_buf_aq_exit: - *words = words_read; return status; } diff --git a/drivers/net/ice/base/ice_nvm.h b/drivers/net/ice/base/ice_nvm.h index 8624d19b19..592ae03c33 100644 --- a/drivers/net/ice/base/ice_nvm.h +++ b/drivers/net/ice/base/ice_nvm.h @@ -84,6 +84,9 @@ ice_nvm_access_get_features(struct ice_nvm_access_cmd *cmd, enum ice_status ice_handle_nvm_access(struct ice_hw *hw, struct ice_nvm_access_cmd *cmd, union ice_nvm_access_data *data); +enum ice_status +ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, + bool read_shadow_ram); enum ice_status ice_init_nvm(struct ice_hw *hw); enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data); enum ice_status -- 2.17.1