get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 103973,
    "url": "http://patches.dpdk.org/api/patches/103973/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20211108185805.3887-4-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-4-eagostini@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20211108185805.3887-4-eagostini@nvidia.com",
    "date": "2021-11-08T18:57:59",
    "name": "[v5,3/9] gpudev: add child device representing a device context",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "00e5d67c2ffc0b2992439b1d9d5dae4eee845cd8",
    "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-4-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/103973/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/103973/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 06A3BA0C4D;\n\tMon,  8 Nov 2021 11:47:32 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id E62784113B;\n\tMon,  8 Nov 2021 11:47:09 +0100 (CET)",
            "from NAM10-MW2-obe.outbound.protection.outlook.com\n (mail-mw2nam10on2073.outbound.protection.outlook.com [40.107.94.73])\n by mails.dpdk.org (Postfix) with ESMTP id C82E24111D\n for <dev@dpdk.org>; Mon,  8 Nov 2021 11:47:06 +0100 (CET)",
            "from MW2PR16CA0057.namprd16.prod.outlook.com (2603:10b6:907:1::34)\n by BY5PR12MB3874.namprd12.prod.outlook.com (2603:10b6:a03:1ad::15) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.11; Mon, 8 Nov\n 2021 10:47:04 +0000",
            "from CO1NAM11FT064.eop-nam11.prod.protection.outlook.com\n (2603:10b6:907:1:cafe::50) by MW2PR16CA0057.outlook.office365.com\n (2603:10b6:907:1::34) 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:04 +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=nDhpo3Grc96XVELzhveTBXBtniTXEMlNll0IkYk/Fwp612XxBrO+g57wo+yN6ARrTM+yGnBLoCvcRHPOMg5JX9eBORw9m/hjUfG1fJ6EQ0rY2xd8vXUBnjQdDnramH8pmjvnQscwYGqKTTEuSe673eNM54AnVRTa5xEeZqOxGMiE2oLmzzExiLVzLtzbeaiQwUOQGgI+Po+eWke0RKxvQCNKUSnQ2yqOJKhp8klJiKYx2V3g28eWDsF+k9iFGdYjciFlT1ZSr/GxNm7G6flHOe992mKc3v08SXyzWv+njy3hvrrbcHf2SPxckWWf5bAtgB6RQVU/4cw5Atc0AhfL+g==",
        "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=TnfqIRyBhFfrJZ+ip7Yeps/B7RWflH5DKzocSlAQKBo=;\n b=Bg8/c2F7V2JQpoB/OsauGiskreSMkb2EerTJFGoVjsxcIY/9r47myGC0rjGJDjuJXYrDzouKtCOcHFdA6617YpQanc90YBRbcsYeU4sTItlISTFctXINiP6CPBjLgw9TD/cDU44b1Wkd+hBcaH5McvW9G9BU85vESVuuI8/GTCEivMTGMKYU1typzvpgOTo7mWbv39Yo8VJ6Nj98Q/j4IzIlFifnT1OcKsl5reXO3DHl4McYRrxP/RK1af1BR7bQiWhfG519WqUf9oVJlVkBQ5N93oQYvfv+rsfRPYsw2MMOgLeJqw/3kmdI6abZuPYkKJfE0SFiFi5NwwfclwQcfw==",
        "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=TnfqIRyBhFfrJZ+ip7Yeps/B7RWflH5DKzocSlAQKBo=;\n b=AGq16BjD01iiWBbMNeeaWEvAIR+XJB0TnhVzCVyDs33xP8pyb+RHuS5pK7mM5HC8vq28LAyrHQt3YXp5+VwX5CqyTgX5NpOTT7nq/ab9/qy/d6K7lPsaipjklIuhmmWy3+n11wT2k0/tr33rcY8Ekvx8w7t13H8dZcGXC2yQE2bMo1qY5VIRie7yk8dhjygs1z/2Igs2XPiehpfzrMUe0tav3NtYcw+addeP+EcJ1PG0OQhonPFIrwyuHm90FWuoOCVx55qun9C6iYTAOtN4Fm/o6ltQ783wCWPtWYa6vHudFU5klzMwWPFzbSyKMti6nSqDYHtsPdupGPkSSFSUuQ==",
        "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:59 +0000",
        "Message-ID": "<20211108185805.3887-4-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": "50693c8f-c5fb-4652-cc7a-08d9a2a51a5a",
        "X-MS-TrafficTypeDiagnostic": "BY5PR12MB3874:",
        "X-LD-Processed": "43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr",
        "X-Microsoft-Antispam-PRVS": "\n <BY5PR12MB3874A3453666623CB907D6B3CD919@BY5PR12MB3874.namprd12.prod.outlook.com>",
        "X-MS-Oob-TLC-OOBClassifiers": "OLM:6790;",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n uCX8Il18zHgJ/6LH9zZrzj+gdx2sHbuJbdhTzRaOjW8zO+SQ26ltpsrKCAAUuyjlPSa2koqvntbBPCD+OY82T/xp7vZHVz1sTTIfjc6J0YN3HYmnoIWASzoH/IYCrRstg8JwtCZAHKHlEgUKzdngrXHbGLPO33oqB1Ifugvs1gjE3BXQPTEISgeopj5AMMBeYwTNm/iLla02DJwBIEHrOuP0nlsCYjEUO3mTi6e9UkqO/ucIsMrC78Wfr8xUogCqP0s0WR+QlnrrmVKsborbuBwOAjSGWgM6Y8DG8Rc0iIW6M/NwQX8Z7L4VMrQ4uAjuh/KEWfup3Cs9wOw3Z6G0oTKMZ9PM0QTU2JxYDxpWFQkCn9PVsFJm5p1tfxHYAF8m9aEqgYjqAtv9djNqfGDWnXbjxRMXsHbd8x6iRuzM8Kqs6DUEhaRpkvyQoGw1LT9oc68vaHJ/13MHn7gAyh1uURDbEu8GvS4Uve57S4WR+pmNjouHMc4mYNquk7zdffYwm5U3N1Lmf9dvWsLzWJvhi3JLs7Utg45gTkgsgAhWPI3KM6ye2v8L3Ei0hBqGiQn3lC9C+Xq3dkizj0Dpq1Rtj88vL6YKfG02y9x7cy0IDq6+Hv10MZVk5Io18SIPNOT036MLIhUIXB8pIF1kONWDKC5gdvvPi22SLzoK/MGR1dBNvd7qDp6QtE3jatk+p+2vhjFvVR8m1wIldD0Bgu2nTA==",
        "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)(46966006)(36840700001)(508600001)(8936002)(4326008)(47076005)(82310400003)(336012)(55016002)(6286002)(86362001)(16526019)(7696005)(8676002)(70206006)(186003)(70586007)(316002)(36860700001)(5660300002)(1076003)(36756003)(2876002)(6916009)(7636003)(356005)(83380400001)(426003)(2906002)(2616005)(26005);\n DIR:OUT; SFP:1101;",
        "X-OriginatorOrg": "Nvidia.com",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "08 Nov 2021 10:47:04.3958 (UTC)",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 50693c8f-c5fb-4652-cc7a-08d9a2a51a5a",
        "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": "BY5PR12MB3874",
        "Subject": "[dpdk-dev] [PATCH v5 3/9] gpudev: add child device representing a\n device context",
        "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\nThe computing device may operate in some isolated contexts.\nMemory and processing are isolated in a silo represented by\na child device.\nThe context is provided as an opaque by the caller of\nrte_gpu_add_child().\n\nSigned-off-by: Thomas Monjalon <thomas@monjalon.net>\n---\n doc/guides/prog_guide/gpudev.rst | 12 ++++++\n lib/gpudev/gpudev.c              | 45 +++++++++++++++++++-\n lib/gpudev/gpudev_driver.h       |  2 +-\n lib/gpudev/rte_gpudev.h          | 71 +++++++++++++++++++++++++++++---\n lib/gpudev/version.map           |  1 +\n 5 files changed, 123 insertions(+), 8 deletions(-)",
    "diff": "diff --git a/doc/guides/prog_guide/gpudev.rst b/doc/guides/prog_guide/gpudev.rst\nindex 6ea7239159..7694639489 100644\n--- a/doc/guides/prog_guide/gpudev.rst\n+++ b/doc/guides/prog_guide/gpudev.rst\n@@ -34,3 +34,15 @@ This library provides a number of features:\n \n API Overview\n ------------\n+\n+Child Device\n+~~~~~~~~~~~~\n+\n+By default, DPDK PCIe module detects and registers physical GPU devices\n+in the system.\n+With the gpudev library is also possible to add additional non-physical devices\n+through an ``uint64_t`` generic handler (e.g. CUDA Driver context)\n+that will be registered internally by the driver as an additional device (child)\n+connected to a physical device (parent).\n+Each device (parent or child) is represented through a ID\n+required to indicate which device a given operation should be executed on.\ndiff --git a/lib/gpudev/gpudev.c b/lib/gpudev/gpudev.c\nindex 07572ae040..aaf41e6071 100644\n--- a/lib/gpudev/gpudev.c\n+++ b/lib/gpudev/gpudev.c\n@@ -80,13 +80,22 @@ rte_gpu_is_valid(int16_t dev_id)\n \treturn false;\n }\n \n+static bool\n+gpu_match_parent(int16_t dev_id, int16_t parent)\n+{\n+\tif (parent == RTE_GPU_ID_ANY)\n+\t\treturn true;\n+\treturn gpus[dev_id].info.parent == parent;\n+}\n+\n int16_t\n-rte_gpu_find_next(int16_t dev_id)\n+rte_gpu_find_next(int16_t dev_id, int16_t parent)\n {\n \tif (dev_id < 0)\n \t\tdev_id = 0;\n \twhile (dev_id < gpu_max &&\n-\t\t\tgpus[dev_id].state == RTE_GPU_STATE_UNUSED)\n+\t\t\t(gpus[dev_id].state == RTE_GPU_STATE_UNUSED ||\n+\t\t\t!gpu_match_parent(dev_id, parent)))\n \t\tdev_id++;\n \n \tif (dev_id >= gpu_max)\n@@ -177,6 +186,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+\tdev->info.parent = RTE_GPU_ID_NONE;\n \tTAILQ_INIT(&dev->callbacks);\n \n \tgpu_count++;\n@@ -185,6 +195,28 @@ rte_gpu_allocate(const char *name)\n \treturn dev;\n }\n \n+int16_t\n+rte_gpu_add_child(const char *name, int16_t parent, uint64_t child_context)\n+{\n+\tstruct rte_gpu *dev;\n+\n+\tif (!rte_gpu_is_valid(parent)) {\n+\t\tGPU_LOG(ERR, \"add child to invalid parent ID %d\", parent);\n+\t\trte_errno = ENODEV;\n+\t\treturn -rte_errno;\n+\t}\n+\n+\tdev = rte_gpu_allocate(name);\n+\tif (dev == NULL)\n+\t\treturn -rte_errno;\n+\n+\tdev->info.parent = parent;\n+\tdev->info.context = child_context;\n+\n+\trte_gpu_complete_new(dev);\n+\treturn dev->info.dev_id;\n+}\n+\n void\n rte_gpu_complete_new(struct rte_gpu *dev)\n {\n@@ -199,10 +231,19 @@ rte_gpu_complete_new(struct rte_gpu *dev)\n int\n rte_gpu_release(struct rte_gpu *dev)\n {\n+\tint16_t dev_id, child;\n+\n \tif (dev == NULL) {\n \t\trte_errno = ENODEV;\n \t\treturn -rte_errno;\n \t}\n+\tdev_id = dev->info.dev_id;\n+\tRTE_GPU_FOREACH_CHILD(child, dev_id) {\n+\t\tGPU_LOG(ERR, \"cannot release device %d with child %d\",\n+\t\t\t\tdev_id, child);\n+\t\trte_errno = EBUSY;\n+\t\treturn -rte_errno;\n+\t}\n \n \tGPU_LOG(DEBUG, \"free device %s (id %d)\",\n \t\t\tdev->info.name, dev->info.dev_id);\ndiff --git a/lib/gpudev/gpudev_driver.h b/lib/gpudev/gpudev_driver.h\nindex 2a7089aa52..4d0077161c 100644\n--- a/lib/gpudev/gpudev_driver.h\n+++ b/lib/gpudev/gpudev_driver.h\n@@ -31,7 +31,7 @@ typedef int (rte_gpu_info_get_t)(struct rte_gpu *dev, struct rte_gpu_info *info)\n struct rte_gpu_ops {\n \t/* Get device info. If NULL, info is just copied. */\n \trte_gpu_info_get_t *dev_info_get;\n-\t/* Close device. */\n+\t/* Close device or child context. */\n \trte_gpu_close_t *dev_close;\n };\n \ndiff --git a/lib/gpudev/rte_gpudev.h b/lib/gpudev/rte_gpudev.h\nindex e1702fbfe4..df75dbdbab 100644\n--- a/lib/gpudev/rte_gpudev.h\n+++ b/lib/gpudev/rte_gpudev.h\n@@ -41,8 +41,12 @@ extern \"C\" {\n struct rte_gpu_info {\n \t/** Unique identifier name. */\n \tconst char *name;\n+\t/** Opaque handler of the device context. */\n+\tuint64_t context;\n \t/** Device ID. */\n \tint16_t dev_id;\n+\t/** ID of the parent device, RTE_GPU_ID_NONE if no parent */\n+\tint16_t parent;\n \t/** Total processors available on device. */\n \tuint32_t processor_count;\n \t/** Total memory available on device. */\n@@ -110,6 +114,33 @@ uint16_t rte_gpu_count_avail(void);\n __rte_experimental\n bool rte_gpu_is_valid(int16_t dev_id);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Create a virtual device representing a context in the parent device.\n+ *\n+ * @param name\n+ *   Unique string to identify the device.\n+ * @param parent\n+ *   Device ID of the parent.\n+ * @param child_context\n+ *   Opaque context handler.\n+ *\n+ * @return\n+ *   Device ID of the new created child, -rte_errno otherwise:\n+ *   - EINVAL if empty name\n+ *   - ENAMETOOLONG if long name\n+ *   - EEXIST if existing device name\n+ *   - ENODEV if invalid parent\n+ *   - EPERM if secondary process\n+ *   - ENOENT if too many devices\n+ *   - ENOMEM if out of space\n+ */\n+__rte_experimental\n+int16_t rte_gpu_add_child(const char *name,\n+\t\tint16_t parent, uint64_t child_context);\n+\n /**\n  * @warning\n  * @b EXPERIMENTAL: this API may change without prior notice.\n@@ -118,13 +149,17 @@ bool rte_gpu_is_valid(int16_t dev_id);\n  *\n  * @param dev_id\n  *   The initial device ID to start the research.\n+ * @param parent\n+ *   The device ID of the parent.\n+ *   RTE_GPU_ID_NONE means no parent.\n+ *   RTE_GPU_ID_ANY means no or any parent.\n  *\n  * @return\n  *   Next device ID corresponding to a valid and initialized computing device,\n  *   RTE_GPU_ID_NONE if there is none.\n  */\n __rte_experimental\n-int16_t rte_gpu_find_next(int16_t dev_id);\n+int16_t rte_gpu_find_next(int16_t dev_id, int16_t parent);\n \n /**\n  * @warning\n@@ -136,15 +171,41 @@ int16_t rte_gpu_find_next(int16_t dev_id);\n  *   The ID of the next possible valid device, usually 0 to iterate all.\n  */\n #define RTE_GPU_FOREACH(dev_id) \\\n-\tfor (dev_id = rte_gpu_find_next(0); \\\n-\t     dev_id > 0; \\\n-\t     dev_id = rte_gpu_find_next(dev_id + 1))\n+\tRTE_GPU_FOREACH_CHILD(dev_id, RTE_GPU_ID_ANY)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Macro to iterate over all valid computing devices having no parent.\n+ *\n+ * @param dev_id\n+ *   The ID of the next possible valid device, usually 0 to iterate all.\n+ */\n+#define RTE_GPU_FOREACH_PARENT(dev_id) \\\n+\tRTE_GPU_FOREACH_CHILD(dev_id, RTE_GPU_ID_NONE)\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Macro to iterate over all valid children of a computing device parent.\n+ *\n+ * @param dev_id\n+ *   The ID of the next possible valid device, usually 0 to iterate all.\n+ * @param parent\n+ *   The device ID of the parent.\n+ */\n+#define RTE_GPU_FOREACH_CHILD(dev_id, parent) \\\n+\tfor (dev_id = rte_gpu_find_next(0, parent); \\\n+\t     dev_id >= 0; \\\n+\t     dev_id = rte_gpu_find_next(dev_id + 1, parent))\n \n /**\n  * @warning\n  * @b EXPERIMENTAL: this API may change without prior notice.\n  *\n- * Close device.\n+ * Close device or child context.\n  * All resources are released.\n  *\n  * @param dev_id\ndiff --git a/lib/gpudev/version.map b/lib/gpudev/version.map\nindex b3b6b76c1c..4a934ed933 100644\n--- a/lib/gpudev/version.map\n+++ b/lib/gpudev/version.map\n@@ -2,6 +2,7 @@ EXPERIMENTAL {\n \tglobal:\n \n \t# added in 21.11\n+\trte_gpu_add_child;\n \trte_gpu_callback_register;\n \trte_gpu_callback_unregister;\n \trte_gpu_close;\n",
    "prefixes": [
        "v5",
        "3/9"
    ]
}