From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM03-CO1-obe.outbound.protection.outlook.com (mail-co1nam03on0061.outbound.protection.outlook.com [104.47.40.61]) by dpdk.org (Postfix) with ESMTP id 64058F60C for ; Mon, 26 Dec 2016 14:21:19 +0100 (CET) Received: from BLUPR0301CA0023.namprd03.prod.outlook.com (10.162.113.161) by MWHPR03MB2478.namprd03.prod.outlook.com (10.169.200.148) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.803.11; Mon, 26 Dec 2016 13:21:18 +0000 Received: from BN1AFFO11FD028.protection.gbl (2a01:111:f400:7c10::151) by BLUPR0301CA0023.outlook.office365.com (2a01:111:e400:5259::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.803.11 via Frontend Transport; Mon, 26 Dec 2016 13:21:17 +0000 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com;nxp.com; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Received: from az84smr01.freescale.net (192.88.158.2) by BN1AFFO11FD028.mail.protection.outlook.com (10.58.52.88) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.789.10 via Frontend Transport; Mon, 26 Dec 2016 13:21:17 +0000 Received: from Tophie.ap.freescale.net ([10.232.14.87]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id uBQDKVCT029786; Mon, 26 Dec 2016 06:21:14 -0700 From: Shreyansh Jain To: CC: , , Shreyansh Jain Date: Mon, 26 Dec 2016 18:53:56 +0530 Message-ID: <1482758645-23057-4-git-send-email-shreyansh.jain@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1482758645-23057-1-git-send-email-shreyansh.jain@nxp.com> References: <1482756644-13726-1-git-send-email-shreyansh.jain@nxp.com> <1482758645-23057-1-git-send-email-shreyansh.jain@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131272320779156317; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.158.2; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(336005)(7916002)(39850400002)(39400400002)(39380400002)(39410400002)(39860400002)(39840400002)(39450400003)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(69596002)(36756003)(50226002)(77096006)(85426001)(92566002)(104016004)(68736007)(110136003)(8936002)(105606002)(626004)(81156014)(8676002)(5660300001)(81166006)(2906002)(6916009)(38730400001)(2950100002)(6666003)(97736004)(48376002)(5003940100001)(189998001)(76176999)(4326007)(356003)(8656002)(47776003)(50986999)(33646002)(2351001)(86362001)(106466001)(305945005)(5890100001)(50466002)(7059030); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR03MB2478; H:az84smr01.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BN1AFFO11FD028; 1:gzuKcfqQKxQP3LJLTJXwbQgc8RpHX2AhBC2+6AOUrHSZGhDx3aOSlcEa99DQer7+OVfwepsDWdf3hLQQ4DExaENRhIyog6oXjUO6bDQxpJmlkHlk5VrHgkZ1XE+H1S17rFOKv7dhRsC4S943bDc0kmWeicnjpawdEX9ufMa+srVUcfGo3Kgm+AbnRPkCT7DXp1WFBtnVrjt4X4WdxZmq1KScF0KCFMsjbDh0UxikMWnNvb4XDBRTFHPNzHSHOOCeh4KYB7rG0ZPPi9eqlGnSIK7MsmrK3vbE9bGAvt7Emr6jwfk1oT24O2xob7R050+l56uD655SUxgEt2ejnFeK7L33HtJrEWgD+TjH8znpF9WWV09NKwdgqohV8ndy+ZjGA4a2+WqrywAzGJFoHwNWgMxFmhAayYw0i8bKnl3IKZmFmfKDqlIQlBZCsuVOlPPzWppH9sDJgvWCqfD7GMBmGKVN4MgX+qHM3WGmf4JQ8K9xQOFKaUMlTwW8zAINDLIcgjw2SjX+embfq9jzmsdDP0fwQ4dOiRWI+XPLxSqNnI/N4oQ27Lty5ZQcbXfkOYc/y8UxUzOW7/l7MuV+n6Ipyn/H1j/4SautGWxcDZndUbXPPNmukPys69qS3pVmjLW1TSqZrg9P8T0UumUQgGE0xc8JqUQOU63o7h42WBXoieA+/uG5bJ2CWEX37w0xk4ggTTjuO6LOvv8U7icSKE1XmmYP5+Kun2htVL7U0QnET/0= MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: bb704024-7195-4844-fb5d-08d42d921358 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:MWHPR03MB2478; X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2478; 3:C6Y3tMjEBufDMWB/M1lxc93U1OXF5OKVeuM5iDL0zw8hkcbCqcvP5k4dfKp3e2Lous0469YyFm4HQwEBlnDrmThwjbdi/8FXyXf39e0NHWXyZFU5+sdJbtZ8PsQ/E11B+dKubMRUw5LvBXPf4PGhwR4eeeUe209WxfAhqbdk+xmpY10/2lZRvHbHmsZPJr7Q7Zuzm1vOG5qRTl7Vaoioon837DVR1Ns0NTzIyu7/XOlQPHdX5aRCKa4UOPlU/Vgxs6DbFfc2ISPpAnx7rBXlYJ2CFsGqMjy1ISksGozhfkiJhC5+od/a/HTq1NzU2RMaWUHbBX0SU1FbQvwUmV0Vx0DlkpfUocCzYuNC1iX2it97se5rW1uUfezntA/WBH9F X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2478; 25:eGwLUUhjWOfEDLU9RFOZGwxRcApwbH0CHXx3pmNNDyXgdPBWgdCtDl8BCNs2SbelYUsHjVVVDwFoHVjvOl17CqBg8R98ppNmrroIuF72e3YB3b1y4TrvHBaebjh0GI4HTMre2dk5Oj8Hq/UxJR+It+UXtF3xcb+E392PNOof8CCIeWrsBMYsg2gWIr0jrmOe+fROKn48y6trUrhuFkNckK0ws2YbWTh3axMB0DjMRww8xYO/TjmzXPh3++pT59pQ2ePIGgWJi2u6ttHDpzd3AHluyZRhyRrW+JDuHwxilN9NguG7G4vZ+0dl15oJe5r7x3XDfci/BPFpjnUNxqs6j50Q1HJLhxm1s4tYCgi45xnnADyg2i2NcSr2urgPoDLQ+p4DpLR1BHK318VPnsy/7pu981f8xfEkjsEg5pynInPpmafbal/lmJJVpwx1xMkVg33CLTps2a+lC3f0csJLXfVAffZ6ZeSd/7B2Tnwl1N8yJNhc2kc4+yycx0T3lewSpz9mTtKn6UwZ7NixlYmBLs/vYPaISzEP9WAthO/AJODjQtxmeRuKWIrM1DWUDAZij6Wml6vHq/IDntK4X0Gi0zmdqddsDWAinmw5hDvlct00jSvrw6UC0dEoASeigWFp6qoJFVopWaWwImDPQ/gltT2CJbzUq7rToBgRm0l+oxxzkqfAQ2CQN6ggGdzEjRMImaMgYKuHThmNx22u68NMpCQLm+yy1AlKigHDpvWZsh904kZPA0+p50xGf28iZ/DtOy1wkv0BmbVdjYHJROEy1IMIAkkFRLzmfzAdutPq1s7FHbBg4MxGaOKROGhhHuoG X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2478; 31:3CVtHmYrhH1aYFTorrd+WVThJ1ykZa5ESmGmQt9jOIraa6v31cZKAOjt0b/WJ7dC3ff0dj3weOjveAAgVkiEg5zBOIkqd8MC93ZghKPnCY9X0XOSyE4ZKahvly5IWR67/7pYKvxYaFUfTaHvABnTtJlzuEaSCGHnxKs1vGZfZp1VpSVmRbagtoEP1hXQXBoZRh3o3tc3lxTLMiSDkxp55C2zI3dpwLJ8ThEQyId7LcONMcaMwoA718ZJgnPv35DlLpWFsKlCgZxuFxxcu6uOslTvcdHpPVLTdFsZtaSNPio= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6095060)(601004)(2401047)(13024025)(13023025)(13015025)(13017025)(13018025)(8121501046)(5005006)(3002001)(10201501046)(6055026)(6096035)(20161123561025)(20161123559025)(20161123556025)(20161123565025)(20161123563025); SRVR:MWHPR03MB2478; BCL:0; PCL:0; RULEID:(400006); SRVR:MWHPR03MB2478; X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2478; 4:of7dixmZNnLsU2aIQyi3zgBbwKMRbDpay6+fXBPX2NxAoOo7wXTl4+lviFNvBxkHlNcIArTVqDHZ0uQipdb4LmCBGMWOwAWILr3nxeHGHQBCJC7K57Ha4vnceVIxG4b69eW29+cc9fZQnGfGpe/1E09AvEXn50+flKCWZWVwLM8ZMtAb53USlEYCiJgdFnkdm+xySdxTvNv4wdHdYe/KOttpmLCG6Ib+zqKY3FO7D9FEUxDzPG8zdsXbl6SGj3D0NYuATS9vt1+Hu/Nq8PX7Zc9LSSsmVkea2XsztC9AQ0BvBLysro+xkNm1k/3bx2QnjKUFKHG4hFNpvvxpJj/PTNFImimfgpKt3+CRRABxDbKQU2exfA0qNlVRHZJ2cJXby4iMSAyaqMkJ5R7Lb5gvlG4UhgtQrklXXLk5O2MmLbwKNiDaAyWE1ohZpSFIt9+G+V1w4IDtiAMZN4h9xcfRj0Qwr4FBUMlmTcmb4CWn1+tVbKVVzp7d2hIabe0xOMj+0Y0FXvtI46zeN61FGUtGfBtM6S9TLv1/HCz3oDfU7meYK7xSGAP08Y2lMRNM0H3NjM98mIuIc4qqaulH86bRAra0iAlDoRjnmzsNAC8LmoCY3Ky0uRFe+qRCCX/LjKt3yy7TcQ4303ctR1FjqkjdvfDmoeE0uPjrb7jJYu46W4lLrqrPw2BQbmM0T2aPZBBFvTCjuaBXRzHqWuS105NBF99qUB7M0BQ0SvXU802s5jrbH8lTNhBwJrkNEeiluR0l X-Forefront-PRVS: 016885DD9B X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR03MB2478; 23:xFtIb34ZV5DIlG9wQjsRKPv83wRTSuw7P5rwdrbCD?= =?us-ascii?Q?dcjS4l7m/MQJVQDj0EbhoRsgE10B4A9S+xR9OMOlTEe5HP0QvTJh+t1VA7mt?= =?us-ascii?Q?Gjip2PVinKzbtW5+BjRxE6y9sTtlOG2v9DXvMY62BTjAstLghWlh30EV1WGr?= =?us-ascii?Q?SYVbBDogpWjPBabCS66m55+7ybYHt35aULvfyPRucABC/PyY/pahfCahOBlU?= =?us-ascii?Q?Hupw27Gt+eKPT//8r3uNobhR7grJXoEcaHAiUhA6T/Ca44yzoTF30OZ/N0Yk?= =?us-ascii?Q?QEGh+ycqaYUj7KJf/sSRDSyDcurWz92Js+mctI7dRbMHtQ0O0XXX5JV6owfT?= =?us-ascii?Q?SN+IFGObbcUranTs0v/g1pzVBGogURGOgPo5jIghLi55Eiau2AtKmH0kUSHn?= =?us-ascii?Q?kKKvJx6YeMkL0gr1l8ThIrrsRCBkWw8suZU4why1D7GITg327K2EPhEHqeJg?= =?us-ascii?Q?yPsF/HHMjglfh9Munk9xKaTz5y+piteejzXMU4FWDmuH0oWyDKbr6hy3g2pO?= =?us-ascii?Q?H4q0xy438gB0IfJlvS6CmkoPPF1LlcZDzVnb8DkOOJbNm8FNDnco1IgAHVbl?= =?us-ascii?Q?Ic3VK3KQmC9s5lZCbMMwkWw4kFWaZ1GuYX2RLXJJ366I6AOHehq91sBizFQP?= =?us-ascii?Q?JeOLD9T4uvISwDBDwkIfb310boEAunp37y5SYEmul69j5LDufMJfxMW/bu4+?= =?us-ascii?Q?mx3ysw82YeU+OitgTGONMwmveTVPvxbX8VC8wOsgKEmgdh1TwU6KIWehP0F0?= =?us-ascii?Q?4BzSIaf9311UZ57nfSjKo8Lmpsv0GrFGvEobhl6tdX5Uw27VuVlRh2hK95h2?= =?us-ascii?Q?8C572d3d9jO4hOcgG1V/1jwvo6/hjiBEYSV05DSS4e5kwkzdh71JBx/DDDco?= =?us-ascii?Q?E3KF1b5LR3ImuWTgbKNKDuMQMbcyZpVGVnZWIVMMZtyj2KB8xZtnDvh7O1JU?= =?us-ascii?Q?4BppZ9B5Vu9XuWs414f5Dk8brHZj1h43dXiQrJMA/iqYMm5928vmbqioxWxk?= =?us-ascii?Q?8xUQvcG117U0Mjy8xsADMh+1MwDW+kSzz6Bga4McRCK801TafsofEJjdhCqj?= =?us-ascii?Q?BxdXNsYt06WdIJqH9aJhbtE2HeH0d7T6iLJUPvggnNI+7YnAu3MKKBUhj/I6?= =?us-ascii?Q?rPl83+yaoBAHuAhezPqVyD1cPUCKJRR005Fw93ktKK8MlUdpbtd25qb8lqYq?= =?us-ascii?Q?x8akeC3kVGYO3Bhq97nDFS59E/V1touJGiZpKvSKTxpJDvpIRPMAi1mDwEmK?= =?us-ascii?Q?OuPeRwv07TKbT1NSeFtqat8eNdwxzdlX//PgNy6GJd8Pua0YnFfHBHrg9ufI?= =?us-ascii?Q?2v2cfGbXke0KtFq0knM7A+xOoJvp7MFwELE/gnmud0o?= X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2478; 6:9jKExzCH5709wYGVzQ6oYdkk/U15tTe67qcunIJrqHACN01lddRT5xOT/Rr3ZCN7jneA32wlrg9dl5rfeWcA2siHn5/tUnhrcTYN7IafYlvMY0lJm+wKyJB5+P2u6sRXlTcQV3FBv+KmuBRsbac9gZ1iCBArJh/z00WdPYNFx7gepKWT3l7Vtg5s7uY2mSCW7yS/PUgdosOGx4H1gxX2SuFjp0IJc09NzB6iN5ogm/EpVyc5ULRA//hwzR5pKme0+UVOm3vP6DcZPwnXDjpR77pkR6qG9YFSnbLsfE3Xamtab66M30csOdtUudCRP282Dml9Znmldwiiy/ZBBK38k7YHbz2nBLmd9WnG+FRkkfv85QbIeUUUNIcLBez8j/6ODkBZaCW2SiiFBoX4B3tBhrC8srsrU4TbukjBFsYY7aO+nywmBSnkKqmN1WbkhXjx; 5:g4BKbIqYtOD7KWXd4lWsVb30mUhWrvvoapA/2aJFcealjW8u2aCiMRtHWmwiztNKhaHQff77rk30gZCIGRI0gEhKqBjXQ05xetjzfUBmpnkRqUjQKLm9rg6AGt8nm+xt2QFnJKsE0r6zx0aDpKukUNZrm5ENW8W/wtbiJfMYggxXyMyX84LTx/zeHz/TqX7/; 24:DWYbAODA8JVDLBI9zAlNPBrLwQVwKYvxVzvJ0xteqosH4XGLvB+/PWLzdEobmsZLCO2FoxXVcu1T3em+ghApsU46N8Qpfw4/cDa8W8FBeDc= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; MWHPR03MB2478; 7:iW9W7VykjL8/4Rex2AutmEJwsex4ea1ackhGl3aMUAdd1tmoM4ZVZKdjpAPQMzNc107poetzBSpKcrntGwAIN9bwV/7InO77vMqSymeURUQHtdeQhgzVeVvUOrJOKHb/zByzcC3WWMwci6g+Vp3dVvFjZDENfzHNUAb3Og3gQrjFoAP+RWf3bUNf8NizLMf/oMq+1cXx9rAKt73iF+rrn5Hlqdey6iO2PjZ8l1+BY34qvtadpVZqUto0/bnOjpvfM7I20YFog+uNpmGY+cQth+Zjg6b32Xh1wnbPTy4Aom6SNMpPuICwuxFkRAyD+3x6CVTMGAKin/EV/rRaZPaG4JPaj14m07NeoWlh/L65YSXaRgXdHIHxYUYgG/5x5IhxffLR+T5ayFEpYSumcu2PbIwvfH7d/eq0o8E93/UPXyTGLfVAmrGkR8e2DuyWeugnngDuaNhLIQxVaH/cG6EncA== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Dec 2016 13:21:17.6660 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR03MB2478 Subject: [dpdk-dev] [PATCH v5 03/12] eal/bus: add scan, match and insert support 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: Mon, 26 Dec 2016 13:21:20 -0000 When a PMD is registred, it will associate itself with a bus. A bus is responsible for 'scan' of all the devices attached to it. All the scanned devices are attached to bus specific device_list. During the probe operation, 'match' of the drivers and devices would be done. Also, rather than adding a device to tail, a new device might be added to the list (pivoted on bus) at a predefined position, for example, adding it in order of addressing. Support for this is added as '*bus_insert'. This patch also adds necessary test framework to test the scan and match callbacks. Signed-off-by: Shreyansh Jain --- app/test/test_bus.c | 265 ++++++++++++++++++++++++++++++++ lib/librte_eal/common/eal_common_bus.c | 15 ++ lib/librte_eal/common/include/rte_bus.h | 64 ++++++++ 3 files changed, 344 insertions(+) diff --git a/app/test/test_bus.c b/app/test/test_bus.c index 60950d3..f8af5be 100644 --- a/app/test/test_bus.c +++ b/app/test/test_bus.c @@ -80,12 +80,32 @@ struct dummy_bus { struct rte_bus_list orig_bus_list = TAILQ_HEAD_INITIALIZER(orig_bus_list); +/* Forward declarations for callbacks from bus */ + +/* Bus A + * Scan would register devA1 and devA2 to bus + */ +static int scan_fn_for_busA(struct rte_bus *bus); + +/* Bus B + * Scan would register devB1 and devB2 to bus + */ +static int scan_fn_for_busB(struct rte_bus *bus); + +/* generic implementations wrapped around by above declarations */ +static int generic_scan_fn(struct rte_bus *bus); +static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev); + struct rte_bus busA = { .name = "busA", /* "busA" */ + .scan = scan_fn_for_busA, + .match = generic_match_fn, }; struct rte_bus busB = { .name = "busB", /* "busB */ + .scan = scan_fn_for_busB, + .match = generic_match_fn, }; struct rte_driver driverA = { @@ -184,6 +204,92 @@ dump_device_tree(void) printf("------>8-------\n"); } +/* @internal + * Move over the dummy_buses and find the entry matching the bus object + * passed as argument. + * For each device in that dummy_buses list, register. + * + * @param bus + * bus to scan againt test entry + * @return + * 0 for successful scan, even if no devices are found + * !0 for any error in scanning (like, invalid bus) + */ +static int +generic_scan_fn(struct rte_bus *bus) +{ + int i = 0; + struct rte_device *dev = NULL; + struct dummy_bus *db = NULL; + + if (!bus) + return -1; + + /* Extract the device tree node using the bus passed */ + for (i = 0; dummy_buses[i].name; i++) { + if (!strcmp(dummy_buses[i].name, bus->name)) { + db = &dummy_buses[i]; + break; + } + } + + if (!db) + return -1; + + /* For all the devices in the device tree (dummy_buses), add device */ + for (i = 0; db->devices[i]; i++) { + dev = &(db->devices[i]->dev); + rte_eal_bus_add_device(bus, dev); + } + + return 0; +} + +/* @internal + * Obtain bus from driver object. Match the address of rte_device object + * with all the devices associated with that bus. + * + * Being a test function, all this does is validate that device object + * provided is available on the same bus to which driver is registered. + * + * @param drv + * driver to which matching is to be performed + * @param dev + * device object to match with driver + * @return + * 0 for successful match + * !0 for failed match + */ +static int +generic_match_fn(struct rte_driver *drv, struct rte_device *dev) +{ + struct rte_bus *bus; + struct rte_device *dev_p = NULL; + + /* Match is based entirely on address of 'dev' and 'dev_p' extracted + * from bus->device_list. + */ + + /* a driver is registered with the bus *before* the scan. */ + bus = drv->bus; + TAILQ_FOREACH(dev_p, &bus->device_list, next) { + if (dev == dev_p) + return 0; + } + + return 1; +} + +int +scan_fn_for_busA(struct rte_bus *bus) { + return generic_scan_fn(bus); +} + +int +scan_fn_for_busB(struct rte_bus *bus) { + return generic_scan_fn(bus); +} + static int test_bus_setup(void) { @@ -392,6 +498,155 @@ test_driver_unregistration_on_bus(void) } +static int +test_device_unregistration_on_bus(void) +{ + int i; + struct rte_bus *bus = NULL; + struct rte_device *dev; + + for (i = 0; dummy_buses[i].name; i++) { + bus = rte_eal_bus_get(dummy_buses[i].name); + if (!bus) { + printf("Unable to find bus (%s)\n", + dummy_buses[i].name); + return -1; + } + + /* For bus 'bus', unregister all devices */ + TAILQ_FOREACH(dev, &bus->device_list, next) { + rte_eal_bus_remove_device(dev); + } + } + + for (i = 0; dummy_buses[i].name; i++) { + bus = rte_eal_bus_get(dummy_buses[i].name); + + if (!TAILQ_EMPTY(&bus->device_list)) { + printf("Unable to remove all devices on bus (%s)\n", + bus->name); + return -1; + } + } + + /* All devices from all buses have been removed */ + printf("All devices on all buses unregistered.\n"); + dump_device_tree(); + + return 0; +} + +/* @internal + * For each bus registered, call the scan function to identify devices + * on the bus. + * + * @param void + * @return + * 0 for successful scan + * !0 for unsuccessful scan + * + */ +static int +test_bus_scan(void) +{ + int ret; + struct rte_bus *bus; + + TAILQ_FOREACH(bus, &rte_bus_list, next) { + /* Call the scan function for each bus */ + ret = bus->scan(bus); + if (ret) { + printf("Scan of buses failed.\n"); + return -1; + } + } + + printf("Scan of all buses completed.\n"); + dump_device_tree(); + + return 0; +} + +/* @internal + * Function to perform 'probe' and link devices and drivers on a bus. + * This would work over all the buses registered, and all devices and drivers + * registered with it - call match on each pair. + * Aim is to test the match_fn for each bus. + * + * @param void + * @return + * 0 for successful probe + * !0 for failure in probe + * + */ +static int +test_probe_on_bus(void) +{ + int ret = 0; + int i, j; + struct rte_bus *bus = NULL; + struct rte_device *dev = NULL; + struct rte_driver *drv = NULL; + + /* In case of this test: + * 1. for each bus in rte_bus_list + * 2. for each device in bus->device_list + * 3. for each driver in bus->driver_list + * 4. call match + * 5. link driver and device + * 6. Verify the linkage. + */ + for (i = 0; dummy_buses[i].name; i++) { + /* get bus pointer from dummy_buses itself rather than + * rte_eal_bus_get + */ + bus = dummy_buses[i].bus; + + TAILQ_FOREACH(dev, &bus->device_list, next) { + TAILQ_FOREACH(drv, &bus->driver_list, next) { + if (!bus->match) { + printf("Incorrect bus without match " + "fn: (%s).\n", bus->name); + return -1; + } + + ret = bus->match(drv, dev); + if (ret) { + printf("Device and driver don't " + "belong to same bus.\n"); + return -1; + } + dev->driver = drv; + + /* As match is generic, it always results in + * dev->drv pointing to first driver entry in + * dummy_buses[i] + */ + } + } + } + + /* Verify the linkage. All devices belonging to a dummy_buses[i] + * should have same driver (first driver entry of dummy_buses[i]) + */ + for (i = 0; dummy_buses[i].name; i++) { + drv = dummy_buses[i].drivers[0]; + + for (j = 0; dummy_buses[i].devices[j]; j++) { + dev = &(dummy_buses[i].devices[j]->dev); + if (dev->driver != drv) { + printf("Incorrect driver<->device linkage.\n"); + return -1; + } + } + } + + printf("Probe on all buses successful.\n"); + dump_device_tree(); + + return 0; +} + int test_bus(void) { @@ -408,6 +663,16 @@ test_bus(void) if (test_driver_registration_on_bus()) return -1; + if (test_bus_scan()) + return -1; + + /* Now that the devices and drivers are registered, perform probe */ + if (test_probe_on_bus()) + return -1; + + if (test_device_unregistration_on_bus()) + return -1; + if (test_driver_unregistration_on_bus()) return -1; diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c index 01730f8..5a5ae75 100644 --- a/lib/librte_eal/common/eal_common_bus.c +++ b/lib/librte_eal/common/eal_common_bus.c @@ -58,6 +58,18 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev) dev->bus = bus; } +void +rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev, + struct rte_device *new_dev) +{ + RTE_VERIFY(bus); + RTE_VERIFY(old_dev); + RTE_VERIFY(new_dev); + + TAILQ_INSERT_BEFORE(old_dev, new_dev, next); + new_dev->bus = bus; +} + /** @internal * Remove a device from its bus. */ @@ -130,6 +142,9 @@ rte_eal_bus_register(struct rte_bus *bus) { RTE_VERIFY(bus); RTE_VERIFY(bus->name && strlen(bus->name)); + /* A bus should mandatorily have the scan and match implemented */ + RTE_VERIFY(bus->scan); + RTE_VERIFY(bus->match); /* Initialize the driver and device list associated with the bus */ TAILQ_INIT(&(bus->driver_list)); diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h index ad2873c..da76db3 100644 --- a/lib/librte_eal/common/include/rte_bus.h +++ b/lib/librte_eal/common/include/rte_bus.h @@ -60,6 +60,49 @@ TAILQ_HEAD(rte_bus_list, rte_bus); extern struct rte_bus_list rte_bus_list; /** + * Bus specific scan for devices attached on the bus. + * For each bus object, the scan would be reponsible for finding devices and + * adding them to its private device list. + * + * Successful detection of a device results in rte_device object which is + * embedded within the respective device type (rte_pci_device, for example). + * Thereafter, PCI specific bus would need to perform + * container_of(rte_pci_device) to obtain PCI device object. + * + * Scan failure of a bus is not treated as exit criteria for application. Scan + * for all other buses would still continue. + * + * A bus should mandatorily implement this method. + * + * @param bus + * Reference to the bus on which device is added + * @return + * 0 for successful scan + * !0 (<0) for unsuccessful scan with error value + */ +typedef int (*bus_scan_t)(struct rte_bus *bus); + +/** + * Bus specific match for devices and drivers which can service them. + * For each scanned device, rte_driver->probe would be called for driver + * specific initialization of the device. + * + * It is the work of each bus handler to obtain the specific device object + * using container_of (or typecasting, as a less preferred way). + * + * A bus should mandatorily implement this method. + * + * @param drv + * Driver object attached to the bus + * @param dev + * Device object which is being probed. + * @return + * 0 for successful match + * !0 for unsuccessful match + */ +typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev); + +/** * A structure describing a generic bus. */ struct rte_bus { @@ -69,6 +112,9 @@ struct rte_bus { struct rte_device_list device_list; /**< List of all devices on bus */ const char *name; /**< Name of the bus */ + bus_scan_t scan; /**< Scan for devices attached to bus */ + bus_match_t match; + /**< Match device with drivers associated with the bus */ }; /** @internal @@ -85,6 +131,24 @@ void rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev); /** @internal + * Rather than adding a device to tail, insert at a predefined location. + * This is specifically useful for update device cases, or where addition + * of devices in the list needs to be ordered (addressing, for example). + * + * @param bus + * Handle for bus on which device is to be added + * @param old_dev + * Existing rte_device object before which new device needs to be added + * @param new_dev + * Object for device to be added before old_dev + * @return + * void + */ +void +rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device, + struct rte_device *new_device); + +/** @internal * Remove a device from its bus. * * @param dev -- 2.7.4