get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 108365,
    "url": "http://patchwork.dpdk.org/api/patches/108365/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20220225205025.19575-1-jeffd@silicom-usa.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20220225205025.19575-1-jeffd@silicom-usa.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20220225205025.19575-1-jeffd@silicom-usa.com",
    "date": "2022-02-25T20:50:25",
    "name": "[v4,3/3] net/ixgbe: Fix SFP detection and linking on hotplug",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "aa4b692734659b9f0407bec3febd9c4f68215416",
    "submitter": {
        "id": 2500,
        "url": "http://patchwork.dpdk.org/api/people/2500/?format=api",
        "name": "Jeff Daly",
        "email": "jeffd@silicom-usa.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20220225205025.19575-1-jeffd@silicom-usa.com/mbox/",
    "series": [
        {
            "id": 21901,
            "url": "http://patchwork.dpdk.org/api/series/21901/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=21901",
            "date": "2022-02-25T20:50:25",
            "name": null,
            "version": 4,
            "mbox": "http://patchwork.dpdk.org/series/21901/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/108365/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/108365/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 3EAD5A034C;\n\tFri, 25 Feb 2022 21:50:57 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id C23FB4113D;\n\tFri, 25 Feb 2022 21:50:56 +0100 (CET)",
            "from EUR01-HE1-obe.outbound.protection.outlook.com\n (mail-eopbgr130123.outbound.protection.outlook.com [40.107.13.123])\n by mails.dpdk.org (Postfix) with ESMTP id D3073410FD;\n Fri, 25 Feb 2022 21:50:54 +0100 (CET)",
            "from VI1PR0402MB3517.eurprd04.prod.outlook.com (2603:10a6:803:b::16)\n by VE1PR04MB6463.eurprd04.prod.outlook.com (2603:10a6:803:11d::20)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5017.25; Fri, 25 Feb\n 2022 20:50:51 +0000",
            "from VI1PR0402MB3517.eurprd04.prod.outlook.com\n ([fe80::60a7:f65b:9a18:4d71]) by VI1PR0402MB3517.eurprd04.prod.outlook.com\n ([fe80::60a7:f65b:9a18:4d71%4]) with mapi id 15.20.4975.021; Fri, 25 Feb 2022\n 20:50:51 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=MfVGEUXdocyYIFjZ91U71wrxEk0nGfNRsHMen9gmtaPHmjZF+4jUL69cBKI0zWhYGpa7qFWuw96I5D0P3ED7KxwErhLefbICgR8Kn7qbN74RBBmSECOfyfu2SgRrP9BHtFijPF01s54iisW2n9LBOfwAkS0RxNJ1krAb+3zY0Edfi1NGabWlfnSty3QCp6mKJtyt6nTwa494h6TkwclALGSwGkXuNpCH3KITGIs0Sva9IQlGel/DRWSBdFlOh67IBBAMz+rbhw5kUyd5T0Lt9yRBq6fCEy3C5FpMNmX/bo0PuhNZV5cw66840emF8lksx2tL8Utgm8M7kuOMZNLTIg==",
        "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=Ok9xVAVcyiS5oI+0yOYCh5ALx3rsV/bOXaaDCJYQLCM=;\n b=ftc9rEtb1vBvEn172nfNs+H2TxBEH6ghGPfMlW/zvPqh1T/LXNt8mLutJYcB0V5CP2E86twtwwZ3SKq6h74J+v0+HDF0OkLKDoEa5StgOaVxK2sm53NtQvluOuZYB6zeNGZpRNZ49MVQ1FhJcaHFc810DvRf8yI0YE8LViDhi5S8uDveCqw9lOsqcpUMm7zFR34xsr4ZuyY1Eo7pz3ln2S3NVLiOUDwUTRQGituIsu0+wSHSv574yUuur+lBijdxUpOaaFGqSiGocZg4tB+MlbE34DgE6H+o86C5Henre0P928SGRp5XyOt82A9nRquCnuq6wD8vgi97KIzOQSzShA==",
        "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=Ok9xVAVcyiS5oI+0yOYCh5ALx3rsV/bOXaaDCJYQLCM=;\n b=pO0r2qVOo6brJ5TWRTyykAAKt6ljfj/aIUXgwaX9QYxVtWq50NYPaZqI5EZ/jdtZLQiAjyRlLCfvScbEOpD2A93L0VJ35l/iY4zDcYIiiZYlJiVY/C0kqBwuH9eVBVMVnpx8BmYBCZFqWL1scVaXraPoqYgmKkMYgqxJ72KHPNc=",
        "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 v4 3/3] net/ixgbe: Fix SFP detection and linking on hotplug",
        "Date": "Fri, 25 Feb 2022 15:50:25 -0500",
        "Message-Id": "<20220225205025.19575-1-jeffd@silicom-usa.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20211206221922.644187-1-stephend@silicom-usa.com>",
        "References": "<20211206221922.644187-1-stephend@silicom-usa.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "BN0PR04CA0084.namprd04.prod.outlook.com\n (2603:10b6:408:ea::29) 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": "8cf66516-76fc-4b7b-8083-08d9f8a081e1",
        "X-MS-TrafficTypeDiagnostic": "VE1PR04MB6463:EE_",
        "X-Microsoft-Antispam-PRVS": "\n <VE1PR04MB6463DD654654690673923B5AEA3E9@VE1PR04MB6463.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 k153CgZbRN9yHjTmSUjyfQM79+tHUUYj8RS93vBAvKGfo0qHKC+y+475/DHP8TmD8CLGf5Eae46MNujA+Py4nKzWGiT6Ws/2+n8sZBO5pZbTZ1kDJZUlKZESbgehxF3jQeY1lvwvw0rZo/FgKwbE4IJ8XYkm/+mXNx0cD6/zdNckGD0iY7ujMHn9nX4OZDXh/G1kJ4/+zotEbBBJauBH1lFdNH6UousqRHPWB/mXPfEa2/bm+MCkvGeqEF/icph4Fj8tbuJS6rQbszNGptvOsaVSShGRRMy479Vimu4UYcoKk4osGc9OT0hBK7FCwmhwa4D3ujxLFDpeXi+8G6wFoQ+T4YRe8jLZCh5rIcN6zce3Q/ftYueymMjkp04GkkS+o9PQtF7ErLXk5nSlN+UaKsQvEG6BnClcesrFnGc88xg7MVYLrfYo16k2ch7c/0qefVtsTrcPPWzfA4Ne7DFb0BehCfDncauShdQ4pmGpGF6qUEwbt3eQz4E8pPSGYXQ8PJ8I5kjVVr6DXon+3HlhsQK6lepftYHLwcy1fRhWVJN5IMqs78WBE+8mRyf3qhb//diaSpR9a4gywnxWkgQDHYymr1FPLSWdCSI4TWLn1DO72pzT3Zmkbba2NHKhrbeWL5jzwp8z0UM93iyUNREf4+oiAb/15vD0A9oMykuw2zTfQ5e/qWITsDcyNolQHixDAoi3xP4+kNcSOUe0LtPRqw==",
        "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)(38350700002)(6666004)(1076003)(5660300002)(26005)(38100700002)(8676002)(8936002)(508600001)(186003)(4326008)(6916009)(2616005)(66946007)(66556008)(66476007)(6486002)(6512007)(54906003)(36756003)(6506007)(52116002)(83380400001)(2906002)(30864003)(86362001)(316002);\n DIR:OUT; SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "\n KLBfFdPpKrMhzpi4V7Q947MLiMBDSng8aGdK0Y0w9jqG7pZWLMcDbDBa0Tdhc2Oo9prdN+PFJ/FNjb4BvQEs6Qjkbg6c1GDkdq3R3Wphr51Gd8wXB5lU7r8negQHkTSS0M/3osQy727H4PWxkqCLYA1JB2P6u6yldLN2bJpb0PIUxEOwEz24TH0E4Qvl+O/iUMbQDAkleKQwtsRWZOzSDp6lMzPeAh2ubV/UEc3Z06I6RYEJzSTwmVMnCyMRwuNhAcpCuidJrew5S4cXwkFO4Xe1+42U7Gn7whw0EUZ/PnRe8U5WIe0jo7xyTAd9+FDNpQuGNdpHXSMvZ2GA7mGvls6rOCVxi01XE+b57WyUioYJkJjnpLmUDU0zwSQ5g5saTt8nMPProYWvd1TNYYN9+ebWSbtMS2f9F60FhrTwg8lGv5b5PhDRqbP8kQb7PrWjoPkwCq0QMnWQ+tRKKKMH/Gj/25/dMgb5Ta8EGwgGwY8muLbYbMfM7X5yqtEiTryAZ5Ayhr5UowGAt/JGz/Oqh76zVtLJpXJ0FlBHIZYVnOc47pdQbmio/aExNYktqf4DGvIZCuw6VJ4Xdo/KJhCqypIRNPAsIFneNqGI/myabFdu2M71vAPqSBlloaAXeafJ4ijri7T2ezJ6QKw+QFDn3dCbdcHRfbiKSjPxNRSLOgMOOO7bHYn0khGRO8Gmk9WWUYruVe+KxQByzWqxvQtIP4Ut5IkNeVjNdW1/u6Uo0AnzfI0h8WhlR1kQcyt/ne9GJPJxYJoSnddayPDEJW9gmanGLXiOWmPJ5B5Hfa3tOhoFJjE3GM1og2+5ADlDzdmy9VnAhG7Hu4WO+D1Y2G5BHwuIqwx2Qd7cVr0GfGP7QVEDwKrfaDP6B4t4KrELwh5VCP7mo1uyb5uW8t+oCmh9XMKF9KGULOc5ZBAPY2mXRvXOoi16USgP7fsjMn+HXX3uVN7dCJHbyFX9Swtp8KnWoTFYzAB1OG3OzIvp4QRLkHeP0jra7p09c+w58oBOCti7T6q3K6u7YIoFx5/yVl7eVMRmQvp2r85U4RIeb8wW1aiB1AA/PdyYtyorSeDIwxzOOiG4RpsatyWUeuIK+vX3gsE9dTQkhY/5qknEvcjlgNezhlLt74pCxNlFwLXXZrdRAgNYgk2Y218BkSe79huXIcrMqnsrKGKbLgq/OL45ekgILtT0KpHrEtd4RkV8CYVCVkiIEt+0BRO8MwBGJrbMolSmKFki8MSRJ0SHUac3TPv+9zs/5GVYajXh8Bi2BV7CSJUyDVXbFkOOqkrA8+G3FncPhrdDKBraQzWhw4FoZjvhZ21AUZCVvx+jRqWz50XlifGu8oSGHNIeHWfxq8ELJOp+FfSPLGB/o2fGhNl5lHXVvKgN77LIGT7w3wQGaZW5OQ1f5myx6dZuPRpnhL3XJ3c18jSTHXkWs2Ha/PBV0VuFTLnvGS4dSne0SfqzTWdwFn+ricwUBL7k7AL7M1Ab1JpaF8Dsy/OJ9Rdiq1HgCwSx+++Esx5xqwZ5P9yx7cUoHRO2xGsgin0KJsquIhcY/X4IcMvImA/frh+KKlmg7YIg5fGeBVzLIyMyXbHrC8P6Yqor0bpX4zImQ8AhqGcmrw==",
        "X-OriginatorOrg": "silicom-usa.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 8cf66516-76fc-4b7b-8083-08d9f8a081e1",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n VI1PR0402MB3517.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "25 Feb 2022 20:50:51.1349 (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 ecos4MpyO3WS7e4OTEUYeLiYmgaLzypgFDUnKWC7wcE+L65BQOsuG/nO5y77ZoqjMg11suBcJl9zN9yn+R7oXg==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "VE1PR04MB6463",
        "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 | 499 +++++++++++++++++++++++--------\n drivers/net/ixgbe/ixgbe_ethdev.h |  14 +-\n 2 files changed, 392 insertions(+), 121 deletions(-)",
    "diff": "diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c\nindex e8f07cb405..b70985bb1d 100644\n--- a/drivers/net/ixgbe/ixgbe_ethdev.c\n+++ b/drivers/net/ixgbe/ixgbe_ethdev.c\n@@ -229,9 +229,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@@ -766,6 +763,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@@ -1032,6 +1056,306 @@ ixgbe_swfw_lock_reset(struct ixgbe_hw *hw)\n \tixgbe_release_swfw_semaphore(hw, mask);\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@@ -1054,6 +1378,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@@ -1124,6 +1449,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@@ -2558,8 +2894,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@@ -2580,9 +2919,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@@ -2815,6 +3151,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@@ -2860,13 +3210,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@@ -2945,7 +3303,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@@ -2976,7 +3333,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@@ -4128,57 +4484,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@@ -4218,11 +4523,8 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,\n \t\t\t    int wait_to_complete, int vf)\n {\n \tstruct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);\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@@ -4237,9 +4539,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@@ -4254,7 +4553,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@@ -4267,32 +4566,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@@ -4498,8 +4771,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@@ -4515,6 +4786,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@@ -4566,11 +4845,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@@ -4605,16 +4886,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@@ -4637,8 +4916,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@@ -4668,13 +4945,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@@ -5316,9 +5590,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@@ -5398,12 +5669,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@@ -5422,8 +5687,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 69e0e82a5b..d243e417e9 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@@ -507,7 +506,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@@ -670,6 +669,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": [
        "v4",
        "3/3"
    ]
}