get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 17126,
    "url": "http://patches.dpdk.org/api/patches/17126/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1479740470-6723-33-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-33-git-send-email-arybchenko@solarflare.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1479740470-6723-33-git-send-email-arybchenko@solarflare.com",
    "date": "2016-11-21T15:00:46",
    "name": "[dpdk-dev,32/56] net/sfc: implement driver operation to init device on attach",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "d0d59c64fb4ec0d2251f4f5361bb538243e7440d",
    "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-33-git-send-email-arybchenko@solarflare.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/17126/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/17126/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 39A48D514;\n\tMon, 21 Nov 2016 16:03:09 +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 167B6376D\n\tfor <dev@dpdk.org>; Mon, 21 Nov 2016 16:01:34 +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\te4c03385.0.1541303.00-2318.3424214.nbfkord-smmo02.seg.att.com\n\t(envelope-from <arybchenko@solarflare.com>); \n\tMon, 21 Nov 2016 15:01:35 +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:22 -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\tuALF1KdA007190 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\tuALF1J3N006765 for <dev@dpdk.org>; Mon, 21 Nov 2016 15:01:20 GMT"
        ],
        "X-MXL-Hash": "58330c4f2849706c-c3c2f972dc018135aaa6c0e52e50be0ea0577dc8",
        "From": "Andrew Rybchenko <arybchenko@solarflare.com>",
        "To": "<dev@dpdk.org>",
        "Date": "Mon, 21 Nov 2016 15:00:46 +0000",
        "Message-ID": "<1479740470-6723-33-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=m46YgpYouJgSWnsLt]",
            "[cMA:9 a=PA03WX8tBzeizutn5_OT:22]"
        ],
        "X-Spam": "[F=0.2000000000; CM=0.500; S=0.200(2015072901)]",
        "X-MAIL-FROM": "<arybchenko@solarflare.com>",
        "X-SOURCE-IP": "[12.187.104.26]",
        "Subject": "[dpdk-dev] [PATCH 32/56] net/sfc: implement driver operation to\n\tinit device on attach",
        "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": "The setup and configuration of the PMD is not performance sensitive,\nbut is not thread safe either. It is possible that the multiple\nread/writes during PMD setup and configuration could be corrupted\nin a multi-thread environment.  Since this is not performance\nsensitive, the developer can choose to add their own layer to provide\nthread-safe setup and configuration. It is expected that, in most\napplications, the initial configuration of the network ports would be\ndone by a single thread at startup.\n\nReviewed-by: Andy Moreton <amoreton@solarflare.com>\nSigned-off-by: Andrew Rybchenko <arybchenko@solarflare.com>\n---\n drivers/net/sfc/efx/Makefile     |   2 +\n drivers/net/sfc/efx/sfc.c        | 227 +++++++++++++++++++++++++++++++++++++++\n drivers/net/sfc/efx/sfc.h        | 100 +++++++++++++++++\n drivers/net/sfc/efx/sfc_debug.h  |  12 +++\n drivers/net/sfc/efx/sfc_ethdev.c |  52 ++++++++-\n drivers/net/sfc/efx/sfc_mcdi.c   | 197 +++++++++++++++++++++++++++++++++\n 6 files changed, 589 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/sfc/efx/sfc.c\n create mode 100644 drivers/net/sfc/efx/sfc_mcdi.c",
    "diff": "diff --git a/drivers/net/sfc/efx/Makefile b/drivers/net/sfc/efx/Makefile\nindex de95ea8..eadb1ea 100644\n--- a/drivers/net/sfc/efx/Makefile\n+++ b/drivers/net/sfc/efx/Makefile\n@@ -82,6 +82,8 @@ LIBABIVER := 1\n #\n SRCS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc_ethdev.c\n SRCS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc_kvargs.c\n+SRCS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc.c\n+SRCS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc_mcdi.c\n \n VPATH += $(SRCDIR)/base\n \ndiff --git a/drivers/net/sfc/efx/sfc.c b/drivers/net/sfc/efx/sfc.c\nnew file mode 100644\nindex 0000000..2a17d26\n--- /dev/null\n+++ b/drivers/net/sfc/efx/sfc.c\n@@ -0,0 +1,227 @@\n+/*-\n+ * Copyright (c) 2016 Solarflare Communications Inc.\n+ * All rights reserved.\n+ *\n+ * This software was jointly developed between OKTET Labs (under contract\n+ * for Solarflare) and Solarflare Communications, Inc.\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+\n+/* sysconf() */\n+#include <unistd.h>\n+\n+#include <rte_errno.h>\n+\n+#include \"efx.h\"\n+\n+#include \"sfc.h\"\n+#include \"sfc_log.h\"\n+\n+\n+int\n+sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,\n+\t      size_t len, int socket_id, efsys_mem_t *esmp)\n+{\n+\tconst struct rte_memzone *mz;\n+\n+\tsfc_log_init(sa, \"name=%s id=%u len=%lu socket_id=%d\",\n+\t\t     name, id, len, socket_id);\n+\n+\tmz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,\n+\t\t\t\t      sysconf(_SC_PAGESIZE), socket_id);\n+\tif (mz == NULL) {\n+\t\tsfc_err(sa, \"cannot reserve DMA zone for %s:%u %#x@%d: %s\",\n+\t\t\tname, (unsigned int)id, (unsigned int)len, socket_id,\n+\t\t\trte_strerror(rte_errno));\n+\t\treturn ENOMEM;\n+\t}\n+\n+\tesmp->esm_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr);\n+\tif (esmp->esm_addr == RTE_BAD_PHYS_ADDR) {\n+\t\t(void)rte_memzone_free(mz);\n+\t\treturn EFAULT;\n+\t}\n+\n+\tesmp->esm_mz = mz;\n+\tesmp->esm_base = mz->addr;\n+\n+\treturn 0;\n+}\n+\n+void\n+sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp)\n+{\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"name=%s\", esmp->esm_mz->name);\n+\n+\trc = rte_memzone_free(esmp->esm_mz);\n+\tif (rc != 0)\n+\t\tsfc_err(sa, \"rte_memzone_free(() failed: %d\", rc);\n+\n+\tmemset(esmp, 0, sizeof(*esmp));\n+}\n+\n+static int\n+sfc_mem_bar_init(struct sfc_adapter *sa)\n+{\n+\tstruct rte_eth_dev *eth_dev = sa->eth_dev;\n+\tstruct rte_pci_device *pci_dev = eth_dev->pci_dev;\n+\tefsys_bar_t *ebp = &sa->mem_bar;\n+\tunsigned int i;\n+\tstruct rte_mem_resource *res;\n+\n+\tfor (i = 0; i < RTE_DIM(pci_dev->mem_resource); i++) {\n+\t\tres = &pci_dev->mem_resource[i];\n+\t\tif ((res->len != 0) && (res->phys_addr != 0)) {\n+\t\t\t/* Found first memory BAR */\n+\t\t\tSFC_BAR_LOCK_INIT(ebp, eth_dev->data->name);\n+\t\t\tebp->esb_rid = i;\n+\t\t\tebp->esb_dev = pci_dev;\n+\t\t\tebp->esb_base = res->addr;\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\treturn EFAULT;\n+}\n+\n+static void\n+sfc_mem_bar_fini(struct sfc_adapter *sa)\n+{\n+\tefsys_bar_t *ebp = &sa->mem_bar;\n+\n+\tSFC_BAR_LOCK_DESTROY(ebp);\n+\tmemset(ebp, 0, sizeof(*ebp));\n+}\n+\n+int\n+sfc_attach(struct sfc_adapter *sa)\n+{\n+\tstruct rte_pci_device *pci_dev = sa->eth_dev->pci_dev;\n+\tefx_nic_t *enp;\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tsa->socket_id = rte_socket_id();\n+\n+\tsfc_log_init(sa, \"init mem bar\");\n+\trc = sfc_mem_bar_init(sa);\n+\tif (rc != 0)\n+\t\tgoto fail_mem_bar_init;\n+\n+\tsfc_log_init(sa, \"get family\");\n+\trc = efx_family(pci_dev->id.vendor_id, pci_dev->id.device_id,\n+\t\t\t&sa->family);\n+\tif (rc != 0)\n+\t\tgoto fail_family;\n+\tsfc_log_init(sa, \"family is %u\", sa->family);\n+\n+\tsfc_log_init(sa, \"create nic\");\n+\trte_spinlock_init(&sa->nic_lock);\n+\trc = efx_nic_create(sa->family, (efsys_identifier_t *)sa,\n+\t\t\t    &sa->mem_bar, &sa->nic_lock, &enp);\n+\tif (rc != 0)\n+\t\tgoto fail_nic_create;\n+\tsa->nic = enp;\n+\n+\trc = sfc_mcdi_init(sa);\n+\tif (rc != 0)\n+\t\tgoto fail_mcdi_init;\n+\n+\tsfc_log_init(sa, \"probe nic\");\n+\trc = efx_nic_probe(enp);\n+\tif (rc != 0)\n+\t\tgoto fail_nic_probe;\n+\n+\tefx_mcdi_new_epoch(enp);\n+\n+\tsfc_log_init(sa, \"reset nic\");\n+\trc = efx_nic_reset(enp);\n+\tif (rc != 0)\n+\t\tgoto fail_nic_reset;\n+\n+\t/* Initialize NIC to double-check hardware */\n+\tsfc_log_init(sa, \"init nic\");\n+\trc = efx_nic_init(enp);\n+\tif (rc != 0)\n+\t\tgoto fail_nic_init;\n+\n+\tsfc_log_init(sa, \"fini nic\");\n+\tefx_nic_fini(enp);\n+\n+\tsa->rxq_max = 1;\n+\tsa->txq_max = 1;\n+\n+\tsa->state = SFC_ADAPTER_INITIALIZED;\n+\n+\tsfc_log_init(sa, \"done\");\n+\treturn 0;\n+\n+fail_nic_init:\n+fail_nic_reset:\n+\tsfc_log_init(sa, \"unprobe nic\");\n+\tefx_nic_unprobe(enp);\n+\n+fail_nic_probe:\n+\tsfc_mcdi_fini(sa);\n+\n+fail_mcdi_init:\n+\tsfc_log_init(sa, \"destroy nic\");\n+\tsa->nic = NULL;\n+\tefx_nic_destroy(enp);\n+\n+fail_nic_create:\n+fail_family:\n+\tsfc_mem_bar_fini(sa);\n+\n+fail_mem_bar_init:\n+\tsfc_log_init(sa, \"failed %d\", rc);\n+\treturn rc;\n+}\n+\n+void\n+sfc_detach(struct sfc_adapter *sa)\n+{\n+\tefx_nic_t *enp = sa->nic;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tSFC_ASSERT(sfc_adapter_is_locked(sa));\n+\n+\tsfc_log_init(sa, \"unprobe nic\");\n+\tefx_nic_unprobe(enp);\n+\n+\tsfc_mcdi_fini(sa);\n+\n+\tsfc_log_init(sa, \"destroy nic\");\n+\tsa->nic = NULL;\n+\tefx_nic_destroy(enp);\n+\n+\tsfc_mem_bar_fini(sa);\n+\n+\tsa->state = SFC_ADAPTER_UNINITIALIZED;\n+}\ndiff --git a/drivers/net/sfc/efx/sfc.h b/drivers/net/sfc/efx/sfc.h\nindex 16fd2bb..01d652d 100644\n--- a/drivers/net/sfc/efx/sfc.h\n+++ b/drivers/net/sfc/efx/sfc.h\n@@ -34,18 +34,118 @@\n \n #include <rte_ethdev.h>\n #include <rte_kvargs.h>\n+#include <rte_spinlock.h>\n+\n+#include \"efx.h\"\n \n #ifdef __cplusplus\n extern \"C\" {\n #endif\n \n+/*\n+ * +---------------+\n+ * | UNINITIALIZED |<-----------+\n+ * +---------------+\t\t|\n+ *\t|.eth_dev_init\t\t|.eth_dev_uninit\n+ *\tV\t\t\t|\n+ * +---------------+------------+\n+ * |  INITIALIZED  |\n+ * +---------------+\n+ */\n+enum sfc_adapter_state {\n+\tSFC_ADAPTER_UNINITIALIZED = 0,\n+\tSFC_ADAPTER_INITIALIZED,\n+\n+\tSFC_ADAPTER_NSTATES\n+};\n+\n+enum sfc_mcdi_state {\n+\tSFC_MCDI_UNINITIALIZED = 0,\n+\tSFC_MCDI_INITIALIZED,\n+\tSFC_MCDI_BUSY,\n+\tSFC_MCDI_COMPLETED,\n+\n+\tSFC_MCDI_NSTATES\n+};\n+\n+struct sfc_mcdi {\n+\trte_spinlock_t\t\t\tlock;\n+\tefsys_mem_t\t\t\tmem;\n+\tenum sfc_mcdi_state\t\tstate;\n+\tefx_mcdi_transport_t\t\ttransport;\n+};\n+\n /* Adapter private data */\n struct sfc_adapter {\n+\t/*\n+\t * PMD setup and configuration is not thread safe.\n+\t * Since it is not performance sensitive, it is better to guarantee\n+\t * thread-safety and add device level lock.\n+\t * Adapter control operations which change its state should\n+\t * acquire the lock.\n+\t */\n+\trte_spinlock_t\t\t\tlock;\n+\tenum sfc_adapter_state\t\tstate;\n \tstruct rte_eth_dev\t\t*eth_dev;\n \tstruct rte_kvargs\t\t*kvargs;\n \tbool\t\t\t\tdebug_init;\n+\tint\t\t\t\tsocket_id;\n+\tefsys_bar_t\t\t\tmem_bar;\n+\tefx_family_t\t\t\tfamily;\n+\tefx_nic_t\t\t\t*nic;\n+\trte_spinlock_t\t\t\tnic_lock;\n+\n+\tstruct sfc_mcdi\t\t\tmcdi;\n+\n+\tunsigned int\t\t\trxq_max;\n+\tunsigned int\t\t\ttxq_max;\n };\n \n+/*\n+ * Add wrapper functions to acquire/release lock to be able to remove or\n+ * change the lock in one place.\n+ */\n+\n+static inline void\n+sfc_adapter_lock_init(struct sfc_adapter *sa)\n+{\n+\trte_spinlock_init(&sa->lock);\n+}\n+\n+static inline int\n+sfc_adapter_is_locked(struct sfc_adapter *sa)\n+{\n+\treturn rte_spinlock_is_locked(&sa->lock);\n+}\n+\n+static inline void\n+sfc_adapter_lock(struct sfc_adapter *sa)\n+{\n+\trte_spinlock_lock(&sa->lock);\n+}\n+\n+static inline void\n+sfc_adapter_unlock(struct sfc_adapter *sa)\n+{\n+\trte_spinlock_unlock(&sa->lock);\n+}\n+\n+static inline void\n+sfc_adapter_lock_destroy(struct sfc_adapter *sa)\n+{\n+\t/* Just for symmetry of the API */\n+}\n+\n+int sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,\n+\t\t  size_t len, int socket_id, efsys_mem_t *esmp);\n+void sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp);\n+\n+int sfc_attach(struct sfc_adapter *sa);\n+void sfc_detach(struct sfc_adapter *sa);\n+\n+int sfc_mcdi_init(struct sfc_adapter *sa);\n+void sfc_mcdi_fini(struct sfc_adapter *sa);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/drivers/net/sfc/efx/sfc_debug.h b/drivers/net/sfc/efx/sfc_debug.h\nindex de3ec61..2c3988b 100644\n--- a/drivers/net/sfc/efx/sfc_debug.h\n+++ b/drivers/net/sfc/efx/sfc_debug.h\n@@ -42,4 +42,16 @@\n #define\tSFC_ASSERT(exp)\t\t\tRTE_ASSERT(exp)\n #endif\n \n+/* Log PMD message, automatically add prefix and \\n */\n+#define\tsfc_panic(sa, fmt, args...) \\\n+\tdo {\t\t\t\t\t\t\t\t\\\n+\t\tconst struct rte_eth_dev *_dev = (sa)->eth_dev;\t\t\\\n+\t\tconst struct rte_pci_device *_pci_dev = _dev->pci_dev;\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\trte_panic(\"sfc \" PCI_PRI_FMT \" #%\" PRIu8 \": \" fmt \"\\n\",\t\\\n+\t\t\t  _pci_dev->addr.domain, _pci_dev->addr.bus,\t\\\n+\t\t\t  _pci_dev->addr.devid, _pci_dev->addr.function,\\\n+\t\t\t  _dev->data->port_id, ##args);\t\t\t\\\n+\t} while (0)\n+\n #endif /* _SFC_DEBUG_H_ */\ndiff --git a/drivers/net/sfc/efx/sfc_ethdev.c b/drivers/net/sfc/efx/sfc_ethdev.c\nindex 0deff07..e5b609c 100644\n--- a/drivers/net/sfc/efx/sfc_ethdev.c\n+++ b/drivers/net/sfc/efx/sfc_ethdev.c\n@@ -31,6 +31,8 @@\n #include <rte_ethdev.h>\n #include <rte_pci.h>\n \n+#include \"efx.h\"\n+\n #include \"sfc.h\"\n #include \"sfc_debug.h\"\n #include \"sfc_log.h\"\n@@ -55,6 +57,8 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)\n \tstruct sfc_adapter *sa = dev->data->dev_private;\n \tstruct rte_pci_device *pci_dev = dev->pci_dev;\n \tint rc;\n+\tconst efx_nic_cfg_t *encp;\n+\tconst struct ether_addr *from;\n \n \t/* Required for logging */\n \tsa->eth_dev = dev;\n@@ -73,11 +77,43 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)\n \n \tsfc_log_init(sa, \"entry\");\n \n+\tdev->data->mac_addrs = rte_zmalloc(\"sfc\", ETHER_ADDR_LEN, 0);\n+\tif (dev->data->mac_addrs == NULL) {\n+\t\trc = ENOMEM;\n+\t\tgoto fail_mac_addrs;\n+\t}\n+\n+\tsfc_adapter_lock_init(sa);\n+\tsfc_adapter_lock(sa);\n+\n+\tsfc_log_init(sa, \"attaching\");\n+\trc = sfc_attach(sa);\n+\tif (rc != 0)\n+\t\tgoto fail_attach;\n+\n+\tencp = efx_nic_cfg_get(sa->nic);\n+\n+\t/*\n+\t * The arguments are really reverse order in comparison to\n+\t * Linux kernel. Copy from NIC config to Ethernet device data.\n+\t */\n+\tfrom = (const struct ether_addr *)(encp->enc_mac_addr);\n+\tether_addr_copy(from, &dev->data->mac_addrs[0]);\n+\n \tdev->dev_ops = &sfc_eth_dev_ops;\n \n+\tsfc_adapter_unlock(sa);\n+\n \tsfc_log_init(sa, \"done\");\n \treturn 0;\n \n+fail_attach:\n+\tsfc_adapter_unlock(sa);\n+\tsfc_adapter_lock_destroy(sa);\n+\trte_free(dev->data->mac_addrs);\n+\tdev->data->mac_addrs = NULL;\n+\n+fail_mac_addrs:\n fail_kvarg_debug_init:\n \tsfc_kvargs_cleanup(sa);\n \n@@ -94,10 +130,20 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)\n \n \tsfc_log_init(sa, \"entry\");\n \n+\tsfc_adapter_lock(sa);\n+\n+\tsfc_detach(sa);\n+\n+\trte_free(dev->data->mac_addrs);\n+\tdev->data->mac_addrs = NULL;\n+\n \tdev->dev_ops = NULL;\n \n \tsfc_kvargs_cleanup(sa);\n \n+\tsfc_adapter_unlock(sa);\n+\tsfc_adapter_lock_destroy(sa);\n+\n \tsfc_log_init(sa, \"done\");\n \n \t/* Required for logging, so cleanup last */\n@@ -106,13 +152,17 @@ sfc_eth_dev_uninit(struct rte_eth_dev *dev)\n }\n \n static const struct rte_pci_id pci_id_sfc_efx_map[] = {\n+\t{ RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_FARMINGDALE) },\n+\t{ RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_GREENPORT) },\n+\t{ RTE_PCI_DEVICE(EFX_PCI_VENID_SFC, EFX_PCI_DEVID_MEDFORD) },\n \t{ .vendor_id = 0 /* sentinel */ }\n };\n \n static struct eth_driver sfc_efx_pmd = {\n \t.pci_drv = {\n \t\t.id_table = pci_id_sfc_efx_map,\n-\t\t.drv_flags = 0,\n+\t\t.drv_flags =\n+\t\t\tRTE_PCI_DRV_NEED_MAPPING,\n \t\t.probe = rte_eth_dev_pci_probe,\n \t\t.remove = rte_eth_dev_pci_remove,\n \t},\ndiff --git a/drivers/net/sfc/efx/sfc_mcdi.c b/drivers/net/sfc/efx/sfc_mcdi.c\nnew file mode 100644\nindex 0000000..bf641d9\n--- /dev/null\n+++ b/drivers/net/sfc/efx/sfc_mcdi.c\n@@ -0,0 +1,197 @@\n+/*-\n+ * Copyright (c) 2016 Solarflare Communications Inc.\n+ * All rights reserved.\n+ *\n+ * This software was jointly developed between OKTET Labs (under contract\n+ * for Solarflare) and Solarflare Communications, Inc.\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+\n+#include <rte_cycles.h>\n+\n+#include \"efx.h\"\n+#include \"efx_mcdi.h\"\n+#include \"efx_regs_mcdi.h\"\n+\n+#include \"sfc.h\"\n+#include \"sfc_log.h\"\n+\n+#define\tSFC_MCDI_POLL_INTERVAL_MIN_US\t10\t\t/* 10us in 1us units */\n+#define\tSFC_MCDI_POLL_INTERVAL_MAX_US\t(US_PER_S / 10)\t/* 100ms in 1us units */\n+#define\tSFC_MCDI_WATCHDOG_INTERVAL_US\t(10 * US_PER_S)\t/* 10s in 1us units */\n+\n+static void\n+sfc_mcdi_timeout(struct sfc_adapter *sa)\n+{\n+\tsfc_warn(sa, \"MC TIMEOUT\");\n+\n+\tsfc_panic(sa, \"MCDI timeout handling is not implemented\\n\");\n+}\n+\n+static void\n+sfc_mcdi_poll(struct sfc_adapter *sa)\n+{\n+\tefx_nic_t *enp;\n+\tunsigned int delay_total;\n+\tunsigned int delay_us;\n+\tboolean_t aborted;\n+\n+\tdelay_total = 0;\n+\tdelay_us = SFC_MCDI_POLL_INTERVAL_MIN_US;\n+\tenp = sa->nic;\n+\n+\tdo {\n+\t\tif (efx_mcdi_request_poll(enp))\n+\t\t\treturn;\n+\n+\t\tif (delay_total > SFC_MCDI_WATCHDOG_INTERVAL_US) {\n+\t\t\taborted = efx_mcdi_request_abort(enp);\n+\t\t\tSFC_ASSERT(aborted);\n+\t\t\tsfc_mcdi_timeout(sa);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\trte_delay_us(delay_us);\n+\n+\t\tdelay_total += delay_us;\n+\n+\t\t/* Exponentially back off the poll frequency */\n+\t\tRTE_BUILD_BUG_ON(SFC_MCDI_POLL_INTERVAL_MAX_US > UINT_MAX / 2);\n+\t\tdelay_us *= 2;\n+\t\tif (delay_us > SFC_MCDI_POLL_INTERVAL_MAX_US)\n+\t\t\tdelay_us = SFC_MCDI_POLL_INTERVAL_MAX_US;\n+\n+\t} while (1);\n+}\n+\n+static void\n+sfc_mcdi_execute(void *arg, efx_mcdi_req_t *emrp)\n+{\n+\tstruct sfc_adapter *sa = (struct sfc_adapter *)arg;\n+\tstruct sfc_mcdi *mcdi = &sa->mcdi;\n+\n+\trte_spinlock_lock(&mcdi->lock);\n+\n+\tSFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED);\n+\n+\tefx_mcdi_request_start(sa->nic, emrp, B_FALSE);\n+\tsfc_mcdi_poll(sa);\n+\n+\trte_spinlock_unlock(&mcdi->lock);\n+}\n+\n+static void\n+sfc_mcdi_ev_cpl(void *arg)\n+{\n+\tstruct sfc_adapter *sa = (struct sfc_adapter *)arg;\n+\tstruct sfc_mcdi *mcdi = &sa->mcdi;\n+\n+\tSFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED);\n+\n+\t/* MCDI is polled, completions are not expected */\n+\tSFC_ASSERT(0);\n+}\n+\n+static void\n+sfc_mcdi_exception(void *arg, efx_mcdi_exception_t eme)\n+{\n+\tstruct sfc_adapter *sa = (struct sfc_adapter *)arg;\n+\n+\tsfc_warn(sa, \"MC %s\",\n+\t    (eme == EFX_MCDI_EXCEPTION_MC_REBOOT) ? \"REBOOT\" :\n+\t    (eme == EFX_MCDI_EXCEPTION_MC_BADASSERT) ? \"BADASSERT\" : \"UNKNOWN\");\n+\n+\tsfc_panic(sa, \"MCDI exceptions handling is not implemented\\n\");\n+}\n+\n+int\n+sfc_mcdi_init(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_mcdi *mcdi;\n+\tsize_t max_msg_size;\n+\tefx_mcdi_transport_t *emtp;\n+\tint rc;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tmcdi = &sa->mcdi;\n+\n+\tSFC_ASSERT(mcdi->state == SFC_MCDI_UNINITIALIZED);\n+\n+\trte_spinlock_init(&mcdi->lock);\n+\n+\tmcdi->state = SFC_MCDI_INITIALIZED;\n+\n+\tmax_msg_size = sizeof(uint32_t) + MCDI_CTL_SDU_LEN_MAX_V2;\n+\trc = sfc_dma_alloc(sa, \"mcdi\", 0, max_msg_size, sa->socket_id,\n+\t\t\t   &mcdi->mem);\n+\tif (rc != 0)\n+\t\tgoto fail_dma_alloc;\n+\n+\temtp = &mcdi->transport;\n+\temtp->emt_context = sa;\n+\temtp->emt_dma_mem = &mcdi->mem;\n+\temtp->emt_execute = sfc_mcdi_execute;\n+\temtp->emt_ev_cpl = sfc_mcdi_ev_cpl;\n+\temtp->emt_exception = sfc_mcdi_exception;\n+\n+\tsfc_log_init(sa, \"init MCDI\");\n+\trc = efx_mcdi_init(sa->nic, emtp);\n+\tif (rc != 0)\n+\t\tgoto fail_mcdi_init;\n+\n+\treturn 0;\n+\n+fail_mcdi_init:\n+\tmemset(emtp, 0, sizeof(*emtp));\n+\tsfc_dma_free(sa, &mcdi->mem);\n+\n+fail_dma_alloc:\n+\tmcdi->state = SFC_MCDI_UNINITIALIZED;\n+\treturn rc;\n+}\n+\n+void\n+sfc_mcdi_fini(struct sfc_adapter *sa)\n+{\n+\tstruct sfc_mcdi *mcdi;\n+\tefx_mcdi_transport_t *emtp;\n+\n+\tsfc_log_init(sa, \"entry\");\n+\n+\tmcdi = &sa->mcdi;\n+\temtp = &mcdi->transport;\n+\n+\trte_spinlock_lock(&mcdi->lock);\n+\n+\tSFC_ASSERT(mcdi->state == SFC_MCDI_INITIALIZED);\n+\tmcdi->state = SFC_MCDI_UNINITIALIZED;\n+\n+\tsfc_log_init(sa, \"fini MCDI\");\n+\tefx_mcdi_fini(sa->nic);\n+\tmemset(emtp, 0, sizeof(*emtp));\n+\n+\trte_spinlock_unlock(&mcdi->lock);\n+\n+\tsfc_dma_free(sa, &mcdi->mem);\n+}\n",
    "prefixes": [
        "dpdk-dev",
        "32/56"
    ]
}