get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 103972,
    "url": "http://patches.dpdk.org/api/patches/103972/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20211108185805.3887-3-eagostini@nvidia.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": "<20211108185805.3887-3-eagostini@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20211108185805.3887-3-eagostini@nvidia.com",
    "date": "2021-11-08T18:57:58",
    "name": "[v5,2/9] gpudev: add event notification",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "dce815841f95cb953073a71894aa6e28c322b632",
    "submitter": {
        "id": 1571,
        "url": "http://patches.dpdk.org/api/people/1571/?format=api",
        "name": "Elena Agostini",
        "email": "eagostini@nvidia.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20211108185805.3887-3-eagostini@nvidia.com/mbox/",
    "series": [
        {
            "id": 20381,
            "url": "http://patches.dpdk.org/api/series/20381/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=20381",
            "date": "2021-11-08T18:57:56",
            "name": "GPU library",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/20381/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/103972/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/103972/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 6D540A0C4D;\n\tMon,  8 Nov 2021 11:47:21 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 9035841122;\n\tMon,  8 Nov 2021 11:47:08 +0100 (CET)",
            "from NAM04-DM6-obe.outbound.protection.outlook.com\n (mail-dm6nam08on2083.outbound.protection.outlook.com [40.107.102.83])\n by mails.dpdk.org (Postfix) with ESMTP id C4066410E4\n for <dev@dpdk.org>; Mon,  8 Nov 2021 11:47:05 +0100 (CET)",
            "from MW2PR16CA0061.namprd16.prod.outlook.com (2603:10b6:907:1::38)\n by BY5PR12MB4289.namprd12.prod.outlook.com (2603:10b6:a03:204::14) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.10; Mon, 8 Nov\n 2021 10:47:04 +0000",
            "from CO1NAM11FT064.eop-nam11.prod.protection.outlook.com\n (2603:10b6:907:1:cafe::11) by MW2PR16CA0061.outlook.office365.com\n (2603:10b6:907:1::38) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.10 via Frontend\n Transport; Mon, 8 Nov 2021 10:47:04 +0000",
            "from mail.nvidia.com (216.228.112.34) by\n CO1NAM11FT064.mail.protection.outlook.com (10.13.175.77) with Microsoft SMTP\n Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id\n 15.20.4669.10 via Frontend Transport; Mon, 8 Nov 2021 10:47:03 +0000",
            "from nvidia.com (172.20.187.6) by HQMAIL107.nvidia.com\n (172.20.187.13) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Mon, 8 Nov\n 2021 10:47:01 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=JWf7ktbb6+PMl07uiAIEPGDSX0ZfH2P5vepLxNOSBEdwn8zMre6u+i3hDMDeFCJp+kqMqzbHWi4yF6vqZ1bnVgPIsgDpDir9LtxIKonff/LNQz/mEg9T/HTel7NT1Ak6xuDgynFvwAWBERWaGszrBphc4H/3M7X9eqxOH9GWuWlDFUOre+/BuQ/reNjVQvRsFYLCPKdaqUmnUUvClbsEL4EYnGCxevN/lcpPGuYZBNuEFEdXFCxB0kElGc0e/Kdk3lAHzObHqKM6KXqezXOBc/X57GchgS9hyVpwjagNmmo6o7uQaTHKx9lWWWQLNJ61ulwownyQTxv6RK6Kl2N+fg==",
        "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=Y6WzzOVaJDEQN6r0+nyZE+iVv62w3kb2RicpotIK7Z0=;\n b=f5Xds7SyVrODL1c1Qq5Avtx/vAc86Q1qPAXiHNImdjsKLIJnSyPjMxTlKJtOKl/FbWr7agEHuOCiyS9XrzvIiBjD+DPrHddFr3RzRtNao2/ATVaPQfYsRMwsgKG90zc9FsoJ6amC7twtiCsx97/tP1mRNzboMTbewHkMNv/Oft42cJrEq68pkPTWCXR2vqCR+VPiJp5G+7HEb5QWYBe79wotWXZrjVVPFtumarfveuniq3ux+WCGhqm5tDpEUag+4DQooNq30ouxIvZAXjQZ7e0NRC98mlcK436vjx03dr8gWtF5SWzE5l7GyazoWOnYESUtq9uoCJBt3QPPrBQcrw==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.112.34) smtp.rcpttodomain=monjalon.net smtp.mailfrom=nvidia.com;\n dmarc=pass (p=quarantine sp=quarantine pct=100) action=none\n header.from=nvidia.com; dkim=none (message not signed); arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=Y6WzzOVaJDEQN6r0+nyZE+iVv62w3kb2RicpotIK7Z0=;\n b=jN95WoUZibywmZga73cFbPyKSZZMUvA5PlOKxlqIkLvdeLllHvAsBeaUgD/F5dp4lg3bOvkcpnBcoNAi28zYBJiM9Kh5YjTTMk7n0CufM2Kz7vCdjnCQ83OIZAzEUowChfAxBP40wqmw/FI3OcdFz5pnSE5jX2uOax4b6XGiHtoGF5huXsXgWzjBP01M9yQI9o8779Ww3qDrBxHpGouwSrlVtsf+bLE6h+LZHDXukorIawS0PWPda59JKIEl7Gxd2LQtGVlKfgIKuMGx2o7IGHpIlRT15SIAe+udgfGsEYG4rh6TxyMDLcKvnJ9lLfwWet6o8pgKL0z6aUTvBS00aA==",
        "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 216.228.112.34)\n smtp.mailfrom=nvidia.com; monjalon.net; dkim=none (message not signed)\n header.d=none;monjalon.net; dmarc=pass action=none header.from=nvidia.com;",
        "Received-SPF": "Pass (protection.outlook.com: domain of nvidia.com designates\n 216.228.112.34 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.112.34; helo=mail.nvidia.com;",
        "From": "<eagostini@nvidia.com>",
        "To": "<dev@dpdk.org>",
        "CC": "Thomas Monjalon <thomas@monjalon.net>",
        "Date": "Mon, 8 Nov 2021 18:57:58 +0000",
        "Message-ID": "<20211108185805.3887-3-eagostini@nvidia.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20211108185805.3887-1-eagostini@nvidia.com>",
        "References": "<20210602203531.2288645-1-thomas@monjalon.net>\n <20211108185805.3887-1-eagostini@nvidia.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[172.20.187.6]",
        "X-ClientProxiedBy": "HQMAIL105.nvidia.com (172.20.187.12) To\n HQMAIL107.nvidia.com (172.20.187.13)",
        "X-EOPAttributedMessage": "0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-Correlation-Id": "574e3bec-5bcf-46ed-4168-08d9a2a519e1",
        "X-MS-TrafficTypeDiagnostic": "BY5PR12MB4289:",
        "X-LD-Processed": "43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr",
        "X-Microsoft-Antispam-PRVS": "\n <BY5PR12MB4289EB9B8F029C8063CC0D42CD919@BY5PR12MB4289.namprd12.prod.outlook.com>",
        "X-MS-Oob-TLC-OOBClassifiers": "OLM:8273;",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n L8k3PP2XUvxvFKiW5YMOFh1znCxnvlO9gtvdKV0fJ+UWCSP/B6VgO/jjwvuJsQBHZneIOBsyIm2IvOXm2Abl3rjU4ZDnRSCm43LU6FSiTlF/bOuxVXMPLdFZSTXtfwEC93p3tdAGsemInG7solYVnMBivpDA+irtt86l1ZFKzWT0d5nzLpc+tCl2mhVcisimgZKGe/ToTPgAXGdC5A+6imAs/FZRJre2Cv1BcYwhXaMJoWHN3UC7DW+myS8l/uxEXHdouDyIO3Dkma452cj0dUrI2LBQpSWGp9X8WMdE6kmg6Db4QDVk+BL1Nd37x7qk0kiQ6ThR0VMfCnujSvD7aI77P1OA6YsqHFarU7HFpixJ/gBhAXmrXBJywpq0Uw1iYp6MVrmiCgZE8mc8lCzvlbooWiMVv5C6QH6yD94WwZK8KExrj1Lv7Z5cZRUiEw3nx4F8d0s9L3B+QLT3fOI7uczilWUYq4irk2SrJb1CEzY+zRlI41SBPpsR7WoSm2SI9UM4TGfDUFy1xupGpm9XcLT1E+XUWeGG6otta1BlqpsMjiVBGdJnNJND2GXvSEy3VG9Rz/VbJyHggVmyIGyGPzpwMSD/WlGCi/IGGOjz4kPDDIxHLIjard2UpQecaprRrDecrzvoj2co4rk1ZiolTefK8ebLVAoUxDDetUk4AEpUzs0P16qJoF9M2YhnMYZlY5IqD+FN6RVVZy1tOIYfig==",
        "X-Forefront-Antispam-Report": "CIP:216.228.112.34; CTRY:US; LANG:en; SCL:1;\n SRV:;\n IPV:NLI; SFV:NSPM; H:mail.nvidia.com; PTR:schybrid03.nvidia.com; CAT:NONE;\n SFS:(4636009)(36840700001)(46966006)(8936002)(55016002)(186003)(36756003)(83380400001)(26005)(508600001)(2616005)(2876002)(86362001)(426003)(6286002)(6916009)(6666004)(16526019)(70586007)(336012)(5660300002)(4326008)(82310400003)(7696005)(356005)(8676002)(7636003)(70206006)(36860700001)(15650500001)(316002)(2906002)(47076005)(1076003);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "08 Nov 2021 10:47:03.6092 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 574e3bec-5bcf-46ed-4168-08d9a2a519e1",
        "X-MS-Exchange-CrossTenant-Id": "43083d15-7273-40c1-b7db-39efd9ccc17a",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[216.228.112.34];\n Helo=[mail.nvidia.com]",
        "X-MS-Exchange-CrossTenant-AuthSource": "\n CO1NAM11FT064.eop-nam11.prod.protection.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "BY5PR12MB4289",
        "Subject": "[dpdk-dev] [PATCH v5 2/9] gpudev: add event notification",
        "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",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Thomas Monjalon <thomas@monjalon.net>\n\nCallback functions may be registered for a device event.\nCallback management is per-process and not thread-safe.\n\nThe events RTE_GPU_EVENT_NEW and RTE_GPU_EVENT_DEL\nare notified respectively after creation and before removal\nof a device, as part of the library functions.\nSome future events may be emitted from drivers.\n\nSigned-off-by: Thomas Monjalon <thomas@monjalon.net>\n---\n lib/gpudev/gpudev.c        | 148 +++++++++++++++++++++++++++++++++++++\n lib/gpudev/gpudev_driver.h |   7 ++\n lib/gpudev/rte_gpudev.h    |  70 ++++++++++++++++++\n lib/gpudev/version.map     |   3 +\n 4 files changed, 228 insertions(+)",
    "diff": "diff --git a/lib/gpudev/gpudev.c b/lib/gpudev/gpudev.c\nindex aeb021f2cc..07572ae040 100644\n--- a/lib/gpudev/gpudev.c\n+++ b/lib/gpudev/gpudev.c\n@@ -3,6 +3,7 @@\n  */\n \n #include <rte_eal.h>\n+#include <rte_tailq.h>\n #include <rte_string_fns.h>\n #include <rte_errno.h>\n #include <rte_log.h>\n@@ -27,6 +28,16 @@ static int16_t gpu_max;\n /* Number of currently valid devices */\n static int16_t gpu_count;\n \n+/* Event callback object */\n+struct rte_gpu_callback {\n+\tTAILQ_ENTRY(rte_gpu_callback) next;\n+\trte_gpu_callback_t *function;\n+\tvoid *user_data;\n+\tenum rte_gpu_event event;\n+};\n+static rte_rwlock_t gpu_callback_lock = RTE_RWLOCK_INITIALIZER;\n+static void gpu_free_callbacks(struct rte_gpu *dev);\n+\n int\n rte_gpu_init(size_t dev_max)\n {\n@@ -166,6 +177,7 @@ rte_gpu_allocate(const char *name)\n \tdev->info.name = dev->name;\n \tdev->info.dev_id = dev_id;\n \tdev->info.numa_node = -1;\n+\tTAILQ_INIT(&dev->callbacks);\n \n \tgpu_count++;\n \tGPU_LOG(DEBUG, \"new device %s (id %d) of total %d\",\n@@ -180,6 +192,8 @@ rte_gpu_complete_new(struct rte_gpu *dev)\n \t\treturn;\n \n \tdev->state = RTE_GPU_STATE_INITIALIZED;\n+\tdev->state = RTE_GPU_STATE_INITIALIZED;\n+\trte_gpu_notify(dev, RTE_GPU_EVENT_NEW);\n }\n \n int\n@@ -192,6 +206,9 @@ rte_gpu_release(struct rte_gpu *dev)\n \n \tGPU_LOG(DEBUG, \"free device %s (id %d)\",\n \t\t\tdev->info.name, dev->info.dev_id);\n+\trte_gpu_notify(dev, RTE_GPU_EVENT_DEL);\n+\n+\tgpu_free_callbacks(dev);\n \tdev->state = RTE_GPU_STATE_UNUSED;\n \tgpu_count--;\n \n@@ -224,6 +241,137 @@ rte_gpu_close(int16_t dev_id)\n \treturn firsterr;\n }\n \n+int\n+rte_gpu_callback_register(int16_t dev_id, enum rte_gpu_event event,\n+\t\trte_gpu_callback_t *function, void *user_data)\n+{\n+\tint16_t next_dev, last_dev;\n+\tstruct rte_gpu_callback_list *callbacks;\n+\tstruct rte_gpu_callback *callback;\n+\n+\tif (!rte_gpu_is_valid(dev_id) && dev_id != RTE_GPU_ID_ANY) {\n+\t\tGPU_LOG(ERR, \"register callback of invalid ID %d\", dev_id);\n+\t\trte_errno = ENODEV;\n+\t\treturn -rte_errno;\n+\t}\n+\tif (function == NULL) {\n+\t\tGPU_LOG(ERR, \"cannot register callback without function\");\n+\t\trte_errno = EINVAL;\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tif (dev_id == RTE_GPU_ID_ANY) {\n+\t\tnext_dev = 0;\n+\t\tlast_dev = gpu_max - 1;\n+\t} else {\n+\t\tnext_dev = last_dev = dev_id;\n+\t}\n+\n+\trte_rwlock_write_lock(&gpu_callback_lock);\n+\tdo {\n+\t\tcallbacks = &gpus[next_dev].callbacks;\n+\n+\t\t/* check if not already registered */\n+\t\tTAILQ_FOREACH(callback, callbacks, next) {\n+\t\t\tif (callback->event == event &&\n+\t\t\t\t\tcallback->function == function &&\n+\t\t\t\t\tcallback->user_data == user_data) {\n+\t\t\t\tGPU_LOG(INFO, \"callback already registered\");\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t}\n+\n+\t\tcallback = malloc(sizeof(*callback));\n+\t\tif (callback == NULL) {\n+\t\t\tGPU_LOG(ERR, \"cannot allocate callback\");\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t\tcallback->function = function;\n+\t\tcallback->user_data = user_data;\n+\t\tcallback->event = event;\n+\t\tTAILQ_INSERT_TAIL(callbacks, callback, next);\n+\n+\t} while (++next_dev <= last_dev);\n+\trte_rwlock_write_unlock(&gpu_callback_lock);\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_gpu_callback_unregister(int16_t dev_id, enum rte_gpu_event event,\n+\t\trte_gpu_callback_t *function, void *user_data)\n+{\n+\tint16_t next_dev, last_dev;\n+\tstruct rte_gpu_callback_list *callbacks;\n+\tstruct rte_gpu_callback *callback, *nextcb;\n+\n+\tif (!rte_gpu_is_valid(dev_id) && dev_id != RTE_GPU_ID_ANY) {\n+\t\tGPU_LOG(ERR, \"unregister callback of invalid ID %d\", dev_id);\n+\t\trte_errno = ENODEV;\n+\t\treturn -rte_errno;\n+\t}\n+\tif (function == NULL) {\n+\t\tGPU_LOG(ERR, \"cannot unregister callback without function\");\n+\t\trte_errno = EINVAL;\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tif (dev_id == RTE_GPU_ID_ANY) {\n+\t\tnext_dev = 0;\n+\t\tlast_dev = gpu_max - 1;\n+\t} else {\n+\t\tnext_dev = last_dev = dev_id;\n+\t}\n+\n+\trte_rwlock_write_lock(&gpu_callback_lock);\n+\tdo {\n+\t\tcallbacks = &gpus[next_dev].callbacks;\n+\t\tRTE_TAILQ_FOREACH_SAFE(callback, callbacks, next, nextcb) {\n+\t\t\tif (callback->event != event ||\n+\t\t\t\t\tcallback->function != function ||\n+\t\t\t\t\t(callback->user_data != user_data &&\n+\t\t\t\t\tuser_data != (void *)-1))\n+\t\t\t\tcontinue;\n+\t\t\tTAILQ_REMOVE(callbacks, callback, next);\n+\t\t\tfree(callback);\n+\t\t}\n+\t} while (++next_dev <= last_dev);\n+\trte_rwlock_write_unlock(&gpu_callback_lock);\n+\n+\treturn 0;\n+}\n+\n+static void\n+gpu_free_callbacks(struct rte_gpu *dev)\n+{\n+\tstruct rte_gpu_callback_list *callbacks;\n+\tstruct rte_gpu_callback *callback, *nextcb;\n+\n+\tcallbacks = &dev->callbacks;\n+\trte_rwlock_write_lock(&gpu_callback_lock);\n+\tRTE_TAILQ_FOREACH_SAFE(callback, callbacks, next, nextcb) {\n+\t\tTAILQ_REMOVE(callbacks, callback, next);\n+\t\tfree(callback);\n+\t}\n+\trte_rwlock_write_unlock(&gpu_callback_lock);\n+}\n+\n+void\n+rte_gpu_notify(struct rte_gpu *dev, enum rte_gpu_event event)\n+{\n+\tint16_t dev_id;\n+\tstruct rte_gpu_callback *callback;\n+\n+\tdev_id = dev->info.dev_id;\n+\trte_rwlock_read_lock(&gpu_callback_lock);\n+\tTAILQ_FOREACH(callback, &dev->callbacks, next) {\n+\t\tif (callback->event != event || callback->function == NULL)\n+\t\t\tcontinue;\n+\t\tcallback->function(dev_id, event, callback->user_data);\n+\t}\n+\trte_rwlock_read_unlock(&gpu_callback_lock);\n+}\n+\n int\n rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info)\n {\ndiff --git a/lib/gpudev/gpudev_driver.h b/lib/gpudev/gpudev_driver.h\nindex 9e096e3b64..2a7089aa52 100644\n--- a/lib/gpudev/gpudev_driver.h\n+++ b/lib/gpudev/gpudev_driver.h\n@@ -12,6 +12,7 @@\n #define RTE_GPUDEV_DRIVER_H\n \n #include <stdint.h>\n+#include <sys/queue.h>\n \n #include <rte_dev.h>\n \n@@ -43,6 +44,8 @@ struct rte_gpu {\n \tstruct rte_gpu_info info;\n \t/* Driver functions. */\n \tstruct rte_gpu_ops ops;\n+\t/* Event callback list. */\n+\tTAILQ_HEAD(rte_gpu_callback_list, rte_gpu_callback) callbacks;\n \t/* Current state (used or not) in the running process. */\n \tenum rte_gpu_state state; /* Updated by this library. */\n \t/* Driver-specific private data for the running process. */\n@@ -64,4 +67,8 @@ void rte_gpu_complete_new(struct rte_gpu *dev);\n __rte_internal\n int rte_gpu_release(struct rte_gpu *dev);\n \n+/* Call registered callbacks. No multi-process event. */\n+__rte_internal\n+void rte_gpu_notify(struct rte_gpu *dev, enum rte_gpu_event);\n+\n #endif /* RTE_GPUDEV_DRIVER_H */\ndiff --git a/lib/gpudev/rte_gpudev.h b/lib/gpudev/rte_gpudev.h\nindex eb7cfa8c59..e1702fbfe4 100644\n--- a/lib/gpudev/rte_gpudev.h\n+++ b/lib/gpudev/rte_gpudev.h\n@@ -31,6 +31,11 @@ extern \"C\" {\n \n /** Empty device ID. */\n #define RTE_GPU_ID_NONE -1\n+/** Catch-all device ID. */\n+#define RTE_GPU_ID_ANY INT16_MIN\n+\n+/** Catch-all callback data. */\n+#define RTE_GPU_CALLBACK_ANY_DATA ((void *)-1)\n \n /** Store device info. */\n struct rte_gpu_info {\n@@ -46,6 +51,18 @@ struct rte_gpu_info {\n \tint16_t numa_node;\n };\n \n+/** Flags passed in notification callback. */\n+enum rte_gpu_event {\n+\t/** Device is just initialized. */\n+\tRTE_GPU_EVENT_NEW,\n+\t/** Device is going to be released. */\n+\tRTE_GPU_EVENT_DEL,\n+};\n+\n+/** Prototype of event callback function. */\n+typedef void (rte_gpu_callback_t)(int16_t dev_id,\n+\t\tenum rte_gpu_event event, void *user_data);\n+\n /**\n  * @warning\n  * @b EXPERIMENTAL: this API may change without prior notice.\n@@ -141,6 +158,59 @@ int16_t rte_gpu_find_next(int16_t dev_id);\n __rte_experimental\n int rte_gpu_close(int16_t dev_id);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Register a function as event callback.\n+ * A function may be registered multiple times for different events.\n+ *\n+ * @param dev_id\n+ *   Device ID to get notified about.\n+ *   RTE_GPU_ID_ANY means all devices.\n+ * @param event\n+ *   Device event to be registered for.\n+ * @param function\n+ *   Callback function to be called on event.\n+ * @param user_data\n+ *   Optional parameter passed in the callback.\n+ *\n+ * @return\n+ *   0 on success, -rte_errno otherwise:\n+ *   - ENODEV if invalid dev_id\n+ *   - EINVAL if NULL function\n+ *   - ENOMEM if out of memory\n+ */\n+__rte_experimental\n+int rte_gpu_callback_register(int16_t dev_id, enum rte_gpu_event event,\n+\t\trte_gpu_callback_t *function, void *user_data);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Unregister for an event.\n+ *\n+ * @param dev_id\n+ *   Device ID to be silenced.\n+ *   RTE_GPU_ID_ANY means all devices.\n+ * @param event\n+ *   Registered event.\n+ * @param function\n+ *   Registered function.\n+ * @param user_data\n+ *   Optional parameter as registered.\n+ *   RTE_GPU_CALLBACK_ANY_DATA is a catch-all.\n+ *\n+ * @return\n+ *   0 on success, -rte_errno otherwise:\n+ *   - ENODEV if invalid dev_id\n+ *   - EINVAL if NULL function\n+ */\n+__rte_experimental\n+int rte_gpu_callback_unregister(int16_t dev_id, enum rte_gpu_event event,\n+\t\trte_gpu_callback_t *function, void *user_data);\n+\n /**\n  * @warning\n  * @b EXPERIMENTAL: this API may change without prior notice.\ndiff --git a/lib/gpudev/version.map b/lib/gpudev/version.map\nindex 6ac6b327e2..b3b6b76c1c 100644\n--- a/lib/gpudev/version.map\n+++ b/lib/gpudev/version.map\n@@ -2,6 +2,8 @@ EXPERIMENTAL {\n \tglobal:\n \n \t# added in 21.11\n+\trte_gpu_callback_register;\n+\trte_gpu_callback_unregister;\n \trte_gpu_close;\n \trte_gpu_count_avail;\n \trte_gpu_find_next;\n@@ -16,5 +18,6 @@ INTERNAL {\n \trte_gpu_allocate;\n \trte_gpu_complete_new;\n \trte_gpu_get_by_name;\n+\trte_gpu_notify;\n \trte_gpu_release;\n };\n",
    "prefixes": [
        "v5",
        "2/9"
    ]
}