get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 109621,
    "url": "https://patches.dpdk.org/api/patches/109621/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20220412174220.31195-3-jeffd@silicom-usa.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": "<20220412174220.31195-3-jeffd@silicom-usa.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220412174220.31195-3-jeffd@silicom-usa.com",
    "date": "2022-04-12T17:42:20",
    "name": "[v6,2/2] net/ixgbe: Fix SFP detection and linking on hotplug",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "6e8e7036efabeea31b5c4862b3111274c4e5d138",
    "submitter": {
        "id": 2500,
        "url": "https://patches.dpdk.org/api/people/2500/?format=api",
        "name": "Jeff Daly",
        "email": "jeffd@silicom-usa.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20220412174220.31195-3-jeffd@silicom-usa.com/mbox/",
    "series": [
        {
            "id": 22490,
            "url": "https://patches.dpdk.org/api/series/22490/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=22490",
            "date": "2022-04-12T17:42:18",
            "name": "ixgbe SFP handling fixes",
            "version": 6,
            "mbox": "https://patches.dpdk.org/series/22490/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/109621/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/109621/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D602BA0505;\n\tTue, 12 Apr 2022 19:42:45 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 535A8427ED;\n\tTue, 12 Apr 2022 19:42:39 +0200 (CEST)",
            "from EUR05-VI1-obe.outbound.protection.outlook.com\n (mail-vi1eur05on2091.outbound.protection.outlook.com [40.107.21.91])\n by mails.dpdk.org (Postfix) with ESMTP id CDCFE41611;\n Tue, 12 Apr 2022 19:42:36 +0200 (CEST)",
            "from VI1PR0402MB3517.eurprd04.prod.outlook.com (2603:10a6:803:b::16)\n by DB7PR04MB4539.eurprd04.prod.outlook.com (2603:10a6:5:36::18) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5144.29; Tue, 12 Apr\n 2022 17:42:35 +0000",
            "from VI1PR0402MB3517.eurprd04.prod.outlook.com\n ([fe80::5dd5:47e1:1cef:cc4e]) by VI1PR0402MB3517.eurprd04.prod.outlook.com\n ([fe80::5dd5:47e1:1cef:cc4e%6]) with mapi id 15.20.5144.029; Tue, 12 Apr 2022\n 17:42:35 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=be1Hsu7S9vobh3mC1ebq/9PEj98Fg8VhtREopv5gjHygDSvum/B7ozDVz8OvWIpjbA/7dddpjdYXk/ZTPeFwFBW9utTkHgpXM3lKY96aIZZwNvezXz8ZHrOD4jwqAhUopqIgOKZFaUCplHI0F4i3s7Y1aj/aRw1c+mShTV8ynkw0PXDStDhK0Dx87qk8FavYPmAuCqdr7Pl52PJRj8QzB7UerPtpG8sCsYKSPLqDtTZ7jV8e5r0t5Jw/9p4VKAkjnMtAwf8Fptv0QFQgs6OCBVR2FjceqRjhK0m0Sj6l6h3xCTr7atfzt9fuYurTlHI2TzP45GBbkxFqq01E0oeBGg==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector9901;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=7Ykiizy18gfZk32oxHrUiDwxYo07YIuHxmQAEzF04oU=;\n b=cjiLJdARIA4c9y4oDRRTJkyr3/DVD4Snvcm/cYybRzW1zEwj0GPL/B+LzyOrVOnn4gPrlxGUDIvjh5EF/FFJmUqrcYv+Wm//b7I8YHnx/N0xmkxPzkGjT6AKZ5htPl1mdyg3uPl8bgOpqksGmR5LMQ5b8asXpFLIj8pNoAwr4epljNuSnBKdUmw6NdzH49Pz6eNbsKP5HHGBtFZ8LHMUB5QtRmykzQ0tSAEIDizeo73AC0CUHm3G7+SJt3FQQKfleKsuaxP+1aJqrP5tLib3greh746cws9YpFivu6msPOnXgmZzxPggfhmSQefpDi9qUdwAdJySd/fCXqmkpd06BA==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=silicom-usa.com; dmarc=pass action=none\n header.from=silicom-usa.com; dkim=pass header.d=silicom-usa.com; arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=SILICOMLTD.onmicrosoft.com; s=selector2-SILICOMLTD-onmicrosoft-com;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=7Ykiizy18gfZk32oxHrUiDwxYo07YIuHxmQAEzF04oU=;\n b=ttUGTZzGUy2hvF18RPnHDa3OhotBDzOKlXsRm376jrWFrGWXb3oPoPn8HISj2qqb+g4jg03sPHbOiXgjUakblpdM6McBuaqBlVg5MWjvbMgnq6FDEgL/PwEwmBV5rPA68DVqepcimbYFHG1IuFl1VB8Q7e/rX3j6TnG8PMalk0M=",
        "Authentication-Results": "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=silicom-usa.com;",
        "From": "Jeff Daly <jeffd@silicom-usa.com>",
        "To": "dev@dpdk.org",
        "Cc": "stable@dpdk.org, Stephen Douthit <stephend@silicom-usa.com>,\n Haiyue Wang <haiyue.wang@intel.com>",
        "Subject": "[PATCH v6 2/2] net/ixgbe: Fix SFP detection and linking on hotplug",
        "Date": "Tue, 12 Apr 2022 13:42:20 -0400",
        "Message-Id": "<20220412174220.31195-3-jeffd@silicom-usa.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20220412174220.31195-1-jeffd@silicom-usa.com>",
        "References": "<20220228152937.21247-1-jeffd@silicom-usa.com>\n <20220412174220.31195-1-jeffd@silicom-usa.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "MN2PR08CA0012.namprd08.prod.outlook.com\n (2603:10b6:208:239::17) To VI1PR0402MB3517.eurprd04.prod.outlook.com\n (2603:10a6:803:b::16)",
        "MIME-Version": "1.0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-Correlation-Id": "a69a81b5-23df-46f3-1af1-08da1cabd419",
        "X-MS-TrafficTypeDiagnostic": "DB7PR04MB4539:EE_",
        "X-Microsoft-Antispam-PRVS": "\n <DB7PR04MB4539ED879904853D1188FA41EAED9@DB7PR04MB4539.eurprd04.prod.outlook.com>",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n XfdbNVmKYBkX042kVw+g+J9SYkxOSBLAGNNvb60GSALj5rh7qEuXUybmUHR8oMct/5iJwwAnSUPEj471c+LaX+TBnqwrUYQO3TUrPK/D4euJozZBlofKb1oB+81pGyUfkU5Etd6Dk2i5FdXFboSYMAUtXWpbRohjQf0dyzxL1aOJ55iNc/IAa2z/UpBqVN1IRb4VqIlrSKipVhZweMiXe+Bp8vb7R53Q3gyBeh8Om4V990FGADqj6vZY+XYLFZWl3eq7Y8si4xRQX64Zr5OPN1fdJwJfMkJ/QcLs47PCsRVTMGtT6Av1UU6s5pL2zV5rVsJKnWg8Oe6lRPaeLILq1Ky5BtLZ8fL7YI58Zjsa5YNggNlAKpZAdlJlOuUnYSEE6AVl2f+SZI/IbCiTGYrGAu42Eg4OSL9EdGlnmOsU5P/zOd1cYoAU0PsYGLIEUw2iZGlpYIX1seWDB7XCrHNBFXz1LIlPzgVPUMlzCGcOE7nrpkEaOk8wbRnZjzW2zleN2QdoEZgepFqSaSYYjnTYlQoEd4jfChRb6uUv1SLD18vucJ+Q7RqWDSFWbqYBe/pkozv62cvCZX7ukZn/ZHd1XwsltMQUlUTha8u2eMepNQ49+Xc+M9pHC/Wt2vpj1KY55FrXYJ/eMFLDE6+Nhju9QkTI9G8Gb4/NwCKHWdryF57N9xS0XjNakk14vGdNja4JgO+/zStPx/A+VAlBrfnlHg==",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:VI1PR0402MB3517.eurprd04.prod.outlook.com; PTR:;\n CAT:NONE;\n SFS:(13230001)(4636009)(366004)(5660300002)(8676002)(6486002)(4326008)(6666004)(52116002)(508600001)(30864003)(38350700002)(38100700002)(66946007)(8936002)(6512007)(6506007)(66476007)(66556008)(2906002)(86362001)(1076003)(2616005)(6916009)(186003)(26005)(54906003)(36756003)(316002)(83380400001);\n DIR:OUT; SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "\n CCdk9+q8DMgfG61IK9QeoZlSBnbTUsehuyAPoeEDc9l333BwwJjLUESEqa33t3+9cmgvDKNp0qwlXIFKaFpeusRCTJ74DLR4STo9CkQy9yV4fvDGKtee7S8LnuEfHnvX4V6twgT8kvTAePxwMx6Lc5/yZ52mDv1yeX5iuz9frJO3edfQ8x7Ok5h4VJGZF3uGZbLdMCYBisEQU9d4EpN5kDhvZNixvJwJQXgthJPf+tpIlS0B51TYBfIj1zQ3QV3Oh86GPFCA0FBXRvLFU8dKVR1oYXTnljnjYKWfCDA7rhQqnxCwNJpSUxojf47+zPsF1PFsGdBZn81V3rqvNZ3CrurTQVxH09k1dy+M5VnrIx09BSRqLwbc77aYWuI3CN9cY/anatwIJMBkK5mMbCp/4aFKPAtr1C8bL0R4qQ4pPi2YXSx/x8SChy1VzQ4pJ4J4m3wM2ljChgUhr8yl6l6Z+/xOuKf1rOKOHECShJVYo6wbSILmbJ5Dgq9eCamjenFpcgdbNHcOcfPySYgIHc4qSoAmqerAtNfI/npbKBnpnGK9YHcS2g2EtBwret6OiYrJD0ptUsWWC2Co+g6Po4TCKodzG5Fie/bSTXgsP7AtDRZr7h5EkKST5LXbEPWgJdH9NDupy2pyNMO9UGu3cklftg2cpHtDfeRA7diloFOuHYajldcePUH65CpVAVpD59duYwdI5bAGvcqZxh2jAWbGdSWi8eWepWIdMSruC5HRSrCdsoMdmwK8gZWva2931BdAIAxBKh8yBUwGfp6o/kzS+kNj/3g4TTMLRyPEE9UGi9CDqY6UAMdk8OYX3QRcFrnm1BscQ5fhryjf8HQC5TMLDPFrspD9CvIozbZF4+eEE6gd0N0rERnYHWRkjd5i43iJEl1i/qBRwjxoc7b8CU/k5sfFaFzjIu3d+CaJxsEOzW5trJMPYh3aug157HxNh6dQqjm1rPzbJ7RlcKnGxVEwbpGdUQRdQH9iSDxvExadgUuoSkv87ubAFE96BpKgT0Hiva8zzVF8ntJwuZ7qU2sednU/Wm00b012xtBcYCBRmsJ3CgtbwtsbRUwrKrDjO2zJNDKg2hDGYJgtSsskkpoUPoaBWBA7d/s3OJkM/bJ13/5cm3QvB0x7dFINL7KclnkxZUjPaIHKgAom6lToDEsuAxFnCMhSBOm+5cE0V9RVx/KT2jynHvNKok5/Q7loCYnh+6PnNObLsbpPgnwG8unGggyVLunA1bnUaeFs2pNmELrMVnENn8CZ78bKYcNnDqWu43ubJWBsR13FNfRYkaGZFh0/wcuLsVtvzITjiusKJE1ySiugAc5aSSG45Q3YVHJ8oo3UupCoy1KXNNtjS+fiJMpByUCFhD49U7HoDdF40jDqrF04SzFA/d1VVEPsW+ry8GKittroj06EH+yms50nav6/ds5Ohc/5hPD/1vSu0wfSFR58ztpC47Yyby39YL9HCm0QTjP0Mu7xZ2wQJmWijm+SIuY4YSe9ydw97juMUsc/7nGr7+qnKpn4bd5U3Y6KuOOieMsVQgdGzzi6mAXY43Snc/wiePD1WocnYyqF3WRs45d0vcNOWgogR5FdpXaVFN3abCPm0L0w+i7uB608l89NEDqMJF+dsL0ZLAQwmvS7PNUXmMX+jj/halyo4bF8DLNRyVlv6+HvlGhFCcGulKhqumx1RhXJzO2Jg970NO7cxjWhPYTYNI/pGTmqeE3tyOY0c4XZGZ/REQb39WA0QA==",
        "X-OriginatorOrg": "silicom-usa.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n a69a81b5-23df-46f3-1af1-08da1cabd419",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n VI1PR0402MB3517.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "12 Apr 2022 17:42:35.1934 (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "c9e326d8-ce47-4930-8612-cc99d3c87ad1",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n eQu+XSvS6yjJvIiSmkloEeb8elnvDT6RdJmMmS/VSXYAE454UbY2NOeAPgF2CBh2ZovxiZPP8vr2MaWlvfXL0g==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DB7PR04MB4539",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Currently the ixgbe driver does not ID any SFP except for the first one\nplugged in. This can lead to no-link, or incorrect speed conditions.\n\nFor example:\n\n* If link is initially established with a 1G SFP, and later a 1G/10G\nmultispeed part is later installed, then the MAC link setup functions are\nnever called to change from 1000BASE-X to 10GBASE-R mode, and the link\nstays running at the slower rate.\n\n* If link is initially established with a 1G SFP, and later a 10G only\nmodule is later installed, no link is established, since we are still\ntrasnsmitting in 1000BASE-X mode to a 10GBASE-R only partner.\n\nRefactor the SFP ID/setup, and link setup code, to more closely match the\nflow of the mainline kernel driver which does not have these issues.  In\nthat driver a service task runs periodically to handle these operations\nbased on bit flags that have been set (usually via interrupt or userspace\nrequest), and then get cleared once the requested subtask has been\ncompleted.\n\nFixes: af75078fece (\"first public release\")\nCc: stable@dpdk.org\n\nSigned-off-by: Stephen Douthit <stephend@silicom-usa.com>\nSigned-off-by: Jeff Daly <jeffd@silicom-usa.com>\n---\n drivers/net/ixgbe/ixgbe_ethdev.c | 533 +++++++++++++++++++++++--------\n drivers/net/ixgbe/ixgbe_ethdev.h |  14 +-\n 2 files changed, 410 insertions(+), 137 deletions(-)",
    "diff": "diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c\nindex f31bbb7895..9e720eee47 100644\n--- a/drivers/net/ixgbe/ixgbe_ethdev.c\n+++ b/drivers/net/ixgbe/ixgbe_ethdev.c\n@@ -236,9 +236,6 @@ static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);\n static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev);\n static void ixgbe_dev_interrupt_handler(void *param);\n static void ixgbe_dev_interrupt_delayed_handler(void *param);\n-static void *ixgbe_dev_setup_link_thread_handler(void *param);\n-static int ixgbe_dev_wait_setup_link_complete(struct rte_eth_dev *dev,\n-\t\t\t\t\t      uint32_t timeout_ms);\n \n static int ixgbe_add_rar(struct rte_eth_dev *dev,\n \t\t\tstruct rte_ether_addr *mac_addr,\n@@ -775,6 +772,33 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {\n #define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) /\t\\\n \t\tsizeof(rte_ixgbevf_stats_strings[0]))\n \n+/**\n+ * This function is the same as ixgbe_need_crosstalk_fix() in base/ixgbe_common.c\n+ *\n+ * ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix\n+ * @hw: pointer to hardware structure\n+ *\n+ * Contains the logic to identify if we need to verify link for the\n+ * crosstalk fix\n+ **/\n+static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw)\n+{\n+\t/* Does FW say we need the fix */\n+\tif (!hw->need_crosstalk_fix)\n+\t\treturn false;\n+\n+\t/* Only consider SFP+ PHYs i.e. media type fiber */\n+\tswitch (ixgbe_get_media_type(hw)) {\n+\tcase ixgbe_media_type_fiber:\n+\tcase ixgbe_media_type_fiber_qsfp:\n+\t\tbreak;\n+\tdefault:\n+\t\treturn false;\n+\t}\n+\n+\treturn true;\n+}\n+\n /*\n  * This function is the same as ixgbe_is_sfp() in base/ixgbe.h.\n  */\n@@ -1064,6 +1088,306 @@ ixgbe_parse_devargs(struct ixgbe_adapter *adapter,\n \trte_kvargs_free(kvlist);\n }\n \n+/**\n+ * ixgbe_check_sfp_cage - Find present status of SFP module\n+ * @hw: pointer to hardware structure\n+ *\n+ * Find if a SFP module is present and if this device supports SFPs\n+ **/\n+enum ixgbe_sfp_cage_status ixgbe_check_sfp_cage(struct ixgbe_hw *hw)\n+{\n+\tenum ixgbe_sfp_cage_status sfp_cage_status;\n+\n+\t/* If we're not a fiber/fiber_qsfp, no cage to check */\n+\tswitch (hw->mac.ops.get_media_type(hw)) {\n+\tcase ixgbe_media_type_fiber:\n+\tcase ixgbe_media_type_fiber_qsfp:\n+\t\tbreak;\n+\tdefault:\n+\t\treturn IXGBE_SFP_CAGE_NOCAGE;\n+\t}\n+\n+\tswitch (hw->mac.type) {\n+\tcase ixgbe_mac_82599EB:\n+\t\tsfp_cage_status = !!(IXGBE_READ_REG(hw, IXGBE_ESDP) &\n+\t\t\t     IXGBE_ESDP_SDP2);\n+\t\tbreak;\n+\tcase ixgbe_mac_X550EM_x:\n+\tcase ixgbe_mac_X550EM_a:\n+\t\t/* SDP0 is the active low signal PRSNT#, so invert this */\n+\t\tsfp_cage_status = !(IXGBE_READ_REG(hw, IXGBE_ESDP) &\n+\t\t\t\t  IXGBE_ESDP_SDP0);\n+\t\tbreak;\n+\tdefault:\n+\t\t/* Don't know how to check this device type yet */\n+\t\tsfp_cage_status = IXGBE_SFP_CAGE_UNKNOWN;\n+\t\tDEBUGOUT(\"IXGBE_SFP_CAGE_UNKNOWN, unknown mac type %d\\n\",\n+\t\t\t hw->mac.type);\n+\t\tbreak;\n+\t}\n+\n+\tDEBUGOUT(\"sfp status %d for mac type %d\\n\", sfp_cage_status, hw->mac.type);\n+\treturn sfp_cage_status;\n+}\n+\n+static s32\n+ixgbe_sfp_id_and_setup(struct rte_eth_dev *dev)\n+{\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tenum ixgbe_sfp_cage_status sfp_cage_status;\n+\ts32 err;\n+\n+\t/* Can't ID or setup SFP if it's not plugged in */\n+\tsfp_cage_status = ixgbe_check_sfp_cage(hw);\n+\tif (sfp_cage_status == IXGBE_SFP_CAGE_EMPTY ||\n+\t    sfp_cage_status == IXGBE_SFP_CAGE_NOCAGE)\n+\t\treturn IXGBE_ERR_SFP_NOT_PRESENT;\n+\n+\t/* Something's in the cage, ID it */\n+\thw->phy.ops.identify_sfp(hw);\n+\n+\t/* Unknown module type, give up */\n+\tif (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {\n+\t\tPMD_DRV_LOG(ERR, \"unknown SFP type, giving up\");\n+\t\treturn IXGBE_ERR_SFP_NOT_SUPPORTED;\n+\t}\n+\n+\t/* This should be a redundant check, since we looked at the\n+\t * PRSNT# signal from the cage above, but just in case this is\n+\t * an SFP that's slow to respond to I2C pokes correctly, try it\n+\t * again later\n+\t */\n+\tif (hw->phy.sfp_type == ixgbe_sfp_type_not_present) {\n+\t\tPMD_DRV_LOG(ERR, \"IDed SFP as absent but cage PRSNT# active!?\");\n+\t\treturn IXGBE_ERR_SFP_NOT_PRESENT;\n+\t}\n+\n+\t/* SFP is present and identified, try to set it up */\n+\terr = hw->mac.ops.setup_sfp(hw);\n+\tif (err)\n+\t\tPMD_DRV_LOG(ERR, \"setup_sfp() failed %d\", err);\n+\n+\treturn err;\n+}\n+\n+static void\n+ixgbe_sfp_service(struct rte_eth_dev *dev)\n+{\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct ixgbe_interrupt *intr =\n+\t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n+\tenum ixgbe_sfp_cage_status sfp_cage_status;\n+\ts32 err;\n+\tu8 sff_id;\n+\tbool have_int = false;\n+\n+\t/* If there's no module cage, then there's nothing to service */\n+\tsfp_cage_status = ixgbe_check_sfp_cage(hw);\n+\tif (sfp_cage_status == IXGBE_SFP_CAGE_NOCAGE) {\n+\t\tPMD_DRV_LOG(DEBUG, \"No SFP to service\\n\");\n+\t\treturn;\n+\t}\n+\n+\t/* TODO - Even for platforms where ixgbe_check_sfp_cage() gives a clear\n+\t * status result, if there's no interrupts, or no interrupt for the SFP\n+\t * cage present pin, even if other interrupts exist, then we still need\n+\t * to poll here to set the flag.\n+\t */\n+#ifndef RTE_EXEC_ENV_FREEBSD\n+\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n+\tstruct rte_intr_handle *intr_handle = pci_dev->intr_handle;\n+\tif (rte_intr_allow_others(intr_handle)) {\n+\t\t/* check if lsc interrupt is enabled */\n+\t\tif (dev->data->dev_conf.intr_conf.lsc)\n+\t\t\thave_int = true;\n+\t}\n+#endif /* #ifdef RTE_EXEC_ENV_FREEBSD */\n+\n+\tif (!have_int && sfp_cage_status == IXGBE_SFP_CAGE_EMPTY) {\n+\t\tintr->flags |= IXGBE_FLAG_NEED_SFP_SETUP;\n+\t\tPMD_DRV_LOG(DEBUG, \"No SFP, no LSC, set NEED_SFP_SETUP\\n\");\n+\t}\n+\n+\t/* For platforms that don't have a way to read the PRESENT# signal from\n+\t * the SFP cage, fallback to doing an I2C read and seeing if it's ACKed\n+\t * to determine if a module is present\n+\t */\n+\tif (sfp_cage_status == IXGBE_SFP_CAGE_UNKNOWN) {\n+\t\tPMD_DRV_LOG(DEBUG,\n+\t\t\t    \"SFP present unknown (int? %d), try I2C read\\n\",\n+\t\t\t    have_int);\n+\n+\t\t/* Rather than calling identify_sfp, which will read a lot of I2C\n+\t\t * registers (and in a slow processor intensive fashion due to\n+\t\t * bit-banging, just read the SFF ID register, which is at a\n+\t\t * common address across SFP/SFP+/QSFP modules and see if\n+\t\t * there's a NACK.  This works since we only expect a NACK if no\n+\t\t * module is present\n+\t\t */\n+\t\terr = ixgbe_read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, &sff_id);\n+\t\tif (err != IXGBE_SUCCESS) {\n+\t\t\tPMD_DRV_LOG(DEBUG, \"Received I2C NAK from SFP, set NEED_SFP_SETUP flag\\n\");\n+\t\t\tintr->flags |= IXGBE_FLAG_NEED_SFP_SETUP;\n+\t\t\tsfp_cage_status = IXGBE_SFP_CAGE_EMPTY;\n+\t\t} else {\n+\t\t\tPMD_DRV_LOG(DEBUG, \"SFP ID read ACKed\");\n+\t\t\tsfp_cage_status = IXGBE_SFP_CAGE_FULL;\n+\t\t}\n+\t}\n+\n+\tif (sfp_cage_status == IXGBE_SFP_CAGE_EMPTY) {\n+\t\tPMD_DRV_LOG(DEBUG, \"SFP absent, cage_status %d\\n\", sfp_cage_status);\n+\t\treturn;\n+\t}\n+\n+\t/* No setup requested?\tNothing to do */\n+\tif (!(intr->flags & IXGBE_FLAG_NEED_SFP_SETUP))\n+\t\treturn;\n+\n+\terr = ixgbe_sfp_id_and_setup(dev);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(DEBUG, \"failed to ID & setup SFP %d\", err);\n+\t\treturn;\n+\t}\n+\n+\t/* Setup is done, clear the flag, but make sure link config runs for new SFP */\n+\tintr->flags &= ~IXGBE_FLAG_NEED_SFP_SETUP;\n+\tintr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;\n+\n+\t/*\n+\t * Since this is a new SFP, clear the old advertised speed mask so we don't\n+\t * end up using an old slower rate\n+\t */\n+\thw->phy.autoneg_advertised = 0;\n+}\n+\n+static void\n+ixgbe_link_service(struct rte_eth_dev *dev)\n+{\n+\tstruct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct ixgbe_interrupt *intr =\n+\t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n+\tbool link_up, autoneg = false, have_int = false;\n+\tu32 speed;\n+\ts32 err;\n+\n+\t/* Test if we have a LSC interrupt for this platform, if not we need to\n+\t * manually check the link register since IXGBE_FLAG_NEED_LINK_CONFIG\n+\t * will never be set in the interrupt handler\n+\t */\n+#ifndef RTE_EXEC_ENV_FREEBSD\n+\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n+\tstruct rte_intr_handle *intr_handle = pci_dev->intr_handle;\n+\tif (rte_intr_allow_others(intr_handle)) {\n+\t\t/* check if lsc interrupt is enabled */\n+\t\tif (dev->data->dev_conf.intr_conf.lsc)\n+\t\t\thave_int = true;\n+\t}\n+#endif /* #ifdef RTE_EXEC_ENV_FREEBSD */\n+\n+\t/* Skip if we still need to setup an SFP, or if no link config requested\n+\t */\n+\tif ((intr->flags & IXGBE_FLAG_NEED_SFP_SETUP) ||\n+\t    (!(intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG) && have_int))\n+\t\treturn;\n+\n+\tif (!have_int && !(intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG)) {\n+\t\terr = ixgbe_check_link(hw, &speed, &link_up, 0);\n+\t\tif (!err && !link_up) {\n+\t\t\tintr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;\n+\t\t\tPMD_DRV_LOG(DEBUG, \"Link down, no LSC, set NEED_LINK_CONFIG\\n\");\n+\t\t} else {\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\tspeed = hw->phy.autoneg_advertised;\n+\tif (!speed)\n+\t\tixgbe_get_link_capabilities(hw, &speed, &autoneg);\n+\n+\terr = ixgbe_setup_link(hw, speed, true);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"ixgbe_setup_link failed %d\", err);\n+\t\treturn;\n+\t}\n+\n+\tintr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;\n+}\n+\n+static void\n+ixgbe_link_update_service(struct rte_eth_dev *dev)\n+{\n+\t/* Update internal link status, waiting for link */\n+\tif (!ixgbe_dev_link_update(dev, 0)) {\n+\t\tixgbe_dev_link_status_print(dev);\n+\t\trte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);\n+\t}\n+}\n+\n+/*\n+ * Service task thread to handle periodic tasks\n+ */\n+static void *\n+ixgbe_dev_service_thread_handler(void *param)\n+{\n+\tstruct rte_eth_dev *dev = (struct rte_eth_dev *)param;\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tuint64_t start, ticks, service_ms;\n+\tuint32_t speed;\n+\ts32 err;\n+\tbool link_up;\n+\n+\twhile (1) {\n+\t\tixgbe_sfp_service(dev);\n+\t\tixgbe_link_service(dev);\n+\t\tixgbe_link_update_service(dev);\n+\n+\t\t/* Run the service thread handler more frequently when link is\n+\t\t * down to reduce link up latency (every 200ms vs 1s)\n+\t\t *\n+\t\t * Use a number of smaller sleeps to decrease exit latency when\n+\t\t * ixgbe_dev_stop() wants this thread to join\n+\t\t */\n+\t\terr = ixgbe_check_link(hw, &speed, &link_up, 0);\n+\t\tif (err == IXGBE_SUCCESS && link_up)\n+\t\t\tservice_ms = 2000;\n+\t\telse\n+\t\t\tservice_ms = 100;\n+\n+\t\t/* Call msec_delay in a loop with several smaller sleeps to\n+\t\t * provide periodic thread cancellation points\n+\t\t */\n+\t\tstart = rte_get_timer_cycles();\n+\t\tticks = (uint64_t)service_ms * rte_get_timer_hz() / 1E3;\n+\t\twhile ((rte_get_timer_cycles() - start) < ticks)\n+\t\t\tmsec_delay(100);\n+\t}\n+\n+\t/* Never return */\n+\treturn NULL;\n+}\n+\n+static s32\n+eth_ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,\n+\t\t\t\t bool *link_up, bool link_up_wait_to_complete)\n+{\n+\tif (ixgbe_need_crosstalk_fix(hw)) {\n+\t\tenum ixgbe_sfp_cage_status sfp_cage_status;\n+\n+\t\tsfp_cage_status = ixgbe_check_sfp_cage(hw);\n+\t\tif (sfp_cage_status != IXGBE_SFP_CAGE_FULL) {\n+\t\t\t*link_up = false;\n+\t\t\t*speed = IXGBE_LINK_SPEED_UNKNOWN;\n+\t\t\treturn IXGBE_SUCCESS;\n+\t\t}\n+\t}\n+\n+\treturn ixgbe_check_mac_link_generic(hw, speed, link_up, link_up_wait_to_complete);\n+}\n+\n /*\n  * This function is based on code in ixgbe_attach() in base/ixgbe.c.\n  * It returns 0 on success.\n@@ -1071,7 +1395,6 @@ ixgbe_parse_devargs(struct ixgbe_adapter *adapter,\n static int\n eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n {\n-\tstruct ixgbe_adapter *ad = eth_dev->data->dev_private;\n \tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);\n \tstruct rte_intr_handle *intr_handle = pci_dev->intr_handle;\n \tstruct ixgbe_hw *hw =\n@@ -1086,6 +1409,7 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \t\tIXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);\n \tstruct ixgbe_bw_conf *bw_conf =\n \t\tIXGBE_DEV_PRIVATE_TO_BW_CONF(eth_dev->data->dev_private);\n+\tstruct ixgbe_mac_info *mac = &hw->mac;\n \tuint32_t ctrl_ext;\n \tuint16_t csum;\n \tint diag, i, ret;\n@@ -1126,7 +1450,6 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \t\treturn 0;\n \t}\n \n-\trte_atomic32_clear(&ad->link_thread_running);\n \tixgbe_parse_devargs(eth_dev->data->dev_private,\n \t\t\t    pci_dev->device.devargs);\n \trte_eth_copy_pci_info(eth_dev, pci_dev);\n@@ -1158,6 +1481,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)\n \t\treturn -EIO;\n \t}\n \n+\t/* override mac_link_check to check for sfp cage full/empty */\n+\tswitch (hw->mac.type) {\n+\tcase ixgbe_mac_X550EM_x:\n+\tcase ixgbe_mac_X550EM_a:\n+\tcase ixgbe_mac_82599EB:\n+\t\tmac->ops.check_link = eth_ixgbe_check_mac_link_generic;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n \t/* pick up the PCI bus settings for reporting later */\n \tixgbe_get_bus_info(hw);\n \n@@ -1581,7 +1915,6 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)\n {\n \tint diag;\n \tuint32_t tc, tcs;\n-\tstruct ixgbe_adapter *ad = eth_dev->data->dev_private;\n \tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);\n \tstruct rte_intr_handle *intr_handle = pci_dev->intr_handle;\n \tstruct ixgbe_hw *hw =\n@@ -1624,7 +1957,6 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)\n \t\treturn 0;\n \t}\n \n-\trte_atomic32_clear(&ad->link_thread_running);\n \tixgbevf_parse_devargs(eth_dev->data->dev_private,\n \t\t\t      pci_dev->device.devargs);\n \n@@ -2426,6 +2758,8 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)\n \tstruct ixgbe_interrupt *intr =\n \t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n \tstruct ixgbe_adapter *adapter = dev->data->dev_private;\n+\tstruct ixgbe_hw *hw =\n+\t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n \tint ret;\n \n \tPMD_INIT_FUNC_TRACE();\n@@ -2444,6 +2778,10 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)\n \t/* set flag to update link status after init */\n \tintr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;\n \n+\t/* set flag to setup SFP after init */\n+\tif (ixgbe_is_sfp(hw))\n+\t\tintr->flags |= IXGBE_FLAG_NEED_SFP_SETUP;\n+\n \t/*\n \t * Initialize to TRUE. If any of Rx queues doesn't meet the bulk\n \t * allocation or vector Rx preconditions we will reset it.\n@@ -2463,13 +2801,24 @@ ixgbe_dev_phy_intr_setup(struct rte_eth_dev *dev)\n \t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n \tuint32_t gpie;\n \n-\t/* only set up it on X550EM_X */\n+\t/* only set up it on X550EM_X (external PHY interrupt)\n+\t * or on X550EM_a_* for SFP_PRSNT# de-assertion (SFP removal)\n+\t */\n \tif (hw->mac.type == ixgbe_mac_X550EM_x) {\n \t\tgpie = IXGBE_READ_REG(hw, IXGBE_GPIE);\n \t\tgpie |= IXGBE_SDP0_GPIEN_X550EM_x;\n \t\tIXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);\n \t\tif (hw->phy.type == ixgbe_phy_x550em_ext_t)\n \t\t\tintr->mask |= IXGBE_EICR_GPI_SDP0_X550EM_x;\n+\t} else if (hw->mac.type == ixgbe_mac_X550EM_a) {\n+\t\tgpie = IXGBE_READ_REG(hw, IXGBE_GPIE);\n+\t\tgpie |= IXGBE_SDP0_GPIEN_X550EM_a;\n+\t\tIXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);\n+\t\tintr->mask |= IXGBE_EICR_GPI_SDP0_X550EM_a;\n+\t} else {\n+\t\tPMD_DRV_LOG(DEBUG,\n+\t\t\t    \"No PHY/SFP interrupt for MAC %d, PHY %d\\n\",\n+\t\t\t    hw->mac.type, hw->phy.type);\n \t}\n }\n \n@@ -2592,8 +2941,11 @@ ixgbe_flow_ctrl_enable(struct rte_eth_dev *dev, struct ixgbe_hw *hw)\n static int\n ixgbe_dev_start(struct rte_eth_dev *dev)\n {\n+\tstruct ixgbe_adapter *ad = dev->data->dev_private;\n \tstruct ixgbe_hw *hw =\n \t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tstruct ixgbe_interrupt *intr =\n+\t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n \tstruct ixgbe_vf_info *vfinfo =\n \t\t*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);\n \tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n@@ -2614,9 +2966,6 @@ ixgbe_dev_start(struct rte_eth_dev *dev)\n \n \tPMD_INIT_FUNC_TRACE();\n \n-\t/* Stop the link setup handler before resetting the HW. */\n-\tixgbe_dev_wait_setup_link_complete(dev, 0);\n-\n \t/* disable uio/vfio intr/eventfd mapping */\n \trte_intr_disable(intr_handle);\n \n@@ -2732,12 +3081,6 @@ ixgbe_dev_start(struct rte_eth_dev *dev)\n \t\t}\n \t}\n \n-\tif (ixgbe_is_sfp(hw) && hw->phy.multispeed_fiber) {\n-\t\terr = hw->mac.ops.setup_sfp(hw);\n-\t\tif (err)\n-\t\t\tgoto error;\n-\t}\n-\n \tif (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) {\n \t\t/* Turn on the copper */\n \t\tixgbe_set_phy_power(hw, true);\n@@ -2849,6 +3192,20 @@ ixgbe_dev_start(struct rte_eth_dev *dev)\n \tixgbe_l2_tunnel_conf(dev);\n \tixgbe_filter_restore(dev);\n \n+\t/* Spawn service thread */\n+\tif (ixgbe_is_sfp(hw)) {\n+\t\tintr->flags |= IXGBE_FLAG_NEED_SFP_SETUP;\n+\t\terr = rte_ctrl_thread_create(&ad->service_thread_tid,\n+\t\t\t\t\t     \"ixgbe-service-thread\",\n+\t\t\t\t\t     NULL,\n+\t\t\t\t\t     ixgbe_dev_service_thread_handler,\n+\t\t\t\t\t     dev);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"service_thread err\");\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+\n \tif (tm_conf->root && !tm_conf->committed)\n \t\tPMD_DRV_LOG(WARNING,\n \t\t\t    \"please call hierarchy_commit() \"\n@@ -2859,12 +3216,6 @@ ixgbe_dev_start(struct rte_eth_dev *dev)\n \tif (err)\n \t\tgoto error;\n \n-\t/*\n-\t * Update link status right before return, because it may\n-\t * start link configuration process in a separate thread.\n-\t */\n-\tixgbe_dev_link_update(dev, 0);\n-\n \t/* setup the macsec setting register */\n \tif (macsec_setting->offload_en)\n \t\tixgbe_dev_macsec_register_enable(dev, macsec_setting);\n@@ -2894,13 +3245,21 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)\n \tint vf;\n \tstruct ixgbe_tm_conf *tm_conf =\n \t\tIXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);\n+\tvoid *res;\n+\ts32 err;\n \n \tif (hw->adapter_stopped)\n \t\treturn 0;\n \n \tPMD_INIT_FUNC_TRACE();\n \n-\tixgbe_dev_wait_setup_link_complete(dev, 0);\n+\t/* Cancel the service thread, and wait for it to join */\n+\terr = pthread_cancel(adapter->service_thread_tid);\n+\tif (err)\n+\t\tPMD_DRV_LOG(ERR, \"failed to cancel service thread %d\", err);\n+\terr = pthread_join(adapter->service_thread_tid, &res);\n+\tif (err)\n+\t\tPMD_DRV_LOG(ERR, \"failed to join service thread %d\", err);\n \n \t/* disable interrupts */\n \tixgbe_disable_intr(hw);\n@@ -2979,7 +3338,6 @@ ixgbe_dev_set_link_up(struct rte_eth_dev *dev)\n \t} else {\n \t\t/* Turn on the laser */\n \t\tixgbe_enable_tx_laser(hw);\n-\t\tixgbe_dev_link_update(dev, 0);\n \t}\n \n \treturn 0;\n@@ -3010,7 +3368,6 @@ ixgbe_dev_set_link_down(struct rte_eth_dev *dev)\n \t} else {\n \t\t/* Turn off the laser */\n \t\tixgbe_disable_tx_laser(hw);\n-\t\tixgbe_dev_link_update(dev, 0);\n \t}\n \n \treturn 0;\n@@ -4163,57 +4520,6 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,\n \treturn ret_val;\n }\n \n-/*\n- * If @timeout_ms was 0, it means that it will not return until link complete.\n- * It returns 1 on complete, return 0 on timeout.\n- */\n-static int\n-ixgbe_dev_wait_setup_link_complete(struct rte_eth_dev *dev, uint32_t timeout_ms)\n-{\n-#define WARNING_TIMEOUT    9000 /* 9s  in total */\n-\tstruct ixgbe_adapter *ad = dev->data->dev_private;\n-\tuint32_t timeout = timeout_ms ? timeout_ms : WARNING_TIMEOUT;\n-\n-\twhile (rte_atomic32_read(&ad->link_thread_running)) {\n-\t\tmsec_delay(1);\n-\t\ttimeout--;\n-\n-\t\tif (timeout_ms) {\n-\t\t\tif (!timeout)\n-\t\t\t\treturn 0;\n-\t\t} else if (!timeout) {\n-\t\t\t/* It will not return until link complete */\n-\t\t\ttimeout = WARNING_TIMEOUT;\n-\t\t\tPMD_DRV_LOG(ERR, \"IXGBE link thread not complete too long time!\");\n-\t\t}\n-\t}\n-\n-\treturn 1;\n-}\n-\n-static void *\n-ixgbe_dev_setup_link_thread_handler(void *param)\n-{\n-\tstruct rte_eth_dev *dev = (struct rte_eth_dev *)param;\n-\tstruct ixgbe_adapter *ad = dev->data->dev_private;\n-\tstruct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n-\tstruct ixgbe_interrupt *intr =\n-\t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n-\tu32 speed;\n-\tbool autoneg = false;\n-\n-\tpthread_detach(pthread_self());\n-\tspeed = hw->phy.autoneg_advertised;\n-\tif (!speed)\n-\t\tixgbe_get_link_capabilities(hw, &speed, &autoneg);\n-\n-\tixgbe_setup_link(hw, speed, true);\n-\n-\tintr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;\n-\trte_atomic32_clear(&ad->link_thread_running);\n-\treturn NULL;\n-}\n-\n /*\n  * In freebsd environment, nic_uio drivers do not support interrupts,\n  * rte_intr_callback_register() will fail to register interrupts.\n@@ -4256,8 +4562,6 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,\n \tstruct ixgbe_adapter *ad = dev->data->dev_private;\n \tstruct rte_eth_link link;\n \tixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;\n-\tstruct ixgbe_interrupt *intr =\n-\t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n \tbool link_up;\n \tint diag;\n \tint wait = 1;\n@@ -4272,9 +4576,6 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,\n \n \thw->mac.get_link_status = true;\n \n-\tif (intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG)\n-\t\treturn rte_eth_linkstatus_set(dev, &link);\n-\n \t/* check if it needs to wait to complete, if lsc interrupt is enabled */\n \tif (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0)\n \t\twait = 0;\n@@ -4289,7 +4590,7 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,\n \telse\n \t\tdiag = ixgbe_check_link(hw, &link_speed, &link_up, wait);\n \n-\tif (diag != 0) {\n+\tif (diag != 0 || !link_up) {\n \t\tlink.link_speed = RTE_ETH_SPEED_NUM_100M;\n \t\tlink.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;\n \t\treturn rte_eth_linkstatus_set(dev, &link);\n@@ -4302,32 +4603,6 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,\n \t\t\tlink_up = 0;\n \t}\n \n-\tif (link_up == 0) {\n-\t\tif (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {\n-\t\t\tixgbe_dev_wait_setup_link_complete(dev, 0);\n-\t\t\tif (rte_atomic32_test_and_set(&ad->link_thread_running)) {\n-\t\t\t\t/* To avoid race condition between threads, set\n-\t\t\t\t * the IXGBE_FLAG_NEED_LINK_CONFIG flag only\n-\t\t\t\t * when there is no link thread running.\n-\t\t\t\t */\n-\t\t\t\tintr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;\n-\t\t\t\tif (rte_ctrl_thread_create(&ad->link_thread_tid,\n-\t\t\t\t\t\"ixgbe-link-handler\",\n-\t\t\t\t\tNULL,\n-\t\t\t\t\tixgbe_dev_setup_link_thread_handler,\n-\t\t\t\t\tdev) < 0) {\n-\t\t\t\t\tPMD_DRV_LOG(ERR,\n-\t\t\t\t\t\t\"Create link thread failed!\");\n-\t\t\t\t\trte_atomic32_clear(&ad->link_thread_running);\n-\t\t\t\t}\n-\t\t\t} else {\n-\t\t\t\tPMD_DRV_LOG(ERR,\n-\t\t\t\t\t\"Other link thread is running now!\");\n-\t\t\t}\n-\t\t}\n-\t\treturn rte_eth_linkstatus_set(dev, &link);\n-\t}\n-\n \tlink.link_status = RTE_ETH_LINK_UP;\n \tlink.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;\n \n@@ -4533,8 +4808,6 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)\n \teicr = IXGBE_READ_REG(hw, IXGBE_EICR);\n \tPMD_DRV_LOG(DEBUG, \"eicr %x\", eicr);\n \n-\tintr->flags = 0;\n-\n \t/* set flag for async link update */\n \tif (eicr & IXGBE_EICR_LSC)\n \t\tintr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;\n@@ -4550,6 +4823,14 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)\n \t    (eicr & IXGBE_EICR_GPI_SDP0_X550EM_x))\n \t\tintr->flags |= IXGBE_FLAG_PHY_INTERRUPT;\n \n+\t/* Check for loss of SFP */\n+\t/* TODO - For platforms that don't have this flag, do we need to set\n+\t *  NEED_SFP_SETUP on LSC if we're a SFP platform?\n+\t */\n+\tif (hw->mac.type ==  ixgbe_mac_X550EM_a &&\n+\t    (eicr & IXGBE_EICR_GPI_SDP0_X550EM_a))\n+\t\tintr->flags |= IXGBE_FLAG_NEED_SFP_SETUP;\n+\n \treturn 0;\n }\n \n@@ -4601,11 +4882,13 @@ ixgbe_dev_link_status_print(struct rte_eth_dev *dev)\n static int\n ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)\n {\n+\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n+\tstruct rte_intr_handle *intr_handle = pci_dev->intr_handle;\n \tstruct ixgbe_interrupt *intr =\n \t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n-\tint64_t timeout;\n \tstruct ixgbe_hw *hw =\n \t\tIXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\n+\tint64_t timeout;\n \n \tPMD_DRV_LOG(DEBUG, \"intr action type %d\", intr->flags);\n \n@@ -4640,16 +4923,14 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)\n \t\tif (rte_eal_alarm_set(timeout * 1000,\n \t\t\t\t      ixgbe_dev_interrupt_delayed_handler, (void *)dev) < 0)\n \t\t\tPMD_DRV_LOG(ERR, \"Error setting alarm\");\n-\t\telse {\n-\t\t\t/* remember original mask */\n-\t\t\tintr->mask_original = intr->mask;\n+\t\telse\n \t\t\t/* only disable lsc interrupt */\n \t\t\tintr->mask &= ~IXGBE_EIMS_LSC;\n-\t\t}\n \t}\n \n \tPMD_DRV_LOG(DEBUG, \"enable intr immediately\");\n \tixgbe_enable_intr(dev);\n+\trte_intr_ack(intr_handle);\n \n \treturn 0;\n }\n@@ -4672,8 +4953,6 @@ static void\n ixgbe_dev_interrupt_delayed_handler(void *param)\n {\n \tstruct rte_eth_dev *dev = (struct rte_eth_dev *)param;\n-\tstruct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);\n-\tstruct rte_intr_handle *intr_handle = pci_dev->intr_handle;\n \tstruct ixgbe_interrupt *intr =\n \t\tIXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);\n \tstruct ixgbe_hw *hw =\n@@ -4703,13 +4982,10 @@ ixgbe_dev_interrupt_delayed_handler(void *param)\n \t\tintr->flags &= ~IXGBE_FLAG_MACSEC;\n \t}\n \n-\t/* restore original mask */\n-\tintr->mask = intr->mask_original;\n-\tintr->mask_original = 0;\n+\tif (dev->data->dev_conf.intr_conf.lsc != 0)\n+\t\tintr->mask |= IXGBE_EICR_LSC;\n \n-\tPMD_DRV_LOG(DEBUG, \"enable intr in delayed handler S[%08x]\", eicr);\n \tixgbe_enable_intr(dev);\n-\trte_intr_ack(intr_handle);\n }\n \n /**\n@@ -5351,9 +5627,6 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)\n \n \tPMD_INIT_FUNC_TRACE();\n \n-\t/* Stop the link setup handler before resetting the HW. */\n-\tixgbe_dev_wait_setup_link_complete(dev, 0);\n-\n \terr = hw->mac.ops.reset_hw(hw);\n \n \t/**\n@@ -5433,12 +5706,6 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)\n \t/* Re-enable interrupt for VF */\n \tixgbevf_intr_enable(dev);\n \n-\t/*\n-\t * Update link status right before return, because it may\n-\t * start link configuration process in a separate thread.\n-\t */\n-\tixgbevf_dev_link_update(dev, 0);\n-\n \thw->adapter_stopped = false;\n \n \treturn 0;\n@@ -5457,8 +5724,6 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)\n \n \tPMD_INIT_FUNC_TRACE();\n \n-\tixgbe_dev_wait_setup_link_complete(dev, 0);\n-\n \tixgbevf_intr_disable(dev);\n \n \tdev->data->dev_started = 0;\ndiff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h\nindex cc6049a66a..d8d0bebd04 100644\n--- a/drivers/net/ixgbe/ixgbe_ethdev.h\n+++ b/drivers/net/ixgbe/ixgbe_ethdev.h\n@@ -29,6 +29,7 @@\n #define IXGBE_FLAG_PHY_INTERRUPT    (uint32_t)(1 << 2)\n #define IXGBE_FLAG_MACSEC           (uint32_t)(1 << 3)\n #define IXGBE_FLAG_NEED_LINK_CONFIG (uint32_t)(1 << 4)\n+#define IXGBE_FLAG_NEED_SFP_SETUP   ((uint32_t)(1 << 5))\n \n /*\n  * Defines that were not part of ixgbe_type.h as they are not used by the\n@@ -223,8 +224,6 @@ struct ixgbe_rte_flow_rss_conf {\n struct ixgbe_interrupt {\n \tuint32_t flags;\n \tuint32_t mask;\n-\t/*to save original mask during delayed handler */\n-\tuint32_t mask_original;\n };\n \n struct ixgbe_stat_mapping_registers {\n@@ -510,7 +509,7 @@ struct ixgbe_adapter {\n \tuint8_t pflink_fullchk;\n \tuint8_t mac_ctrl_frame_fwd;\n \trte_atomic32_t link_thread_running;\n-\tpthread_t link_thread_tid;\n+\tpthread_t service_thread_tid;\n };\n \n struct ixgbe_vf_representor {\n@@ -673,6 +672,15 @@ int ixgbe_syn_filter_set(struct rte_eth_dev *dev,\n \t\t\tstruct rte_eth_syn_filter *filter,\n \t\t\tbool add);\n \n+enum ixgbe_sfp_cage_status {\n+\tIXGBE_SFP_CAGE_EMPTY = 0,\n+\tIXGBE_SFP_CAGE_FULL,\n+\tIXGBE_SFP_CAGE_UNKNOWN = -1,\n+\tIXGBE_SFP_CAGE_NOCAGE = -2,\n+};\n+enum ixgbe_sfp_cage_status ixgbe_check_sfp_cage(struct ixgbe_hw *hw);\n+\n+\n /**\n  * l2 tunnel configuration.\n  */\n",
    "prefixes": [
        "v6",
        "2/2"
    ]
}