get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/94331/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 94331,
    "url": "https://patches.dpdk.org/api/patches/94331/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20210617110005.4132926-7-jiawenwu@trustnetic.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20210617110005.4132926-7-jiawenwu@trustnetic.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20210617110005.4132926-7-jiawenwu@trustnetic.com",
    "date": "2021-06-17T10:59:52",
    "name": "[v6,06/19] net/ngbe: init and validate EEPROM",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "fac06fb05a9d7528d51f306fb938fa3c1d72b9d2",
    "submitter": {
        "id": 1932,
        "url": "https://patches.dpdk.org/api/people/1932/?format=api",
        "name": "Jiawen Wu",
        "email": "jiawenwu@trustnetic.com"
    },
    "delegate": {
        "id": 3961,
        "url": "https://patches.dpdk.org/api/users/3961/?format=api",
        "username": "arybchenko",
        "first_name": "Andrew",
        "last_name": "Rybchenko",
        "email": "andrew.rybchenko@oktetlabs.ru"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20210617110005.4132926-7-jiawenwu@trustnetic.com/mbox/",
    "series": [
        {
            "id": 17372,
            "url": "https://patches.dpdk.org/api/series/17372/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=17372",
            "date": "2021-06-17T10:59:46",
            "name": "net: ngbe PMD",
            "version": 6,
            "mbox": "https://patches.dpdk.org/series/17372/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/94331/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/94331/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id ED08EA0C4D;\n\tThu, 17 Jun 2021 12:58:54 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 4F6D441121;\n\tThu, 17 Jun 2021 12:58:22 +0200 (CEST)",
            "from smtpbg506.qq.com (smtpbg506.qq.com [203.205.250.33])\n by mails.dpdk.org (Postfix) with ESMTP id B0651410FC\n for <dev@dpdk.org>; Thu, 17 Jun 2021 12:58:19 +0200 (CEST)",
            "from wxdbg.localdomain.com (unknown [183.129.236.74])\n by esmtp6.qq.com (ESMTP) with\n id ; Thu, 17 Jun 2021 18:58:14 +0800 (CST)"
        ],
        "X-QQ-mid": "bizesmtp46t1623927495tpdjpa6h",
        "X-QQ-SSF": "01400000000000D0E000B00A0000000",
        "X-QQ-FEAT": "ChTsRoALjQDaJpQ4lAf0tM2Y8EguggKeq/vHfipXaceItB0qLXxCL7B01rvuK\n tYAbxvtWXyGAzfT0gpF1fvbydbq555kBiqyrTH5fjOcT0gC8pgftzAljpXU/Z/tAYJC/02M\n zXyYoOsF3AXozV3uzktX7MHX+LtTpPA09BpCZPRf7QQz3a79daosgZweNl4DBJAM5gtAD0H\n e44CGAp/fOp16z3VsIB4Tkr3YW9Z0xa0rg8+snWs7IX8BCYTQ1n/D7JleERqo2/ihzntzjL\n V/UmKyRC4f2bKnDyBnQ442NFttB9CZ0bwPcfSBxJ28KQmdXGtHTYSwl2pcb6NvX2gC4SYnb\n U4Tgl041uzCWs1Yan/lOyt+yFheTlbTAG/ZDcBW",
        "X-QQ-GoodBg": "2",
        "From": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "To": "dev@dpdk.org",
        "Cc": "Jiawen Wu <jiawenwu@trustnetic.com>",
        "Date": "Thu, 17 Jun 2021 18:59:52 +0800",
        "Message-Id": "<20210617110005.4132926-7-jiawenwu@trustnetic.com>",
        "X-Mailer": "git-send-email 2.27.0",
        "In-Reply-To": "<20210617110005.4132926-1-jiawenwu@trustnetic.com>",
        "References": "<20210617110005.4132926-1-jiawenwu@trustnetic.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-QQ-SENDSIZE": "520",
        "Feedback-ID": "bizesmtp:trustnetic.com:qybgforeign:qybgforeign5",
        "X-QQ-Bgrelay": "1",
        "Subject": "[dpdk-dev] [PATCH v6 06/19] net/ngbe: init and validate EEPROM",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Reset swfw lock before NVM access, init EEPROM and validate the\nchecksum.\n\nSigned-off-by: Jiawen Wu <jiawenwu@trustnetic.com>\n---\n drivers/net/ngbe/base/meson.build   |   2 +\n drivers/net/ngbe/base/ngbe_dummy.h  |  23 ++++\n drivers/net/ngbe/base/ngbe_eeprom.c | 203 ++++++++++++++++++++++++++++\n drivers/net/ngbe/base/ngbe_eeprom.h |  17 +++\n drivers/net/ngbe/base/ngbe_hw.c     |  83 ++++++++++++\n drivers/net/ngbe/base/ngbe_hw.h     |   3 +\n drivers/net/ngbe/base/ngbe_mng.c    | 198 +++++++++++++++++++++++++++\n drivers/net/ngbe/base/ngbe_mng.h    |  65 +++++++++\n drivers/net/ngbe/base/ngbe_type.h   |  24 ++++\n drivers/net/ngbe/ngbe_ethdev.c      |  39 ++++++\n 10 files changed, 657 insertions(+)\n create mode 100644 drivers/net/ngbe/base/ngbe_eeprom.c\n create mode 100644 drivers/net/ngbe/base/ngbe_eeprom.h\n create mode 100644 drivers/net/ngbe/base/ngbe_mng.c\n create mode 100644 drivers/net/ngbe/base/ngbe_mng.h",
    "diff": "diff --git a/drivers/net/ngbe/base/meson.build b/drivers/net/ngbe/base/meson.build\nindex fdbfa99916..ddd122ec45 100644\n--- a/drivers/net/ngbe/base/meson.build\n+++ b/drivers/net/ngbe/base/meson.build\n@@ -2,7 +2,9 @@\n # Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.\n \n sources = [\n+\t'ngbe_eeprom.c',\n \t'ngbe_hw.c',\n+\t'ngbe_mng.c',\n ]\n \n error_cflags = []\ndiff --git a/drivers/net/ngbe/base/ngbe_dummy.h b/drivers/net/ngbe/base/ngbe_dummy.h\nindex 75b4e50bca..ade03eae81 100644\n--- a/drivers/net/ngbe/base/ngbe_dummy.h\n+++ b/drivers/net/ngbe/base/ngbe_dummy.h\n@@ -28,9 +28,32 @@\n static inline void ngbe_bus_set_lan_id_dummy(struct ngbe_hw *TUP0)\n {\n }\n+/* struct ngbe_rom_operations */\n+static inline s32 ngbe_rom_init_params_dummy(struct ngbe_hw *TUP0)\n+{\n+\treturn NGBE_ERR_OPS_DUMMY;\n+}\n+static inline s32 ngbe_rom_validate_checksum_dummy(struct ngbe_hw *TUP0,\n+\t\t\t\t\tu16 *TUP1)\n+{\n+\treturn NGBE_ERR_OPS_DUMMY;\n+}\n+static inline s32 ngbe_mac_acquire_swfw_sync_dummy(struct ngbe_hw *TUP0,\n+\t\t\t\t\tu32 TUP1)\n+{\n+\treturn NGBE_ERR_OPS_DUMMY;\n+}\n+static inline void ngbe_mac_release_swfw_sync_dummy(struct ngbe_hw *TUP0,\n+\t\t\t\t\tu32 TUP1)\n+{\n+}\n static inline void ngbe_init_ops_dummy(struct ngbe_hw *hw)\n {\n \thw->bus.set_lan_id = ngbe_bus_set_lan_id_dummy;\n+\thw->rom.init_params = ngbe_rom_init_params_dummy;\n+\thw->rom.validate_checksum = ngbe_rom_validate_checksum_dummy;\n+\thw->mac.acquire_swfw_sync = ngbe_mac_acquire_swfw_sync_dummy;\n+\thw->mac.release_swfw_sync = ngbe_mac_release_swfw_sync_dummy;\n }\n \n #endif /* _NGBE_TYPE_DUMMY_H_ */\ndiff --git a/drivers/net/ngbe/base/ngbe_eeprom.c b/drivers/net/ngbe/base/ngbe_eeprom.c\nnew file mode 100644\nindex 0000000000..0ebbb7a29e\n--- /dev/null\n+++ b/drivers/net/ngbe/base/ngbe_eeprom.c\n@@ -0,0 +1,203 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.\n+ * Copyright(c) 2010-2017 Intel Corporation\n+ */\n+\n+#include \"ngbe_hw.h\"\n+#include \"ngbe_mng.h\"\n+#include \"ngbe_eeprom.h\"\n+\n+/**\n+ *  ngbe_init_eeprom_params - Initialize EEPROM params\n+ *  @hw: pointer to hardware structure\n+ *\n+ *  Initializes the EEPROM parameters ngbe_rom_info within the\n+ *  ngbe_hw struct in order to set up EEPROM access.\n+ **/\n+s32 ngbe_init_eeprom_params(struct ngbe_hw *hw)\n+{\n+\tstruct ngbe_rom_info *eeprom = &hw->rom;\n+\tu32 eec;\n+\tu16 eeprom_size;\n+\n+\tDEBUGFUNC(\"ngbe_init_eeprom_params\");\n+\n+\tif (eeprom->type != ngbe_eeprom_unknown)\n+\t\treturn 0;\n+\n+\teeprom->type = ngbe_eeprom_none;\n+\t/* Set default semaphore delay to 10ms which is a well\n+\t * tested value\n+\t */\n+\teeprom->semaphore_delay = 10; /*ms*/\n+\t/* Clear EEPROM page size, it will be initialized as needed */\n+\teeprom->word_page_size = 0;\n+\n+\t/*\n+\t * Check for EEPROM present first.\n+\t * If not present leave as none\n+\t */\n+\teec = rd32(hw, NGBE_SPISTAT);\n+\tif (!(eec & NGBE_SPISTAT_BPFLASH)) {\n+\t\teeprom->type = ngbe_eeprom_flash;\n+\n+\t\t/*\n+\t\t * SPI EEPROM is assumed here.  This code would need to\n+\t\t * change if a future EEPROM is not SPI.\n+\t\t */\n+\t\teeprom_size = 4096;\n+\t\teeprom->word_size = eeprom_size >> 1;\n+\t}\n+\n+\teeprom->address_bits = 16;\n+\teeprom->sw_addr = 0x80;\n+\n+\tDEBUGOUT(\"eeprom params: type = %d, size = %d, address bits: \"\n+\t\t  \"%d %d\\n\", eeprom->type, eeprom->word_size,\n+\t\t  eeprom->address_bits, eeprom->sw_addr);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ *  ngbe_get_eeprom_semaphore - Get hardware semaphore\n+ *  @hw: pointer to hardware structure\n+ *\n+ *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method\n+ **/\n+s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw)\n+{\n+\ts32 status = NGBE_ERR_EEPROM;\n+\tu32 timeout = 2000;\n+\tu32 i;\n+\tu32 swsm;\n+\n+\tDEBUGFUNC(\"ngbe_get_eeprom_semaphore\");\n+\n+\n+\t/* Get SMBI software semaphore between device drivers first */\n+\tfor (i = 0; i < timeout; i++) {\n+\t\t/*\n+\t\t * If the SMBI bit is 0 when we read it, then the bit will be\n+\t\t * set and we have the semaphore\n+\t\t */\n+\t\tswsm = rd32(hw, NGBE_SWSEM);\n+\t\tif (!(swsm & NGBE_SWSEM_PF)) {\n+\t\t\tstatus = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tusec_delay(50);\n+\t}\n+\n+\tif (i == timeout) {\n+\t\tDEBUGOUT(\"Driver can't access the eeprom - SMBI Semaphore \"\n+\t\t\t \"not granted.\\n\");\n+\t\t/*\n+\t\t * this release is particularly important because our attempts\n+\t\t * above to get the semaphore may have succeeded, and if there\n+\t\t * was a timeout, we should unconditionally clear the semaphore\n+\t\t * bits to free the driver to make progress\n+\t\t */\n+\t\tngbe_release_eeprom_semaphore(hw);\n+\n+\t\tusec_delay(50);\n+\t\t/*\n+\t\t * one last try\n+\t\t * If the SMBI bit is 0 when we read it, then the bit will be\n+\t\t * set and we have the semaphore\n+\t\t */\n+\t\tswsm = rd32(hw, NGBE_SWSEM);\n+\t\tif (!(swsm & NGBE_SWSEM_PF))\n+\t\t\tstatus = 0;\n+\t}\n+\n+\t/* Now get the semaphore between SW/FW through the SWESMBI bit */\n+\tif (status == 0) {\n+\t\tfor (i = 0; i < timeout; i++) {\n+\t\t\t/* Set the SW EEPROM semaphore bit to request access */\n+\t\t\twr32m(hw, NGBE_MNGSWSYNC,\n+\t\t\t\tNGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ);\n+\n+\t\t\t/*\n+\t\t\t * If we set the bit successfully then we got the\n+\t\t\t * semaphore.\n+\t\t\t */\n+\t\t\tswsm = rd32(hw, NGBE_MNGSWSYNC);\n+\t\t\tif (swsm & NGBE_MNGSWSYNC_REQ)\n+\t\t\t\tbreak;\n+\n+\t\t\tusec_delay(50);\n+\t\t}\n+\n+\t\t/*\n+\t\t * Release semaphores and return error if SW EEPROM semaphore\n+\t\t * was not granted because we don't have access to the EEPROM\n+\t\t */\n+\t\tif (i >= timeout) {\n+\t\t\tDEBUGOUT(\"SWESMBI Software EEPROM semaphore not granted.\\n\");\n+\t\t\tngbe_release_eeprom_semaphore(hw);\n+\t\t\tstatus = NGBE_ERR_EEPROM;\n+\t\t}\n+\t} else {\n+\t\tDEBUGOUT(\"Software semaphore SMBI between device drivers \"\n+\t\t\t \"not granted.\\n\");\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ *  ngbe_release_eeprom_semaphore - Release hardware semaphore\n+ *  @hw: pointer to hardware structure\n+ *\n+ *  This function clears hardware semaphore bits.\n+ **/\n+void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)\n+{\n+\tDEBUGFUNC(\"ngbe_release_eeprom_semaphore\");\n+\n+\twr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0);\n+\twr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0);\n+\tngbe_flush(hw);\n+}\n+\n+/**\n+ *  ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum\n+ *  @hw: pointer to hardware structure\n+ *  @checksum_val: calculated checksum\n+ *\n+ *  Performs checksum calculation and validates the EEPROM checksum.  If the\n+ *  caller does not need checksum_val, the value can be NULL.\n+ **/\n+s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,\n+\t\t\t\t\t   u16 *checksum_val)\n+{\n+\tu32 eeprom_cksum_devcap = 0;\n+\tint err = 0;\n+\n+\tDEBUGFUNC(\"ngbe_validate_eeprom_checksum_em\");\n+\tUNREFERENCED_PARAMETER(checksum_val);\n+\n+\t/* Check EEPROM only once */\n+\tif (hw->bus.lan_id == 0) {\n+\t\twr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);\n+\t\twr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);\n+\t} else {\n+\t\teeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS);\n+\t\thw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);\n+\t}\n+\n+\tif (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) {\n+\t\terr = ngbe_hic_check_cap(hw);\n+\t\tif (err != 0) {\n+\t\t\tPMD_INIT_LOG(ERR,\n+\t\t\t\t\"The EEPROM checksum is not valid: %d\", err);\n+\t\t\treturn -EIO;\n+\t\t}\n+\t}\n+\n+\thw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff;\n+\n+\treturn err;\n+}\n+\ndiff --git a/drivers/net/ngbe/base/ngbe_eeprom.h b/drivers/net/ngbe/base/ngbe_eeprom.h\nnew file mode 100644\nindex 0000000000..0c2819df4a\n--- /dev/null\n+++ b/drivers/net/ngbe/base/ngbe_eeprom.h\n@@ -0,0 +1,17 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.\n+ * Copyright(c) 2010-2017 Intel Corporation\n+ */\n+\n+#ifndef _NGBE_EEPROM_H_\n+#define _NGBE_EEPROM_H_\n+\n+#define NGBE_CALSUM_CAP_STATUS         0x10224\n+#define NGBE_EEPROM_VERSION_STORE_REG  0x1022C\n+\n+s32 ngbe_init_eeprom_params(struct ngbe_hw *hw);\n+s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, u16 *checksum_val);\n+s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw);\n+void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw);\n+\n+#endif /* _NGBE_EEPROM_H_ */\ndiff --git a/drivers/net/ngbe/base/ngbe_hw.c b/drivers/net/ngbe/base/ngbe_hw.c\nindex 014bb0faee..de6b75e1c0 100644\n--- a/drivers/net/ngbe/base/ngbe_hw.c\n+++ b/drivers/net/ngbe/base/ngbe_hw.c\n@@ -4,6 +4,8 @@\n  */\n \n #include \"ngbe_type.h\"\n+#include \"ngbe_eeprom.h\"\n+#include \"ngbe_mng.h\"\n #include \"ngbe_hw.h\"\n \n /**\n@@ -25,6 +27,77 @@ void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw)\n \tbus->func = bus->lan_id;\n }\n \n+/**\n+ *  ngbe_acquire_swfw_sync - Acquire SWFW semaphore\n+ *  @hw: pointer to hardware structure\n+ *  @mask: Mask to specify which semaphore to acquire\n+ *\n+ *  Acquires the SWFW semaphore through the MNGSEM register for the specified\n+ *  function (CSR, PHY0, PHY1, EEPROM, Flash)\n+ **/\n+s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask)\n+{\n+\tu32 mngsem = 0;\n+\tu32 swmask = NGBE_MNGSEM_SW(mask);\n+\tu32 fwmask = NGBE_MNGSEM_FW(mask);\n+\tu32 timeout = 200;\n+\tu32 i;\n+\n+\tDEBUGFUNC(\"ngbe_acquire_swfw_sync\");\n+\n+\tfor (i = 0; i < timeout; i++) {\n+\t\t/*\n+\t\t * SW NVM semaphore bit is used for access to all\n+\t\t * SW_FW_SYNC bits (not just NVM)\n+\t\t */\n+\t\tif (ngbe_get_eeprom_semaphore(hw))\n+\t\t\treturn NGBE_ERR_SWFW_SYNC;\n+\n+\t\tmngsem = rd32(hw, NGBE_MNGSEM);\n+\t\tif (mngsem & (fwmask | swmask)) {\n+\t\t\t/* Resource is currently in use by FW or SW */\n+\t\t\tngbe_release_eeprom_semaphore(hw);\n+\t\t\tmsec_delay(5);\n+\t\t} else {\n+\t\t\tmngsem |= swmask;\n+\t\t\twr32(hw, NGBE_MNGSEM, mngsem);\n+\t\t\tngbe_release_eeprom_semaphore(hw);\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\t/* If time expired clear the bits holding the lock and retry */\n+\tif (mngsem & (fwmask | swmask))\n+\t\tngbe_release_swfw_sync(hw, mngsem & (fwmask | swmask));\n+\n+\tmsec_delay(5);\n+\treturn NGBE_ERR_SWFW_SYNC;\n+}\n+\n+/**\n+ *  ngbe_release_swfw_sync - Release SWFW semaphore\n+ *  @hw: pointer to hardware structure\n+ *  @mask: Mask to specify which semaphore to release\n+ *\n+ *  Releases the SWFW semaphore through the MNGSEM register for the specified\n+ *  function (CSR, PHY0, PHY1, EEPROM, Flash)\n+ **/\n+void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask)\n+{\n+\tu32 mngsem;\n+\tu32 swmask = mask;\n+\n+\tDEBUGFUNC(\"ngbe_release_swfw_sync\");\n+\n+\tngbe_get_eeprom_semaphore(hw);\n+\n+\tmngsem = rd32(hw, NGBE_MNGSEM);\n+\tmngsem &= ~swmask;\n+\twr32(hw, NGBE_MNGSEM, mngsem);\n+\n+\tngbe_release_eeprom_semaphore(hw);\n+}\n+\n /**\n  *  ngbe_set_mac_type - Sets MAC type\n  *  @hw: pointer to the HW structure\n@@ -134,12 +207,22 @@ void ngbe_map_device_id(struct ngbe_hw *hw)\n s32 ngbe_init_ops_pf(struct ngbe_hw *hw)\n {\n \tstruct ngbe_bus_info *bus = &hw->bus;\n+\tstruct ngbe_mac_info *mac = &hw->mac;\n+\tstruct ngbe_rom_info *rom = &hw->rom;\n \n \tDEBUGFUNC(\"ngbe_init_ops_pf\");\n \n \t/* BUS */\n \tbus->set_lan_id = ngbe_set_lan_id_multi_port;\n \n+\t/* MAC */\n+\tmac->acquire_swfw_sync = ngbe_acquire_swfw_sync;\n+\tmac->release_swfw_sync = ngbe_release_swfw_sync;\n+\n+\t/* EEPROM */\n+\trom->init_params = ngbe_init_eeprom_params;\n+\trom->validate_checksum = ngbe_validate_eeprom_checksum_em;\n+\n \treturn 0;\n }\n \ndiff --git a/drivers/net/ngbe/base/ngbe_hw.h b/drivers/net/ngbe/base/ngbe_hw.h\nindex 7d5de49248..5e508fb67f 100644\n--- a/drivers/net/ngbe/base/ngbe_hw.h\n+++ b/drivers/net/ngbe/base/ngbe_hw.h\n@@ -10,6 +10,9 @@\n \n void ngbe_set_lan_id_multi_port(struct ngbe_hw *hw);\n \n+s32 ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask);\n+void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask);\n+\n s32 ngbe_init_shared_code(struct ngbe_hw *hw);\n s32 ngbe_set_mac_type(struct ngbe_hw *hw);\n s32 ngbe_init_ops_pf(struct ngbe_hw *hw);\ndiff --git a/drivers/net/ngbe/base/ngbe_mng.c b/drivers/net/ngbe/base/ngbe_mng.c\nnew file mode 100644\nindex 0000000000..87891a91e1\n--- /dev/null\n+++ b/drivers/net/ngbe/base/ngbe_mng.c\n@@ -0,0 +1,198 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.\n+ * Copyright(c) 2010-2017 Intel Corporation\n+ */\n+\n+#include \"ngbe_type.h\"\n+#include \"ngbe_mng.h\"\n+\n+/**\n+ *  ngbe_hic_unlocked - Issue command to manageability block unlocked\n+ *  @hw: pointer to the HW structure\n+ *  @buffer: command to write and where the return status will be placed\n+ *  @length: length of buffer, must be multiple of 4 bytes\n+ *  @timeout: time in ms to wait for command completion\n+ *\n+ *  Communicates with the manageability block. On success return 0\n+ *  else returns semaphore error when encountering an error acquiring\n+ *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.\n+ *\n+ *  This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held\n+ *  by the caller.\n+ **/\n+static s32\n+ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout)\n+{\n+\tu32 value, loop;\n+\tu16 i, dword_len;\n+\n+\tDEBUGFUNC(\"ngbe_hic_unlocked\");\n+\n+\tif (!length || length > NGBE_PMMBX_BSIZE) {\n+\t\tDEBUGOUT(\"Buffer length failure buffersize=%d.\\n\", length);\n+\t\treturn NGBE_ERR_HOST_INTERFACE_COMMAND;\n+\t}\n+\n+\t/* Calculate length in DWORDs. We must be DWORD aligned */\n+\tif (length % sizeof(u32)) {\n+\t\tDEBUGOUT(\"Buffer length failure, not aligned to dword\");\n+\t\treturn NGBE_ERR_INVALID_ARGUMENT;\n+\t}\n+\n+\tdword_len = length >> 2;\n+\n+\t/* The device driver writes the relevant command block\n+\t * into the ram area.\n+\t */\n+\tfor (i = 0; i < dword_len; i++) {\n+\t\twr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i]));\n+\t\tbuffer[i] = rd32a(hw, NGBE_MNGMBX, i);\n+\t}\n+\tngbe_flush(hw);\n+\n+\t/* Setting this bit tells the ARC that a new command is pending. */\n+\twr32m(hw, NGBE_MNGMBXCTL,\n+\t      NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY);\n+\n+\t/* Check command completion */\n+\tloop = po32m(hw, NGBE_MNGMBXCTL,\n+\t\tNGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY,\n+\t\t&value, timeout, 1000);\n+\tif (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) {\n+\t\tDEBUGOUT(\"Command has failed with no status valid.\\n\");\n+\t\treturn NGBE_ERR_HOST_INTERFACE_COMMAND;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ *  ngbe_host_interface_command - Issue command to manageability block\n+ *  @hw: pointer to the HW structure\n+ *  @buffer: contains the command to write and where the return status will\n+ *   be placed\n+ *  @length: length of buffer, must be multiple of 4 bytes\n+ *  @timeout: time in ms to wait for command completion\n+ *  @return_data: read and return data from the buffer (true) or not (false)\n+ *   Needed because FW structures are big endian and decoding of\n+ *   these fields can be 8 bit or 16 bit based on command. Decoding\n+ *   is not easily understood without making a table of commands.\n+ *   So we will leave this up to the caller to read back the data\n+ *   in these cases.\n+ *\n+ *  Communicates with the manageability block. On success return 0\n+ *  else returns semaphore error when encountering an error acquiring\n+ *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.\n+ **/\n+static s32\n+ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,\n+\t\t\t\t u32 length, u32 timeout, bool return_data)\n+{\n+\tu32 hdr_size = sizeof(struct ngbe_hic_hdr);\n+\tstruct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer;\n+\tu16 buf_len;\n+\ts32 err;\n+\tu32 bi;\n+\tu32 dword_len;\n+\n+\tDEBUGFUNC(\"ngbe_host_interface_command\");\n+\n+\tif (length == 0 || length > NGBE_PMMBX_BSIZE) {\n+\t\tDEBUGOUT(\"Buffer length failure buffersize=%d.\\n\", length);\n+\t\treturn NGBE_ERR_HOST_INTERFACE_COMMAND;\n+\t}\n+\n+\t/* Take management host interface semaphore */\n+\terr = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = ngbe_hic_unlocked(hw, buffer, length, timeout);\n+\tif (err)\n+\t\tgoto rel_out;\n+\n+\tif (!return_data)\n+\t\tgoto rel_out;\n+\n+\t/* Calculate length in DWORDs */\n+\tdword_len = hdr_size >> 2;\n+\n+\t/* first pull in the header so we know the buffer length */\n+\tfor (bi = 0; bi < dword_len; bi++)\n+\t\tbuffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);\n+\n+\t/*\n+\t * If there is any thing in data position pull it in\n+\t * Read Flash command requires reading buffer length from\n+\t * two byes instead of one byte\n+\t */\n+\tif (resp->cmd == 0x30) {\n+\t\tfor (; bi < dword_len + 2; bi++)\n+\t\t\tbuffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);\n+\n+\t\tbuf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)\n+\t\t\t\t  & 0xF00) | resp->buf_len;\n+\t\thdr_size += (2 << 2);\n+\t} else {\n+\t\tbuf_len = resp->buf_len;\n+\t}\n+\tif (!buf_len)\n+\t\tgoto rel_out;\n+\n+\tif (length < buf_len + hdr_size) {\n+\t\tDEBUGOUT(\"Buffer not large enough for reply message.\\n\");\n+\t\terr = NGBE_ERR_HOST_INTERFACE_COMMAND;\n+\t\tgoto rel_out;\n+\t}\n+\n+\t/* Calculate length in DWORDs, add 3 for odd lengths */\n+\tdword_len = (buf_len + 3) >> 2;\n+\n+\t/* Pull in the rest of the buffer (bi is where we left off) */\n+\tfor (; bi <= dword_len; bi++)\n+\t\tbuffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);\n+\n+rel_out:\n+\thw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX);\n+\n+\treturn err;\n+}\n+\n+s32 ngbe_hic_check_cap(struct ngbe_hw *hw)\n+{\n+\tstruct ngbe_hic_read_shadow_ram command;\n+\ts32 err;\n+\tint i;\n+\n+\tDEBUGFUNC(\"\\n\");\n+\n+\tcommand.hdr.req.cmd = FW_EEPROM_CHECK_STATUS;\n+\tcommand.hdr.req.buf_lenh = 0;\n+\tcommand.hdr.req.buf_lenl = 0;\n+\tcommand.hdr.req.checksum = FW_DEFAULT_CHECKSUM;\n+\n+\t/* convert offset from words to bytes */\n+\tcommand.address = 0;\n+\t/* one word */\n+\tcommand.length = 0;\n+\n+\tfor (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {\n+\t\terr = ngbe_host_interface_command(hw, (u32 *)&command,\n+\t\t\t\tsizeof(command),\n+\t\t\t\tNGBE_HI_COMMAND_TIMEOUT, true);\n+\t\tif (err)\n+\t\t\tcontinue;\n+\n+\t\tcommand.hdr.rsp.ret_status &= 0x1F;\n+\t\tif (command.hdr.rsp.ret_status !=\n+\t\t\tFW_CEM_RESP_STATUS_SUCCESS)\n+\t\t\terr = NGBE_ERR_HOST_INTERFACE_COMMAND;\n+\n+\t\tbreak;\n+\t}\n+\n+\tif (!err && command.address != FW_CHECKSUM_CAP_ST_PASS)\n+\t\terr = NGBE_ERR_EEPROM_CHECKSUM;\n+\n+\treturn err;\n+}\ndiff --git a/drivers/net/ngbe/base/ngbe_mng.h b/drivers/net/ngbe/base/ngbe_mng.h\nnew file mode 100644\nindex 0000000000..383e0dc0d1\n--- /dev/null\n+++ b/drivers/net/ngbe/base/ngbe_mng.h\n@@ -0,0 +1,65 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018-2020 Beijing WangXun Technology Co., Ltd.\n+ * Copyright(c) 2010-2017 Intel Corporation\n+ */\n+\n+#ifndef _NGBE_MNG_H_\n+#define _NGBE_MNG_H_\n+\n+#include \"ngbe_type.h\"\n+\n+#define NGBE_PMMBX_QSIZE       64 /* Num of dwords in range */\n+#define NGBE_PMMBX_BSIZE       (NGBE_PMMBX_QSIZE * 4)\n+#define NGBE_HI_COMMAND_TIMEOUT        5000 /* Process HI command limit */\n+\n+/* CEM Support */\n+#define FW_CEM_MAX_RETRIES              3\n+#define FW_CEM_RESP_STATUS_SUCCESS      0x1\n+#define FW_DEFAULT_CHECKSUM             0xFF /* checksum always 0xFF */\n+#define FW_EEPROM_CHECK_STATUS\t\t0xE9\n+\n+#define FW_CHECKSUM_CAP_ST_PASS\t0x80658383\n+#define FW_CHECKSUM_CAP_ST_FAIL\t0x70657376\n+\n+/* Host Interface Command Structures */\n+struct ngbe_hic_hdr {\n+\tu8 cmd;\n+\tu8 buf_len;\n+\tunion {\n+\t\tu8 cmd_resv;\n+\t\tu8 ret_status;\n+\t} cmd_or_resp;\n+\tu8 checksum;\n+};\n+\n+struct ngbe_hic_hdr2_req {\n+\tu8 cmd;\n+\tu8 buf_lenh;\n+\tu8 buf_lenl;\n+\tu8 checksum;\n+};\n+\n+struct ngbe_hic_hdr2_rsp {\n+\tu8 cmd;\n+\tu8 buf_lenl;\n+\tu8 ret_status;     /* 7-5: high bits of buf_len, 4-0: status */\n+\tu8 checksum;\n+};\n+\n+union ngbe_hic_hdr2 {\n+\tstruct ngbe_hic_hdr2_req req;\n+\tstruct ngbe_hic_hdr2_rsp rsp;\n+};\n+\n+/* These need to be dword aligned */\n+struct ngbe_hic_read_shadow_ram {\n+\tunion ngbe_hic_hdr2 hdr;\n+\tu32 address;\n+\tu16 length;\n+\tu16 pad2;\n+\tu16 data;\n+\tu16 pad3;\n+};\n+\n+s32 ngbe_hic_check_cap(struct ngbe_hw *hw);\n+#endif /* _NGBE_MNG_H_ */\ndiff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h\nindex d172f2702f..c727338bd5 100644\n--- a/drivers/net/ngbe/base/ngbe_type.h\n+++ b/drivers/net/ngbe/base/ngbe_type.h\n@@ -10,6 +10,13 @@\n #include \"ngbe_osdep.h\"\n #include \"ngbe_devids.h\"\n \n+enum ngbe_eeprom_type {\n+\tngbe_eeprom_unknown = 0,\n+\tngbe_eeprom_spi,\n+\tngbe_eeprom_flash,\n+\tngbe_eeprom_none /* No NVM support */\n+};\n+\n enum ngbe_mac_type {\n \tngbe_mac_unknown = 0,\n \tngbe_mac_em,\n@@ -49,7 +56,23 @@ struct ngbe_bus_info {\n \tu8 lan_id;\n };\n \n+struct ngbe_rom_info {\n+\ts32 (*init_params)(struct ngbe_hw *hw);\n+\ts32 (*validate_checksum)(struct ngbe_hw *hw, u16 *checksum_val);\n+\n+\tenum ngbe_eeprom_type type;\n+\tu32 semaphore_delay;\n+\tu16 word_size;\n+\tu16 address_bits;\n+\tu16 word_page_size;\n+\tu32 sw_addr;\n+\tu32 saved_version;\n+\tu16 cksum_devcap;\n+};\n+\n struct ngbe_mac_info {\n+\ts32 (*acquire_swfw_sync)(struct ngbe_hw *hw, u32 mask);\n+\tvoid (*release_swfw_sync)(struct ngbe_hw *hw, u32 mask);\n \tenum ngbe_mac_type type;\n };\n \n@@ -63,6 +86,7 @@ struct ngbe_hw {\n \tvoid *back;\n \tstruct ngbe_mac_info mac;\n \tstruct ngbe_phy_info phy;\n+\tstruct ngbe_rom_info rom;\n \tstruct ngbe_bus_info bus;\n \tu16 device_id;\n \tu16 vendor_id;\ndiff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c\nindex a355c7dc29..c779c46dd5 100644\n--- a/drivers/net/ngbe/ngbe_ethdev.c\n+++ b/drivers/net/ngbe/ngbe_ethdev.c\n@@ -32,6 +32,29 @@ static const struct rte_pci_id pci_id_ngbe_map[] = {\n \t{ .vendor_id = 0, /* sentinel */ },\n };\n \n+/*\n+ * Ensure that all locks are released before first NVM or PHY access\n+ */\n+static void\n+ngbe_swfw_lock_reset(struct ngbe_hw *hw)\n+{\n+\tuint16_t mask;\n+\n+\t/*\n+\t * These ones are more tricky since they are common to all ports; but\n+\t * swfw_sync retries last long enough (1s) to be almost sure that if\n+\t * lock can not be taken it is due to an improper lock of the\n+\t * semaphore.\n+\t */\n+\tmask = NGBE_MNGSEM_SWPHY |\n+\t       NGBE_MNGSEM_SWMBX |\n+\t       NGBE_MNGSEM_SWFLASH;\n+\tif (hw->mac.acquire_swfw_sync(hw, mask) < 0)\n+\t\tPMD_DRV_LOG(DEBUG, \"SWFW common locks released\");\n+\n+\thw->mac.release_swfw_sync(hw, mask);\n+}\n+\n static int\n eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n {\n@@ -60,6 +83,22 @@ eth_ngbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \t\treturn -EIO;\n \t}\n \n+\t/* Unlock any pending hardware semaphore */\n+\tngbe_swfw_lock_reset(hw);\n+\n+\terr = hw->rom.init_params(hw);\n+\tif (err != 0) {\n+\t\tPMD_INIT_LOG(ERR, \"The EEPROM init failed: %d\", err);\n+\t\treturn -EIO;\n+\t}\n+\n+\t/* Make sure we have a good EEPROM before we read from it */\n+\terr = hw->rom.validate_checksum(hw, NULL);\n+\tif (err != 0) {\n+\t\tPMD_INIT_LOG(ERR, \"The EEPROM checksum is not valid: %d\", err);\n+\t\treturn -EIO;\n+\t}\n+\n \treturn 0;\n }\n \n",
    "prefixes": [
        "v6",
        "06/19"
    ]
}