get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 17147,
    "url": "http://patches.dpdk.org/api/patches/17147/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1479740470-6723-28-git-send-email-arybchenko@solarflare.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<1479740470-6723-28-git-send-email-arybchenko@solarflare.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1479740470-6723-28-git-send-email-arybchenko@solarflare.com",
    "date": "2016-11-21T15:00:41",
    "name": "[dpdk-dev,27/56] net/sfc: import libefx VPD support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "e48efa6882e3c7ba88fc4c33de043287405857e1",
    "submitter": {
        "id": 607,
        "url": "http://patches.dpdk.org/api/people/607/?format=api",
        "name": "Andrew Rybchenko",
        "email": "arybchenko@solarflare.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1479740470-6723-28-git-send-email-arybchenko@solarflare.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/17147/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/17147/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 228E7D5EE;\n\tMon, 21 Nov 2016 16:03:37 +0100 (CET)",
            "from nbfkord-smmo02.seg.att.com (nbfkord-smmo02.seg.att.com\n\t[209.65.160.78]) by dpdk.org (Postfix) with ESMTP id 05F5A376D\n\tfor <dev@dpdk.org>; Mon, 21 Nov 2016 16:01:42 +0100 (CET)",
            "from unknown [12.187.104.26]\n\tby nbfkord-smmo02.seg.att.com(mxl_mta-7.2.4-7) with SMTP id\n\t65c03385.0.1541294.00-2318.3424252.nbfkord-smmo02.seg.att.com\n\t(envelope-from <arybchenko@solarflare.com>); \n\tMon, 21 Nov 2016 15:01:43 +0000 (UTC)",
            "from ocex03.SolarFlarecom.com (10.20.40.36) by\n\tocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server\n\t(TLS) id 15.0.1044.25; Mon, 21 Nov 2016 07:01:21 -0800",
            "from opal.uk.solarflarecom.com (10.17.10.1) by\n\tocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server\n\t(TLS) id\n\t15.0.1044.25 via Frontend Transport; Mon, 21 Nov 2016 07:01:21 -0800",
            "from uklogin.uk.solarflarecom.com (uklogin.uk.solarflarecom.com\n\t[10.17.10.10])\n\tby opal.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id\n\tuALF1KZ5007177 for <dev@dpdk.org>; Mon, 21 Nov 2016 15:01:20 GMT",
            "from uklogin.uk.solarflarecom.com (localhost.localdomain\n\t[127.0.0.1])\n\tby uklogin.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id\n\tuALF1J3I006765 for <dev@dpdk.org>; Mon, 21 Nov 2016 15:01:20 GMT"
        ],
        "X-MXL-Hash": "58330c5704b66674-2261805d091a89bd0de604657a54ea7d50218f8f",
        "From": "Andrew Rybchenko <arybchenko@solarflare.com>",
        "To": "<dev@dpdk.org>",
        "Date": "Mon, 21 Nov 2016 15:00:41 +0000",
        "Message-ID": "<1479740470-6723-28-git-send-email-arybchenko@solarflare.com>",
        "X-Mailer": "git-send-email 1.8.2.3",
        "In-Reply-To": "<1479740470-6723-1-git-send-email-arybchenko@solarflare.com>",
        "References": "<1479740470-6723-1-git-send-email-arybchenko@solarflare.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-AnalysisOut": [
            "[v=2.1 cv=UI/baXry c=1 sm=1 tr=0 a=8BlWFWvVlq5taO8ncb8nKg==]",
            "[:17 a=L24OOQBejmoA:10 a=zRKbQ67AAAAA:8 a=3GrCDlYVIJQyu3IVW]",
            "[YgA:9 a=exQ6MQGMmSocVnse:21 a=P9IBJz2fGRAHCa5E:21 a=Vn3oHg]",
            "[RaNP4Gyy6j:21 a=PA03WX8tBzeizutn5_OT:22]"
        ],
        "X-Spam": "[F=0.2526741478; CM=0.500; S=0.252(2015072901)]",
        "X-MAIL-FROM": "<arybchenko@solarflare.com>",
        "X-SOURCE-IP": "[12.187.104.26]",
        "Subject": "[dpdk-dev] [PATCH 27/56] net/sfc: import libefx VPD support",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Provide API to read/write PCI Vital Product Data.\n\nEFSYS_OPT_VPD should be enabled to use it.\n\nFrom Solarflare Communications Inc.\n\nSigned-off-by: Andrew Rybchenko <arybchenko@solarflare.com>\n---\n drivers/net/sfc/efx/base/ef10_impl.h  |   63 ++\n drivers/net/sfc/efx/base/ef10_vpd.c   |  463 +++++++++++++++\n drivers/net/sfc/efx/base/efx.h        |   82 +++\n drivers/net/sfc/efx/base/efx_check.h  |    7 +\n drivers/net/sfc/efx/base/efx_impl.h   |   78 +++\n drivers/net/sfc/efx/base/efx_vpd.c    | 1016 +++++++++++++++++++++++++++++++++\n drivers/net/sfc/efx/base/siena_impl.h |   63 ++\n drivers/net/sfc/efx/base/siena_vpd.c  |  618 ++++++++++++++++++++\n 8 files changed, 2390 insertions(+)\n create mode 100644 drivers/net/sfc/efx/base/ef10_vpd.c\n create mode 100644 drivers/net/sfc/efx/base/efx_vpd.c\n create mode 100644 drivers/net/sfc/efx/base/siena_vpd.c",
    "diff": "diff --git a/drivers/net/sfc/efx/base/ef10_impl.h b/drivers/net/sfc/efx/base/ef10_impl.h\nindex d533b15..f13534c 100644\n--- a/drivers/net/sfc/efx/base/ef10_impl.h\n+++ b/drivers/net/sfc/efx/base/ef10_impl.h\n@@ -817,6 +817,69 @@ ef10_nic_pio_unlink(\n \n /* VPD */\n \n+#if EFSYS_OPT_VPD\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_init(\n+\t__in\t\t\tefx_nic_t *enp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_size(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out\t\t\tsize_t *sizep);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_read(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_verify(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_reinit(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_get(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tefx_vpd_value_t *evvp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_set(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_next(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tefx_vpd_value_t *evvp,\n+\t__inout\t\t\tunsigned int *contp);\n+\n+extern __checkReturn\t\tefx_rc_t\n+ef10_vpd_write(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t\t\t\tvoid\n+ef10_vpd_fini(\n+\t__in\t\t\tefx_nic_t *enp);\n+\n+#endif\t/* EFSYS_OPT_VPD */\n+\n \n /* RX */\n \ndiff --git a/drivers/net/sfc/efx/base/ef10_vpd.c b/drivers/net/sfc/efx/base/ef10_vpd.c\nnew file mode 100644\nindex 0000000..71123a9\n--- /dev/null\n+++ b/drivers/net/sfc/efx/base/ef10_vpd.c\n@@ -0,0 +1,463 @@\n+/*\n+ * Copyright (c) 2009-2016 Solarflare Communications Inc.\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions are met:\n+ *\n+ * 1. Redistributions of source code must retain the above copyright notice,\n+ *    this list of conditions and the following disclaimer.\n+ * 2. Redistributions in binary form must reproduce the above copyright notice,\n+ *    this list of conditions and the following disclaimer in the documentation\n+ *    and/or other materials provided with the distribution.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ *\n+ * The views and conclusions contained in the software and documentation are\n+ * those of the authors and should not be interpreted as representing official\n+ * policies, either expressed or implied, of the FreeBSD Project.\n+ */\n+\n+#include \"efx.h\"\n+#include \"efx_impl.h\"\n+\n+\n+#if EFSYS_OPT_VPD\n+\n+#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD\n+\n+#include \"ef10_tlv_layout.h\"\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_init(\n+\t__in\t\t\tefx_nic_t *enp)\n+{\n+\tcaddr_t svpd;\n+\tsize_t svpd_size;\n+\tuint32_t pci_pf;\n+\tuint32_t tag;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\tif (enp->en_nic_cfg.enc_vpd_is_global) {\n+\t\ttag = TLV_TAG_GLOBAL_STATIC_VPD;\n+\t} else {\n+\t\tpci_pf = enp->en_nic_cfg.enc_pf;\n+\t\ttag = TLV_TAG_PF_STATIC_VPD(pci_pf);\n+\t}\n+\n+\t/*\n+\t * The VPD interface exposes VPD resources from the combined static and\n+\t * dynamic VPD storage. As the static VPD configuration should *never*\n+\t * change, we can cache it.\n+\t */\n+\tsvpd = NULL;\n+\tsvpd_size = 0;\n+\trc = ef10_nvram_partn_read_tlv(enp,\n+\t    NVRAM_PARTITION_TYPE_STATIC_CONFIG,\n+\t    tag, &svpd, &svpd_size);\n+\tif (rc != 0) {\n+\t\tif (rc == EACCES) {\n+\t\t\t/* Unprivileged functions cannot access VPD */\n+\t\t\tgoto out;\n+\t\t}\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (svpd != NULL && svpd_size > 0) {\n+\t\tif ((rc = efx_vpd_hunk_verify(svpd, svpd_size, NULL)) != 0)\n+\t\t\tgoto fail2;\n+\t}\n+\n+\tenp->en_arch.ef10.ena_svpd = svpd;\n+\tenp->en_arch.ef10.ena_svpd_length = svpd_size;\n+\n+out:\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, svpd_size, svpd);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_size(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out\t\t\tsize_t *sizep)\n+{\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\t/*\n+\t * This function returns the total size the user should allocate\n+\t * for all VPD operations. We've already cached the static vpd,\n+\t * so we just need to return an upper bound on the dynamic vpd,\n+\t * which is the size of the DYNAMIC_CONFIG partition.\n+\t */\n+\tif ((rc = efx_mcdi_nvram_info(enp, NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,\n+\t\t    sizep, NULL, NULL, NULL)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_read(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tcaddr_t dvpd;\n+\tsize_t dvpd_size;\n+\tuint32_t pci_pf;\n+\tuint32_t tag;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\tif (enp->en_nic_cfg.enc_vpd_is_global) {\n+\t\ttag = TLV_TAG_GLOBAL_DYNAMIC_VPD;\n+\t} else {\n+\t\tpci_pf = enp->en_nic_cfg.enc_pf;\n+\t\ttag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);\n+\t}\n+\n+\tif ((rc = ef10_nvram_partn_read_tlv(enp,\n+\t\t    NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,\n+\t\t    tag, &dvpd, &dvpd_size)) != 0)\n+\t\tgoto fail1;\n+\n+\tif (dvpd_size > size) {\n+\t\trc = ENOSPC;\n+\t\tgoto fail2;\n+\t}\n+\tmemcpy(data, dvpd, dvpd_size);\n+\n+\t/* Pad data with all-1s, consistent with update operations */\n+\tmemset(data + dvpd_size, 0xff, size - dvpd_size);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, dvpd_size, dvpd);\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, dvpd_size, dvpd);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_verify(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tefx_vpd_tag_t stag;\n+\tefx_vpd_tag_t dtag;\n+\tefx_vpd_keyword_t skey;\n+\tefx_vpd_keyword_t dkey;\n+\tunsigned int scont;\n+\tunsigned int dcont;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\t/*\n+\t * Strictly you could take the view that dynamic vpd is optional.\n+\t * Instead, to conform more closely to the read/verify/reinit()\n+\t * paradigm, we require dynamic vpd. ef10_vpd_reinit() will\n+\t * reinitialize it as required.\n+\t */\n+\tif ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)\n+\t\tgoto fail1;\n+\n+\t/*\n+\t * Verify that there is no duplication between the static and\n+\t * dynamic cfg sectors.\n+\t */\n+\tif (enp->en_arch.ef10.ena_svpd_length == 0)\n+\t\tgoto done;\n+\n+\tdcont = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_hunk_next(data, size, &dtag,\n+\t\t    &dkey, NULL, NULL, &dcont)) != 0)\n+\t\t\tgoto fail2;\n+\t\tif (dcont == 0)\n+\t\t\tbreak;\n+\n+\t\t/*\n+\t\t * Skip the RV keyword. It should be present in both the static\n+\t\t * and dynamic cfg sectors.\n+\t\t */\n+\t\tif (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))\n+\t\t\tcontinue;\n+\n+\t\tscont = 0;\n+\t\t_NOTE(CONSTANTCONDITION)\n+\t\twhile (1) {\n+\t\t\tif ((rc = efx_vpd_hunk_next(\n+\t\t\t    enp->en_arch.ef10.ena_svpd,\n+\t\t\t    enp->en_arch.ef10.ena_svpd_length, &stag, &skey,\n+\t\t\t    NULL, NULL, &scont)) != 0)\n+\t\t\t\tgoto fail3;\n+\t\t\tif (scont == 0)\n+\t\t\t\tbreak;\n+\n+\t\t\tif (stag == dtag && skey == dkey) {\n+\t\t\t\trc = EEXIST;\n+\t\t\t\tgoto fail4;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+done:\n+\treturn (0);\n+\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_reinit(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tboolean_t wantpid;\n+\tefx_rc_t rc;\n+\n+\t/*\n+\t * Only create an ID string if the dynamic cfg doesn't have one\n+\t */\n+\tif (enp->en_arch.ef10.ena_svpd_length == 0)\n+\t\twantpid = B_TRUE;\n+\telse {\n+\t\tunsigned int offset;\n+\t\tuint8_t length;\n+\n+\t\trc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,\n+\t\t\t\t    enp->en_arch.ef10.ena_svpd_length,\n+\t\t\t\t    EFX_VPD_ID, 0, &offset, &length);\n+\t\tif (rc == 0)\n+\t\t\twantpid = B_FALSE;\n+\t\telse if (rc == ENOENT)\n+\t\t\twantpid = B_TRUE;\n+\t\telse\n+\t\t\tgoto fail1;\n+\t}\n+\n+\tif ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)\n+\t\tgoto fail2;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_get(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tunsigned int offset;\n+\tuint8_t length;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\t/* Attempt to satisfy the request from svpd first */\n+\tif (enp->en_arch.ef10.ena_svpd_length > 0) {\n+\t\tif ((rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,\n+\t\t    enp->en_arch.ef10.ena_svpd_length, evvp->evv_tag,\n+\t\t    evvp->evv_keyword, &offset, &length)) == 0) {\n+\t\t\tevvp->evv_length = length;\n+\t\t\tmemcpy(evvp->evv_value,\n+\t\t\t    enp->en_arch.ef10.ena_svpd + offset, length);\n+\t\t\treturn (0);\n+\t\t} else if (rc != ENOENT)\n+\t\t\tgoto fail1;\n+\t}\n+\n+\t/* And then from the provided data buffer */\n+\tif ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,\n+\t    evvp->evv_keyword, &offset, &length)) != 0) {\n+\t\tif (rc == ENOENT)\n+\t\t\treturn (rc);\n+\t\tgoto fail2;\n+\t}\n+\n+\tevvp->evv_length = length;\n+\tmemcpy(evvp->evv_value, data + offset, length);\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_set(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\t/* If the provided (tag,keyword) exists in svpd, then it is readonly */\n+\tif (enp->en_arch.ef10.ena_svpd_length > 0) {\n+\t\tunsigned int offset;\n+\t\tuint8_t length;\n+\n+\t\tif ((rc = efx_vpd_hunk_get(enp->en_arch.ef10.ena_svpd,\n+\t\t    enp->en_arch.ef10.ena_svpd_length, evvp->evv_tag,\n+\t\t    evvp->evv_keyword, &offset, &length)) == 0) {\n+\t\t\trc = EACCES;\n+\t\t\tgoto fail1;\n+\t\t}\n+\t}\n+\n+\tif ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)\n+\t\tgoto fail2;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_next(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tefx_vpd_value_t *evvp,\n+\t__inout\t\t\tunsigned int *contp)\n+{\n+\t_NOTE(ARGUNUSED(enp, data, size, evvp, contp))\n+\n+\treturn (ENOTSUP);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+ef10_vpd_write(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tsize_t vpd_length;\n+\tuint32_t pci_pf;\n+\tuint32_t tag;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\tif (enp->en_nic_cfg.enc_vpd_is_global) {\n+\t\ttag = TLV_TAG_GLOBAL_DYNAMIC_VPD;\n+\t} else {\n+\t\tpci_pf = enp->en_nic_cfg.enc_pf;\n+\t\ttag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);\n+\t}\n+\n+\t/* Determine total length of new dynamic VPD */\n+\tif ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)\n+\t\tgoto fail1;\n+\n+\t/* Store new dynamic VPD in all segments in DYNAMIC_CONFIG partition */\n+\tif ((rc = ef10_nvram_partn_write_segment_tlv(enp,\n+\t\t    NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,\n+\t\t    tag, data, vpd_length, B_TRUE)) != 0) {\n+\t\tgoto fail2;\n+\t}\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t\t\t\tvoid\n+ef10_vpd_fini(\n+\t__in\t\t\tefx_nic_t *enp)\n+{\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||\n+\t\t    enp->en_family == EFX_FAMILY_MEDFORD);\n+\n+\tif (enp->en_arch.ef10.ena_svpd_length > 0) {\n+\t\tEFSYS_KMEM_FREE(enp->en_esip, enp->en_arch.ef10.ena_svpd_length,\n+\t\t\t\tenp->en_arch.ef10.ena_svpd);\n+\n+\t\tenp->en_arch.ef10.ena_svpd = NULL;\n+\t\tenp->en_arch.ef10.ena_svpd_length = 0;\n+\t}\n+}\n+\n+#endif\t/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */\n+\n+#endif\t/* EFSYS_OPT_VPD */\ndiff --git a/drivers/net/sfc/efx/base/efx.h b/drivers/net/sfc/efx/base/efx.h\nindex d224fc0..1811879 100644\n--- a/drivers/net/sfc/efx/base/efx.h\n+++ b/drivers/net/sfc/efx/base/efx.h\n@@ -1241,6 +1241,88 @@ efx_nic_get_vi_pool(\n \t__out\t\tuint32_t *txq_countp);\n \n \n+#if EFSYS_OPT_VPD\n+\n+typedef enum efx_vpd_tag_e {\n+\tEFX_VPD_ID = 0x02,\n+\tEFX_VPD_END = 0x0f,\n+\tEFX_VPD_RO = 0x10,\n+\tEFX_VPD_RW = 0x11,\n+} efx_vpd_tag_t;\n+\n+typedef uint16_t efx_vpd_keyword_t;\n+\n+typedef struct efx_vpd_value_s {\n+\tefx_vpd_tag_t\t\tevv_tag;\n+\tefx_vpd_keyword_t\tevv_keyword;\n+\tuint8_t\t\t\tevv_length;\n+\tuint8_t\t\t\tevv_value[0x100];\n+} efx_vpd_value_t;\n+\n+\n+#define\tEFX_VPD_KEYWORD(x, y) ((x) | ((y) << 8))\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_init(\n+\t__in\t\t\tefx_nic_t *enp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_size(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out\t\t\tsize_t *sizep);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_read(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_verify(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_reinit(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_get(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tefx_vpd_value_t *evvp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_set(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__inout_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_next(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__inout_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tefx_vpd_value_t *evvp,\n+\t__inout\t\t\tunsigned int *contp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_write(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t\t\t\tvoid\n+efx_vpd_fini(\n+\t__in\t\t\tefx_nic_t *enp);\n+\n+#endif\t/* EFSYS_OPT_VPD */\n+\n /* NVRAM */\n \n #if EFSYS_OPT_NVRAM\ndiff --git a/drivers/net/sfc/efx/base/efx_check.h b/drivers/net/sfc/efx/base/efx_check.h\nindex e6ef077..bd0a482 100644\n--- a/drivers/net/sfc/efx/base/efx_check.h\n+++ b/drivers/net/sfc/efx/base/efx_check.h\n@@ -290,6 +290,13 @@\n # error \"STAT_NAME is obsolete (replaced by NAMES).\"\n #endif\n \n+#if EFSYS_OPT_VPD\n+/* Support PCI Vital Product Data (VPD) */\n+# if !(EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)\n+#  error \"VPD requires SIENA or HUNTINGTON or MEDFORD\"\n+# endif\n+#endif /* EFSYS_OPT_VPD */\n+\n #ifdef EFSYS_OPT_WOL\n # error \"WOL is obsolete and is not supported\"\n #endif /* EFSYS_OPT_WOL */\ndiff --git a/drivers/net/sfc/efx/base/efx_impl.h b/drivers/net/sfc/efx/base/efx_impl.h\nindex 6b84f43..980f964 100644\n--- a/drivers/net/sfc/efx/base/efx_impl.h\n+++ b/drivers/net/sfc/efx/base/efx_impl.h\n@@ -477,6 +477,24 @@ typedef struct efx_nvram_ops_s {\n } efx_nvram_ops_t;\n #endif /* EFSYS_OPT_NVRAM */\n \n+#if EFSYS_OPT_VPD\n+typedef struct efx_vpd_ops_s {\n+\tefx_rc_t\t(*evpdo_init)(efx_nic_t *);\n+\tefx_rc_t\t(*evpdo_size)(efx_nic_t *, size_t *);\n+\tefx_rc_t\t(*evpdo_read)(efx_nic_t *, caddr_t, size_t);\n+\tefx_rc_t\t(*evpdo_verify)(efx_nic_t *, caddr_t, size_t);\n+\tefx_rc_t\t(*evpdo_reinit)(efx_nic_t *, caddr_t, size_t);\n+\tefx_rc_t\t(*evpdo_get)(efx_nic_t *, caddr_t, size_t,\n+\t\t\t\t\tefx_vpd_value_t *);\n+\tefx_rc_t\t(*evpdo_set)(efx_nic_t *, caddr_t, size_t,\n+\t\t\t\t\tefx_vpd_value_t *);\n+\tefx_rc_t\t(*evpdo_next)(efx_nic_t *, caddr_t, size_t,\n+\t\t\t\t\tefx_vpd_value_t *, unsigned int *);\n+\tefx_rc_t\t(*evpdo_write)(efx_nic_t *, caddr_t, size_t);\n+\tvoid\t\t(*evpdo_fini)(efx_nic_t *);\n+} efx_vpd_ops_t;\n+#endif\t/* EFSYS_OPT_VPD */\n+\n #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM\n \n \t__checkReturn\t\tefx_rc_t\n@@ -591,6 +609,9 @@ struct efx_nic_s {\n \tefx_nvram_type_t\ten_nvram_locked;\n \tconst efx_nvram_ops_t\t*en_envop;\n #endif\t/* EFSYS_OPT_NVRAM */\n+#if EFSYS_OPT_VPD\n+\tconst efx_vpd_ops_t\t*en_evpdop;\n+#endif\t/* EFSYS_OPT_VPD */\n #if EFSYS_OPT_RX_SCALE\n \tefx_rx_hash_support_t\ten_hash_support;\n \tefx_rx_scale_support_t\ten_rss_support;\n@@ -603,6 +624,10 @@ struct efx_nic_s {\n #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD\n \t\t\tunsigned int\t\tenu_partn_mask;\n #endif\t/* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */\n+#if EFSYS_OPT_VPD\n+\t\t\tcaddr_t\t\t\tenu_svpd;\n+\t\t\tsize_t\t\t\tenu_svpd_length;\n+#endif\t/* EFSYS_OPT_VPD */\n \t\t\tint\t\t\tenu_unused;\n \t\t} siena;\n #endif\t/* EFSYS_OPT_SIENA */\n@@ -614,6 +639,10 @@ struct efx_nic_s {\n \t\t\tint\t\t\tena_vi_base;\n \t\t\tint\t\t\tena_vi_count;\n \t\t\tint\t\t\tena_vi_shift;\n+#if EFSYS_OPT_VPD\n+\t\t\tcaddr_t\t\t\tena_svpd;\n+\t\t\tsize_t\t\t\tena_svpd_length;\n+#endif\t/* EFSYS_OPT_VPD */\n \t\t\tefx_piobuf_handle_t\tena_piobuf_handle[EF10_MAX_PIOBUF_NBUFS];\n \t\t\tuint32_t\t\tena_piobuf_count;\n \t\t\tuint32_t\t\tena_pio_alloc_map[EF10_MAX_PIOBUF_NBUFS];\n@@ -1020,6 +1049,55 @@ extern\t\t\tvoid\n efx_phy_unprobe(\n \t__in\t\tefx_nic_t *enp);\n \n+#if EFSYS_OPT_VPD\n+\n+/* VPD utility functions */\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_length(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tsize_t *lengthp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_verify(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out_opt\t\tboolean_t *cksummedp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_reinit(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tboolean_t wantpid);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_get(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_tag_t tag,\n+\t__in\t\t\tefx_vpd_keyword_t keyword,\n+\t__out\t\t\tunsigned int *payloadp,\n+\t__out\t\t\tuint8_t *paylenp);\n+\n+extern\t__checkReturn\t\t\tefx_rc_t\n+efx_vpd_hunk_next(\n+\t__in_bcount(size)\t\tcaddr_t data,\n+\t__in\t\t\t\tsize_t size,\n+\t__out\t\t\t\tefx_vpd_tag_t *tagp,\n+\t__out\t\t\t\tefx_vpd_keyword_t *keyword,\n+\t__out_opt\t\t\tunsigned int *payloadp,\n+\t__out_opt\t\t\tuint8_t *paylenp,\n+\t__inout\t\t\t\tunsigned int *contp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_set(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp);\n+\n+#endif\t/* EFSYS_OPT_VPD */\n+\n #if EFSYS_OPT_DIAG\n \n extern\tefx_sram_pattern_fn_t\t__efx_sram_pattern_fns[];\ndiff --git a/drivers/net/sfc/efx/base/efx_vpd.c b/drivers/net/sfc/efx/base/efx_vpd.c\nnew file mode 100644\nindex 0000000..1e47df2\n--- /dev/null\n+++ b/drivers/net/sfc/efx/base/efx_vpd.c\n@@ -0,0 +1,1016 @@\n+/*\n+ * Copyright (c) 2009-2016 Solarflare Communications Inc.\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions are met:\n+ *\n+ * 1. Redistributions of source code must retain the above copyright notice,\n+ *    this list of conditions and the following disclaimer.\n+ * 2. Redistributions in binary form must reproduce the above copyright notice,\n+ *    this list of conditions and the following disclaimer in the documentation\n+ *    and/or other materials provided with the distribution.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ *\n+ * The views and conclusions contained in the software and documentation are\n+ * those of the authors and should not be interpreted as representing official\n+ * policies, either expressed or implied, of the FreeBSD Project.\n+ */\n+\n+#include \"efx.h\"\n+#include \"efx_impl.h\"\n+\n+#if EFSYS_OPT_VPD\n+\n+#define\tTAG_TYPE_LBN 7\n+#define\tTAG_TYPE_WIDTH 1\n+#define\tTAG_TYPE_LARGE_ITEM_DECODE 1\n+#define\tTAG_TYPE_SMALL_ITEM_DECODE 0\n+\n+#define\tTAG_SMALL_ITEM_NAME_LBN 3\n+#define\tTAG_SMALL_ITEM_NAME_WIDTH 4\n+#define\tTAG_SMALL_ITEM_SIZE_LBN 0\n+#define\tTAG_SMALL_ITEM_SIZE_WIDTH 3\n+\n+#define\tTAG_LARGE_ITEM_NAME_LBN 0\n+#define\tTAG_LARGE_ITEM_NAME_WIDTH 7\n+\n+#define\tTAG_NAME_END_DECODE 0x0f\n+#define\tTAG_NAME_ID_STRING_DECODE 0x02\n+#define\tTAG_NAME_VPD_R_DECODE 0x10\n+#define\tTAG_NAME_VPD_W_DECODE 0x11\n+\n+#if EFSYS_OPT_SIENA\n+\n+static const efx_vpd_ops_t\t__efx_vpd_siena_ops = {\n+\tsiena_vpd_init,\t\t/* evpdo_init */\n+\tsiena_vpd_size,\t\t/* evpdo_size */\n+\tsiena_vpd_read,\t\t/* evpdo_read */\n+\tsiena_vpd_verify,\t/* evpdo_verify */\n+\tsiena_vpd_reinit,\t/* evpdo_reinit */\n+\tsiena_vpd_get,\t\t/* evpdo_get */\n+\tsiena_vpd_set,\t\t/* evpdo_set */\n+\tsiena_vpd_next,\t\t/* evpdo_next */\n+\tsiena_vpd_write,\t/* evpdo_write */\n+\tsiena_vpd_fini,\t\t/* evpdo_fini */\n+};\n+\n+#endif\t/* EFSYS_OPT_SIENA */\n+\n+#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD\n+\n+static const efx_vpd_ops_t\t__efx_vpd_ef10_ops = {\n+\tef10_vpd_init,\t\t/* evpdo_init */\n+\tef10_vpd_size,\t\t/* evpdo_size */\n+\tef10_vpd_read,\t\t/* evpdo_read */\n+\tef10_vpd_verify,\t/* evpdo_verify */\n+\tef10_vpd_reinit,\t/* evpdo_reinit */\n+\tef10_vpd_get,\t\t/* evpdo_get */\n+\tef10_vpd_set,\t\t/* evpdo_set */\n+\tef10_vpd_next,\t\t/* evpdo_next */\n+\tef10_vpd_write,\t\t/* evpdo_write */\n+\tef10_vpd_fini,\t\t/* evpdo_fini */\n+};\n+\n+#endif\t/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_init(\n+\t__in\t\t\tefx_nic_t *enp)\n+{\n+\tconst efx_vpd_ops_t *evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);\n+\tEFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_VPD));\n+\n+\tswitch (enp->en_family) {\n+#if EFSYS_OPT_SIENA\n+\tcase EFX_FAMILY_SIENA:\n+\t\tevpdop = &__efx_vpd_siena_ops;\n+\t\tbreak;\n+#endif\t/* EFSYS_OPT_SIENA */\n+\n+#if EFSYS_OPT_HUNTINGTON\n+\tcase EFX_FAMILY_HUNTINGTON:\n+\t\tevpdop = &__efx_vpd_ef10_ops;\n+\t\tbreak;\n+#endif\t/* EFSYS_OPT_HUNTINGTON */\n+\n+#if EFSYS_OPT_MEDFORD\n+\tcase EFX_FAMILY_MEDFORD:\n+\t\tevpdop = &__efx_vpd_ef10_ops;\n+\t\tbreak;\n+#endif\t/* EFSYS_OPT_MEDFORD */\n+\n+\tdefault:\n+\t\tEFSYS_ASSERT(0);\n+\t\trc = ENOTSUP;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (evpdop->evpdo_init != NULL) {\n+\t\tif ((rc = evpdop->evpdo_init(enp)) != 0)\n+\t\t\tgoto fail2;\n+\t}\n+\n+\tenp->en_evpdop = evpdop;\n+\tenp->en_mod_flags |= EFX_MOD_VPD;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_size(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out\t\t\tsize_t *sizep)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_size(enp, sizep)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_read(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_read(enp, data, size)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_verify(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_verify(enp, data, size)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_reinit(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif (evpdop->evpdo_reinit == NULL) {\n+\t\trc = ENOTSUP;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif ((rc = evpdop->evpdo_reinit(enp, data, size)) != 0)\n+\t\tgoto fail2;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_get(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_get(enp, data, size, evvp)) != 0) {\n+\t\tif (rc == ENOENT)\n+\t\t\treturn (rc);\n+\n+\t\tgoto fail1;\n+\t}\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_set(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__inout_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_set(enp, data, size, evvp)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_next(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__inout_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tefx_vpd_value_t *evvp,\n+\t__inout\t\t\tunsigned int *contp)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_next(enp, data, size, evvp, contp)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_write(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif ((rc = evpdop->evpdo_write(enp, data, size)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+static\t__checkReturn\t\tefx_rc_t\n+efx_vpd_next_tag(\n+\t__in\t\t\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tunsigned int *offsetp,\n+\t__out\t\t\tefx_vpd_tag_t *tagp,\n+\t__out\t\t\tuint16_t *lengthp)\n+{\n+\tefx_byte_t byte;\n+\tefx_word_t word;\n+\tuint8_t name;\n+\tuint16_t length;\n+\tsize_t headlen;\n+\tefx_rc_t rc;\n+\n+\tif (*offsetp >= size) {\n+\t\trc = EFAULT;\n+\t\tgoto fail1;\n+\t}\n+\n+\tEFX_POPULATE_BYTE_1(byte, EFX_BYTE_0, data[*offsetp]);\n+\n+\tswitch (EFX_BYTE_FIELD(byte, TAG_TYPE)) {\n+\tcase TAG_TYPE_SMALL_ITEM_DECODE:\n+\t\theadlen = 1;\n+\n+\t\tname = EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_NAME);\n+\t\tlength = (uint16_t)EFX_BYTE_FIELD(byte, TAG_SMALL_ITEM_SIZE);\n+\n+\t\tbreak;\n+\n+\tcase TAG_TYPE_LARGE_ITEM_DECODE:\n+\t\theadlen = 3;\n+\n+\t\tif (*offsetp + headlen > size) {\n+\t\t\trc = EFAULT;\n+\t\t\tgoto fail2;\n+\t\t}\n+\n+\t\tname = EFX_BYTE_FIELD(byte, TAG_LARGE_ITEM_NAME);\n+\t\tEFX_POPULATE_WORD_2(word,\n+\t\t\t\t    EFX_BYTE_0, data[*offsetp + 1],\n+\t\t\t\t    EFX_BYTE_1, data[*offsetp + 2]);\n+\t\tlength = EFX_WORD_FIELD(word, EFX_WORD_0);\n+\n+\t\tbreak;\n+\n+\tdefault:\n+\t\trc = EFAULT;\n+\t\tgoto fail2;\n+\t}\n+\n+\tif (*offsetp + headlen + length > size) {\n+\t\trc = EFAULT;\n+\t\tgoto fail3;\n+\t}\n+\n+\tEFX_STATIC_ASSERT(TAG_NAME_END_DECODE == EFX_VPD_END);\n+\tEFX_STATIC_ASSERT(TAG_NAME_ID_STRING_DECODE == EFX_VPD_ID);\n+\tEFX_STATIC_ASSERT(TAG_NAME_VPD_R_DECODE == EFX_VPD_RO);\n+\tEFX_STATIC_ASSERT(TAG_NAME_VPD_W_DECODE == EFX_VPD_RW);\n+\tif (name != EFX_VPD_END && name != EFX_VPD_ID &&\n+\t    name != EFX_VPD_RO) {\n+\t\trc = EFAULT;\n+\t\tgoto fail4;\n+\t}\n+\n+\t*tagp = name;\n+\t*lengthp = length;\n+\t*offsetp += headlen;\n+\n+\treturn (0);\n+\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+static\t__checkReturn\t\tefx_rc_t\n+efx_vpd_next_keyword(\n+\t__in_bcount(size)\tcaddr_t tag,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tunsigned int pos,\n+\t__out\t\t\tefx_vpd_keyword_t *keywordp,\n+\t__out\t\t\tuint8_t *lengthp)\n+{\n+\tefx_vpd_keyword_t keyword;\n+\tuint8_t length;\n+\tefx_rc_t rc;\n+\n+\tif (pos + 3U > size) {\n+\t\trc = EFAULT;\n+\t\tgoto fail1;\n+\t}\n+\n+\tkeyword = EFX_VPD_KEYWORD(tag[pos], tag[pos + 1]);\n+\tlength = tag[pos + 2];\n+\n+\tif (length == 0 || pos + 3U + length > size) {\n+\t\trc = EFAULT;\n+\t\tgoto fail2;\n+\t}\n+\n+\t*keywordp = keyword;\n+\t*lengthp = length;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_length(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tsize_t *lengthp)\n+{\n+\tefx_vpd_tag_t tag;\n+\tunsigned int offset;\n+\tuint16_t taglen;\n+\tefx_rc_t rc;\n+\n+\toffset = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_next_tag(data, size, &offset,\n+\t\t    &tag, &taglen)) != 0)\n+\t\t\tgoto fail1;\n+\t\toffset += taglen;\n+\t\tif (tag == EFX_VPD_END)\n+\t\t\tbreak;\n+\t}\n+\n+\t*lengthp = offset;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_verify(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out_opt\t\tboolean_t *cksummedp)\n+{\n+\tefx_vpd_tag_t tag;\n+\tefx_vpd_keyword_t keyword;\n+\tunsigned int offset;\n+\tunsigned int pos;\n+\tunsigned int i;\n+\tuint16_t taglen;\n+\tuint8_t keylen;\n+\tuint8_t cksum;\n+\tboolean_t cksummed = B_FALSE;\n+\tefx_rc_t rc;\n+\n+\t/*\n+\t * Parse every tag,keyword in the existing VPD. If the csum is present,\n+\t * the assert it is correct, and is the final keyword in the RO block.\n+\t */\n+\toffset = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_next_tag(data, size, &offset,\n+\t\t    &tag, &taglen)) != 0)\n+\t\t\tgoto fail1;\n+\t\tif (tag == EFX_VPD_END)\n+\t\t\tbreak;\n+\t\telse if (tag == EFX_VPD_ID)\n+\t\t\tgoto done;\n+\n+\t\tfor (pos = 0; pos != taglen; pos += 3 + keylen) {\n+\t\t\t/* RV keyword must be the last in the block */\n+\t\t\tif (cksummed) {\n+\t\t\t\trc = EFAULT;\n+\t\t\t\tgoto fail2;\n+\t\t\t}\n+\n+\t\t\tif ((rc = efx_vpd_next_keyword(data + offset,\n+\t\t\t    taglen, pos, &keyword, &keylen)) != 0)\n+\t\t\t\tgoto fail3;\n+\n+\t\t\tif (keyword == EFX_VPD_KEYWORD('R', 'V')) {\n+\t\t\t\tcksum = 0;\n+\t\t\t\tfor (i = 0; i < offset + pos + 4; i++)\n+\t\t\t\t\tcksum += data[i];\n+\n+\t\t\t\tif (cksum != 0) {\n+\t\t\t\t\trc = EFAULT;\n+\t\t\t\t\tgoto fail4;\n+\t\t\t\t}\n+\n+\t\t\t\tcksummed = B_TRUE;\n+\t\t\t}\n+\t\t}\n+\n+\tdone:\n+\t\toffset += taglen;\n+\t}\n+\n+\tif (!cksummed) {\n+\t\trc = EFAULT;\n+\t\tgoto fail5;\n+\t}\n+\n+\tif (cksummedp != NULL)\n+\t\t*cksummedp = cksummed;\n+\n+\treturn (0);\n+\n+fail5:\n+\tEFSYS_PROBE(fail5);\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+static\tuint8_t\t__efx_vpd_blank_pid[] = {\n+\t/* Large resource type ID length 1 */\n+\t0x82, 0x01, 0x00,\n+\t/* Product name ' ' */\n+\t0x32,\n+};\n+\n+static uint8_t __efx_vpd_blank_r[] = {\n+\t/* Large resource type VPD-R length 4 */\n+\t0x90, 0x04, 0x00,\n+\t/* RV keyword length 1 */\n+\t'R', 'V', 0x01,\n+\t/* RV payload checksum */\n+\t0x00,\n+};\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_reinit(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tboolean_t wantpid)\n+{\n+\tunsigned int offset = 0;\n+\tunsigned int pos;\n+\tefx_byte_t byte;\n+\tuint8_t cksum;\n+\tefx_rc_t rc;\n+\n+\tif (size < 0x100) {\n+\t\trc = ENOSPC;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (wantpid) {\n+\t\tmemcpy(data + offset, __efx_vpd_blank_pid,\n+\t\t    sizeof (__efx_vpd_blank_pid));\n+\t\toffset += sizeof (__efx_vpd_blank_pid);\n+\t}\n+\n+\tmemcpy(data + offset, __efx_vpd_blank_r, sizeof (__efx_vpd_blank_r));\n+\toffset += sizeof (__efx_vpd_blank_r);\n+\n+\t/* Update checksum */\n+\tcksum = 0;\n+\tfor (pos = 0; pos < offset; pos++)\n+\t\tcksum += data[pos];\n+\tdata[offset - 1] -= cksum;\n+\n+\t/* Append trailing tag */\n+\tEFX_POPULATE_BYTE_3(byte,\n+\t\t\t    TAG_TYPE, TAG_TYPE_SMALL_ITEM_DECODE,\n+\t\t\t    TAG_SMALL_ITEM_NAME, TAG_NAME_END_DECODE,\n+\t\t\t    TAG_SMALL_ITEM_SIZE, 0);\n+\tdata[offset] = EFX_BYTE_FIELD(byte, EFX_BYTE_0);\n+\toffset++;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\t\tefx_rc_t\n+efx_vpd_hunk_next(\n+\t__in_bcount(size)\t\tcaddr_t data,\n+\t__in\t\t\t\tsize_t size,\n+\t__out\t\t\t\tefx_vpd_tag_t *tagp,\n+\t__out\t\t\t\tefx_vpd_keyword_t *keywordp,\n+\t__out_opt\t\t\tunsigned int *payloadp,\n+\t__out_opt\t\t\tuint8_t *paylenp,\n+\t__inout\t\t\t\tunsigned int *contp)\n+{\n+\tefx_vpd_tag_t tag;\n+\tefx_vpd_keyword_t keyword = 0;\n+\tunsigned int offset;\n+\tunsigned int pos;\n+\tunsigned int index;\n+\tuint16_t taglen;\n+\tuint8_t keylen;\n+\tuint8_t paylen;\n+\tefx_rc_t rc;\n+\n+\toffset = index = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_next_tag(data, size, &offset,\n+\t\t    &tag, &taglen)) != 0)\n+\t\t\tgoto fail1;\n+\n+\t\tif (tag == EFX_VPD_END) {\n+\t\t\tkeyword = 0;\n+\t\t\tpaylen = 0;\n+\t\t\tindex = 0;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (tag == EFX_VPD_ID) {\n+\t\t\tif (index++ == *contp) {\n+\t\t\t\tEFSYS_ASSERT3U(taglen, <, 0x100);\n+\t\t\t\tkeyword = 0;\n+\t\t\t\tpaylen = (uint8_t)MIN(taglen, 0xff);\n+\n+\t\t\t\tgoto done;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tfor (pos = 0; pos != taglen; pos += 3 + keylen) {\n+\t\t\t\tif ((rc = efx_vpd_next_keyword(data + offset,\n+\t\t\t\t    taglen, pos, &keyword, &keylen)) != 0)\n+\t\t\t\t\tgoto fail2;\n+\n+\t\t\t\tif (index++ == *contp) {\n+\t\t\t\t\toffset += pos + 3;\n+\t\t\t\t\tpaylen = keylen;\n+\n+\t\t\t\t\tgoto done;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\toffset += taglen;\n+\t}\n+\n+done:\n+\t*tagp = tag;\n+\t*keywordp = keyword;\n+\tif (payloadp != NULL)\n+\t\t*payloadp = offset;\n+\tif (paylenp != NULL)\n+\t\t*paylenp = paylen;\n+\n+\t*contp = index;\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_get(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_tag_t tag,\n+\t__in\t\t\tefx_vpd_keyword_t keyword,\n+\t__out\t\t\tunsigned int *payloadp,\n+\t__out\t\t\tuint8_t *paylenp)\n+{\n+\tefx_vpd_tag_t itag;\n+\tefx_vpd_keyword_t ikeyword;\n+\tunsigned int offset;\n+\tunsigned int pos;\n+\tuint16_t taglen;\n+\tuint8_t keylen;\n+\tefx_rc_t rc;\n+\n+\toffset = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_next_tag(data, size, &offset,\n+\t\t    &itag, &taglen)) != 0)\n+\t\t\tgoto fail1;\n+\t\tif (itag == EFX_VPD_END)\n+\t\t\tbreak;\n+\n+\t\tif (itag == tag) {\n+\t\t\tif (itag == EFX_VPD_ID) {\n+\t\t\t\tEFSYS_ASSERT3U(taglen, <, 0x100);\n+\n+\t\t\t\t*paylenp = (uint8_t)MIN(taglen, 0xff);\n+\t\t\t\t*payloadp = offset;\n+\t\t\t\treturn (0);\n+\t\t\t}\n+\n+\t\t\tfor (pos = 0; pos != taglen; pos += 3 + keylen) {\n+\t\t\t\tif ((rc = efx_vpd_next_keyword(data + offset,\n+\t\t\t\t    taglen, pos, &ikeyword, &keylen)) != 0)\n+\t\t\t\t\tgoto fail2;\n+\n+\t\t\t\tif (ikeyword == keyword) {\n+\t\t\t\t\t*paylenp = keylen;\n+\t\t\t\t\t*payloadp = offset + pos + 3;\n+\t\t\t\t\treturn (0);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\toffset += taglen;\n+\t}\n+\n+\t/* Not an error */\n+\treturn (ENOENT);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+efx_vpd_hunk_set(\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tefx_word_t word;\n+\tefx_vpd_tag_t tag;\n+\tefx_vpd_keyword_t keyword;\n+\tunsigned int offset;\n+\tunsigned int pos;\n+\tunsigned int taghead;\n+\tunsigned int source;\n+\tunsigned int dest;\n+\tunsigned int i;\n+\tuint16_t taglen;\n+\tuint8_t keylen;\n+\tuint8_t cksum;\n+\tsize_t used;\n+\tefx_rc_t rc;\n+\n+\tswitch (evvp->evv_tag) {\n+\tcase EFX_VPD_ID:\n+\t\tif (evvp->evv_keyword != 0) {\n+\t\t\trc = EINVAL;\n+\t\t\tgoto fail1;\n+\t\t}\n+\n+\t\t/* Can't delete the ID keyword */\n+\t\tif (evvp->evv_length == 0) {\n+\t\t\trc = EINVAL;\n+\t\t\tgoto fail1;\n+\t\t}\n+\t\tbreak;\n+\n+\tcase EFX_VPD_RO:\n+\t\tif (evvp->evv_keyword == EFX_VPD_KEYWORD('R', 'V')) {\n+\t\t\trc = EINVAL;\n+\t\t\tgoto fail1;\n+\t\t}\n+\t\tbreak;\n+\n+\tdefault:\n+\t\trc = EINVAL;\n+\t\tgoto fail1;\n+\t}\n+\n+\t/* Determine total size of all current tags */\n+\tif ((rc = efx_vpd_hunk_length(data, size, &used)) != 0)\n+\t\tgoto fail2;\n+\n+\toffset = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\ttaghead = offset;\n+\t\tif ((rc = efx_vpd_next_tag(data, size, &offset,\n+\t\t    &tag, &taglen)) != 0)\n+\t\t\tgoto fail3;\n+\t\tif (tag == EFX_VPD_END)\n+\t\t\tbreak;\n+\t\telse if (tag != evvp->evv_tag) {\n+\t\t\toffset += taglen;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* We only support modifying large resource tags */\n+\t\tif (offset - taghead != 3) {\n+\t\t\trc = EINVAL;\n+\t\t\tgoto fail4;\n+\t\t}\n+\n+\t\t/*\n+\t\t * Work out the offset of the byte immediately after the\n+\t\t * old (=source) and new (=dest) new keyword/tag\n+\t\t */\n+\t\tpos = 0;\n+\t\tif (tag == EFX_VPD_ID) {\n+\t\t\tsource = offset + taglen;\n+\t\t\tdest = offset + evvp->evv_length;\n+\t\t\tgoto check_space;\n+\t\t}\n+\n+\t\tEFSYS_ASSERT3U(tag, ==, EFX_VPD_RO);\n+\t\tsource = dest = 0;\n+\t\tfor (pos = 0; pos != taglen; pos += 3 + keylen) {\n+\t\t\tif ((rc = efx_vpd_next_keyword(data + offset,\n+\t\t\t    taglen, pos, &keyword, &keylen)) != 0)\n+\t\t\t\tgoto fail5;\n+\n+\t\t\tif (keyword == evvp->evv_keyword &&\n+\t\t\t    evvp->evv_length == 0) {\n+\t\t\t\t/* Deleting this keyword */\n+\t\t\t\tsource = offset + pos + 3 + keylen;\n+\t\t\t\tdest = offset + pos;\n+\t\t\t\tbreak;\n+\n+\t\t\t} else if (keyword == evvp->evv_keyword) {\n+\t\t\t\t/* Adjusting this keyword */\n+\t\t\t\tsource = offset + pos + 3 + keylen;\n+\t\t\t\tdest = offset + pos + 3 + evvp->evv_length;\n+\t\t\t\tbreak;\n+\n+\t\t\t} else if (keyword == EFX_VPD_KEYWORD('R', 'V')) {\n+\t\t\t\t/* The RV keyword must be at the end */\n+\t\t\t\tEFSYS_ASSERT3U(pos + 3 + keylen, ==, taglen);\n+\n+\t\t\t\t/*\n+\t\t\t\t * The keyword doesn't already exist. If the\n+\t\t\t\t * user deleting a non-existant keyword then\n+\t\t\t\t * this is a no-op.\n+\t\t\t\t */\n+\t\t\t\tif (evvp->evv_length == 0)\n+\t\t\t\t\treturn (0);\n+\n+\t\t\t\t/* Insert this keyword before the RV keyword */\n+\t\t\t\tsource = offset + pos;\n+\t\t\t\tdest = offset + pos + 3 + evvp->evv_length;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\tcheck_space:\n+\t\tif (used + dest > size + source) {\n+\t\t\trc = ENOSPC;\n+\t\t\tgoto fail6;\n+\t\t}\n+\n+\t\t/* Move trailing data */\n+\t\t(void) memmove(data + dest, data + source, used - source);\n+\n+\t\t/* Copy contents */\n+\t\tmemcpy(data + dest - evvp->evv_length, evvp->evv_value,\n+\t\t    evvp->evv_length);\n+\n+\t\t/* Insert new keyword header if required */\n+\t\tif (tag != EFX_VPD_ID && evvp->evv_length > 0) {\n+\t\t\tEFX_POPULATE_WORD_1(word, EFX_WORD_0,\n+\t\t\t\t\t    evvp->evv_keyword);\n+\t\t\tdata[offset + pos + 0] =\n+\t\t\t    EFX_WORD_FIELD(word, EFX_BYTE_0);\n+\t\t\tdata[offset + pos + 1] =\n+\t\t\t    EFX_WORD_FIELD(word, EFX_BYTE_1);\n+\t\t\tdata[offset + pos + 2] = evvp->evv_length;\n+\t\t}\n+\n+\t\t/* Modify tag length (large resource type) */\n+\t\ttaglen += (dest - source);\n+\t\tEFX_POPULATE_WORD_1(word, EFX_WORD_0, taglen);\n+\t\tdata[offset - 2] = EFX_WORD_FIELD(word, EFX_BYTE_0);\n+\t\tdata[offset - 1] = EFX_WORD_FIELD(word, EFX_BYTE_1);\n+\n+\t\tgoto checksum;\n+\t}\n+\n+\t/* Unable to find the matching tag */\n+\trc = ENOENT;\n+\tgoto fail7;\n+\n+checksum:\n+\t/* Find the RV tag, and update the checksum */\n+\toffset = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_next_tag(data, size, &offset,\n+\t\t    &tag, &taglen)) != 0)\n+\t\t\tgoto fail8;\n+\t\tif (tag == EFX_VPD_END)\n+\t\t\tbreak;\n+\t\tif (tag == EFX_VPD_RO) {\n+\t\t\tfor (pos = 0; pos != taglen; pos += 3 + keylen) {\n+\t\t\t\tif ((rc = efx_vpd_next_keyword(data + offset,\n+\t\t\t\t    taglen, pos, &keyword, &keylen)) != 0)\n+\t\t\t\t\tgoto fail9;\n+\n+\t\t\t\tif (keyword == EFX_VPD_KEYWORD('R', 'V')) {\n+\t\t\t\t\tcksum = 0;\n+\t\t\t\t\tfor (i = 0; i < offset + pos + 3; i++)\n+\t\t\t\t\t\tcksum += data[i];\n+\t\t\t\t\tdata[i] = -cksum;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\toffset += taglen;\n+\t}\n+\n+\t/* Zero out the unused portion */\n+\t(void) memset(data + offset + taglen, 0xff, size - offset - taglen);\n+\n+\treturn (0);\n+\n+fail9:\n+\tEFSYS_PROBE(fail9);\n+fail8:\n+\tEFSYS_PROBE(fail8);\n+fail7:\n+\tEFSYS_PROBE(fail7);\n+fail6:\n+\tEFSYS_PROBE(fail6);\n+fail5:\n+\tEFSYS_PROBE(fail5);\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t\t\t\tvoid\n+efx_vpd_fini(\n+\t__in\t\t\tefx_nic_t *enp)\n+{\n+\tconst efx_vpd_ops_t *evpdop = enp->en_evpdop;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VPD);\n+\n+\tif (evpdop->evpdo_fini != NULL)\n+\t\tevpdop->evpdo_fini(enp);\n+\n+\tenp->en_evpdop = NULL;\n+\tenp->en_mod_flags &= ~EFX_MOD_VPD;\n+}\n+\n+#endif\t/* EFSYS_OPT_VPD */\ndiff --git a/drivers/net/sfc/efx/base/siena_impl.h b/drivers/net/sfc/efx/base/siena_impl.h\nindex 6a427b9..ea6de98 100644\n--- a/drivers/net/sfc/efx/base/siena_impl.h\n+++ b/drivers/net/sfc/efx/base/siena_impl.h\n@@ -232,6 +232,69 @@ siena_nvram_partn_set_version(\n \n #endif\t/* EFSYS_OPT_NVRAM */\n \n+#if EFSYS_OPT_VPD\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_init(\n+\t__in\t\t\tefx_nic_t *enp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_size(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out\t\t\tsize_t *sizep);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_read(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_verify(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_reinit(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_get(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tefx_vpd_value_t *evvp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_set(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp);\n+\n+extern\t__checkReturn\t\tefx_rc_t\n+siena_vpd_next(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tefx_vpd_value_t *evvp,\n+\t__inout\t\t\tunsigned int *contp);\n+\n+extern __checkReturn\t\tefx_rc_t\n+siena_vpd_write(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size);\n+\n+extern\t\t\t\tvoid\n+siena_vpd_fini(\n+\t__in\t\t\tefx_nic_t *enp);\n+\n+#endif\t/* EFSYS_OPT_VPD */\n+\n typedef struct siena_link_state_s {\n \tuint32_t\t\tsls_adv_cap_mask;\n \tuint32_t\t\tsls_lp_cap_mask;\ndiff --git a/drivers/net/sfc/efx/base/siena_vpd.c b/drivers/net/sfc/efx/base/siena_vpd.c\nnew file mode 100644\nindex 0000000..4fb2e42\n--- /dev/null\n+++ b/drivers/net/sfc/efx/base/siena_vpd.c\n@@ -0,0 +1,618 @@\n+/*\n+ * Copyright (c) 2009-2016 Solarflare Communications Inc.\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions are met:\n+ *\n+ * 1. Redistributions of source code must retain the above copyright notice,\n+ *    this list of conditions and the following disclaimer.\n+ * 2. Redistributions in binary form must reproduce the above copyright notice,\n+ *    this list of conditions and the following disclaimer in the documentation\n+ *    and/or other materials provided with the distribution.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ *\n+ * The views and conclusions contained in the software and documentation are\n+ * those of the authors and should not be interpreted as representing official\n+ * policies, either expressed or implied, of the FreeBSD Project.\n+ */\n+\n+#include \"efx.h\"\n+#include \"efx_impl.h\"\n+\n+#if EFSYS_OPT_VPD\n+\n+#if EFSYS_OPT_SIENA\n+\n+static\t__checkReturn\t\t\tefx_rc_t\n+siena_vpd_get_static(\n+\t__in\t\t\t\tefx_nic_t *enp,\n+\t__in\t\t\t\tuint32_t partn,\n+\t__deref_out_bcount_opt(*sizep)\tcaddr_t *svpdp,\n+\t__out\t\t\t\tsize_t *sizep)\n+{\n+\tsiena_mc_static_config_hdr_t *scfg;\n+\tcaddr_t svpd;\n+\tsize_t size;\n+\tuint8_t cksum;\n+\tunsigned int vpd_offset;\n+\tunsigned int vpd_length;\n+\tunsigned int hdr_length;\n+\tunsigned int pos;\n+\tunsigned int region;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 ||\n+\t\t    partn == MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1);\n+\n+\t/* Allocate sufficient memory for the entire static cfg area */\n+\tif ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)\n+\t\tgoto fail1;\n+\n+\tEFSYS_KMEM_ALLOC(enp->en_esip, size, scfg);\n+\tif (scfg == NULL) {\n+\t\trc = ENOMEM;\n+\t\tgoto fail2;\n+\t}\n+\n+\tif ((rc = siena_nvram_partn_read(enp, partn, 0,\n+\t    (caddr_t)scfg, SIENA_NVRAM_CHUNK)) != 0)\n+\t\tgoto fail3;\n+\n+\t/* Verify the magic number */\n+\tif (EFX_DWORD_FIELD(scfg->magic, EFX_DWORD_0) !=\n+\t    SIENA_MC_STATIC_CONFIG_MAGIC) {\n+\t\trc = EINVAL;\n+\t\tgoto fail4;\n+\t}\n+\n+\t/* All future versions of the structure must be backwards compatible */\n+\tEFX_STATIC_ASSERT(SIENA_MC_STATIC_CONFIG_VERSION == 0);\n+\n+\thdr_length = EFX_WORD_FIELD(scfg->length, EFX_WORD_0);\n+\tvpd_offset = EFX_DWORD_FIELD(scfg->static_vpd_offset, EFX_DWORD_0);\n+\tvpd_length = EFX_DWORD_FIELD(scfg->static_vpd_length, EFX_DWORD_0);\n+\n+\t/* Verify the hdr doesn't overflow the sector size */\n+\tif (hdr_length > size || vpd_offset > size || vpd_length > size ||\n+\t    vpd_length + vpd_offset > size) {\n+\t\trc = EINVAL;\n+\t\tgoto fail5;\n+\t}\n+\n+\t/* Read the remainder of scfg + static vpd */\n+\tregion = vpd_offset + vpd_length;\n+\tif (region > SIENA_NVRAM_CHUNK) {\n+\t\tif ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,\n+\t\t    (caddr_t)scfg + SIENA_NVRAM_CHUNK,\n+\t\t    region - SIENA_NVRAM_CHUNK)) != 0)\n+\t\t\tgoto fail6;\n+\t}\n+\n+\t/* Verify checksum */\n+\tcksum = 0;\n+\tfor (pos = 0; pos < hdr_length; pos++)\n+\t\tcksum += ((uint8_t *)scfg)[pos];\n+\tif (cksum != 0) {\n+\t\trc = EINVAL;\n+\t\tgoto fail7;\n+\t}\n+\n+\tif (vpd_length == 0)\n+\t\tsvpd = NULL;\n+\telse {\n+\t\t/* Copy the vpd data out */\n+\t\tEFSYS_KMEM_ALLOC(enp->en_esip, vpd_length, svpd);\n+\t\tif (svpd == NULL) {\n+\t\t\trc = ENOMEM;\n+\t\t\tgoto fail8;\n+\t\t}\n+\t\tmemcpy(svpd, (caddr_t)scfg + vpd_offset, vpd_length);\n+\t}\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, size, scfg);\n+\n+\t*svpdp = svpd;\n+\t*sizep = vpd_length;\n+\n+\treturn (0);\n+\n+fail8:\n+\tEFSYS_PROBE(fail8);\n+fail7:\n+\tEFSYS_PROBE(fail7);\n+fail6:\n+\tEFSYS_PROBE(fail6);\n+fail5:\n+\tEFSYS_PROBE(fail5);\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, size, scfg);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_init(\n+\t__in\t\t\tefx_nic_t *enp)\n+{\n+\tefx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);\n+\tcaddr_t svpd = NULL;\n+\tunsigned int partn;\n+\tsize_t size = 0;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\tpartn = (emip->emi_port == 1)\n+\t\t? MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0\n+\t\t: MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1;\n+\n+\t/*\n+\t * We need the static VPD sector to present a unified static+dynamic\n+\t * VPD, that is, basically on every read, write, verify cycle. Since\n+\t * it should *never* change we can just cache it here.\n+\t */\n+\tif ((rc = siena_vpd_get_static(enp, partn, &svpd, &size)) != 0)\n+\t\tgoto fail1;\n+\n+\tif (svpd != NULL && size > 0) {\n+\t\tif ((rc = efx_vpd_hunk_verify(svpd, size, NULL)) != 0)\n+\t\t\tgoto fail2;\n+\t}\n+\n+\tenp->en_u.siena.enu_svpd = svpd;\n+\tenp->en_u.siena.enu_svpd_length = size;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, size, svpd);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_size(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out\t\t\tsize_t *sizep)\n+{\n+\tefx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);\n+\tuint32_t partn;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\t/*\n+\t * This function returns the total size the user should allocate\n+\t * for all VPD operations. We've already cached the static vpd,\n+\t * so we just need to return an upper bound on the dynamic vpd.\n+\t * Since the dynamic_config structure can change under our feet,\n+\t * (as version numbers are inserted), just be safe and return the\n+\t * total size of the dynamic_config *sector*\n+\t */\n+\tpartn = (emip->emi_port == 1)\n+\t\t? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0\n+\t\t: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;\n+\n+\tif ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_read(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__out_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tefx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);\n+\tsiena_mc_dynamic_config_hdr_t *dcfg = NULL;\n+\tunsigned int vpd_length;\n+\tunsigned int vpd_offset;\n+\tunsigned int dcfg_partn;\n+\tsize_t dcfg_size;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\tdcfg_partn = (emip->emi_port == 1)\n+\t\t? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0\n+\t\t: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;\n+\n+\tif ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,\n+\t    B_TRUE, &dcfg, &dcfg_size)) != 0)\n+\t\tgoto fail1;\n+\n+\tvpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);\n+\tvpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);\n+\n+\tif (vpd_length > size) {\n+\t\trc = EFAULT;\t/* Invalid dcfg: header bigger than sector */\n+\t\tgoto fail2;\n+\t}\n+\n+\tEFSYS_ASSERT3U(vpd_length, <=, size);\n+\tmemcpy(data, (caddr_t)dcfg + vpd_offset, vpd_length);\n+\n+\t/* Pad data with all-1s, consistent with update operations */\n+\tmemset(data + vpd_length, 0xff, size - vpd_length);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_verify(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tefx_vpd_tag_t stag;\n+\tefx_vpd_tag_t dtag;\n+\tefx_vpd_keyword_t skey;\n+\tefx_vpd_keyword_t dkey;\n+\tunsigned int scont;\n+\tunsigned int dcont;\n+\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\t/*\n+\t * Strictly you could take the view that dynamic vpd is optional.\n+\t * Instead, to conform more closely to the read/verify/reinit()\n+\t * paradigm, we require dynamic vpd. siena_vpd_reinit() will\n+\t * reinitialize it as required.\n+\t */\n+\tif ((rc = efx_vpd_hunk_verify(data, size, NULL)) != 0)\n+\t\tgoto fail1;\n+\n+\t/*\n+\t * Verify that there is no duplication between the static and\n+\t * dynamic cfg sectors.\n+\t */\n+\tif (enp->en_u.siena.enu_svpd_length == 0)\n+\t\tgoto done;\n+\n+\tdcont = 0;\n+\t_NOTE(CONSTANTCONDITION)\n+\twhile (1) {\n+\t\tif ((rc = efx_vpd_hunk_next(data, size, &dtag,\n+\t\t    &dkey, NULL, NULL, &dcont)) != 0)\n+\t\t\tgoto fail2;\n+\t\tif (dcont == 0)\n+\t\t\tbreak;\n+\n+\t\t/*\n+\t\t * Skip the RV keyword. It should be present in both the static\n+\t\t * and dynamic cfg sectors.\n+\t\t */\n+\t\tif (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))\n+\t\t\tcontinue;\n+\n+\t\tscont = 0;\n+\t\t_NOTE(CONSTANTCONDITION)\n+\t\twhile (1) {\n+\t\t\tif ((rc = efx_vpd_hunk_next(\n+\t\t\t    enp->en_u.siena.enu_svpd,\n+\t\t\t    enp->en_u.siena.enu_svpd_length, &stag, &skey,\n+\t\t\t    NULL, NULL, &scont)) != 0)\n+\t\t\t\tgoto fail3;\n+\t\t\tif (scont == 0)\n+\t\t\t\tbreak;\n+\n+\t\t\tif (stag == dtag && skey == dkey) {\n+\t\t\t\trc = EEXIST;\n+\t\t\t\tgoto fail4;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+done:\n+\treturn (0);\n+\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_reinit(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tboolean_t wantpid;\n+\tefx_rc_t rc;\n+\n+\t/*\n+\t * Only create a PID if the dynamic cfg doesn't have one\n+\t */\n+\tif (enp->en_u.siena.enu_svpd_length == 0)\n+\t\twantpid = B_TRUE;\n+\telse {\n+\t\tunsigned int offset;\n+\t\tuint8_t length;\n+\n+\t\trc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,\n+\t\t\t\t    enp->en_u.siena.enu_svpd_length,\n+\t\t\t\t    EFX_VPD_ID, 0, &offset, &length);\n+\t\tif (rc == 0)\n+\t\t\twantpid = B_FALSE;\n+\t\telse if (rc == ENOENT)\n+\t\t\twantpid = B_TRUE;\n+\t\telse\n+\t\t\tgoto fail1;\n+\t}\n+\n+\tif ((rc = efx_vpd_hunk_reinit(data, size, wantpid)) != 0)\n+\t\tgoto fail2;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_get(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__inout\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tunsigned int offset;\n+\tuint8_t length;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\t/* Attempt to satisfy the request from svpd first */\n+\tif (enp->en_u.siena.enu_svpd_length > 0) {\n+\t\tif ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,\n+\t\t    enp->en_u.siena.enu_svpd_length, evvp->evv_tag,\n+\t\t    evvp->evv_keyword, &offset, &length)) == 0) {\n+\t\t\tevvp->evv_length = length;\n+\t\t\tmemcpy(evvp->evv_value,\n+\t\t\t    enp->en_u.siena.enu_svpd + offset, length);\n+\t\t\treturn (0);\n+\t\t} else if (rc != ENOENT)\n+\t\t\tgoto fail1;\n+\t}\n+\n+\t/* And then from the provided data buffer */\n+\tif ((rc = efx_vpd_hunk_get(data, size, evvp->evv_tag,\n+\t    evvp->evv_keyword, &offset, &length)) != 0) {\n+\t\tif (rc == ENOENT)\n+\t\t\treturn (rc);\n+\n+\t\tgoto fail2;\n+\t}\n+\n+\tevvp->evv_length = length;\n+\tmemcpy(evvp->evv_value, data + offset, length);\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_set(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__in\t\t\tefx_vpd_value_t *evvp)\n+{\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\t/* If the provided (tag,keyword) exists in svpd, then it is readonly */\n+\tif (enp->en_u.siena.enu_svpd_length > 0) {\n+\t\tunsigned int offset;\n+\t\tuint8_t length;\n+\n+\t\tif ((rc = efx_vpd_hunk_get(enp->en_u.siena.enu_svpd,\n+\t\t    enp->en_u.siena.enu_svpd_length, evvp->evv_tag,\n+\t\t    evvp->evv_keyword, &offset, &length)) == 0) {\n+\t\t\trc = EACCES;\n+\t\t\tgoto fail1;\n+\t\t}\n+\t}\n+\n+\tif ((rc = efx_vpd_hunk_set(data, size, evvp)) != 0)\n+\t\tgoto fail2;\n+\n+\treturn (0);\n+\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_next(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size,\n+\t__out\t\t\tefx_vpd_value_t *evvp,\n+\t__inout\t\t\tunsigned int *contp)\n+{\n+\t_NOTE(ARGUNUSED(enp, data, size, evvp, contp))\n+\n+\treturn (ENOTSUP);\n+}\n+\n+\t__checkReturn\t\tefx_rc_t\n+siena_vpd_write(\n+\t__in\t\t\tefx_nic_t *enp,\n+\t__in_bcount(size)\tcaddr_t data,\n+\t__in\t\t\tsize_t size)\n+{\n+\tefx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);\n+\tsiena_mc_dynamic_config_hdr_t *dcfg = NULL;\n+\tunsigned int vpd_offset;\n+\tunsigned int dcfg_partn;\n+\tunsigned int hdr_length;\n+\tunsigned int pos;\n+\tuint8_t cksum;\n+\tsize_t partn_size, dcfg_size;\n+\tsize_t vpd_length;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\t/* Determine total length of all tags */\n+\tif ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)\n+\t\tgoto fail1;\n+\n+\t/* Lock dynamic config sector for write, and read structure only */\n+\tdcfg_partn = (emip->emi_port == 1)\n+\t\t? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0\n+\t\t: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;\n+\n+\tif ((rc = siena_nvram_partn_size(enp, dcfg_partn, &partn_size)) != 0)\n+\t\tgoto fail2;\n+\n+\tif ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)\n+\t\tgoto fail3;\n+\n+\tif ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,\n+\t    B_FALSE, &dcfg, &dcfg_size)) != 0)\n+\t\tgoto fail4;\n+\n+\thdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);\n+\n+\t/* Allocated memory should have room for the new VPD */\n+\tif (hdr_length + vpd_length > dcfg_size) {\n+\t\trc = ENOSPC;\n+\t\tgoto fail5;\n+\t}\n+\n+\t/* Copy in new vpd and update header */\n+\tvpd_offset = dcfg_size - vpd_length;\n+\tEFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset, EFX_DWORD_0, vpd_offset);\n+\tmemcpy((caddr_t)dcfg + vpd_offset, data, vpd_length);\n+\tEFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, vpd_length);\n+\n+\t/* Update the checksum */\n+\tcksum = 0;\n+\tfor (pos = 0; pos < hdr_length; pos++)\n+\t\tcksum += ((uint8_t *)dcfg)[pos];\n+\tdcfg->csum.eb_u8[0] -= cksum;\n+\n+\t/* Erase and write the new sector */\n+\tif ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, partn_size)) != 0)\n+\t\tgoto fail6;\n+\n+\t/* Write out the new structure to nvram */\n+\tif ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0, (caddr_t)dcfg,\n+\t    vpd_offset + vpd_length)) != 0)\n+\t\tgoto fail7;\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);\n+\n+\tsiena_nvram_partn_unlock(enp, dcfg_partn);\n+\n+\treturn (0);\n+\n+fail7:\n+\tEFSYS_PROBE(fail7);\n+fail6:\n+\tEFSYS_PROBE(fail6);\n+fail5:\n+\tEFSYS_PROBE(fail5);\n+\n+\tEFSYS_KMEM_FREE(enp->en_esip, dcfg_size, dcfg);\n+fail4:\n+\tEFSYS_PROBE(fail4);\n+\n+\tsiena_nvram_partn_unlock(enp, dcfg_partn);\n+fail3:\n+\tEFSYS_PROBE(fail3);\n+fail2:\n+\tEFSYS_PROBE(fail2);\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\treturn (rc);\n+}\n+\n+\t\t\t\tvoid\n+siena_vpd_fini(\n+\t__in\t\t\tefx_nic_t *enp)\n+{\n+\tEFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);\n+\n+\tif (enp->en_u.siena.enu_svpd_length > 0) {\n+\t\tEFSYS_KMEM_FREE(enp->en_esip, enp->en_u.siena.enu_svpd_length,\n+\t\t\t\tenp->en_u.siena.enu_svpd);\n+\n+\t\tenp->en_u.siena.enu_svpd = NULL;\n+\t\tenp->en_u.siena.enu_svpd_length = 0;\n+\t}\n+}\n+\n+#endif\t/* EFSYS_OPT_SIENA */\n+\n+#endif\t/* EFSYS_OPT_VPD */\n",
    "prefixes": [
        "dpdk-dev",
        "27/56"
    ]
}