From patchwork Sun Dec 4 10:11:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shreyansh Jain X-Patchwork-Id: 17624 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 48B4AFA4B; Sun, 4 Dec 2016 11:10:14 +0100 (CET) Received: from NAM03-CO1-obe.outbound.protection.outlook.com (mail-co1nam03on0055.outbound.protection.outlook.com [104.47.40.55]) by dpdk.org (Postfix) with ESMTP id 066612BF6 for ; Sun, 4 Dec 2016 11:09:16 +0100 (CET) Received: from BLUPR0301CA0032.namprd03.prod.outlook.com (10.162.113.170) by BY2PR0301MB1573.namprd03.prod.outlook.com (10.163.28.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.761.9; Sun, 4 Dec 2016 10:09:14 +0000 Received: from BL2FFO11OLC003.protection.gbl (2a01:111:f400:7c09::118) by BLUPR0301CA0032.outlook.office365.com (2a01:111:e400:5259::42) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.761.9 via Frontend Transport; Sun, 4 Dec 2016 10:09:13 +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 BL2FFO11OLC003.mail.protection.outlook.com (10.173.161.187) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.734.4 via Frontend Transport; Sun, 4 Dec 2016 10:09:10 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:; UpperCasedChecksum:; SizeAsReceived:684; Count:10 Received: from Tophie.ap.freescale.net ([10.232.14.87]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id uB4A8pK8019825; Sun, 4 Dec 2016 03:09:06 -0700 From: Shreyansh Jain To: CC: , , Shreyansh Jain Date: Sun, 4 Dec 2016 15:41:19 +0530 Message-ID: <1480846288-2517-5-git-send-email-shreyansh.jain@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com> References: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com> X-IncomingHeaderCount: 10 X-EOPAttributedMessage: 0 X-Matching-Connectors: 131253197534238898; (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)(7916002)(2980300002)(1109001)(1110001)(336004)(339900001)(199003)(189002)(106466001)(68736007)(5890100001)(33646002)(2351001)(105606002)(76176999)(50986999)(48376002)(36756003)(50466002)(47776003)(69596002)(97736004)(189998001)(92566002)(5003940100001)(305945005)(7846002)(8676002)(356003)(8666005)(4326007)(2950100002)(38730400001)(110136003)(6916009)(81166006)(81156014)(8936002)(6666003)(104016004)(626004)(86362001)(77096006)(85426001)(5660300001)(2906002)(39450400002)(39380400001)(39400400001)(50226002)(39410400001)(7059030); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR0301MB1573; H:az84smr01.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11OLC003; 1:3cwuBU1hFi7SS6TGEDYjVQ0YH0SUdY+wWWLQ5mFqi3Sc1HDgrqWHFOWXs5e7PB5vBahEbCJ6Gmz4FEu0VvEqH03dsECBtb6euos5/6G4WJjrFrOAQxDR0FRwPYupyIOuwQm/k9pjDlYAjJLvHobwSQ7MPVc2pIKv4P2HI85h0K/k4cLlhImhfwkuefXMLyPacoedGK+lSxM+6iy5mXKvXMFNlc2FAGSxrDNISoyqTfqpMrKROfvtsWIWiAKYytCgorZVAvFLNeB8SQqL8dxTFTQleZtue8TBIuij3YF1o/BMdpoDs72xRL6ex8WIvan5kVWig95wae0Y8boiz6oOiCstZ8U+6uN+/4WYJbIbU1Xo/9rKNRuKARbKJQSQc8wKbp7EY2nvOcnJJB1cfuBZebg6LTg0e3AT9e8zM7HOwvJqMQJvmX1SQ2YYMJG23VO5xE2ToqRIWXpib/v8n9YEBd9FPoHtXIieaqmVUCs/LGU1o1ou5QBiOrqh68ZNHtiAnF4qEGqm0Q7oMUN5PyV/5xPYn3mFSr06Q+loMWTKvPPZpNMLtjJ8jFVSaoSg2KOlJSWijDg005ioUn/X111SaahiEOhRPFDy/nY3DPa+gsqir4ujfV23Dgu6BikeJ/6jxP+2VGhSDHyLBQEJjQMOut8H+P+a5lL/KGro0XfQ5CE+wr91Ov+UMbpwYnkBoKmBoz+nmfsBQ28O6nMGvmdxhzVT7BO5ZPib8kaWNSV7L/U= MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: a52b5e1d-255b-45af-3754-08d41c2d991e X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:BY2PR0301MB1573; X-Microsoft-Exchange-Diagnostics: 1; BY2PR0301MB1573; 3:MUccKQ+JyRaZc9pWw2/zyXCmHUOIZwKFnk97/UVsj1fDu2do8NEI1uacIFVto6Gveo+VfmhccgiHYXiMs1WVeCKkHKsPkOswzAT7SGqQNaU9ozqGIBlLiLshUbWODGuB003tdKfCQuRSM4akHk9x4Zyr2DWRmcu0FCg1T24zSj5c7K6ZinNl+vayePzU1r7ckmu98Un9XCBekhv0lnzVPEyAFgiejT0LS4x0+yx0eIGTGes8UC+9bwJ5vNbrkNdVzEdTI/qypNjDSrGnsvFuj3DKExidqf2jh1bhkwW/P3melHkJiQnfSGOMS+1+/g+cRg7q2t9SQ64/ebR7NfzZXmfCTtx9rD1frOfLA+uJ2IsfvA3t2DUfoD/LNOujP5g6 X-Microsoft-Exchange-Diagnostics: 1; BY2PR0301MB1573; 25:9t4+qSEeK9yy58F29rXoxHqX4URiu5AgsUqIkkFHU2RjhT7V+GtMNi5DRcLhkAGglUiSmKkhokBEI3BelYuiRitSwKFOrefYYQexefUbHoW/AgGo2sUNmcoL76f2zmZ12OiLPhR+IPiayEV5stGuPE8SI0orww3LUAJG71EPak+IuORDs93ERy+z6HEuvEVJoxLqP5Yc3C2NyFSL/28we3jizRcZGTYqdT3KlAT81oviQYDLXJCQG/lodE14ocMTBe9rLIYMNM5Atzg+dwEO3xyMHFbSFNL1wXAL8d5TaCjPNxBPARNZysbIk3l6NDwYgTHqWrXKPC5CawS0btKeMeVDDYEXk6Osi6tflqxt/1kg3LEMBfPmibFsXWNTmH43Hx29+WiRwEn75bLDENUAM6R1fANzDRcQq6iEX0mbLVOX5UndpW6TRdEyFhYP3bjKrVDU4h5PuYnDf0ZOHq6TleotFotUbXYOPbo30qYfoke46+1l/U16iBiLoYJK916WSKOOJwc1dq6hP9Mqb5QL/kbeD/vlssE0R/yYJeVNpZ4WkzOP17itaJqPdseqfH4CHphXcg88nkGtoM0HP8GwmjGv9TNFcc2xrFFKgMTzhnaYfx93cmEMCICkTACzo9VS7MtauL5o7ZayX4YvJ6fEtjc8F1d4qxrennEJD0HPEUn6Fot53vMpwxg18SheCmWP/94E4kpb3VooOcEXdW/k4WJ9K6GFKLiLB/Jm4SSz5qYCKdthqOsh8arRNFxF76YwBmY9nLtjnU60T7fVH14GBx0tx320Fk1mg4jpL8AOE9gMSWNloO3gesf8E7nLikZy X-Microsoft-Exchange-Diagnostics: 1; BY2PR0301MB1573; 31:sbten+TptGH9CjcW9FC41rPh5PFFf+rKDYQbMZPJdg9/bLJ9z0lSgL5AMXIgxWZ9Dl5uBa1DFPTJYmstpvR/LgplY+noStVmIN0W57GDXC7t6pR3aSNBfiQV0gmJgqeF7y3BEpJFLCJ7mkRchsqgUEuIsx34paBTUyaUo4dU0IvQtCT+tfi68De4vrZydHx9e274MkFr1td/o5fdalhZ28WEmq1W0pc6NQu+1NDYPN3ckRAAWtoErm2+HThUXarFiVo7Gz5q8rGzImd+m/m3fw== 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)(13017025)(13015025)(13024025)(13018025)(13023025)(5005006)(8121501046)(3002001)(10201501046)(6055026)(6096035)(20161123556025)(20161123561025)(20161123563025)(20161123565025)(20161123559025); SRVR:BY2PR0301MB1573; BCL:0; PCL:0; RULEID:(400006); SRVR:BY2PR0301MB1573; X-Microsoft-Exchange-Diagnostics: 1; BY2PR0301MB1573; 4:6j13paUBsTG7s3v2CSVO9xozKeRqIIthO+tDaDlJaSK6JFGEoQQcLzftGkbfGYNfIOYry6OWH0G4wBw8kZADsliBjnExu3egyicnSvQrwMyebsLFx0y/se37zrH7XCWkIYBUIhWfsU/DyAe2HGAD8Nx/KQgmXsmhRIf56wlyu8fE+ufM36ZFVy7/05yrSmrWVYb2blnLPIhC8ShSn0Iyc9eztpmgb4ucZW/fKWW/5A8PcjcFmXNZH4mDp8dH/CXExVDdB4BTWGUKa0Q7/a3vqq6HyFPakh3yBAJVdBCtnMuWj03qGDj4W3myyhkaFYCEPBWPli2bH01rxSQ7Hq/4II1cnJ1W7fo95g/9EHYAvO590/pNRjN5a8Zo1sClmg8BfaSexKADF9nGrpgjciNI0DUrfzM5I/ujVAvVqblg8K03Siz+uCG/t+51rvi/XBb16cPlybNPTTSF6AxwyIxBKhWaaQbqniFNZfNT0qkSkFy9WFH2whzhRqrn6DML6HakX6kOPR3h1afc3912s9TPtTmGztCoeSDifgwHZRB9wLjM5tpk1ejQ9tuP0ZtioiznPTRM6MNYta4T/Um65jN78c81dL0I6TNjuC45SNEU3Ug8OHU/bnpgJ/RKppBFHZBRG1FIhsQH1zuKo5M9OqMffcTi4R7L3/11OvZYTmn4uV9hBrEvl26CopYd1I0W8pwaeWrwkH7wBNwN30yLAfLQDyM39id9PGC0oW1j8d3i23BmLmvHVrlwxfwHchA8zYJq X-Forefront-PRVS: 014617085B X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR0301MB1573; 23:lXxEhmydlX0LQjoTN31K99RGYx+Mj91Zt30Zif5?= =?us-ascii?Q?F8ES8d7gcaPW7Zg2q6BiGUcsftM2DlBJi3L9JDfQwEwKZtn6I93wKM/a2Cc4?= =?us-ascii?Q?jOiGpGYNYiVz0dmMxoG8EvNb+0JGiBv5mAwu7cmmWC5Xw5Pd1as7NS7Mm/yv?= =?us-ascii?Q?S5qENXg78XzG2aHumbwVFsG8r5pIqo7ZPFeKoWWbJ0QvXE1natoxt+zCq7Q/?= =?us-ascii?Q?YosxgvruwO+o1DJdww8hrJFFjygmOB1XP6UZX7yToz/o8b9EJ+JK4oaBLPP6?= =?us-ascii?Q?7InAfKJAgQWJkdMNpcAuoO6zHBpfND8/+RuxxQqsSdT3LBgxSSDYpbwX/sV7?= =?us-ascii?Q?/CprS2qs2vL9ZTLcnLClzqddjOM/9+BLQ8Nul/5q2damiwgWQTs2wu2F5+QB?= =?us-ascii?Q?Gkeea3Wg6RNmkH5ROlyXDQAo1ZaPJcqysCfep6Eypr7kq6Kkei6nJcwyGqPI?= =?us-ascii?Q?pQqT9jonmQoVuG0mbrok1Zjp2sNmiSa1wsqWAnbpgRW7cKCgHgUgp5pxRKHU?= =?us-ascii?Q?LpohCUvB6kpORF37NHtbhv5pXrkrkrBpDn+oHwQSMY3QfTPn4825amgUsrOv?= =?us-ascii?Q?1sf/vmUNe82HO7Q3+fsMXld/BAvdsYvlbDD8d8fNq/p3URvrWcdvYip/5Nc+?= =?us-ascii?Q?fl5DfRDkcYsmNQyBRz6KSBUXHLy2/gf9gjBsUpTJRJQd4WpuMNMXDBd+adLE?= =?us-ascii?Q?ov2KrOZue341Udx9Olm3ZR8r8Oi9/RaGAuyybSz2sg1uFM6Pf5TQUabSWCHS?= =?us-ascii?Q?m8KaReYkApgP2MV3JU56q4CBy5qyKDbd7XSdZushbabzCSPLNZ8wpvlRVCGC?= =?us-ascii?Q?8kdGVZBOmHQ973eKBdMkLNr0HZRZvmFSS8cYS9XUWBS3JFG0pSFuHE0UbNBM?= =?us-ascii?Q?AB7zSocIEcbNe/5mW55i3RI9bTM6zVAgqYiU7NEWIlvqZGGT+6B+7UIAGCHH?= =?us-ascii?Q?rpQdOkLvUde93TG4VaQtBxbmaxptL7k3OgKtUYH++PcX+ExTKNSi5oyimZnl?= =?us-ascii?Q?N47ARrBe3N6/Yc8V4kTlgHW8A8ThuDgdpMgjXyZLxJZo+uGxaBVVBwLK6H6h?= =?us-ascii?Q?niBjEcqgAhxtilET9lqgyRIWB1Xd5rteiMxtX6BxaLMlzrbS92x950ZzWm+W?= =?us-ascii?Q?wsuEDukDb/sO3mIiObRZfCQksZ5hSswFKW4d7Jy8yr5t17llRQ1r1CbHOJxt?= =?us-ascii?Q?CU+tMy5jk6dZ/+jFYfsAjZk/Ju8dtSdb1UI5oj+tRyslv3a+50ekz0zEfLtr?= =?us-ascii?Q?mrzWbWesIAqp4KCbqn5gdlyuXLB6k1D+TgQtBvbJy?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR0301MB1573; 6:T1nnEYJSMSGzkc9BtYjx1U0bflr51HKfScYGeVbP14Mvxhwz8u4sHFYqJicxihAaUhviA/lByKkUoJQ9Dr6vy/jyFhALvhYl5+IoRXx/aRyKNfDP0f6ZYAkrdeTYcKwjmGGbGyy++++A1tUBsDvSY8p7K27cAIyS/B7tbpeHf+1IS8ZCzwJ78HQrWItUDpQn3NlmpLLjqPgYnD1DS5DnfJCcJrdPD0IkPxtRI5/l0y1e8XBr3JknEGY/0LZwZ2sCUpRE/CK/nXOmgyd6x13Vh+EF7G4K6bi8ulekcTBscluXM86HdNvt8kjz2Xkob7VQnXe6rbPwJpkxXYq10Tt3F6cbli57kEXR2HUbT+ZSdW7qz3YPdvA0RiiP7vWAcJ0uPLC63FrbeghYLYUCZ5guuqQj+1ZGlN7WxA7a0q+Njd7ouk3aIR8oBguIXVyrdYfI; 5:tqKOCSphRfaRxyFTXnDDz3Uby0Ib446k199ouj+0/W4P91DoEoT3YlyLPCUbjuzwxwNeLRZlcVbJp+6/Oz+mTXxN456QBIWGoxvmDRsEh4Kc7FGuGaOQaZgFjEDjj8pvoAP2QC5oho3nQ/CPgCeBEF7mf4AyjgETri0NqHVeR0/OCQw8MNSh1aYtVX84JOgA; 24:oojTiay+uq5f5gAn1Tp96k5CJekaNLc0nayvbkdmE0Ei8AcLREHSeOBVnJ00SjuXGHbwyP6RcTsPi8oslFWxM61mE/oOlcu1DJcUaRQAJqc= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BY2PR0301MB1573; 7:Qiu7PE1l3RWsVdIyxKNTvl3CUBfi58NxjWyzFL1ZLPCqz/8K1yKwmkq2ALpF03j5djUo+qF25qXMzqAKq2zqhckwanNy+qstGVFvcgKF6C+czOalZUUcaXoWb5GOcrgduQHH/XUZqWhhMwzxWAFRGyyRWraRxsIFApP9w/xXvfzyDjRBvwn29iNYFEBHniHy9g6X+ujgSv7n0hXUXyJTSZsbR/MF8cs85R+DlzX7w2nNZe7BP6Mc3V2FydYdjYG97ISg2rYrfnC3SOC1wkLSiGFJqshfEttYQ4g/Eq4OED8NAwE/WbaIrmkdGeMTXklVc6wPgXfyzGNmYSzUJsQJwgkuhPBUEJrKVeB/mKPZXiTr+vWdJ1iqxrVyDixJPxEr37zfYA752/ned099WD/7JeLY5+YWiBc8lyWKyo9meQYZ6JIgOwWPMoWgUyE3OdHdGFga/QcafowREvVUMFLkGA== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Dec 2016 10:09:10.4911 (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: BY2PR0301MB1573 Subject: [dpdk-dev] [PATCH 04/13] eal/bus: add scan and match 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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. 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 | 3 + lib/librte_eal/common/include/rte_bus.h | 46 ++++++ 3 files changed, 314 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..2473fe4 100644 --- a/lib/librte_eal/common/eal_common_bus.c +++ b/lib/librte_eal/common/eal_common_bus.c @@ -132,6 +132,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..b41105c 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