get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 17134,
    "url": "https://patches.dpdk.org/api/patches/17134/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1479740470-6723-23-git-send-email-arybchenko@solarflare.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1479740470-6723-23-git-send-email-arybchenko@solarflare.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1479740470-6723-23-git-send-email-arybchenko@solarflare.com",
    "date": "2016-11-21T15:00:36",
    "name": "[dpdk-dev,22/56] net/sfc: import libefx loopback control support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "a3647b804816a816cdd3e76ab454cd619f5f7ab6",
    "submitter": {
        "id": 607,
        "url": "https://patches.dpdk.org/api/people/607/?format=api",
        "name": "Andrew Rybchenko",
        "email": "arybchenko@solarflare.com"
    },
    "delegate": {
        "id": 319,
        "url": "https://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1479740470-6723-23-git-send-email-arybchenko@solarflare.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/17134/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/17134/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 68DE4D588;\n\tMon, 21 Nov 2016 16:03:22 +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 6F7882A5D\n\tfor <dev@dpdk.org>; Mon, 21 Nov 2016 16:01:37 +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\t05c03385.0.1541296.00-2362.3424226.nbfkord-smmo02.seg.att.com\n\t(envelope-from <arybchenko@solarflare.com>); \n\tMon, 21 Nov 2016 15:01:37 +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\tuALF1K2d007162 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\tuALF1J3D006765 for <dev@dpdk.org>; Mon, 21 Nov 2016 15:01:20 GMT"
        ],
        "X-MXL-Hash": "58330c5164b8adf2-c34b1afa501f93fcbb1e078c1607ac34848afe80",
        "From": "Andrew Rybchenko <arybchenko@solarflare.com>",
        "To": "<dev@dpdk.org>",
        "Date": "Mon, 21 Nov 2016 15:00:36 +0000",
        "Message-ID": "<1479740470-6723-23-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=oRrPKEy2kVU0EK0rN]",
            "[yAA:9 a=TpvnO824xIqVzHSz:21 a=JKs8bMaG9R7Z1fla:21 a=laHvG-]",
            "[NHmLIo8LD9:21 a=PA03WX8tBzeizutn5_OT:22]"
        ],
        "X-Spam": "[F=0.4999999987; CM=0.500; S=0.499(2015072901)]",
        "X-MAIL-FROM": "<arybchenko@solarflare.com>",
        "X-SOURCE-IP": "[12.187.104.26]",
        "Subject": "[dpdk-dev] [PATCH 22/56] net/sfc: import libefx loopback control\n\tsupport",
        "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": "EFSYS_OPT_LOOPBACK 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  |  13 +++\n drivers/net/sfc/efx/base/ef10_mac.c   |  36 +++++++\n drivers/net/sfc/efx/base/ef10_nic.c   |   9 ++\n drivers/net/sfc/efx/base/ef10_phy.c   |  45 ++++++++\n drivers/net/sfc/efx/base/efx.h        |  74 +++++++++++++\n drivers/net/sfc/efx/base/efx_check.h  |   7 ++\n drivers/net/sfc/efx/base/efx_impl.h   |   8 ++\n drivers/net/sfc/efx/base/efx_mac.c    |   6 ++\n drivers/net/sfc/efx/base/efx_mcdi.h   |   6 ++\n drivers/net/sfc/efx/base/efx_nic.c    | 188 ++++++++++++++++++++++++++++++++++\n drivers/net/sfc/efx/base/efx_port.c   | 101 ++++++++++++++++++\n drivers/net/sfc/efx/base/siena_impl.h |  13 +++\n drivers/net/sfc/efx/base/siena_mac.c  |  36 +++++++\n drivers/net/sfc/efx/base/siena_nic.c  |   9 ++\n drivers/net/sfc/efx/base/siena_phy.c  |  42 ++++++++\n 15 files changed, 593 insertions(+)",
    "diff": "diff --git a/drivers/net/sfc/efx/base/ef10_impl.h b/drivers/net/sfc/efx/base/ef10_impl.h\nindex f70773c..e468b24 100644\n--- a/drivers/net/sfc/efx/base/ef10_impl.h\n+++ b/drivers/net/sfc/efx/base/ef10_impl.h\n@@ -259,6 +259,16 @@ extern\t\t\tvoid\n ef10_mac_filter_default_rxq_clear(\n \t__in\t\tefx_nic_t *enp);\n \n+#if EFSYS_OPT_LOOPBACK\n+\n+extern\t__checkReturn\tefx_rc_t\n+ef10_mac_loopback_set(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_link_mode_t link_mode,\n+\t__in\t\tefx_loopback_type_t loopback_type);\n+\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n #if EFSYS_OPT_MAC_STATS\n \n extern\t__checkReturn\t\t\tefx_rc_t\n@@ -337,6 +347,9 @@ typedef struct ef10_link_state_s {\n \tuint32_t\t\tels_lp_cap_mask;\n \tunsigned int\t\tels_fcntl;\n \tefx_link_mode_t\t\tels_link_mode;\n+#if EFSYS_OPT_LOOPBACK\n+\tefx_loopback_type_t\tels_loopback;\n+#endif\n \tboolean_t\t\tels_mac_up;\n } ef10_link_state_t;\n \ndiff --git a/drivers/net/sfc/efx/base/ef10_mac.c b/drivers/net/sfc/efx/base/ef10_mac.c\nindex 477d0e7..488633f 100644\n--- a/drivers/net/sfc/efx/base/ef10_mac.c\n+++ b/drivers/net/sfc/efx/base/ef10_mac.c\n@@ -443,6 +443,42 @@ ef10_mac_filter_default_rxq_clear(\n }\n \n \n+#if EFSYS_OPT_LOOPBACK\n+\n+\t__checkReturn\tefx_rc_t\n+ef10_mac_loopback_set(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_link_mode_t link_mode,\n+\t__in\t\tefx_loopback_type_t loopback_type)\n+{\n+\tefx_port_t *epp = &(enp->en_port);\n+\tconst efx_phy_ops_t *epop = epp->ep_epop;\n+\tefx_loopback_type_t old_loopback_type;\n+\tefx_link_mode_t old_loopback_link_mode;\n+\tefx_rc_t rc;\n+\n+\t/* The PHY object handles this on EF10 */\n+\told_loopback_type = epp->ep_loopback_type;\n+\told_loopback_link_mode = epp->ep_loopback_link_mode;\n+\tepp->ep_loopback_type = loopback_type;\n+\tepp->ep_loopback_link_mode = link_mode;\n+\n+\tif ((rc = epop->epo_reconfigure(enp)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\tepp->ep_loopback_type = old_loopback_type;\n+\tepp->ep_loopback_link_mode = old_loopback_link_mode;\n+\n+\treturn (rc);\n+}\n+\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n #if EFSYS_OPT_MAC_STATS\n \n \t__checkReturn\t\t\tefx_rc_t\ndiff --git a/drivers/net/sfc/efx/base/ef10_nic.c b/drivers/net/sfc/efx/base/ef10_nic.c\nindex f28edd2..fec6a69 100644\n--- a/drivers/net/sfc/efx/base/ef10_nic.c\n+++ b/drivers/net/sfc/efx/base/ef10_nic.c\n@@ -1377,10 +1377,19 @@ ef10_nic_probe(\n \t\tgoto fail5;\n #endif\n \n+#if EFSYS_OPT_LOOPBACK\n+\tif ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)\n+\t\tgoto fail6;\n+#endif\n+\n \tencp->enc_features = enp->en_features;\n \n \treturn (0);\n \n+#if EFSYS_OPT_LOOPBACK\n+fail6:\n+\tEFSYS_PROBE(fail6);\n+#endif\n #if EFSYS_OPT_MAC_STATS\n fail5:\n \tEFSYS_PROBE(fail5);\ndiff --git a/drivers/net/sfc/efx/base/ef10_phy.c b/drivers/net/sfc/efx/base/ef10_phy.c\nindex cc00250..81309f2 100644\n--- a/drivers/net/sfc/efx/base/ef10_phy.c\n+++ b/drivers/net/sfc/efx/base/ef10_phy.c\n@@ -235,6 +235,30 @@ ef10_phy_get_link(\n \t\t\t    MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),\n \t\t\t    &elsp->els_link_mode, &elsp->els_fcntl);\n \n+#if EFSYS_OPT_LOOPBACK\n+\t/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);\n+\n+\telsp->els_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n \telsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;\n \n \treturn (0);\n@@ -289,8 +313,29 @@ ef10_phy_reconfigure(\n \tMCDI_IN_SET_DWORD_FIELD(req, SET_LINK_IN_CAP,\n \t    PHY_CAP_40000FDX, (cap_mask >> EFX_PHY_CAP_40000FDX) & 0x1);\n \n+#if EFSYS_OPT_LOOPBACK\n+\tMCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,\n+\t\t    epp->ep_loopback_type);\n+\tswitch (epp->ep_loopback_link_mode) {\n+\tcase EFX_LINK_100FDX:\n+\t\tspeed = 100;\n+\t\tbreak;\n+\tcase EFX_LINK_1000FDX:\n+\t\tspeed = 1000;\n+\t\tbreak;\n+\tcase EFX_LINK_10000FDX:\n+\t\tspeed = 10000;\n+\t\tbreak;\n+\tcase EFX_LINK_40000FDX:\n+\t\tspeed = 40000;\n+\t\tbreak;\n+\tdefault:\n+\t\tspeed = 0;\n+\t}\n+#else\n \tMCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);\n \tspeed = 0;\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n \tMCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);\n \n #if EFSYS_OPT_PHY_FLAGS\ndiff --git a/drivers/net/sfc/efx/base/efx.h b/drivers/net/sfc/efx/base/efx.h\nindex 9ca80f6..70569e7 100644\n--- a/drivers/net/sfc/efx/base/efx.h\n+++ b/drivers/net/sfc/efx/base/efx.h\n@@ -646,6 +646,77 @@ extern\t__checkReturn\tefx_rc_t\n efx_port_init(\n \t__in\t\tefx_nic_t *enp);\n \n+#if EFSYS_OPT_LOOPBACK\n+\n+typedef enum efx_loopback_type_e {\n+\tEFX_LOOPBACK_OFF = 0,\n+\tEFX_LOOPBACK_DATA = 1,\n+\tEFX_LOOPBACK_GMAC = 2,\n+\tEFX_LOOPBACK_XGMII = 3,\n+\tEFX_LOOPBACK_XGXS = 4,\n+\tEFX_LOOPBACK_XAUI = 5,\n+\tEFX_LOOPBACK_GMII = 6,\n+\tEFX_LOOPBACK_SGMII = 7,\n+\tEFX_LOOPBACK_XGBR = 8,\n+\tEFX_LOOPBACK_XFI = 9,\n+\tEFX_LOOPBACK_XAUI_FAR = 10,\n+\tEFX_LOOPBACK_GMII_FAR = 11,\n+\tEFX_LOOPBACK_SGMII_FAR = 12,\n+\tEFX_LOOPBACK_XFI_FAR = 13,\n+\tEFX_LOOPBACK_GPHY = 14,\n+\tEFX_LOOPBACK_PHY_XS = 15,\n+\tEFX_LOOPBACK_PCS = 16,\n+\tEFX_LOOPBACK_PMA_PMD = 17,\n+\tEFX_LOOPBACK_XPORT = 18,\n+\tEFX_LOOPBACK_XGMII_WS = 19,\n+\tEFX_LOOPBACK_XAUI_WS = 20,\n+\tEFX_LOOPBACK_XAUI_WS_FAR = 21,\n+\tEFX_LOOPBACK_XAUI_WS_NEAR = 22,\n+\tEFX_LOOPBACK_GMII_WS = 23,\n+\tEFX_LOOPBACK_XFI_WS = 24,\n+\tEFX_LOOPBACK_XFI_WS_FAR = 25,\n+\tEFX_LOOPBACK_PHYXS_WS = 26,\n+\tEFX_LOOPBACK_PMA_INT = 27,\n+\tEFX_LOOPBACK_SD_NEAR = 28,\n+\tEFX_LOOPBACK_SD_FAR = 29,\n+\tEFX_LOOPBACK_PMA_INT_WS = 30,\n+\tEFX_LOOPBACK_SD_FEP2_WS = 31,\n+\tEFX_LOOPBACK_SD_FEP1_5_WS = 32,\n+\tEFX_LOOPBACK_SD_FEP_WS = 33,\n+\tEFX_LOOPBACK_SD_FES_WS = 34,\n+\tEFX_LOOPBACK_NTYPES\n+} efx_loopback_type_t;\n+\n+typedef enum efx_loopback_kind_e {\n+\tEFX_LOOPBACK_KIND_OFF = 0,\n+\tEFX_LOOPBACK_KIND_ALL,\n+\tEFX_LOOPBACK_KIND_MAC,\n+\tEFX_LOOPBACK_KIND_PHY,\n+\tEFX_LOOPBACK_NKINDS\n+} efx_loopback_kind_t;\n+\n+extern\t\t\tvoid\n+efx_loopback_mask(\n+\t__in\tefx_loopback_kind_t loopback_kind,\n+\t__out\tefx_qword_t *maskp);\n+\n+extern\t__checkReturn\tefx_rc_t\n+efx_port_loopback_set(\n+\t__in\tefx_nic_t *enp,\n+\t__in\tefx_link_mode_t link_mode,\n+\t__in\tefx_loopback_type_t type);\n+\n+#if EFSYS_OPT_NAMES\n+\n+extern\t__checkReturn\tconst char *\n+efx_loopback_type_name(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_loopback_type_t type);\n+\n+#endif\t/* EFSYS_OPT_NAMES */\n+\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n extern\t__checkReturn\tefx_rc_t\n efx_port_poll(\n \t__in\t\tefx_nic_t *enp,\n@@ -921,6 +992,9 @@ typedef struct efx_nic_cfg_s {\n \tuint32_t\t\tenc_rx_prefix_size;\n \tuint32_t\t\tenc_rx_buf_align_start;\n \tuint32_t\t\tenc_rx_buf_align_end;\n+#if EFSYS_OPT_LOOPBACK\n+\tefx_qword_t\t\tenc_loopback_types[EFX_LINK_NMODES];\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n #if EFSYS_OPT_PHY_FLAGS\n \tuint32_t\t\tenc_phy_flags_mask;\n #endif\t/* EFSYS_OPT_PHY_FLAGS */\ndiff --git a/drivers/net/sfc/efx/base/efx_check.h b/drivers/net/sfc/efx/base/efx_check.h\nindex ac248b3..22cf892 100644\n--- a/drivers/net/sfc/efx/base/efx_check.h\n+++ b/drivers/net/sfc/efx/base/efx_check.h\n@@ -90,6 +90,13 @@\n # endif\n #endif /* EFSYS_OPT_HUNTINGTON */\n \n+#if EFSYS_OPT_LOOPBACK\n+/* Support hardware loopback modes */\n+# if !(EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD)\n+#  error \"LOOPBACK requires SIENA or HUNTINGTON or MEDFORD\"\n+# endif\n+#endif /* EFSYS_OPT_LOOPBACK */\n+\n #ifdef EFSYS_OPT_MAC_FALCON_GMAC\n # error \"MAC_FALCON_GMAC is obsolete and is not supported.\"\n #endif\ndiff --git a/drivers/net/sfc/efx/base/efx_impl.h b/drivers/net/sfc/efx/base/efx_impl.h\nindex e88e8a9..12a8a4f 100644\n--- a/drivers/net/sfc/efx/base/efx_impl.h\n+++ b/drivers/net/sfc/efx/base/efx_impl.h\n@@ -186,6 +186,10 @@ typedef struct efx_mac_ops_s {\n \tefx_rc_t\t(*emo_filter_default_rxq_set)(efx_nic_t *,\n \t\t\t\t\t\t      efx_rxq_t *, boolean_t);\n \tvoid\t\t(*emo_filter_default_rxq_clear)(efx_nic_t *);\n+#if EFSYS_OPT_LOOPBACK\n+\tefx_rc_t\t(*emo_loopback_set)(efx_nic_t *, efx_link_mode_t,\n+\t\t\t\t\t    efx_loopback_type_t);\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n #if EFSYS_OPT_MAC_STATS\n \tefx_rc_t\t(*emo_stats_get_mask)(efx_nic_t *, uint32_t *, size_t);\n \tefx_rc_t\t(*emo_stats_upload)(efx_nic_t *, efsys_mem_t *);\n@@ -261,6 +265,10 @@ typedef struct efx_port_s {\n \tuint8_t\t\t\tep_mulcst_addr_list[EFX_MAC_ADDR_LEN *\n \t\t\t\t\t\t    EFX_MAC_MULTICAST_LIST_MAX];\n \tuint32_t\t\tep_mulcst_addr_count;\n+#if EFSYS_OPT_LOOPBACK\n+\tefx_loopback_type_t\tep_loopback_type;\n+\tefx_link_mode_t\t\tep_loopback_link_mode;\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n #if EFSYS_OPT_PHY_FLAGS\n \tuint32_t\t\tep_phy_flags;\n #endif\t/* EFSYS_OPT_PHY_FLAGS */\ndiff --git a/drivers/net/sfc/efx/base/efx_mac.c b/drivers/net/sfc/efx/base/efx_mac.c\nindex 840b7db..c1d81ef 100644\n--- a/drivers/net/sfc/efx/base/efx_mac.c\n+++ b/drivers/net/sfc/efx/base/efx_mac.c\n@@ -50,6 +50,9 @@ static const efx_mac_ops_t\t__efx_siena_mac_ops = {\n \tsiena_mac_multicast_list_set,\t\t/* emo_multicast_list_set */\n \tNULL,\t\t\t\t\t/* emo_filter_set_default_rxq */\n \tNULL,\t\t\t\t/* emo_filter_default_rxq_clear */\n+#if EFSYS_OPT_LOOPBACK\n+\tsiena_mac_loopback_set,\t\t\t/* emo_loopback_set */\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n #if EFSYS_OPT_MAC_STATS\n \tsiena_mac_stats_get_mask,\t\t/* emo_stats_get_mask */\n \tefx_mcdi_mac_stats_upload,\t\t/* emo_stats_upload */\n@@ -71,6 +74,9 @@ static const efx_mac_ops_t\t__efx_ef10_mac_ops = {\n \tef10_mac_filter_default_rxq_set,\t/* emo_filter_default_rxq_set */\n \tef10_mac_filter_default_rxq_clear,\n \t\t\t\t\t/* emo_filter_default_rxq_clear */\n+#if EFSYS_OPT_LOOPBACK\n+\tef10_mac_loopback_set,\t\t\t/* emo_loopback_set */\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n #if EFSYS_OPT_MAC_STATS\n \tef10_mac_stats_get_mask,\t\t/* emo_stats_get_mask */\n \tefx_mcdi_mac_stats_upload,\t\t/* emo_stats_upload */\ndiff --git a/drivers/net/sfc/efx/base/efx_mcdi.h b/drivers/net/sfc/efx/base/efx_mcdi.h\nindex 6e24313..814f3f4 100644\n--- a/drivers/net/sfc/efx/base/efx_mcdi.h\n+++ b/drivers/net/sfc/efx/base/efx_mcdi.h\n@@ -220,6 +220,12 @@ efx_mcdi_mac_stats_periodic(\n \t__in\t\tboolean_t events);\n \n \n+#if EFSYS_OPT_LOOPBACK\n+extern\t__checkReturn\tefx_rc_t\n+efx_mcdi_get_loopback_modes(\n+\t__in\t\tefx_nic_t *enp);\n+#endif /* EFSYS_OPT_LOOPBACK */\n+\n extern\t__checkReturn\tefx_rc_t\n efx_mcdi_phy_module_get_info(\n \t__in\t\t\tefx_nic_t *enp,\ndiff --git a/drivers/net/sfc/efx/base/efx_nic.c b/drivers/net/sfc/efx/base/efx_nic.c\nindex 95ae8c6..53bb1e2 100644\n--- a/drivers/net/sfc/efx/base/efx_nic.c\n+++ b/drivers/net/sfc/efx/base/efx_nic.c\n@@ -775,6 +775,194 @@ efx_nic_test_tables(\n \n #endif\t/* EFSYS_OPT_DIAG */\n \n+#if EFSYS_OPT_LOOPBACK\n+\n+extern\t\t\tvoid\n+efx_loopback_mask(\n+\t__in\tefx_loopback_kind_t loopback_kind,\n+\t__out\tefx_qword_t *maskp)\n+{\n+\tefx_qword_t mask;\n+\n+\tEFSYS_ASSERT3U(loopback_kind, <, EFX_LOOPBACK_NKINDS);\n+\tEFSYS_ASSERT(maskp != NULL);\n+\n+\t/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XPORT == EFX_LOOPBACK_XPORT);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII_WS == EFX_LOOPBACK_XGMII_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS == EFX_LOOPBACK_XAUI_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_FAR ==\n+\t    EFX_LOOPBACK_XAUI_WS_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_WS_NEAR ==\n+\t    EFX_LOOPBACK_XAUI_WS_NEAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_WS == EFX_LOOPBACK_GMII_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS == EFX_LOOPBACK_XFI_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_WS_FAR ==\n+\t    EFX_LOOPBACK_XFI_WS_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS_WS == EFX_LOOPBACK_PHYXS_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT == EFX_LOOPBACK_PMA_INT);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_NEAR == EFX_LOOPBACK_SD_NEAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FAR == EFX_LOOPBACK_SD_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMA_INT_WS ==\n+\t    EFX_LOOPBACK_PMA_INT_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP2_WS ==\n+\t    EFX_LOOPBACK_SD_FEP2_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP1_5_WS ==\n+\t    EFX_LOOPBACK_SD_FEP1_5_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FEP_WS == EFX_LOOPBACK_SD_FEP_WS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SD_FES_WS == EFX_LOOPBACK_SD_FES_WS);\n+\n+\t/* Build bitmask of possible loopback types */\n+\tEFX_ZERO_QWORD(mask);\n+\n+\tif ((loopback_kind == EFX_LOOPBACK_KIND_OFF) ||\n+\t    (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_OFF);\n+\t}\n+\n+\tif ((loopback_kind == EFX_LOOPBACK_KIND_MAC) ||\n+\t    (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {\n+\t\t/*\n+\t\t * The \"MAC\" grouping has historically been used by drivers to\n+\t\t * mean loopbacks supported by on-chip hardware. Keep that\n+\t\t * meaning here, and include on-chip PHY layer loopbacks.\n+\t\t */\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_DATA);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMAC);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGMII);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGXS);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XGBR);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XAUI_FAR);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GMII_FAR);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SGMII_FAR);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_XFI_FAR);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_INT);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_NEAR);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_SD_FAR);\n+\t}\n+\n+\tif ((loopback_kind == EFX_LOOPBACK_KIND_PHY) ||\n+\t    (loopback_kind == EFX_LOOPBACK_KIND_ALL)) {\n+\t\t/*\n+\t\t * The \"PHY\" grouping has historically been used by drivers to\n+\t\t * mean loopbacks supported by off-chip hardware. Keep that\n+\t\t * meaning here.\n+\t\t */\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_GPHY);\n+\t\tEFX_SET_QWORD_BIT(mask,\tEFX_LOOPBACK_PHY_XS);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PCS);\n+\t\tEFX_SET_QWORD_BIT(mask, EFX_LOOPBACK_PMA_PMD);\n+\t}\n+\n+\t*maskp = mask;\n+}\n+\n+\t__checkReturn\tefx_rc_t\n+efx_mcdi_get_loopback_modes(\n+\t__in\t\tefx_nic_t *enp)\n+{\n+\tefx_nic_cfg_t *encp = &(enp->en_nic_cfg);\n+\tefx_mcdi_req_t req;\n+\tuint8_t payload[MAX(MC_CMD_GET_LOOPBACK_MODES_IN_LEN,\n+\t\t\t    MC_CMD_GET_LOOPBACK_MODES_OUT_LEN)];\n+\tefx_qword_t mask;\n+\tefx_qword_t modes;\n+\tefx_rc_t rc;\n+\n+\t(void) memset(payload, 0, sizeof (payload));\n+\treq.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;\n+\treq.emr_in_buf = payload;\n+\treq.emr_in_length = MC_CMD_GET_LOOPBACK_MODES_IN_LEN;\n+\treq.emr_out_buf = payload;\n+\treq.emr_out_length = MC_CMD_GET_LOOPBACK_MODES_OUT_LEN;\n+\n+\tefx_mcdi_execute(enp, &req);\n+\n+\tif (req.emr_rc != 0) {\n+\t\trc = req.emr_rc;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (req.emr_out_length_used <\n+\t    MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST +\n+\t    MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN) {\n+\t\trc = EMSGSIZE;\n+\t\tgoto fail2;\n+\t}\n+\n+\t/*\n+\t * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree\n+\t * in efx_loopback_mask() and in siena_phy.c:siena_phy_get_link().\n+\t */\n+\tefx_loopback_mask(EFX_LOOPBACK_KIND_ALL, &mask);\n+\n+\tEFX_AND_QWORD(mask,\n+\t    *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_SUGGESTED));\n+\n+\tmodes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_100M);\n+\tEFX_AND_QWORD(modes, mask);\n+\tencp->enc_loopback_types[EFX_LINK_100FDX] = modes;\n+\n+\tmodes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_1G);\n+\tEFX_AND_QWORD(modes, mask);\n+\tencp->enc_loopback_types[EFX_LINK_1000FDX] = modes;\n+\n+\tmodes = *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_10G);\n+\tEFX_AND_QWORD(modes, mask);\n+\tencp->enc_loopback_types[EFX_LINK_10000FDX] = modes;\n+\n+\tif (req.emr_out_length_used >=\n+\t    MC_CMD_GET_LOOPBACK_MODES_OUT_40G_OFST +\n+\t    MC_CMD_GET_LOOPBACK_MODES_OUT_40G_LEN) {\n+\t\t/* Response includes 40G loopback modes */\n+\t\tmodes =\n+\t\t    *MCDI_OUT2(req, efx_qword_t, GET_LOOPBACK_MODES_OUT_40G);\n+\t\tEFX_AND_QWORD(modes, mask);\n+\t\tencp->enc_loopback_types[EFX_LINK_40000FDX] = modes;\n+\t}\n+\n+\tEFX_ZERO_QWORD(modes);\n+\tEFX_SET_QWORD_BIT(modes, EFX_LOOPBACK_OFF);\n+\tEFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_100FDX]);\n+\tEFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_1000FDX]);\n+\tEFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_10000FDX]);\n+\tEFX_OR_QWORD(modes, encp->enc_loopback_types[EFX_LINK_40000FDX]);\n+\tencp->enc_loopback_types[EFX_LINK_UNKNOWN] = modes;\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+#endif /* EFSYS_OPT_LOOPBACK */\n+\n \t__checkReturn\tefx_rc_t\n efx_nic_calculate_pcie_link_bandwidth(\n \t__in\t\tuint32_t pcie_link_width,\ndiff --git a/drivers/net/sfc/efx/base/efx_port.c b/drivers/net/sfc/efx/base/efx_port.c\nindex 291a8e9..518c2a2 100644\n--- a/drivers/net/sfc/efx/base/efx_port.c\n+++ b/drivers/net/sfc/efx/base/efx_port.c\n@@ -125,6 +125,107 @@ efx_port_poll(\n \treturn (rc);\n }\n \n+#if EFSYS_OPT_LOOPBACK\n+\n+\t__checkReturn\tefx_rc_t\n+efx_port_loopback_set(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_link_mode_t link_mode,\n+\t__in\t\tefx_loopback_type_t loopback_type)\n+{\n+\tefx_port_t *epp = &(enp->en_port);\n+\tefx_nic_cfg_t *encp = &(enp->en_nic_cfg);\n+\tconst efx_mac_ops_t *emop = epp->ep_emop;\n+\tefx_rc_t rc;\n+\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);\n+\tEFSYS_ASSERT(emop != NULL);\n+\n+\tEFSYS_ASSERT(link_mode < EFX_LINK_NMODES);\n+\n+\tif (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],\n+\t\tloopback_type) == 0) {\n+\t\trc = ENOTSUP;\n+\t\tgoto fail1;\n+\t}\n+\n+\tif (epp->ep_loopback_type == loopback_type &&\n+\t    epp->ep_loopback_link_mode == link_mode)\n+\t\treturn (0);\n+\n+\tif ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 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+#if EFSYS_OPT_NAMES\n+\n+static const char * const __efx_loopback_type_name[] = {\n+\t\"OFF\",\n+\t\"DATA\",\n+\t\"GMAC\",\n+\t\"XGMII\",\n+\t\"XGXS\",\n+\t\"XAUI\",\n+\t\"GMII\",\n+\t\"SGMII\",\n+\t\"XGBR\",\n+\t\"XFI\",\n+\t\"XAUI_FAR\",\n+\t\"GMII_FAR\",\n+\t\"SGMII_FAR\",\n+\t\"XFI_FAR\",\n+\t\"GPHY\",\n+\t\"PHY_XS\",\n+\t\"PCS\",\n+\t\"PMA_PMD\",\n+\t\"XPORT\",\n+\t\"XGMII_WS\",\n+\t\"XAUI_WS\",\n+\t\"XAUI_WS_FAR\",\n+\t\"XAUI_WS_NEAR\",\n+\t\"GMII_WS\",\n+\t\"XFI_WS\",\n+\t\"XFI_WS_FAR\",\n+\t\"PHYXS_WS\",\n+\t\"PMA_INT\",\n+\t\"SD_NEAR\",\n+\t\"SD_FAR\",\n+\t\"PMA_INT_WS\",\n+\t\"SD_FEP2_WS\",\n+\t\"SD_FEP1_5_WS\",\n+\t\"SD_FEP_WS\",\n+\t\"SD_FES_WS\",\n+};\n+\n+\t__checkReturn\tconst char *\n+efx_loopback_type_name(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_loopback_type_t type)\n+{\n+\tEFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==\n+\t    EFX_LOOPBACK_NTYPES);\n+\n+\t_NOTE(ARGUNUSED(enp))\n+\tEFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);\n+\tEFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);\n+\n+\treturn (__efx_loopback_type_name[type]);\n+}\n+\n+#endif\t/* EFSYS_OPT_NAMES */\n+\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n \t\t\tvoid\n efx_port_fini(\n \t__in\t\tefx_nic_t *enp)\ndiff --git a/drivers/net/sfc/efx/base/siena_impl.h b/drivers/net/sfc/efx/base/siena_impl.h\nindex 98fd2c5..da03098 100644\n--- a/drivers/net/sfc/efx/base/siena_impl.h\n+++ b/drivers/net/sfc/efx/base/siena_impl.h\n@@ -138,6 +138,9 @@ typedef struct siena_link_state_s {\n \tuint32_t\t\tsls_lp_cap_mask;\n \tunsigned int\t\tsls_fcntl;\n \tefx_link_mode_t\t\tsls_link_mode;\n+#if EFSYS_OPT_LOOPBACK\n+\tefx_loopback_type_t\tsls_loopback;\n+#endif\n \tboolean_t\t\tsls_mac_up;\n } siena_link_state_t;\n \n@@ -232,6 +235,16 @@ siena_mac_pdu_get(\n \t__in\tefx_nic_t *enp,\n \t__out\tsize_t *pdu);\n \n+#if EFSYS_OPT_LOOPBACK\n+\n+extern\t__checkReturn\tefx_rc_t\n+siena_mac_loopback_set(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_link_mode_t link_mode,\n+\t__in\t\tefx_loopback_type_t loopback_type);\n+\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n #if EFSYS_OPT_MAC_STATS\n \n extern\t__checkReturn\t\t\tefx_rc_t\ndiff --git a/drivers/net/sfc/efx/base/siena_mac.c b/drivers/net/sfc/efx/base/siena_mac.c\nindex dbe9c6f..29bbff8 100644\n--- a/drivers/net/sfc/efx/base/siena_mac.c\n+++ b/drivers/net/sfc/efx/base/siena_mac.c\n@@ -194,6 +194,42 @@ siena_mac_reconfigure(\n \treturn (rc);\n }\n \n+#if EFSYS_OPT_LOOPBACK\n+\n+\t__checkReturn\tefx_rc_t\n+siena_mac_loopback_set(\n+\t__in\t\tefx_nic_t *enp,\n+\t__in\t\tefx_link_mode_t link_mode,\n+\t__in\t\tefx_loopback_type_t loopback_type)\n+{\n+\tefx_port_t *epp = &(enp->en_port);\n+\tconst efx_phy_ops_t *epop = epp->ep_epop;\n+\tefx_loopback_type_t old_loopback_type;\n+\tefx_link_mode_t old_loopback_link_mode;\n+\tefx_rc_t rc;\n+\n+\t/* The PHY object handles this on Siena */\n+\told_loopback_type = epp->ep_loopback_type;\n+\told_loopback_link_mode = epp->ep_loopback_link_mode;\n+\tepp->ep_loopback_type = loopback_type;\n+\tepp->ep_loopback_link_mode = link_mode;\n+\n+\tif ((rc = epop->epo_reconfigure(enp)) != 0)\n+\t\tgoto fail1;\n+\n+\treturn (0);\n+\n+fail1:\n+\tEFSYS_PROBE1(fail1, efx_rc_t, rc);\n+\n+\tepp->ep_loopback_type = old_loopback_type;\n+\tepp->ep_loopback_link_mode = old_loopback_link_mode;\n+\n+\treturn (rc);\n+}\n+\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n #if EFSYS_OPT_MAC_STATS\n \n \t__checkReturn\t\t\tefx_rc_t\ndiff --git a/drivers/net/sfc/efx/base/siena_nic.c b/drivers/net/sfc/efx/base/siena_nic.c\nindex c77393a..d28d1d2 100644\n--- a/drivers/net/sfc/efx/base/siena_nic.c\n+++ b/drivers/net/sfc/efx/base/siena_nic.c\n@@ -216,10 +216,19 @@ siena_nic_probe(\n \t\tgoto fail10;\n #endif\n \n+#if EFSYS_OPT_LOOPBACK\n+\tif ((rc = efx_mcdi_get_loopback_modes(enp)) != 0)\n+\t\tgoto fail11;\n+#endif\n+\n \tencp->enc_features = enp->en_features;\n \n \treturn (0);\n \n+#if EFSYS_OPT_LOOPBACK\n+fail11:\n+\tEFSYS_PROBE(fail11);\n+#endif\n #if EFSYS_OPT_MAC_STATS\n fail10:\n \tEFSYS_PROBE(fail10);\ndiff --git a/drivers/net/sfc/efx/base/siena_phy.c b/drivers/net/sfc/efx/base/siena_phy.c\nindex 9aeef23..b90ccab 100644\n--- a/drivers/net/sfc/efx/base/siena_phy.c\n+++ b/drivers/net/sfc/efx/base/siena_phy.c\n@@ -226,6 +226,30 @@ siena_phy_get_link(\n \t\t\t    MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),\n \t\t\t    &slsp->sls_link_mode, &slsp->sls_fcntl);\n \n+#if EFSYS_OPT_LOOPBACK\n+\t/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);\n+\tEFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);\n+\n+\tslsp->sls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n+\n \tslsp->sls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;\n \n \treturn (0);\n@@ -273,8 +297,26 @@ siena_phy_reconfigure(\n \t\tPHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1,\n \t\tPHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1);\n \n+#if EFSYS_OPT_LOOPBACK\n+\tMCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE,\n+\t\t    epp->ep_loopback_type);\n+\tswitch (epp->ep_loopback_link_mode) {\n+\tcase EFX_LINK_100FDX:\n+\t\tspeed = 100;\n+\t\tbreak;\n+\tcase EFX_LINK_1000FDX:\n+\t\tspeed = 1000;\n+\t\tbreak;\n+\tcase EFX_LINK_10000FDX:\n+\t\tspeed = 10000;\n+\t\tbreak;\n+\tdefault:\n+\t\tspeed = 0;\n+\t}\n+#else\n \tMCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE);\n \tspeed = 0;\n+#endif\t/* EFSYS_OPT_LOOPBACK */\n \tMCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed);\n \n #if EFSYS_OPT_PHY_FLAGS\n",
    "prefixes": [
        "dpdk-dev",
        "22/56"
    ]
}