From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR01-DB5-obe.outbound.protection.outlook.com (mail-db5eur01on0045.outbound.protection.outlook.com [104.47.2.45]) by dpdk.org (Postfix) with ESMTP id B92BD1B45E for ; Thu, 12 Jul 2018 12:58:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wVB75FBnCjg+pYsnOBtK3bJHxC7f/2jOY+TWYCEw09Q=; b=sqA2Wdcrj17MIjeZbV62blhBamSBNBbkx2ear1C4pGqtiY+llgvXVz3H1qGfAoj+uS//JqGvEyhqGqTxSUmqbrnG3qYccPTKmwqC8V0+uWz/j2LYKSm/bpESupXUbs0Nql0tmP/MfqWWK8E4QVXChtU58DGyTDaxYxp7M4tKduw= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=shreyansh.jain@nxp.com; Received: from [10.232.14.39] (14.142.187.166) by AM6PR04MB4679.eurprd04.prod.outlook.com (2603:10a6:20b:1c::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.952.17; Thu, 12 Jul 2018 10:58:53 +0000 To: Gaetan Rivet References: From: Shreyansh Jain Cc: dev@dpdk.org Message-ID: <1a96a4a1-71fd-74ef-f599-22dc21134ed4@nxp.com> Date: Thu, 12 Jul 2018 16:28:27 +0530 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Originating-IP: [14.142.187.166] X-ClientProxiedBy: BM1PR0101CA0061.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00:19::23) To AM6PR04MB4679.eurprd04.prod.outlook.com (2603:10a6:20b:1c::18) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ccbc6ef9-93ad-450d-de70-08d5e7e6754b X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989117)(5600053)(711020)(4534165)(7168020)(4627221)(201703031133081)(201702281549075)(8990107)(48565401081)(2017052603328)(7153060)(7193020); SRVR:AM6PR04MB4679; X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 3:eIdIEzLPLVnMbdYfaPkLA6QmXh7Lu33Mg0QnxcgrI3G8Q8yjqJpXwa61nCUwzdz9EAI88c6nfoEs7oeiyQjPKXXoqVBEsV7NdJblMgWDkJUDiO9GYSfYJ8YDTEcR7tqs6h8Sg3taZu1g9UYZ9MCSH9FAslJgYViu3h3VJe2Du6W931f9NMS8ABalFgxoj1dARvW5H8ZAz31xM1x2bxAJHujOwiTQ5MzvvQE+oT4Ze/UkIG70kzOYbFC6nKYtGrak; 25:aOAgbb+hE61S81C6Tceu6F97XJ8CKIsdz5RR06gwmFxkqKKYOIchFRX6/FNYGXHaFyQfRJX18MmBxBcymNpRqkX50fhu1wrJzmuJPWFaenGzTDtX9A4CBPN66ZVmfVoklhEolaK9A+Ww3qu675ckyXL/0YS+EJ6k1Dtx44sijM/ruoX/wlt4W6u/6uFErDJYQd+WcrLc4kXgm96Ut2ae/upS1v9R7nLU5xFO4Nb6HTzakKRxkS/S4L1C5MyMvBWDRusYHo6wAOmbruhRigQ+I4elDcVEjmnR9nzm9+VT0/HByUocaaiXEUqq5o7MhtjoUMXXLoY7RfL+QOZIrQmkHw==; 31:OJsE1ZbjCNZGH92sc4FmcUwsPIAamaahOF0XnkoD/+NU2OUv7tl6VHIY0i5dJ1i2ktgQyGhlEN6fkn79Vfwl3UqMGdyRd5kgPNOvEyJOz4eSPGOSuiiIlDZSdCcNGY1WOwHBQT5sEREzYhTLDNd1D2H2YhqFSwoyUfi1w95IyDWJitaDG4SbMiyewCUeRfw9voYhpVgaYAc5c9Luea654oBeOE1aq9kTF7o3lDU0Yxc= X-MS-TrafficTypeDiagnostic: AM6PR04MB4679: X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 20:K+kqKVSuVEO9GFsUp//7BynGGEf5DPiDH8UBBnDlwKaB+pSqAWDtfzZnf+Bwdd7FKekejmpxHP+g7E1tSMVRzffyDGaf19L+BF97BbZPOIkqZL3CS5pVL1KvxIx1ieYwf6mIWLdf/Qd7FnH6dr7HeHQBrJzI41soIqSD4L25ECxu9jXqldFLI622NByFgJf/TVY9PFtwAzMdbn0ROR4d117NyvkK/iQwys0ekadxaz1GjLUuBoHsfofKV1Ki+RJQCldFaJZX8BcMHYRz2LvtkbJs2/14Re0i/39QnrR1hiVojbSp4JNwLBRYYsK5RJrzRpufFZN9xIKm93K0tup905fOBg9Ktq5EGzhEiCO0FaZqpUcpIs3J+lM8u5gLcu++r3OBuUK8TH99uPKsckyL62ABRTMqvrNWVj4gKYiu8RF2FTNP9dBUnn+0Ta8BTFkLNs/VChUqhVaHWJrG+ddbK+WMwUsKywdimY62oPP41McuAaQrqtbxRbKo1XcxuKdH; 4:DzuB76ottAPPM6de0iLUcpQTCrwC9EPjGgPotQ68lcncU2Pk0idcpzViwHqtibKMuGx1k589BFKEdMtQb3Wx303zTCfVkAaZML/+VUeRcVS3WoZsL4AvQ0FpZt0HrmIOm4Ir0dZ2Rl3L67Umb/gVUR1STSuegU4SyFxrGLKrBigk6Z0oZk+/V4lROt7JhVf7CLbfzc38s+Y0qLB30ks9Jy7zWuN62j9L8KEDWbcbMi+Xfgf/U2e4o8Vn1i6m8FR/hxABNooUCPmnT3Dz8nqFUw== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(3002001)(93006095)(93001095)(3231311)(944501410)(52105095)(10201501046)(6055026)(149027)(150027)(6041310)(20161123558120)(20161123564045)(20161123562045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011)(7699016); SRVR:AM6PR04MB4679; BCL:0; PCL:0; RULEID:; SRVR:AM6PR04MB4679; X-Forefront-PRVS: 0731AA2DE6 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6049001)(346002)(376002)(136003)(396003)(39860400002)(366004)(189003)(199004)(67846002)(6486002)(6916009)(81156014)(8936002)(8676002)(476003)(229853002)(5660300001)(65826007)(6246003)(5009440100003)(230700001)(81166006)(486006)(50466002)(44832011)(97736004)(25786009)(66066001)(65956001)(65806001)(47776003)(68736007)(6666003)(4326008)(478600001)(305945005)(52116002)(36756003)(64126003)(106356001)(105586002)(76176011)(31686004)(52146003)(26005)(2486003)(7736002)(23676004)(14444005)(2616005)(77096007)(6116002)(316002)(55236004)(386003)(956004)(53936002)(11346002)(86362001)(31696002)(446003)(186003)(3846002)(16526019)(58126008)(16576012)(2906002)(110426005); DIR:OUT; SFP:1101; SCL:1; SRVR:AM6PR04MB4679; H:[10.232.14.39]; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; Received-SPF: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtBTTZQUjA0TUI0Njc5OzIzOjI1cHZMMTU1UmVKK3IrSFVsZjQraGl0a05v?= =?utf-8?B?d2ZPRFRXUXlUT2xseWZUVDZ3NFdwRGs5TGpiblE0dllTL0RkVWRvVnRBL1lk?= =?utf-8?B?Y2pyNnVhS1BXM2dpOG13L2tTZkFuc2tPd2tqL1RlUmxYK3U2MnB3blR5dCto?= =?utf-8?B?bWUvNkowZ0FKRzJiZitYNFFtVlhGRlluRHhWRWNIS0F6M3loZmtwTXdmdEIw?= =?utf-8?B?dDQ5TW9JV3E1MWVZVUI2endNWXdsL1oyaHR6N21ZMXRsMitmaHVUbTVVWHpF?= =?utf-8?B?WXphTzMwazJPKytxdURHZzFWSWd1Ni9uUUNNQmlWTEhtZXMyNW4rWVlUOUkz?= =?utf-8?B?RElFa2V0TC9ldXNDakg3TE9BUkxRU1l0QnFKQ3k3ek9ibmdqNWlMaE1tN1ZR?= =?utf-8?B?bVV5ckV6UnNaSmV3NHUvTHU3cS84UjVYMHJZdHd3S0xMRjNqNVVqU3NyNUZF?= =?utf-8?B?VG93aUdnenFvNEpxVm5GcGt3QkhkdStDTGJYUjFyekdYci9ld0NzUnpkbkMv?= =?utf-8?B?ZnVHRGVkVWR6MyttR2swaWR5NVhwSzdHaE5ucHVjWmJuakxjcGEyWXJETUlv?= =?utf-8?B?bGZrWUJ1dUFCeDBIM0RxRG54RHpabkxEVTVwYytXY1FRZUF5RVdySjlSL3d1?= =?utf-8?B?Z0wva1pFeWhIdy9Xam5CQ2gvOEhNSG92QmRnaEtCVWJ5VGx2dll2Z0F3VUox?= =?utf-8?B?czAyYkh2TGN2TGNZNkY0c2FNWGZ6SnN1OW5XZHdDTVVrR3pSay9JaHBnZHMx?= =?utf-8?B?bS9PMnlLVHcrcDg5bjE4NTdadmgyd1JmZWhCdkloT2RMelNtSlI3TDFwcnQz?= =?utf-8?B?RkRNTlFRMndvdkUrWllBeWlHcVcvTjJ3K2ZjVDg4bjJMTmliU3JhOHRvZ1lU?= =?utf-8?B?UmRxVWtXWmY1NW9ZQVZWMG5nY2lPTEtFN3RsQ0FxRCtQNno4S1FNWjdENDN5?= =?utf-8?B?ZHk0Q0Y2a0VtYys4LzZEb0NYS2s1UVBQOVdETnRPNmxveEFkamJBMjNHTFZI?= =?utf-8?B?RDU1M2xjN1NtY0syanNBMnBLNnVOZmY4OU9DRXY2N01ha1ZIVG1ySngzUy93?= =?utf-8?B?cDkvV3BtUzExVklza2VoRjR3T1dLMDBnNExnRG9nZnhucVFEQ2pBWWs3OHg2?= =?utf-8?B?RkF3Tmd0TnRjWjdQNTVOK1YwZjYxdVVtcHA1d3lvK1cwbHZ6cjkzTzdZNm1X?= =?utf-8?B?ZzVqa3F3SFBidGdmeFp2Ump1V2I0OUhqQTBSUnNpMXZGL1g2QXk3OWRnVytN?= =?utf-8?B?WksxOGNQOU5rUEFOTkl6ZnNDbVdYOWF6UGN3VHVUQVVvUHZOVi9xanhXZU5Y?= =?utf-8?B?Z2ZNbHRJM1hmYUNCM3dqbEVlV3hES05jaFZjc0YvaE0vOHBWRTU5d2lrL1pt?= =?utf-8?B?SlJJYlRpWTkwQnJRTG9ieTFxOU91c1lhZHZndytQYnQ4TGlnZG1CR3FVTnFj?= =?utf-8?B?N2JsUURMYml0c0puMUJpcHJuM0dKR1g0M0JNWURHeElPOGxWOWFhK0UrL1Rm?= =?utf-8?B?RlVOeDFTNnVSdFZ4a1FqMURHSzUxTk4rdHFEaDdGcFZRc1pyVnJjWXhxLy93?= =?utf-8?B?TmY2NjV5UEp5L3VCamk3RnFadjRpcEtxZHRGVnR3cGVsUCtjSkhWbVg0QTBi?= =?utf-8?B?ZDhrcGdMN0lqMTlrUHJrYURYVmtTQ3BUWGlFNlFnOXFkcWliWUhVNk5nRHJN?= =?utf-8?B?cHNvNElxb2VYSFd6OFduVEdrbWFXTkpQRXlqTjY1NlRUVFRMb1g4V3J2aEdu?= =?utf-8?B?R3V1QTVFaWh5ek1DWktRZGFIUzlRVDNEQUdqVlRESldBZVNlSTF6aGpkRkx4?= =?utf-8?B?REFQRlJJK2FqckZZNnlCRHdNY0N0UzQvOE5DM1Blem5ZMDU1UFZVZndybHNj?= =?utf-8?B?QmgzeGFoWXNmcUZuQ09xelhzaDZHUU9mWE1wN29zcFJQK05mY2FPUzc2Tllz?= =?utf-8?B?Nkp1TU1SQmNvSWQ5RUUxMzAxZXdtN2ZXYTRvWEIvR01qUy82bzdYQWJGYVI4?= =?utf-8?B?TVYxbnByK1Q1SjYyZXR2bFZqMDF2KzdQMkh3cSsxU0hDQXZLeU0rVSthTDlS?= =?utf-8?Q?yx2QbkYt7wOQO3b3LbMBhe4Jm?= X-Microsoft-Antispam-Message-Info: uqUQ5vbhaQxU4DIgXcpd4YPnCAjRgeagpsz421EsfypUWXV3Fje/k+gg7y4dCnapv8klTg2v/OYBRf+FtMkGBtiPdoYVLhRDc48PtubqeVbbeFTPrw4iduR/AIKVExPZGXUwsBNgaqEA1cjLJv0MI4r/8XmBpUMelbIXNmulYt12yg8tRb+s9gVcUSwvljj0vkJae9QIbzEmcS5Evez0c6wEx4V0uBY61+yUMgAzPJEi9q4UgU7cDOj6iOjVAld8aLYzfi4Wu1Z6/81ovG5Jy0LC1L3CFA772Soea/s7l9QrO30rZMss7+t4jFcvt9DDdfjoW7UOrvy5fNv1zFvxTCY7uumXZqOc7k0hhKvJuJU= X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 6:yfENm+yJ/7rBJ2iFQUK/NB7ciTSBoUFXTi9655dYRYTcnY+9/ZRK8B9trv7QXG7eTtv/WVlHQUNrTGbdWftDiC8/NRBU8R4/NdKOT0Y6RLn4n8Nht3HMDCKzmXCUpiX3uUGcLAYhKp5h044AoXLEwh6C8ZGsmwUSPhM8PnjKty1KXFZMf5hKqA3S0hv74XYCXLl5Kyi7Jl6ldX3kajsqybQNOZ+ejv5/B5avXu5czD8IsJDOPwqI+rZJp8NaPkUHA6WuX8VAPoEGRA7qVsxC1cRSR/fKfgVOmD1cOzsZzoGewKAj5uf2hGMvaClt78v+dCEu3pHwKvKAmHJyS5ePyNiSji4jSGP61DBm6Hn7Pim8lhvoVapA5WBRvQQDnfyfqXVdF1vJzGQ9JQ5YbVYexNpGutGLxhMtOPGhSSBPxu1xANMtxML2p0IaVJRzIpApP6w9IJ3/+BSJmmsofpHB/g==; 5:uwDedW6gIcVhtdpKO4c0NFZvjouf3Ky1wA+SAzPoUbPFLe9am7tdqxa4FNcXFDTdT+CYYptroooVjkzdetSGk26rorztYcIhhQaIn61rmHSnU5dxKkjyDMyB5att54/4q7ug7sRbgC2S5eEVrWkIrHk2XvcFRG+9GAYJVuex7o8=; 24:tuebFdjlnxb58VuOOUA0hLtRfxKadXTl+yIrs7qsdqdB5ZW8/Dm0b05BstCMPPUKA4Wc449LmqCPL4K0rStQGPBkOi3tnryAmdeqrcn0YS4= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 7:scMtXvk2vZY3N+58x2EnHtBcgS1Cf+CMyPTKGjqEjbGka27oCXvxOde40Oew2T5ChMxErK2N4pLZ+j04aqIARgF+GD0ElJ7cIN5fv8NKzk8HIeVODucFtVag+KlDiwNwf96HPYwTKuoF+aNb7CqIJuW+Add7U5V9tKYqUvqpdvX2BJxaQRMs3yGVO1jOZdM7J886L21DyniY9zF6lIFWHCZqljUMVGdda7TT9gbNGNSsZcAcTWK8vuYhKtsQQNB8 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jul 2018 10:58:53.2943 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ccbc6ef9-93ad-450d-de70-08d5e7e6754b X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR04MB4679 Subject: Re: [dpdk-dev] [PATCH v11 11/25] eal/dev: implement device iteration X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Jul 2018 10:58:56 -0000 On Thursday 12 July 2018 03:15 AM, Gaetan Rivet wrote: > Use the iteration hooks in the abstraction layers to perform the > requested filtering on the internal device lists. > > Signed-off-by: Gaetan Rivet > --- > lib/librte_eal/common/eal_common_dev.c | 168 ++++++++++++++++++++++++ > lib/librte_eal/common/include/rte_dev.h | 26 ++++ > lib/librte_eal/rte_eal_version.map | 1 + > 3 files changed, 195 insertions(+) > > diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c > index 63e329bd8..b78845f02 100644 > --- a/lib/librte_eal/common/eal_common_dev.c > +++ b/lib/librte_eal/common/eal_common_dev.c > @@ -45,6 +45,28 @@ static struct dev_event_cb_list dev_event_cbs; > /* spinlock for device callbacks */ > static rte_spinlock_t dev_event_lock = RTE_SPINLOCK_INITIALIZER; > > +struct dev_next_ctx { > + struct rte_dev_iterator *it; > + const char *bus_str; > + const char *cls_str; > +}; > + > +#define CTX(it, bus_str, cls_str) \ > + (&(const struct dev_next_ctx){ \ > + .it = it, \ > + .bus_str = bus_str, \ > + .cls_str = cls_str, \ > + }) > + > +#define ITCTX(ptr) \ > + (((struct dev_next_ctx *)(intptr_t)ptr)->it) > + > +#define BUSCTX(ptr) \ > + (((struct dev_next_ctx *)(intptr_t)ptr)->bus_str) > + > +#define CLSCTX(ptr) \ > + (((struct dev_next_ctx *)(intptr_t)ptr)->cls_str) > + > static int cmp_detached_dev_name(const struct rte_device *dev, > const void *_name) > { > @@ -398,3 +420,149 @@ rte_dev_iterator_init(struct rte_dev_iterator *it, > get_out: > return -rte_errno; > } > + > +static char * > +dev_str_sane_copy(const char *str) > +{ > + size_t end; > + char *copy; > + > + end = strcspn(str, ",/"); > + if (str[end] == ',') { > + copy = strdup(&str[end + 1]); > + } else { > + /* '/' or '\0' */ > + copy = strdup(""); > + } Though it doesn't change anything functionally, if you can separate blocks of if-else with new lines, it really makes it easier to read. Like here... > + if (copy == NULL) { > + rte_errno = ENOMEM; > + } else { > + char *slash; > + > + slash = strchr(copy, '/'); > + if (slash != NULL) > + slash[0] = '\0'; > + } > + return copy; > +} > + > +static int > +class_next_dev_cmp(const struct rte_class *cls, > + const void *ctx) > +{ > + struct rte_dev_iterator *it; > + const char *cls_str = NULL; > + void *dev; > + > + if (cls->dev_iterate == NULL) > + return 1; > + it = ITCTX(ctx); > + cls_str = CLSCTX(ctx); > + dev = it->class_device; > + /* it->cls_str != NULL means a class > + * was specified in the devstr. > + */ > + if (it->cls_str != NULL && cls != it->cls) > + return 1; > + /* If an error occurred previously, > + * no need to test further. > + */ > + if (rte_errno != 0) > + return -1; I am guessing here by '..error occurred previously..' you mean sane_copy. If so, why wait until this point to return? Anyway the caller (rte_bus_find, probably) would only look for '0' or non-zero. > + dev = cls->dev_iterate(dev, cls_str, it); > + it->class_device = dev; > + return dev == NULL; > +} > + > +static int > +bus_next_dev_cmp(const struct rte_bus *bus, > + const void *ctx) > +{ > + struct rte_device *dev = NULL; > + struct rte_class *cls = NULL; > + struct rte_dev_iterator *it; > + const char *bus_str = NULL; > + > + if (bus->dev_iterate == NULL) > + return 1; > + it = ITCTX(ctx); > + bus_str = BUSCTX(ctx); > + dev = it->device; > + /* it->bus_str != NULL means a bus > + * was specified in the devstr. > + */ > + if (it->bus_str != NULL && bus != it->bus) > + return 1; > + /* If an error occurred previously, > + * no need to test further. > + */ > + if (rte_errno != 0) > + return -1; > + if (it->cls_str == NULL) { > + dev = bus->dev_iterate(dev, bus_str, it); > + goto end; This is slightly confusing. If it->cls_str == NULL, you do bus->dev_iterate... but > + } > + /* cls_str != NULL */ > + if (dev == NULL) { > +next_dev_on_bus: > + dev = bus->dev_iterate(dev, bus_str, it); When cls_str!=NULL, you still do bus->dev_iterate... So, maybe they are OR case resulting in check of dev==NULL and return (as being done right now by jumping to out)...? And, how can bus iterate over a 'null' device? > + it->device = dev; > + } > + if (dev == NULL) > + return 1; Maybe, this check should move in the if(dev==NULL) above - that way, it can in path of 'next_dev_on_bus' yet do the same as function as its current location. > + if (it->cls != NULL) In what case would (it->cls_str == NULL) but (it->cls != NULL)? > + cls = TAILQ_PREV(it->cls, rte_class_list, next); > + cls = rte_class_find(cls, class_next_dev_cmp, ctx); > + if (cls != NULL) { > + it->cls = cls; > + goto end; > + } > + goto next_dev_on_bus; Maybe I have completely mixed your intention of this function. So, if you still find the above comments naive - maybe you can tell me what you are attempting here? Is it: find next bus and stop if no class specified. find next class as well, iff that too was specified? Reason I am confused is that bus_next_dev_cmp attempts to compare both - bus and class, yet class_next_dev_cmp simply stops by comparing class only. > +end: > + it->device = dev; > + return dev == NULL; > +} A new line should be added here - start of a new function. > +__rte_experimental > +struct rte_device * > +rte_dev_iterator_next(struct rte_dev_iterator *it) > +{ > + struct rte_bus *bus = NULL; > + int old_errno = rte_errno; > + char *bus_str = NULL; > + char *cls_str = NULL; > + > + rte_errno = 0; > + if (it->bus_str == NULL && it->cls_str == NULL) { > + /* Invalid iterator. */ > + rte_errno = EINVAL; > + return NULL; > + } > + if (it->bus != NULL) > + bus = TAILQ_PREV(it->bus, rte_bus_list, next); > + if (it->bus_str != NULL) { > + bus_str = dev_str_sane_copy(it->bus_str); > + if (bus_str == NULL) > + goto out; > + } > + if (it->cls_str != NULL) { > + cls_str = dev_str_sane_copy(it->cls_str); > + if (cls_str == NULL) > + goto out; > + } > + while ((bus = rte_bus_find(bus, bus_next_dev_cmp, > + CTX(it, bus_str, cls_str)))) { > + if (it->device != NULL) { > + it->bus = bus; > + goto out; > + } > + if (it->bus_str != NULL || > + rte_errno != 0) > + break; > + } > + if (rte_errno == 0) > + rte_errno = old_errno; > +out: > + free(bus_str); > + free(cls_str); > + return it->device; > +} > diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h > index fdc812ff8..8638a2bbd 100644 > --- a/lib/librte_eal/common/include/rte_dev.h > +++ b/lib/librte_eal/common/include/rte_dev.h > @@ -355,6 +355,32 @@ __rte_experimental > int > rte_dev_iterator_init(struct rte_dev_iterator *it, const char *str); > > +/** > + * Iterates on a device iterator. > + * > + * Generates a new rte_device handle corresponding to the next element > + * in the list described in comprehension by the iterator. > + * > + * The next object is returned, and the iterator is updated. > + * > + * @param it > + * Device iterator handle. > + * > + * @return > + * An rte_device handle if found. > + * NULL if an error occurred (rte_errno is set). > + * NULL if no device could be found (rte_errno is not set). > + */ > +__rte_experimental > +struct rte_device * > +rte_dev_iterator_next(struct rte_dev_iterator *it); > + > +#define RTE_DEV_FOREACH(dev, devstr, it) \ > + for (rte_dev_iterator_init(it, devstr), \ > + dev = rte_dev_iterator_next(it); \ > + dev != NULL; \ > + dev = rte_dev_iterator_next(it)) > + > #ifdef __cplusplus > } > #endif > diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map > index ac04120d6..4cd5ab3df 100644 > --- a/lib/librte_eal/rte_eal_version.map > +++ b/lib/librte_eal/rte_eal_version.map > @@ -252,6 +252,7 @@ EXPERIMENTAL { > rte_dev_event_monitor_start; > rte_dev_event_monitor_stop; > rte_dev_iterator_init; > + rte_dev_iterator_next; > rte_devargs_add; > rte_devargs_dump; > rte_devargs_insert; >