get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 35114,
    "url": "http://patches.dpdk.org/api/patches/35114/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1518369872-12324-4-git-send-email-matan@mellanox.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1518369872-12324-4-git-send-email-matan@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1518369872-12324-4-git-send-email-matan@mellanox.com",
    "date": "2018-02-11T17:24:32",
    "name": "[dpdk-dev,v6,3/3] net/failsafe: fix hotplug races",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "4332438da7543919c37bd529bb34034d502bde06",
    "submitter": {
        "id": 796,
        "url": "http://patches.dpdk.org/api/people/796/?format=api",
        "name": "Matan Azrad",
        "email": "matan@mellanox.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1518369872-12324-4-git-send-email-matan@mellanox.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/35114/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/35114/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 [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 06EC41B35F;\n\tSun, 11 Feb 2018 18:25:04 +0100 (CET)",
            "from EUR01-DB5-obe.outbound.protection.outlook.com\n\t(mail-db5eur01on0052.outbound.protection.outlook.com [104.47.2.52])\n\tby dpdk.org (Postfix) with ESMTP id 56BD71B33E;\n\tSun, 11 Feb 2018 18:25:00 +0100 (CET)",
            "from mellanox.com (37.142.13.130) by\n\tAM4PR0501MB2657.eurprd05.prod.outlook.com (2603:10a6:200:59::19) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.485.10;\n\tSun, 11 Feb 2018 17:24:58 +0000"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com;\n\ts=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version;\n\tbh=c2NIkmPIO82OKPmNYNwW+Fe3mzMKmIQO96YO0F6SMk8=;\n\tb=sl2rvxKG2FLfz5WiIsmgURwyW0H9vQG61HByTHq9n+d/xCZMlxPwTlQA6piDkR5bHV7gEvx1sRrXmnqnxL4v6AaY1yWHzk1jcq52dRRaIpZ3VNJNSrM2nHLywExSs3VJPiptlvHKUw4ubsM7ChZmoTWyhcgSba1ZPlXQmh3qMoc=",
        "Authentication-Results": "spf=none (sender IP is )\n\tsmtp.mailfrom=matan@mellanox.com; ",
        "From": "Matan Azrad <matan@mellanox.com>",
        "To": "Gaetan Rivet <gaetan.rivet@6wind.com>",
        "Cc": "dev@dpdk.org,\n\tstable@dpdk.org",
        "Date": "Sun, 11 Feb 2018 17:24:32 +0000",
        "Message-Id": "<1518369872-12324-4-git-send-email-matan@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1518369872-12324-1-git-send-email-matan@mellanox.com>",
        "References": "<1518107653-15466-1-git-send-email-matan@mellanox.com>\n\t<1518369872-12324-1-git-send-email-matan@mellanox.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[37.142.13.130]",
        "X-ClientProxiedBy": "VI1PR0501CA0022.eurprd05.prod.outlook.com\n\t(2603:10a6:800:92::32) To AM4PR0501MB2657.eurprd05.prod.outlook.com\n\t(2603:10a6:200:59::19)",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-HT": "Tenant",
        "X-MS-Office365-Filtering-Correlation-Id": "b936e106-6897-4833-e296-08d571746052",
        "X-Microsoft-Antispam": "UriScan:; BCL:0; PCL:0;\n\tRULEID:(7020095)(4652020)(48565401081)(5600026)(4604075)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603307)(7153060)(7193020);\n\tSRVR:AM4PR0501MB2657; ",
        "X-Microsoft-Exchange-Diagnostics": [
            "1; AM4PR0501MB2657;\n\t3:BNHDbEeQbo9pIxe/UkqOQf0SXEcCJgrVdEvfkNME9KrkF5ga5B2V6jIjQPsOQwcMup+7CI5fxgeIS58/Arw6M8eFOYKmwi953wB7CjD/OR5xrVsSPjlBZPSh7aM9K5MLSOg61gtlGdKnBn66o5fGf8M5/uOCrhrSLsabe0KtS+S1q7U/7cBNSQOInlGcJ3Jjd79+MMmAIXNDpvBy3TS3i7/18csCFjyWUiJ4vRG6Lq0jy/1eZl6kpbjG7Qy7z+e8;\n\t25:adUHvyRWWolTtmN34Uc4cSnKTBLoz+sjWrqAanZ8EHND2dJ1ld0Wibc2ZxGNuqrYTodB/Mez9cMykTd65W4MwcKgesEZzF4B73dMlLvW7DtqUQ1bWE16rTiSoydGXVV9E5KegybLfqL8UUgVdBkOLgoGcjL7p1mZuFP/d+aAjIoS0Jwmu6lji/2+IFyglHU6EOJbIXiceJ/YVth2KVkv1eVL9WmeosvN9ANGkfj84e0LfLJwbcNoVO9EUj4tJs8B4rx/Uv8oUXQIufEA66CSuNbzI4S8XpSEduJOv9TUBIbajmTR9BP460jrobh0O/aG7kuDoSTCAjd3Pkkb60m2MA==;\n\t31:f48KyWsG4r0njsUIsuxgJBgbmvrrMbH0xNFQyyOfTD1YNMvpgZZbhFI9/MhrzCBJLkGQ9HdZ2mIiml54nh5XlhYTQrTU5tmxb0xDhY9cjvJvF9gy4J6uHcYSiFmE78tl5Pvi1NxxPGOZvNXjx8fkhJSGiYQ3n4T1oM2ZN2+N7cWEMmsCalENSFGPOyymsWoVTV8m0N13SH1YxXt5diOTiedJe5r9RDppACbglZ8CDnQ=",
            "1; AM4PR0501MB2657;\n\t20:p6y+vmV6/SsUujytjEQr2Srpk3LZkF2G/KbF3TvpZqXbreeCbpestRlBQvJ6qCE3opAEnYYKKavEyRbQZJlewROBViUsEifbfMSuUG0PuRy/96NsJOXHICmzF2LtWq7iultqHBUSh4vYxsLnA5EYpZefqeRwM80icCj3EWdotNy10jMlk1/AeZzKJpyK98M/ddWPI91L7dOoIaO9T+T55xciw6umHcMxmVqfCD4V54LAEti+BYmB/u9fXJkgK9zo4eSEoiN6KrM1VeoyF94aOFuzp7W13LbNUHdekhOVieZLk1UrBfY7o8St8JasTKKnQhN9s+7wiShuJg7LM14qD0EBzwrP97itEDvOpgGEflrYeSKQxLO3F9fZEXQhuKB9BhABabLGB+IZdRwjEktxsRaLVNIQpZmew/jkjCAi9Sn7txuZ44qIE1OhUkBLq5V2B562Y6aApEuOK2uYoNK5WtSIe1qSXyWv+V9WT9UqMTZ4MSqSI1MQ6drTg2DyWtdw;\n\t4:RiHPkwm+jfvBNApAsuME+olPlqPfIgHXTSEHeWrI6ZiuhlAtSc42V7yr1NVr+wg/JSUGZtCLOym0Alw3Njcox2ZTFPRdBdl6xbvetJuJ5aDiD139FrJQ8e4OaNoh2TX3CXHj1W/H+Esid4MBkvqxpNaK1DCNmWIFqNmdWN1QyMC6b9mfcwiV4HleLCvOjRqi9iTb8OGYzbUgQzCYrIUjKdgX4V/3AZZRcuMu54xVVYuFjE3QVHRKQVlS8O7mMKi4L7Pwak2q7jPinis6ITxdc+KrYpKDRC5BdPrgFR7tM0EYc/TxvLe3LrE+nT4Oxelm",
            "=?us-ascii?Q?1; AM4PR0501MB2657;\n\t23:/vpIo6NHKXQFxdc0HhWKW4gMbx6mRwft/ru0QLS?=\n\tdKTm5f1rxja7IYS+sD13l4Z2zdbz+BH9ZL+OegDASbhe2BK/ZWQOVZh3SSFM+hefsuRmFOYetri+7PDiKXjLM6FNUfk+ZsBDwm+rBVfCiQ08Ll4eu5d3nnTsLfmgoXIw+CaEe5F9JE5c+dMh2v744YOGRof26kpkwsuTUJX0XPhL4by4jn8+CJa1pOCZGYqvM9QRXThNwuUNgDByF5Vd+nVegS+JwHXcr7T7pkSoI/9XkDMiBHxBAtbqUGPB43rapCoWzsMWHVuIESgJv75aAsJ2OTltvTrxoK9tfbssIoOcb8rv6mhQe63jJjRX3Y1vZeKynAbu8Ff6Fm75OSn09hoMT/dZbiWrHi+tTVuLEtG8xsagaKegZHMmhHk8yN7jsciZCRToSSqKB/BIcihwoVPW0PtSwg3A1zqf6QBfqsKTLDDPYaxQG9Y5jPgWs2B8zEDLTxQcmc5316zviV/EN0B65v/Nvrxvn+5mEatMSy0vGT+ydLmPoYXOOYUt3Ft14AWSWyuLYg8mXFtuWxxrj9ZDWhwamAxA/2jJCaFEPm7tILhCJrhAwDyRIe7f+76Qcl+aeu7zjQMD3o6I38Xx+U2KEaf1HjBKrx381kY8uh5qcXPajQwafLSytWL/VonLs7AQwLq51NBRaxA8I/2eg36xzjN8LDLfliLAZIfpnHRRlvzBnBKZwzeaYiB5Ped7iCos9UyiU1vLpnzcbHDJwSgLAg+zQKop4b7l4SnNkBiUj3ueMkfsnEt8TPqE8zYthaBlab6dDSGUvzrTFcO7OI9dS1ok0pDRqjkXujdPgUB3qVVxMbeQr64QapxELpVVSPOxv+VLNTlbiM11oEEOzyM7wMq8zdpU37ZkmVTzNXpcXBIFjrFXNRN+fx5pSFKLiYBxwy+8GNF81FIerTMDA6Von/6mSR3IAa5r9OS/DrkRoSNBvZ2kBFl/WIGV7lXayZoZDspR6PVBD//Sd+cCwMLJ9qqY2ek3041rznvGQ4nNiDNbhN3RK0eefVe+H7V4PuxgN5l5QWaYnX2r+lgSPB+I4RRYuc3rjQ7oYvxTlNKyiOujPfm7/ytFCXmfaKdAfH1PHKBebPLlUs/RvIQa0x8iQnvBDwOa1JyXRAjhyui9Z1xeI4r5k47Pt/vH+1q1cSk07j2Jik1wziniyzX5tX955aMU7BvnlAQwewadkEn9RlQ==",
            "1; AM4PR0501MB2657;\n\t6:gfxXpcB4r0vfUIgRqt/qVxXoV86d7MK1nvD8kyf6wlQy53u/t8h8f5zcN+jkOx2dMeWc40WUA/feUN7gxnpr1zbevoR+u3Xgxiz/dwQNttW1d/VP08ATJD4ZfvVRnGNT/n+WQj64MBFplJEt1Jau35NXSO2rRsYOV57+IAVugEZZKTRyFxiU4hUAqLMYnSFVuZUts2KfAogm4KVDKLAjA3AGTsKLqTx9h6SY1cH5K/Hfo36vGQEaNTJlzrDPKiJS0ck8hpK6Nx4uWFa3D55NKBYJxZ4z0hj8tKbZzHLeSt9Hftytws5sxkuQ40+Yd3orJOuS0z06enR6PzUjpDH+2r6WgPEDF6gZvQP6DywBxqE=;\n\t5:xHmsk7HEWoMiLDqp7epnVNAWTKFMce3BQDi3+7MQozLj/LDIZxiW3BduTR3Qg0GO6muXXh9nGoHO/X5UEgZ2JRB8vyvp+dIvh327YbnAbfr6rc5whQWHJfDQl6b2m9UlulVFXZ7O3Kap+OfNLmrq7NA3OAkoM3jPJ+4L0bMFiyA=;\n\t24:U66DiH12pPikI98yWWe5YSBfKZMurD8AAS73mJ3zxRGPX1Cz2ubAhryl2pVpUUVt2GmaStuogaFHY4SB8TUCyVR14NyBOt9mS/w42eFkYdU=;\n\t7:a8Hi8NsSrAmnna+MzDA7bB8EfAi9YsA9vRStoedIGFSfKvWZ3idP8ZryzyTCwMiEq4SNn/pYbTmvmEIldGSV/F1owjEkLSaEWfb5fC0xt/xPFmIJalHOmLbo8dFfH7tJACyLB2rRPUsxMIrFVSfqXrqAJ72b6E03HsVQcTkvOmPqv3R26wji25/osVOKTSfdXoApmmoIGwaRc/CLd1GraMGkPNTk1fUQgkWLdwWQYVB6/9BUZT9gV7WDniOkUB2f"
        ],
        "X-MS-TrafficTypeDiagnostic": "AM4PR0501MB2657:",
        "X-Microsoft-Antispam-PRVS": "<AM4PR0501MB26570F931DF7695824E3125CD2F00@AM4PR0501MB2657.eurprd05.prod.outlook.com>",
        "X-Exchange-Antispam-Report-Test": "UriScan:(60795455431006);",
        "X-Exchange-Antispam-Report-CFA-Test": "BCL:0; PCL:0;\n\tRULEID:(6040501)(2401047)(8121501046)(5005006)(93006095)(93001095)(10201501046)(3231101)(2400082)(944501161)(3002001)(6055026)(6041288)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123560045)(20161123564045)(20161123562045)(6072148)(201708071742011);\n\tSRVR:AM4PR0501MB2657; BCL:0; PCL:0; RULEID:; SRVR:AM4PR0501MB2657; ",
        "X-Forefront-PRVS": "058043A388",
        "X-Forefront-Antispam-Report": "SFV:NSPM;\n\tSFS:(10009020)(396003)(346002)(376002)(39380400002)(39860400002)(366004)(189003)(199004)(50466002)(5660300001)(16526019)(81156014)(8676002)(4326008)(16586007)(186003)(69596002)(81166006)(26005)(76176011)(33026002)(48376002)(105586002)(53936002)(21086003)(386003)(25786009)(2906002)(4720700003)(6666003)(97736004)(106356001)(68736007)(51416003)(6116002)(316002)(2950100002)(478600001)(305945005)(55016002)(47776003)(36756003)(7736002)(86362001)(575784001)(52116002)(8936002)(50226002)(7696005)(66066001)(59450400001)(6916009)(3846002);\n\tDIR:OUT; SFP:1101; SCL:1; SRVR:AM4PR0501MB2657; H:mellanox.com; FPR:;\n\tSPF:None; \n\tPTR:InfoNoRecords; MX:1; A:1; LANG:en; ",
        "Received-SPF": "None (protection.outlook.com: mellanox.com does not designate\n\tpermitted sender hosts)",
        "SpamDiagnosticOutput": "1:99",
        "SpamDiagnosticMetadata": "NSPM",
        "X-OriginatorOrg": "Mellanox.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "11 Feb 2018 17:24:58.1170\n\t(UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "b936e106-6897-4833-e296-08d571746052",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "a652971c-7d2e-4d9b-a6a4-d149256f461b",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "AM4PR0501MB2657",
        "Subject": "[dpdk-dev] [PATCH v6 3/3] net/failsafe: fix hotplug races",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://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": "<https://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": "Fail-safe uses periodic alarm mechanism, running from the host thread,\nto manage the hot-plug events of its sub-devices. This management\nrequires a lot of sub-devices PMDs operations (stop,close,start,etc).\n\nWhile the hot-plug alarm runs in the host thread, the application may\ncall fail-safe operations which directly trigger the sub-devices PMDs\noperations too, This call may occur from any thread decided by the\napplication (probably the master thread).\n\nSo, more than one operation can execute to a sub-device in same time\nwhat can cause a lot of races in the sub-PMDs.\n\nMoreover, some control operations update the fail-safe internal\ndatabases which can be used by the alarm mechanism in the same\ntime, what also can cause to races and crashes.\n\nFail-safe is the owner of its sub-devices and must to synchronize their\nuse according to the ETHDEV ownership rules.\n\nSynchronize hot-plug management by a new lock mechanism uses a mutex to\natomically defend each critical section in the fail-safe hot-plug\nmechanism and control operations to prevent any races between them.\n\nFixes: a46f8d5 (\"net/failsafe: add fail-safe PMD\")\nCc: stable@dpdk.org\n\nSigned-off-by: Matan Azrad <matan@mellanox.com>\n---\n drivers/net/failsafe/Makefile           |   1 +\n drivers/net/failsafe/failsafe.c         |  35 ++++++++\n drivers/net/failsafe/failsafe_ether.c   |   6 +-\n drivers/net/failsafe/failsafe_flow.c    |  20 ++++-\n drivers/net/failsafe/failsafe_ops.c     | 148 ++++++++++++++++++++++++++------\n drivers/net/failsafe/failsafe_private.h |  62 +++++++++++--\n 6 files changed, 239 insertions(+), 33 deletions(-)",
    "diff": "diff --git a/drivers/net/failsafe/Makefile b/drivers/net/failsafe/Makefile\nindex d1ae899..bd2f019 100644\n--- a/drivers/net/failsafe/Makefile\n+++ b/drivers/net/failsafe/Makefile\n@@ -68,5 +68,6 @@ CFLAGS += -pedantic\n LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring\n LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs\n LDLIBS += -lrte_bus_vdev\n+LDLIBS += -lpthread\n \n include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c\nindex 7b2cdbb..c499bfb 100644\n--- a/drivers/net/failsafe/failsafe.c\n+++ b/drivers/net/failsafe/failsafe.c\n@@ -113,17 +113,46 @@\n \t\t\tbreak;\n \t/* if we have non-probed device */\n \tif (i != PRIV(dev)->subs_tail) {\n+\t\tif (fs_lock(dev, 1) != 0)\n+\t\t\tgoto reinstall;\n \t\tret = failsafe_eth_dev_state_sync(dev);\n+\t\tfs_unlock(dev, 1);\n \t\tif (ret)\n \t\t\tERROR(\"Unable to synchronize sub_device state\");\n \t}\n \tfailsafe_dev_remove(dev);\n+reinstall:\n \tret = failsafe_hotplug_alarm_install(dev);\n \tif (ret)\n \t\tERROR(\"Unable to set up next alarm\");\n }\n \n static int\n+fs_mutex_init(struct fs_priv *priv)\n+{\n+\tint ret;\n+\tpthread_mutexattr_t attr;\n+\n+\tret = pthread_mutexattr_init(&attr);\n+\tif (ret) {\n+\t\tERROR(\"Cannot initiate mutex attributes - %s\", strerror(ret));\n+\t\treturn ret;\n+\t}\n+\t/* Allow mutex relocks for the thread holding the mutex. */\n+\tret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);\n+\tif (ret) {\n+\t\tERROR(\"Cannot set mutex type - %s\", strerror(ret));\n+\t\treturn ret;\n+\t}\n+\tret = pthread_mutex_init(&priv->hotplug_mutex, &attr);\n+\tif (ret) {\n+\t\tERROR(\"Cannot initiate mutex - %s\", strerror(ret));\n+\t\treturn ret;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n fs_eth_dev_create(struct rte_vdev_device *vdev)\n {\n \tstruct rte_eth_dev *dev;\n@@ -176,6 +205,9 @@\n \tret = failsafe_eal_init(dev);\n \tif (ret)\n \t\tgoto free_args;\n+\tret = fs_mutex_init(priv);\n+\tif (ret)\n+\t\tgoto free_args;\n \tret = failsafe_hotplug_alarm_install(dev);\n \tif (ret) {\n \t\tERROR(\"Could not set up plug-in event detection\");\n@@ -250,6 +282,9 @@\n \t\tERROR(\"Error while uninitializing sub-EAL\");\n \tfailsafe_args_free(dev);\n \tfs_sub_device_free(dev);\n+\tret = pthread_mutex_destroy(&PRIV(dev)->hotplug_mutex);\n+\tif (ret)\n+\t\tERROR(\"Error while destroying hotplug mutex\");\n \trte_free(PRIV(dev));\n \trte_eth_dev_release_port(dev);\n \treturn ret;\ndiff --git a/drivers/net/failsafe/failsafe_ether.c b/drivers/net/failsafe/failsafe_ether.c\nindex d820faf..8672819 100644\n--- a/drivers/net/failsafe/failsafe_ether.c\n+++ b/drivers/net/failsafe/failsafe_ether.c\n@@ -328,8 +328,11 @@\n \n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\tif (sdev->remove && fs_rxtx_clean(sdev)) {\n+\t\t\tif (fs_lock(dev, 1) != 0)\n+\t\t\t\treturn;\n \t\t\tfs_dev_stats_save(sdev);\n \t\t\tfs_dev_remove(sdev);\n+\t\t\tfs_unlock(dev, 1);\n \t\t}\n }\n \n@@ -428,7 +431,7 @@\n \t\t\t\tvoid *cb_arg, void *out __rte_unused)\n {\n \tstruct sub_device *sdev = cb_arg;\n-\n+\tfs_lock(sdev->fs_dev, 0);\n \t/* Switch as soon as possible tx_dev. */\n \tfs_switch_dev(sdev->fs_dev, sdev);\n \t/* Use safe bursts in any case. */\n@@ -438,6 +441,7 @@\n \t * the callback at the source of the current thread context.\n \t */\n \tsdev->remove = 1;\n+\tfs_unlock(sdev->fs_dev, 0);\n \treturn 0;\n }\n \ndiff --git a/drivers/net/failsafe/failsafe_flow.c b/drivers/net/failsafe/failsafe_flow.c\nindex 4d18e8e..ec8c909 100644\n--- a/drivers/net/failsafe/failsafe_flow.c\n+++ b/drivers/net/failsafe/failsafe_flow.c\n@@ -55,6 +55,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_flow_validate on sub_device %d\", i);\n \t\tret = rte_flow_validate(PORT_ID(sdev),\n@@ -62,9 +63,11 @@\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_flow_validate failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -79,6 +82,7 @@\n \tstruct rte_flow *flow;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tflow = fs_flow_allocate(attr, patterns, actions);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tflow->flows[i] = rte_flow_create(PORT_ID(sdev),\n@@ -90,6 +94,7 @@\n \t\t}\n \t}\n \tTAILQ_INSERT_TAIL(&PRIV(dev)->flow_list, flow, next);\n+\tfs_unlock(dev, 0);\n \treturn flow;\n err:\n \tFOREACH_SUBDEV(sdev, i, dev) {\n@@ -98,6 +103,7 @@\n \t\t\t\tflow->flows[i], error);\n \t}\n \tfs_flow_release(&flow);\n+\tfs_unlock(dev, 0);\n \treturn NULL;\n }\n \n@@ -115,6 +121,7 @@\n \t\treturn -EINVAL;\n \t}\n \tret = 0;\n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tint local_ret;\n \n@@ -131,6 +138,7 @@\n \t}\n \tTAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);\n \tfs_flow_release(&flow);\n+\tfs_unlock(dev, 0);\n \treturn ret;\n }\n \n@@ -144,12 +152,14 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_flow_flush on sub_device %d\", i);\n \t\tret = rte_flow_flush(PORT_ID(sdev), error);\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_flow_flush failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n@@ -157,6 +167,7 @@\n \t\tTAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next);\n \t\tfs_flow_release(&flow);\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -169,15 +180,19 @@\n {\n \tstruct sub_device *sdev;\n \n+\tfs_lock(dev, 0);\n \tsdev = TX_SUBDEV(dev);\n \tif (sdev != NULL) {\n \t\tint ret = rte_flow_query(PORT_ID(sdev),\n \t\t\t\t\t flow->flows[SUB_ID(sdev)],\n \t\t\t\t\t type, arg, error);\n \n-\t\tif ((ret = fs_err(sdev, ret)))\n+\t\tif ((ret = fs_err(sdev, ret))) {\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n+\t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \tWARN(\"No active sub_device to query about its flow\");\n \treturn -1;\n }\n@@ -191,6 +206,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV(sdev, i, dev) {\n \t\tif (sdev->state < DEV_PROBED)\n \t\t\tcontinue;\n@@ -202,11 +218,13 @@\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_flow_isolate failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t\tsdev->flow_isolated = set;\n \t}\n \tPRIV(dev)->flow_isolated = set;\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \ndiff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c\nindex f0e48c1..fe64c68 100644\n--- a/drivers/net/failsafe/failsafe_ops.c\n+++ b/drivers/net/failsafe/failsafe_ops.c\n@@ -94,6 +94,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tsupp_tx_offloads = PRIV(dev)->infos.tx_offload_capa;\n \ttx_offloads = dev->data->dev_conf.txmode.offloads;\n \tif ((tx_offloads & supp_tx_offloads) != tx_offloads) {\n@@ -101,6 +102,7 @@\n \t\tERROR(\"Some Tx offloads are not supported, \"\n \t\t      \"requested 0x%\" PRIx64 \" supported 0x%\" PRIx64,\n \t\t      tx_offloads, supp_tx_offloads);\n+\t\tfs_unlock(dev, 0);\n \t\treturn -rte_errno;\n \t}\n \tFOREACH_SUBDEV(sdev, i, dev) {\n@@ -139,6 +141,7 @@\n \t\t\tif (!fs_err(sdev, ret))\n \t\t\t\tcontinue;\n \t\t\tERROR(\"Could not configure sub_device %d\", i);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t\tif (rmv_interrupt) {\n@@ -165,6 +168,7 @@\n \t}\n \tif (PRIV(dev)->state < DEV_ACTIVE)\n \t\tPRIV(dev)->state = DEV_ACTIVE;\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -175,9 +179,12 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tret = failsafe_rx_intr_install(dev);\n-\tif (ret)\n+\tif (ret) {\n+\t\tfs_unlock(dev, 0);\n \t\treturn ret;\n+\t}\n \tFOREACH_SUBDEV(sdev, i, dev) {\n \t\tif (sdev->state != DEV_ACTIVE)\n \t\t\tcontinue;\n@@ -186,6 +193,7 @@\n \t\tif (ret) {\n \t\t\tif (!fs_err(sdev, ret))\n \t\t\t\tcontinue;\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t\tret = failsafe_rx_intr_install_subdevice(sdev);\n@@ -193,6 +201,7 @@\n \t\t\tif (!fs_err(sdev, ret))\n \t\t\t\tcontinue;\n \t\t\trte_eth_dev_stop(PORT_ID(sdev));\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t\tsdev->state = DEV_STARTED;\n@@ -200,6 +209,7 @@\n \tif (PRIV(dev)->state < DEV_STARTED)\n \t\tPRIV(dev)->state = DEV_STARTED;\n \tfs_switch_dev(dev, NULL);\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -209,6 +219,7 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tPRIV(dev)->state = DEV_STARTED - 1;\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_STARTED) {\n \t\trte_eth_dev_stop(PORT_ID(sdev));\n@@ -216,6 +227,7 @@\n \t\tsdev->state = DEV_STARTED - 1;\n \t}\n \tfailsafe_rx_intr_uninstall(dev);\n+\tfs_unlock(dev, 0);\n }\n \n static int\n@@ -225,15 +237,18 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_eth_dev_set_link_up on sub_device %d\", i);\n \t\tret = rte_eth_dev_set_link_up(PORT_ID(sdev));\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_set_link_up failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -244,15 +259,18 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_eth_dev_set_link_down on sub_device %d\", i);\n \t\tret = rte_eth_dev_set_link_down(PORT_ID(sdev));\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_set_link_down failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -263,6 +281,7 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tfailsafe_hotplug_alarm_cancel(dev);\n \tif (PRIV(dev)->state == DEV_STARTED)\n \t\tdev->dev_ops->dev_stop(dev);\n@@ -273,6 +292,7 @@\n \t\tsdev->state = DEV_ACTIVE - 1;\n \t}\n \tfs_dev_free_queues(dev);\n+\tfs_unlock(dev, 0);\n }\n \n static bool\n@@ -305,14 +325,16 @@\n \tif (queue == NULL)\n \t\treturn;\n \trxq = queue;\n+\tdev = rxq->priv->dev;\n+\tfs_lock(dev, 0);\n \tif (rxq->event_fd > 0)\n \t\tclose(rxq->event_fd);\n-\tdev = rxq->priv->dev;\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\tSUBOPS(sdev, rx_queue_release)\n \t\t\t(ETH(sdev)->data->rx_queues[rxq->qid]);\n \tdev->data->rx_queues[rxq->qid] = NULL;\n \trte_free(rxq);\n+\tfs_unlock(dev, 0);\n }\n \n static int\n@@ -338,6 +360,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \trxq = dev->data->rx_queues[rx_queue_id];\n \tif (rxq != NULL) {\n \t\tfs_rx_queue_release(rxq);\n@@ -353,14 +376,17 @@\n \t\t      dev->data->dev_conf.rxmode.offloads,\n \t\t      PRIV(dev)->infos.rx_offload_capa |\n \t\t      PRIV(dev)->infos.rx_queue_offload_capa);\n+\t\tfs_unlock(dev, 0);\n \t\treturn -rte_errno;\n \t}\n \trxq = rte_zmalloc(NULL,\n \t\t\t  sizeof(*rxq) +\n \t\t\t  sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,\n \t\t\t  RTE_CACHE_LINE_SIZE);\n-\tif (rxq == NULL)\n+\tif (rxq == NULL) {\n+\t\tfs_unlock(dev, 0);\n \t\treturn -ENOMEM;\n+\t}\n \tFOREACH_SUBDEV(sdev, i, dev)\n \t\trte_atomic64_init(&rxq->refcnt[i]);\n \trxq->qid = rx_queue_id;\n@@ -371,8 +397,10 @@\n \trxq->priv = PRIV(dev);\n \trxq->sdev = PRIV(dev)->subs;\n \tret = rte_intr_efd_enable(&intr_handle, 1);\n-\tif (ret < 0)\n+\tif (ret < 0) {\n+\t\tfs_unlock(dev, 0);\n \t\treturn ret;\n+\t}\n \trxq->event_fd = intr_handle.efds[0];\n \tdev->data->rx_queues[rx_queue_id] = rxq;\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n@@ -385,9 +413,11 @@\n \t\t\tgoto free_rxq;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n free_rxq:\n \tfs_rx_queue_release(rxq);\n+\tfs_unlock(dev, 0);\n \treturn ret;\n }\n \n@@ -400,20 +430,21 @@\n \tint ret;\n \tint rc = 0;\n \n+\tfs_lock(dev, 0);\n \tif (idx >= dev->data->nb_rx_queues) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n+\t\trc = -EINVAL;\n+\t\tgoto unlock;\n \t}\n \trxq = dev->data->rx_queues[idx];\n \tif (rxq == NULL || rxq->event_fd <= 0) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n+\t\trc = -EINVAL;\n+\t\tgoto unlock;\n \t}\n \t/* Fail if proxy service is nor running. */\n \tif (PRIV(dev)->rxp.sstate != SS_RUNNING) {\n \t\tERROR(\"failsafe interrupt services are not running\");\n-\t\trte_errno = EAGAIN;\n-\t\treturn -rte_errno;\n+\t\trc = -EAGAIN;\n+\t\tgoto unlock;\n \t}\n \trxq->enable_events = 1;\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n@@ -422,6 +453,8 @@\n \t\tif (ret)\n \t\t\trc = ret;\n \t}\n+unlock:\n+\tfs_unlock(dev, 0);\n \tif (rc)\n \t\trte_errno = -rc;\n \treturn rc;\n@@ -437,14 +470,15 @@\n \tint rc = 0;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tif (idx >= dev->data->nb_rx_queues) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n+\t\trc = -EINVAL;\n+\t\tgoto unlock;\n \t}\n \trxq = dev->data->rx_queues[idx];\n \tif (rxq == NULL || rxq->event_fd <= 0) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n+\t\trc = -EINVAL;\n+\t\tgoto unlock;\n \t}\n \trxq->enable_events = 0;\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n@@ -456,6 +490,8 @@\n \t/* Clear pending events */\n \twhile (read(rxq->event_fd, &u64, sizeof(uint64_t)) >  0)\n \t\t;\n+unlock:\n+\tfs_unlock(dev, 0);\n \tif (rc)\n \t\trte_errno = -rc;\n \treturn rc;\n@@ -492,11 +528,13 @@\n \t\treturn;\n \ttxq = queue;\n \tdev = txq->priv->dev;\n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\tSUBOPS(sdev, tx_queue_release)\n \t\t\t(ETH(sdev)->data->tx_queues[txq->qid]);\n \tdev->data->tx_queues[txq->qid] = NULL;\n \trte_free(txq);\n+\tfs_unlock(dev, 0);\n }\n \n static int\n@@ -511,6 +549,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \ttxq = dev->data->tx_queues[tx_queue_id];\n \tif (txq != NULL) {\n \t\tfs_tx_queue_release(txq);\n@@ -531,14 +570,17 @@\n \t\t      dev->data->dev_conf.txmode.offloads,\n \t\t      PRIV(dev)->infos.tx_offload_capa |\n \t\t      PRIV(dev)->infos.tx_queue_offload_capa);\n+\t\tfs_unlock(dev, 0);\n \t\treturn -rte_errno;\n \t}\n \ttxq = rte_zmalloc(\"ethdev TX queue\",\n \t\t\t  sizeof(*txq) +\n \t\t\t  sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail,\n \t\t\t  RTE_CACHE_LINE_SIZE);\n-\tif (txq == NULL)\n+\tif (txq == NULL) {\n+\t\tfs_unlock(dev, 0);\n \t\treturn -ENOMEM;\n+\t}\n \tFOREACH_SUBDEV(sdev, i, dev)\n \t\trte_atomic64_init(&txq->refcnt[i]);\n \ttxq->qid = tx_queue_id;\n@@ -557,9 +599,11 @@\n \t\t\tgoto free_txq;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n free_txq:\n \tfs_tx_queue_release(txq);\n+\tfs_unlock(dev, 0);\n \treturn ret;\n }\n \n@@ -586,8 +630,10 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\trte_eth_promiscuous_enable(PORT_ID(sdev));\n+\tfs_unlock(dev, 0);\n }\n \n static void\n@@ -596,8 +642,10 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\trte_eth_promiscuous_disable(PORT_ID(sdev));\n+\tfs_unlock(dev, 0);\n }\n \n static void\n@@ -606,8 +654,10 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\trte_eth_allmulticast_enable(PORT_ID(sdev));\n+\tfs_unlock(dev, 0);\n }\n \n static void\n@@ -616,8 +666,10 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\trte_eth_allmulticast_disable(PORT_ID(sdev));\n+\tfs_unlock(dev, 0);\n }\n \n static int\n@@ -628,6 +680,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling link_update on sub_device %d\", i);\n \t\tret = (SUBOPS(sdev, link_update))(ETH(sdev), wait_to_complete);\n@@ -635,6 +688,7 @@\n \t\t    rte_eth_dev_is_removed(PORT_ID(sdev)) == 0) {\n \t\t\tERROR(\"Link update failed for sub_device %d with error %d\",\n \t\t\t      i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n@@ -646,9 +700,11 @@\n \t\tl2 = &ETH(TX_SUBDEV(dev))->data->dev_link;\n \t\tif (memcmp(l1, l2, sizeof(*l1))) {\n \t\t\t*l1 = *l2;\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn 0;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn -1;\n }\n \n@@ -661,6 +717,7 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \trte_memcpy(stats, &PRIV(dev)->stats_accumulator, sizeof(*stats));\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tstruct rte_eth_stats *snapshot = &sdev->stats_snapshot.stats;\n@@ -676,12 +733,14 @@\n \t\t\tERROR(\"Operation rte_eth_stats_get failed for sub_device %d with error %d\",\n \t\t\t\t  i, ret);\n \t\t\t*timestamp = 0;\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t\t*timestamp = rte_rdtsc();\n inc:\n \t\tfailsafe_stats_increment(stats, snapshot);\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -691,11 +750,13 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\trte_eth_stats_reset(PORT_ID(sdev));\n \t\tmemset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats));\n \t}\n \tmemset(&PRIV(dev)->stats_accumulator, 0, sizeof(struct rte_eth_stats));\n+\tfs_unlock(dev, 0);\n }\n \n /**\n@@ -771,14 +832,20 @@\n {\n \tstruct sub_device *sdev;\n \tstruct rte_eth_dev *edev;\n+\tconst uint32_t *ret;\n \n+\tfs_lock(dev, 0);\n \tsdev = TX_SUBDEV(dev);\n-\tif (sdev == NULL)\n-\t\treturn NULL;\n+\tif (sdev == NULL) {\n+\t\tret = NULL;\n+\t\tgoto unlock;\n+\t}\n \tedev = ETH(sdev);\n \t/* ENOTSUP: counts as no supported ptypes */\n-\tif (SUBOPS(sdev, dev_supported_ptypes_get) == NULL)\n-\t\treturn NULL;\n+\tif (SUBOPS(sdev, dev_supported_ptypes_get) == NULL) {\n+\t\tret = NULL;\n+\t\tgoto unlock;\n+\t}\n \t/*\n \t * The API does not permit to do a clean AND of all ptypes,\n \t * It is also incomplete by design and we do not really care\n@@ -786,7 +853,10 @@\n \t * We just return the ptypes of the device of highest\n \t * priority, usually the PREFERRED device.\n \t */\n-\treturn SUBOPS(sdev, dev_supported_ptypes_get)(edev);\n+\tret = SUBOPS(sdev, dev_supported_ptypes_get)(edev);\n+unlock:\n+\tfs_unlock(dev, 0);\n+\treturn ret;\n }\n \n static int\n@@ -796,15 +866,18 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_eth_dev_set_mtu on sub_device %d\", i);\n \t\tret = rte_eth_dev_set_mtu(PORT_ID(sdev), mtu);\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_set_mtu failed for sub_device %d with error %d\",\n \t\t\t      i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -815,15 +888,18 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_eth_dev_vlan_filter on sub_device %d\", i);\n \t\tret = rte_eth_dev_vlan_filter(PORT_ID(sdev), vlan_id, on);\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_vlan_filter failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -832,13 +908,22 @@\n \t\tstruct rte_eth_fc_conf *fc_conf)\n {\n \tstruct sub_device *sdev;\n+\tint ret;\n \n+\tfs_lock(dev, 0);\n \tsdev = TX_SUBDEV(dev);\n-\tif (sdev == NULL)\n-\t\treturn 0;\n-\tif (SUBOPS(sdev, flow_ctrl_get) == NULL)\n-\t\treturn -ENOTSUP;\n-\treturn SUBOPS(sdev, flow_ctrl_get)(ETH(sdev), fc_conf);\n+\tif (sdev == NULL) {\n+\t\tret = 0;\n+\t\tgoto unlock;\n+\t}\n+\tif (SUBOPS(sdev, flow_ctrl_get) == NULL) {\n+\t\tret = -ENOTSUP;\n+\t\tgoto unlock;\n+\t}\n+\tret = SUBOPS(sdev, flow_ctrl_get)(ETH(sdev), fc_conf);\n+unlock:\n+\tfs_unlock(dev, 0);\n+\treturn ret;\n }\n \n static int\n@@ -849,15 +934,18 @@\n \tuint8_t i;\n \tint ret;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_eth_dev_flow_ctrl_set on sub_device %d\", i);\n \t\tret = rte_eth_dev_flow_ctrl_set(PORT_ID(sdev), fc_conf);\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_flow_ctrl_set failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -867,6 +955,7 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \t/* No check: already done within the rte_eth_dev_mac_addr_remove\n \t * call for the fail-safe device.\n \t */\n@@ -874,6 +963,7 @@\n \t\trte_eth_dev_mac_addr_remove(PORT_ID(sdev),\n \t\t\t\t&dev->data->mac_addrs[index]);\n \tPRIV(dev)->mac_addr_pool[index] = 0;\n+\tfs_unlock(dev, 0);\n }\n \n static int\n@@ -887,11 +977,13 @@\n \tuint8_t i;\n \n \tRTE_ASSERT(index < FAILSAFE_MAX_ETHADDR);\n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), mac_addr, vmdq);\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_mac_addr_add failed for sub_device %\"\n \t\t\t      PRIu8 \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n@@ -900,6 +992,7 @@\n \t\tPRIV(dev)->nb_mac_addr = index;\n \t}\n \tPRIV(dev)->mac_addr_pool[index] = vmdq;\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \n@@ -909,8 +1002,10 @@\n \tstruct sub_device *sdev;\n \tuint8_t i;\n \n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)\n \t\trte_eth_dev_default_mac_addr_set(PORT_ID(sdev), mac_addr);\n+\tfs_unlock(dev, 0);\n }\n \n static int\n@@ -928,15 +1023,18 @@\n \t\t*(const void **)arg = &fs_flow_ops;\n \t\treturn 0;\n \t}\n+\tfs_lock(dev, 0);\n \tFOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {\n \t\tDEBUG(\"Calling rte_eth_dev_filter_ctrl on sub_device %d\", i);\n \t\tret = rte_eth_dev_filter_ctrl(PORT_ID(sdev), type, op, arg);\n \t\tif ((ret = fs_err(sdev, ret))) {\n \t\t\tERROR(\"Operation rte_eth_dev_filter_ctrl failed for sub_device %d\"\n \t\t\t      \" with error %d\", i, ret);\n+\t\t\tfs_unlock(dev, 0);\n \t\t\treturn ret;\n \t\t}\n \t}\n+\tfs_unlock(dev, 0);\n \treturn 0;\n }\n \ndiff --git a/drivers/net/failsafe/failsafe_private.h b/drivers/net/failsafe/failsafe_private.h\nindex f3be152..ef1f63b 100644\n--- a/drivers/net/failsafe/failsafe_private.h\n+++ b/drivers/net/failsafe/failsafe_private.h\n@@ -7,6 +7,7 @@\n #define _RTE_ETH_FAILSAFE_PRIVATE_H_\n \n #include <sys/queue.h>\n+#include <pthread.h>\n \n #include <rte_atomic.h>\n #include <rte_dev.h>\n@@ -161,6 +162,9 @@ struct fs_priv {\n \t * appropriate failsafe Rx queue.\n \t */\n \tstruct rx_proxy rxp;\n+\tpthread_mutex_t hotplug_mutex;\n+\t/* Hot-plug mutex is locked by the alarm mechanism. */\n+\tvolatile unsigned int alarm_lock:1;\n \tunsigned int pending_alarm:1; /* An alarm is pending */\n \t/* flow isolation state */\n \tint flow_isolated:1;\n@@ -255,12 +259,6 @@ int failsafe_eth_lsc_event_callback(uint16_t port_id,\n \t     s != NULL;\t\t\t\t\t\\\n \t     s = fs_find_next((dev), i + 1, state, &i))\n \n-/**\n- * Iterator construct over fail-safe sub-devices:\n- * s:   (struct sub_device *), iterator\n- * i:   (uint8_t), increment\n- * dev: (struct rte_eth_dev *), fail-safe ethdev\n- */\n #define FOREACH_SUBDEV(s, i, dev)\t\t\t\\\n \tFOREACH_SUBDEV_STATE(s, i, dev, DEV_UNDEFINED)\n \n@@ -347,6 +345,58 @@ int failsafe_eth_lsc_event_callback(uint16_t port_id,\n }\n \n /*\n+ * Lock hot-plug mutex.\n+ * is_alarm means that the caller is, for sure, the hot-plug alarm mechanism.\n+ */\n+static inline int\n+fs_lock(struct rte_eth_dev *dev, unsigned int is_alarm)\n+{\n+\tint ret;\n+\n+\tif (is_alarm) {\n+\t\tret = pthread_mutex_trylock(&PRIV(dev)->hotplug_mutex);\n+\t\tif (ret) {\n+\t\t\tDEBUG(\"Hot-plug mutex lock trying failed(%s), will try\"\n+\t\t\t      \" again later...\", strerror(ret));\n+\t\t\treturn ret;\n+\t\t}\n+\t\tPRIV(dev)->alarm_lock = 1;\n+\t} else {\n+\t\tret = pthread_mutex_lock(&PRIV(dev)->hotplug_mutex);\n+\t\tif (ret) {\n+\t\t\tERROR(\"Cannot lock mutex(%s)\", strerror(ret));\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\tDEBUG(\"Hot-plug mutex was locked by thread %lu%s\", pthread_self(),\n+\t      PRIV(dev)->alarm_lock ? \" by the hot-plug alarm\" : \"\");\n+\treturn ret;\n+}\n+\n+/*\n+ * Unlock hot-plug mutex.\n+ * is_alarm means that the caller is, for sure, the hot-plug alarm mechanism.\n+ */\n+static inline void\n+fs_unlock(struct rte_eth_dev *dev, unsigned int is_alarm)\n+{\n+\tint ret;\n+\tunsigned int prev_alarm_lock = PRIV(dev)->alarm_lock;\n+\n+\tif (is_alarm) {\n+\t\tRTE_ASSERT(PRIV(dev)->alarm_lock == 1);\n+\t\tPRIV(dev)->alarm_lock = 0;\n+\t}\n+\tret = pthread_mutex_unlock(&PRIV(dev)->hotplug_mutex);\n+\tif (ret)\n+\t\tERROR(\"Cannot unlock hot-plug mutex(%s)\", strerror(ret));\n+\telse\n+\t\tDEBUG(\"Hot-plug mutex was unlocked by thread %lu%s\",\n+\t\t      pthread_self(),\n+\t\t      prev_alarm_lock ? \" by the hot-plug alarm\" : \"\");\n+}\n+\n+/*\n  * Switch emitting device.\n  * If banned is set, banned must not be considered for\n  * the role of emitting device.\n",
    "prefixes": [
        "dpdk-dev",
        "v6",
        "3/3"
    ]
}