From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM02-BL2-obe.outbound.protection.outlook.com (mail-bl2nam02on0082.outbound.protection.outlook.com [104.47.38.82]) by dpdk.org (Postfix) with ESMTP id DD3D62E83 for ; Tue, 13 Dec 2016 14:34:56 +0100 (CET) Received: from DM2PR03CA0035.namprd03.prod.outlook.com (10.141.96.34) by CY1PR0301MB0748.namprd03.prod.outlook.com (10.160.159.154) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.771.8; Tue, 13 Dec 2016 13:34:55 +0000 Received: from BY2FFO11FD023.protection.gbl (2a01:111:f400:7c0c::120) by DM2PR03CA0035.outlook.office365.com (2a01:111:e400:2428::34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.771.8 via Frontend Transport; Tue, 13 Dec 2016 13:34:55 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) 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.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BY2FFO11FD023.mail.protection.outlook.com (10.1.15.212) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.761.6 via Frontend Transport; Tue, 13 Dec 2016 13:34:55 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:; UpperCasedChecksum:; SizeAsReceived:806; Count:10 Received: from Tophie.ap.freescale.net ([10.232.14.87]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id uBDDYRw8005048; Tue, 13 Dec 2016 06:34:52 -0700 From: Shreyansh Jain To: , CC: , , , Shreyansh Jain Date: Tue, 13 Dec 2016 19:07:04 +0530 Message-ID: <1481636232-2300-5-git-send-email-shreyansh.jain@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1481636232-2300-1-git-send-email-shreyansh.jain@nxp.com> References: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com> <1481636232-2300-1-git-send-email-shreyansh.jain@nxp.com> X-IncomingHeaderCount: 10 X-EOPAttributedMessage: 0 X-Matching-Connectors: 131261096952148548; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(336005)(39410400002)(39400400002)(39450400003)(39380400002)(39840400002)(39860400002)(39850400002)(2980300002)(1109001)(1110001)(339900001)(189002)(199003)(68736007)(8936002)(50226002)(50986999)(76176999)(77096006)(38730400001)(189998001)(36756003)(97736004)(106466001)(5890100001)(50466002)(105606002)(104016004)(5001770100001)(86362001)(48376002)(5660300001)(4326007)(626004)(85426001)(2906002)(305945005)(8676002)(33646002)(92566002)(2950100002)(6666003)(81166006)(356003)(8666005)(47776003)(5003940100001)(81156014)(7059030)(2101003); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR0301MB0748; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD023; 1:kNwBQNKaGoGechNVUNmiCAfyhVgn/Qe2IvQ4CcWWnFXlPaK5A7VB5+AjMcAODdkpE3e4Y93zeCd+i01FLyIvWnkcJ5FYmQJbv9HnGlVcSevT6NwKSZuABDkPBJE/cKUwSaLIsxAuccAco2aDsr02Yz7ekF1tZvfn9FmNJss+NMuCYm1gqoX2qGVuV1Hgvpemd+PIT+r2R3uQUUjm1UsSdg5OitYRL6AJE7llAfRCUl7Hyo6vlysSWxrA8qOEYxtTKjX1ZdsV/FZHNC+y/za6JkAsxSQW46pXXgfVYaCrzUQ5ZMwdVL/A/Qdl0ZDzdppi9DN5/3e/CyrdWeEbYu7h0tTX4VJ3q0MgCyCzEPNw3gmYI9WWynqEs1Znyb6PNxmjcnmycNerTVE+DvvazRIYhd7pWLqbXmLaeZwjfXyNsBYZolwIx04oN/uWR0s94dSJOxjLsISW7goikhb3pK4h1JOx3QAzBFufGBBYIoxH4mzl6rVS/iLQu6OdkqPt77wVVTYq4JWbL7CeN8e0bmQ+xGBzbTdyjSPd6Zu/uy1wyqhjcoyclyqRyORElUsq33iWA4lZXrxuuJjxzRWWKaHEezurn6oehmtB7oSkUhUR3MjzIlqGY43ZMSCau2lQLNdWgE67f1cb5OATIL1AW7HddTfLaDkiCLqwkZ5aDDG0HWx8TRDGvXq6OSe5KxxXRmJxv/sOG5nPf3rP5V7QBwr7uH1KLOxgoe/F6R9ILRdv0ytxJJn/6s5RTY8gCiqVzGG61ybtDeUhyKoVxTLODlH9oA== MIME-Version: 1.0 Content-Type: text/plain X-MS-Office365-Filtering-Correlation-Id: 8c21f917-2bf7-445b-3244-08d4235cd320 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:CY1PR0301MB0748; X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0748; 3:P2XPxJXHTnAcSfaYfFel2LkShuzdyaBzW/qR+E2335oK0BKUxiKElGic5Pd034SmHPcI2KS9E4R20xm+xvcnlJYv436b+PszOIB3JsLSoUrUZ0IVGQFm5txIu7sRBz6sM02WAUqeaiC1SGh20eib9B5yhHuHu8EMWn5Kxl7421fEfahHJUWgsSVu2rURNp23kTqeFlby/brFNT9HogJyVCQ3TWp/aFSXAa4Y73XQRIEWl17tisrsWw0XnHvn5CD1c4v0Xg25JdXNsa0wrZPXQfL2aFnX2htWR4LpynqNFx/NaJRfLtdEufWquWD2hRq6DM0c4LMkWrzmJHLKmumDvHcm2zlbsBSyVR2xzy7ToXlFem9KEjGf/PIfafbAROrE X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0748; 25:sgydWdUnYGsSNW/WJeZmAXJ5cie5FsrlnzroA8Cv14eGX8a2SdT2vbVPr3qciyyuuwhxirJ55MaHdCzoXtBu3+PNrrVfINGgQh4eGzJtSBv7mXHxoTuHkytZlXI6Ddea68bPvwRvmyla5XrBEaz9M8LaLyIIMrXS358b+T+yehTEi0Z69IJw6HzlTkJ+NYOfeWbh6ud4CEv1mbzpkde7gtJtOBtM4lBQFDhRqO36KIe0fiieEIN9sX7pMhXFebOWRi/PuQ/NA7ro7vfATH+sj9QYfXEpCVLIf39wVcTXioYh7nAk0UnvUDzhlM17j9C4TvRk/qyj8iog1awv/Kp9wEePUvBUp/G0fzTe0ag5W6dN34jBZV6Fcz8DZAUMMgJl7moCOUnO7dtRsFUPEblZqIAg+ZMK6aeHj7moCkc3qKxRA2jbLtyaihSwrgNBfQSzMAJwVaNHz3Bi5/P8xGjzy1APDRI9tqByKaf1VECHi8inN4o2P3B3P2fUFOhcIaD/3x3BsEiGIHw1WkdcQ+Kv1jJAIDGl4YnIbryDolVh1vUTQBhMdHRLA3mxdnAnG2nDKoloBa94NZZZXyTxYIRZX9qOtirQylaaQ2TUub6F0xUW/khAdZJWaB/pc6RyrOp6SCWpe9z3Ul4dvBeBsqXPltxjQ0o4AMuQS3dXYZwZR5hzJ4mPdKpTYRxWwfe1ri8c7tGmsKq1F12nbYAa/L03YfLdaPejc/P6n4Kj8xpqs3atwMoFjbOqGyLi6K8TlZ7rz8UNOZZRtvY5/s0VWq+dOVCkcHEtAACWA6gfuv4VO5JV4OrL7Oz8tJV/lPWe001N X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0748; 31:IU7PLIru50+0i9h+GQvIJeDjFN8/nl5NQeEwvNT6f74J4BZ/eMDK9tulJ65K5qa7XaJi5hOh+GCjmH0uD+tynxQr+awVrFuHQ2Lg0Ix0/NjiXlwBhQguMnBpDchOLlA9TVPBSrUJ6AzWJh4XfVuUI/t7xpwWgmlssJbMxDkQbMmx5WrJQ8mTDT2r9fJ8+Y37hc5Sp7oh2u11G7Aus1+vqrIben3SBQhsRh0DcDUqRxcP4T33AP3zvymmH406HTzXJD8DIVs/XgK9nzK74gtr1/wMYdcZuZZnci/XLV/Rym8= 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)(13023025)(13024025)(13015025)(13018025)(13017025)(5005006)(8121501046)(3002001)(10201501046)(6055026)(6096035)(20161123563025)(20161123565025)(20161123561025)(20161123556025)(20161123559025); SRVR:CY1PR0301MB0748; BCL:0; PCL:0; RULEID:(400006); SRVR:CY1PR0301MB0748; X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0748; 4:nhVsov+E0KItA1DT5bcLuZSudIMCMu7R4/RLP/ADpF4v+j7sGszEdKSJEbCvo/vVwarqh3IdEiH66cQ2lrLBqxAENxjINcWQOy7ZfgbsKlDXuoFYQjSdNuCzzDMRELjAdLb10eX/CSR7D/Ar9UNbAC+eAeLQcbi5VrnPLmUp8ovTAVOuuN5S25jeUZQQD963o2/1GW9+6W8yMVnbBOaLLmoUTFWqd3wr0jPZmVvRMdTkiJGpe67x33dXHEXPq9n2ui+3Vw4HCGp1A2waheTZuVp6eSSWAhr7t7KTC5aUVNAI+kt0/yfnUcgvehqSSPCi1J18ZFNlpfMvyl9Ac5w7GP7FzblqcMAqUZy/nLVLgUVSv5RsRxRsczSblsuonCBw47kEEXIVP+JSgKwGWg/UuxJVH7KSLCxb62Qtn77hadhg11xhWnkcSsa0tYVUX7hwvuIeyvpsOdabTxDqTS2xjmXFHHG7SGL/6oJniTKq2PKbM0yd+3C0HN5PYgYW0wpug0b1Adgl6MRLhJLe+VajRHoirU+U1FByLBytbjE3yc1GhnR4pa5PSjnJ6um1MtE8xXb9GIcRX5Vhr+WzuxOOZYM2Vw/8mpynC87f21P0AHwv6ZeI68woP074rhXzU9P/djkPRPqpwVuXvmfzgOpW2ghxf3hpgIROTd5YHi44WLDVVtr7ydwV6Tdr8CcQOqalHniTukMVecefM6KUsNs3e90zgmU69gnsF1FJwIGuJmNcjioeS1rbmsQApDyipMIV X-Forefront-PRVS: 01559F388D X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR0301MB0748; 23:f7XxqNOBPY493hNDgsGW1nRtpzDEgiB+SEwgnB/?= =?us-ascii?Q?Uv5uDECrlHaDw11WXAQlJZX04g7UgdKOhdhp0DQc66rUD7CuOzW0bp5IPyg5?= =?us-ascii?Q?x74GND2372nxBktbgFiMKaxPIP7sflKQ8fWGX2xrdCiw4zRxSoTt5nuYLtp2?= =?us-ascii?Q?wmDvm/WOj5t34fLHvgjHyblIlzIwDgtO4ZKsf6Bm3x2EQF32D69yKX/ydZpj?= =?us-ascii?Q?h5zy8MnthlWaZ0j3GiONXfhCiNKvVKJ6xDs4Jql0K+0Ic/QjDUUaqVuMeR5o?= =?us-ascii?Q?qFKB5B8d8R5BmGB2oUvfV+Siy8qaFeoFIMYzDUxq6IlyAycDIHxiAclte6vI?= =?us-ascii?Q?eY37iPRgGJJl4nAsH+A5wCplFpqd08DQ3HpizQws5mXoUn3nlSusdF/2Ykxt?= =?us-ascii?Q?1/itFrSOkVuCIlYYFd8wegjJ8PGC5zLEf18s9TpMDy388usWH8b+ujOyllhT?= =?us-ascii?Q?7fbzrLVZwyADYnqgdiICPhmtuhhkPz/QN2ZB7K5J2YJ3nYLgIf3UUtb4Hhwt?= =?us-ascii?Q?K3DYhRe04hheZKNrgzyljFTCxOt8VD/NXtgsJhP5oDyov6cW+76vVwcwj8Sp?= =?us-ascii?Q?C/L1TyIPhdBjFr3+0mtfM3z5lacN+79TSA4UUB2Y4vmm6jTlxNyRhdLQUvA+?= =?us-ascii?Q?v4mrY8vaTKfhqWYXAoqOqUbgYwPlfrzVJ5YseehE1fE6I39iqL6KY44gy09R?= =?us-ascii?Q?nBCIhv25TyBccAGI/QxARwsWqcxMueVwGVqI7X0ra00aNlQY0GRi9yf1vSSg?= =?us-ascii?Q?UaLeG88GTFS9Niq794pKTvavQPobJI742ZtLNhIPLx98u5iyCm/Rs/YyiQdv?= =?us-ascii?Q?xi+MPz41LX/+kraU3Tz9JLLDZV6yBxHg3/wS5eKBH/JihZnJjcaH73325ngY?= =?us-ascii?Q?FMN+4TGWk5vwsnRm+7FkD7HhDfC123ETr1h/JKJPN3yLbYwxSbQ7bwjMnejx?= =?us-ascii?Q?CIPi2kFodwMbYRnBfEsC3ieQYymNiGu5mMjEoXkZLq6S2XcQRlpRDHHkvGvi?= =?us-ascii?Q?hNJJDAjqOf/2CXwKcNlCZPbv5PBDM3Al4aDF8BdaP/jWDGRBNiAdj0RdKPdX?= =?us-ascii?Q?61AcYa3nAaqLciF+k4dhQz5hHOoY6MY6MfOfDPbfAMr2lBdDaP08Yw3TEZ5v?= =?us-ascii?Q?M5YTaQGAKruu1XhnWwcC3SSlJu+HvwdHXlVjFNSZkuD7ZBQC4qUj8xMbFua+?= =?us-ascii?Q?3LBNXo8vBENJHRp9mpGlD/Eq9ZWW163yET7kzTuJHKyBEPSMlfLMXHu0MaHA?= =?us-ascii?Q?GeVN1msHw3ocQNLU7u+iiLpxN4hFjPQOVDxbGbXqTVny/K0ucOr180gcYCYy?= =?us-ascii?Q?Jb2NOIRJox0WkPTLBbqXsPUI=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0748; 6:/bW0c0JSaD5XON+HR2GXUb+M3rb13ZxAFboW1+nR0WDZ422YcUd8fqyRug4klen0umONs2m1n72ABR0upfwzf30hi900wIA/HHVKYqGw91GkaKTODOvi+7bWhvIB/YbfqsG6PozAazV0nwDxV8+1iknDROG2o577h4jNVuZmVxBVcqdMHf0/vwsvCUiHMwlcNn/wZazqdK3YGwT7oFbfkw+qEChoKL3xVx6yrL+gMSfPtYWZDPsh85n6PTWKWj+DFGkQc4w4kJMJ3s5Q7TXPpajQUSdu2OX57ii1cFjQh3TV3gjAJSGE0cxf/x65mgqbqr7IieO38tA676LNz+w99kjvq5+/32BMUEsnRuWNHbD1EMitMUz+KLmRGzpawPK/oDKjxoRQrmeTeMj0D2gWh3wwGCbOMbpUsnruI2MEyJl2GeFF+XWHRexaTQnb8z0X; 5:5emDKN3GcR+rYPeAe26Xu782x5RDCGXDaJF4SBSULQEEnRkBmVYWTrfXm+dYpy01re0qZaxE8r8QpOlaEIYBFPu0IgIr+0DFPLYIjZ2GQNe6RzhK7RW3dLtQQgjY5z5hj3aFY1ctHwHmjDPiY6PB6chjZKIJm1ic4RQqNybDcOzRtc8FG5pSh8chyfGQWCy1; 24:jrTnGRjXT6cG8UbnIUyQs9wXQOWvgN9p3VJ7GUOf3o0/5T2BI5ZiyRwdTpOsWZZp4zwWxMIWQ0wKaeIQi6uBkxomBw/xzgYrkms94cR0C+k= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; CY1PR0301MB0748; 7:w+l1wOZp0APoqvnjozQW21vSmvvTJTkUuR7e0H3Av3dGPEuPyo7V+EbaoMro45XyuhSk4/7pbMF7gp9rh3Si5Kqaq//EwEKy43JtsClUkpEgJL2H0hKcMuFaTjirjUNBQADPAYdDQI3K6ANCTVDC45SieR5sM0z6x47jRwV83uCscF+JMDwc8WIrUsZzyFzAmkO9itTbuX7zek5+cR1HAxoY6vokRgWX0DcfUWJvXrCaRV3ZPsT+5s1VED9MJlwyi1CL/oBRMdabEj6wrzO0PA7wk0ls61xtbLj5phZbpmXqKubIUsYzWjErAiryYobNZdiXItgm3R+wqRFbtxJDs3YlJzk4UlQjoN9Cke1xgjamlzKKl/Nyl9V8z3NXly8WSRktl8ta+EP8gvbxbzxO7nqPxGSe7WRIQeIN0QuJalhdU8roBU3QHZg90L7gDD7qsxfqec1MoS2ffHkWvFS9Ww== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Dec 2016 13:34:55.0120 (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.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR0301MB0748 Subject: [dpdk-dev] [PATCH v2 04/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: Tue, 13 Dec 2016 13:34:57 -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 | 14 ++ lib/librte_eal/common/include/rte_bus.h | 64 ++++++++ 3 files changed, 343 insertions(+) diff --git a/app/test/test_bus.c b/app/test/test_bus.c index 760d40a..ed95479 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 + */ +int scan_fn_for_busA(struct rte_bus *bus); + +/* Bus B + * Scan would register devB1 and devB2 to bus + */ +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) { @@ -391,6 +497,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_get_bus(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_get_bus(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_get_bus + */ + 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) { @@ -407,6 +662,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 612f64e..3be9c77 100644 --- a/lib/librte_eal/common/eal_common_bus.c +++ b/lib/librte_eal/common/eal_common_bus.c @@ -58,6 +58,17 @@ 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); +} + /** @internal * Remove a device from its bus. */ @@ -132,6 +143,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 f0297a9..d1bd2e8 100644 --- a/lib/librte_eal/common/include/rte_bus.h +++ b/lib/librte_eal/common/include/rte_bus.h @@ -59,6 +59,49 @@ TAILQ_HEAD(rte_bus_list, rte_bus); /* Global Bus list */ 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); + struct rte_bus { TAILQ_ENTRY(rte_bus) next; /**< Next bus object in linked list */ struct rte_driver_list driver_list; @@ -66,6 +109,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 @@ -82,6 +128,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