get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 18529,
    "url": "https://patches.dpdk.org/api/patches/18529/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1482756644-13726-11-git-send-email-shreyansh.jain@nxp.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1482756644-13726-11-git-send-email-shreyansh.jain@nxp.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1482756644-13726-11-git-send-email-shreyansh.jain@nxp.com",
    "date": "2016-12-26T12:50:42",
    "name": "[dpdk-dev,v4,10/12] eal: enable PCI bus and PCI test framework",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2f0eabe6c43d77169bc94ca7fc3284232e005a5f",
    "submitter": {
        "id": 497,
        "url": "https://patches.dpdk.org/api/people/497/?format=api",
        "name": "Shreyansh Jain",
        "email": "shreyansh.jain@nxp.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1482756644-13726-11-git-send-email-shreyansh.jain@nxp.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/18529/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/18529/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 04589F92D;\n\tMon, 26 Dec 2016 13:51:29 +0100 (CET)",
            "from NAM03-CO1-obe.outbound.protection.outlook.com\n\t(mail-co1nam03on0048.outbound.protection.outlook.com [104.47.40.48])\n\tby dpdk.org (Postfix) with ESMTP id 5A6C9690F\n\tfor <dev@dpdk.org>; Mon, 26 Dec 2016 13:51:04 +0100 (CET)",
            "from BN6PR03CA0029.namprd03.prod.outlook.com (10.175.124.15) by\n\tDM2PR0301MB0752.namprd03.prod.outlook.com (10.160.97.148) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id\n\t15.1.803.11; Mon, 26 Dec 2016 12:51:01 +0000",
            "from BN1BFFO11FD030.protection.gbl (2a01:111:f400:7c10::1:179) by\n\tBN6PR03CA0029.outlook.office365.com (2603:10b6:404:10c::15) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.803.11 via\n\tFrontend Transport; Mon, 26 Dec 2016 12:51:01 +0000",
            "from az84smr01.freescale.net (192.88.158.2) by\n\tBN1BFFO11FD030.mail.protection.outlook.com (10.58.144.93) with\n\tMicrosoft SMTP Server (version=TLS1_0,\n\tcipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.789.10\n\tvia Frontend Transport; Mon, 26 Dec 2016 12:51:00 +0000",
            "from Tophie.ap.freescale.net ([10.232.14.87])\n\tby az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id\n\tuBQCl90S011201; Mon, 26 Dec 2016 05:50:57 -0700"
        ],
        "Authentication-Results": "spf=fail (sender IP is 192.88.158.2)\n\tsmtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed)\n\theader.d=none; nxp.com; dmarc=fail action=none header.from=nxp.com;\n\tnxp.com; \n\tdkim=none (message not signed) header.d=none;",
        "Received-SPF": "Fail (protection.outlook.com: domain of nxp.com does not\n\tdesignate 192.88.158.2 as permitted sender)\n\treceiver=protection.outlook.com; \n\tclient-ip=192.88.158.2; helo=az84smr01.freescale.net;",
        "From": "Shreyansh Jain <shreyansh.jain@nxp.com>",
        "To": "<david.marchand@6wind.com>",
        "CC": "<dev@dpdk.org>, <thomas.monjalon@6wind.com>, Shreyansh Jain\n\t<shreyansh.jain@nxp.com>",
        "Date": "Mon, 26 Dec 2016 18:20:42 +0530",
        "Message-ID": "<1482756644-13726-11-git-send-email-shreyansh.jain@nxp.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1482756644-13726-1-git-send-email-shreyansh.jain@nxp.com>",
        "References": "<1481893853-31790-1-git-send-email-shreyansh.jain@nxp.com>\n\t<1482756644-13726-1-git-send-email-shreyansh.jain@nxp.com>",
        "X-EOPAttributedMessage": "0",
        "X-Matching-Connectors": "131272302611791911;\n\t(91ab9b29-cfa4-454e-5278-08d120cd25b8); ()",
        "X-Forefront-Antispam-Report": "CIP:192.88.158.2; IPV:NLI; CTRY:US; EFV:NLI;\n\tSFV:NSPM;\n\tSFS:(10009020)(6009001)(336005)(7916002)(39860400002)(39410400002)(39450400003)(39850400002)(39400400002)(39840400002)(39380400002)(2980300002)(1109001)(1110001)(339900001)(189002)(199003)(356003)(47776003)(106466001)(2351001)(69596002)(8676002)(33646002)(48376002)(110136003)(5660300001)(105606002)(6916009)(6666003)(68736007)(50466002)(2950100002)(36756003)(77096006)(81156014)(81166006)(38730400001)(305945005)(50226002)(626004)(8936002)(76176999)(50986999)(104016004)(8656002)(92566002)(85426001)(86362001)(575784001)(5003940100001)(4326007)(2906002)(97736004)(189998001)(7059030);\n\tDIR:OUT; SFP:1101; SCL:1; SRVR:DM2PR0301MB0752;\n\tH:az84smr01.freescale.net; \n\tFPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; ",
        "X-Microsoft-Exchange-Diagnostics": [
            "1; BN1BFFO11FD030;\n\t1:CiicNUqym3+EgMv+B83nAD14G51+2hD1e2Adz//NKewj+qMbA26v5YWUhCA4NSVd4aImoG3Jr5mjroWZAXWkpE82GvDsUwzK2ekLT+1uZ5f0W8LbmQrSE5XUZ+mEnB+UsUZ8PX4OTpNVyrYqsLKaGrJHbQRDv3bfZ3B9cxUEgF5u4qD1yA7y4d43MwnG3F6l3NI2pYxjT4BWtOKPiCbNhZHPGb4ntGG38OD26Vjy7S40wP83KmZga1F2EYqxdj1HlE754P/i2Zl9luzINgdTpYfjLRCYWETZO/FoIr3BtU1wglHAoKhhTY4AAS70Ubu0k1CfAzlTitsGA+a+X2Wy9fgysSQfreM3UgWyAWH/VVt6epSqvfJKjdu6Rt/LLOpN2pxOJ1HBWkt0kJwha7C7xrW/WtvZhHgCCp/P/0zBVpAF7V2t7Cr8wBTsbQtdRndGB9obo8mPq5ZcHmEOUw58mGpk5FRaMk0zjrg65NzjCBlbG/BtUsdj/d3p4jT37JJLdwuXhk09Pm1fTlokbgpKI7wWsyoZJepJd3Lj23akqtWGdRsnHBoWc0vpmqsm8DpXdz0a3Ql2tbGlqLQQR2Le0uf/DVVaZnnvsN6pTS4Xj2i9EFdnlyXXr2W0nMYuBpa8f/N21DbcUc6ty6mHFqsRCZwNUF4RBnJDmGFURRVgD4LF0uykY+8+TUWXl+UwYEfMvC5AzVy4zwdxVJ1VYCrP+kazYVo7Aer0XAtjYxq7c9Y=",
            "1; DM2PR0301MB0752;\n\t3:eVx6W02DYV3yUutsH2nlhfcWDz/3cWgOV5lG5orXY42K/rlCmDmWk4OwlpggL0VEE+0cO5EqYV6tETdplSF/Sx+dxF3MJijtsgibvDATncHfh3zsq7ABo5Pq6DBwVa0wFQnkTThFCuGPbPdZhUTwsESPSGkhxxfRYB65V2BN+0DSazZUTMT6oZCNpr3BSjMzRSGB8DR1VvoI5D04LRAEIbR9rAkSISmCG9HFYQ8o2xm0ufnJDgEd3U8P7W/NMw3BpJcKW1Gel4/CUbUvpgR04vF9JJ6zdLKqGI+/Q8b8ZXx5ADn/gQrvMo4r64PQJ8vGGf70E4EBDmqAF61PmGlpILvLhJe+0fzZmkERXShjxzg=",
            "1; DM2PR0301MB0752;\n\t25:Y/9i8TJMiuHqnx4hcC7JAKQbKruN9B+s/oeO2sTea8RpiPL41LsV27dz7+qdHtuSF/qegjmkAwV/d3wEFnpdFW9+HWZN6wY4/sTkXy9eDnmJw+Ax6RnmsG1pSQnOW8QOxO54wcWQBMuEICkobPAbevlhbyfl4TzwyKObx444TgRMuG8Ju4n08GXdTSiPpHjve3V5QkUcPJWyvXWiVz5L/W2zKZ6xX4w3xKCZzr4mV+arpawCwoYZ74s6t7B6hCRHzmnyNFneJynvawjdvqBSIV3+QFmbpBhGcQczk8yTSNME7bV/o6dg7oM4l6eoyUMpWZvbjjqY3DMUrkO+foOinbMuvRWlWllNeRp0Cnf/cNuGKvVSqJ/+KmpE4Hh2bNXklm0POLwHakg0/8cIVFkNF3VemIxdIUW+RIao3ePy7sLUzEpGkqOB/e4mtBEVaDDrcA1gJx1kvj1zMAtDfV8lqe/wTnTSVvA102A/4b00i2ljBNzJoqHKWlKZ8HF9//zM6Zb4L9YPR/a/kKer643wLqWtdnvdnxi2oKbMSLyM823CC5MnEH/JACblsbD/L8WdxLsbLURxW+94LweZT0yCYKD6e03W9tF/xxkMpYWN3xslu2AxAj/GgnZ+Oo7yFGAAF+cnFTyDJyGCGXcl5yRjvjRspa+Co5Xq+P7KoNafvIJB+AW5WArxpIwqAQTz7N8bLH8VAlWI/zBM0WV4Wkp9uwuakVCatzokSXc73txfW7kdA3XA1gS52khUcYMszFJasvO9RzpRLeyHOhXgOiQaGS0ROzggIG2FSzVomKXLE0rid1n4qFQUfDYuf75ZE75P",
            "1; DM2PR0301MB0752;\n\t31:ZRKXSlTuKhVL8qEjraQen8WiHTSBwKlVEBvLDmB4iaVZwpnleUQ7SQnWh1XDNzh7FMv2+084br3Ad6mdqm/CF0d/+is2ci39gYym9N8wOPWTBjZaxF4fot6GxYctdht902hLDZVFsk03Rs0/WZtumiSLjRmoo4CJu9OmExTbIZa9GkwgTXD9vGKV6gtxMkZolPd1HdmyME8qmomyS257kVZtGECjIOnN/mfm6l2WW3hDoSp7XPmC/yq/S0BEgPihia6lVi1luOH8JBAQGQXcMQjcZ+cmYT5rwLS3ssw9yVU=",
            "1; DM2PR0301MB0752;\n\t4:M909VqyZTWNVqBDH6irrf9ihQTMdGMfMxU9yufxdJ1hzAx/E3/EOObonJg7Ygv8gbcHfwm/03VaaSsaah40zAiBEr5PLd9UGSzgW7/tc/TrHCQV28mry/EZSiQEqYxWUGBUawnXmNrDBA421ikCHdBMLrJJsQUllesx+xtOz9OY8jrWmCgpKpNehaliN4XyZYdgkCtB2xQkV0Xr8BNVTZxRjfuSvEnMeqhY8PhjScZZH5Wg8xyVpO758yHct3TZR/vMAzlBymsOfCTt+aWO74a3jxD9vL8zEE4hcdi6SO0k8+u5tm7MkrQAWkXnA2es2Rrnf8mW1VZc18KLHeYoPXwvtW7/ZsAfIyoxu3ll0djdvfYoQw1EvPHbh+tfRqaA25cXqBsljjkq9wdbnjh4nJfh+wd6p4xc4Mr4CnvC5WJ9GEFw+Hy8ln8aakfL+brt8jHBirsich8aETdveU8MqGQF3/R3JU5lPddfHDmbJ09QbeMi0Q8IlADpJkPm+RVh90xfV3I+NiLz+ZBazzmXAnPduPZpg+FjWbHglxqyOyg1tpBGl0riKeQEpobZHMUlVB+f5sdD5g0IoxyBSSkJ0amHKFPoCRA65kvVaYW3a+co50W9WAxGstaKyl9jVKF8nWULKEdvpxoCorSkKc7IGh7u4HWqD/oG9pEj1x5m/d4evxK2j1pAj3wR8+OZPH7LXB8feSI/d17g5lNRKia15LjU1WilcXWWmUzdUqPhfPfY=",
            "=?us-ascii?Q?1; DM2PR0301MB0752;\n\t23:kXvQjK5HmKdCifa3J4uZT/EkDFQZv01jzmb+bXp?=\n\tuv6aJ676iB/7qohVz8fSwTcZsxk8jkzKpNqw6Bjh+v/vx3yEuTwJEokS/Ec6O0GEBB7k0VpUnPp4uhDOBdKcoVyF9q+TaLjL2xGXFpp1nKGx4o404ObCsYhEjziNHyvyrc25NWIuj+86Cs3szZNC+iUZXQX+1Xhf3rOJ/lVNi/K54Cw626eNZNyYHjRhM3l3M7cYXW6jeW+CTjn19vVp8vmdlzjdhdW/vRN4h1WFFUOP/mcNROTBZ9sgwex0g3Qh3Kr+depozUbvGzggwxol1w2pImAPQfq/bsvTLCfDYGYysTLLtWgMOvrJz4EeYKW7ujytps5hIYx8gYCuGX1LQu6TyCDy0qUAJSBZDUNjDF7Wqr0NgCjCBk6lC5gUrC8l3dKh+4NZPEM0pGK6gwceLgrKBZ8hv9eJBESJjxS5I+woLwczDzj//SbOvO+8S0iY12ra3uAqtIHaQrGaE+wpes9sMpfmywW2COTt18+B/iGfDb9RB3HoW6gR4wPch3v0PIZQ9lB2XlIekP/V4UVLSAIyO6nHDQ3lOPZfZy4MwlEd9Gjou44FCYFyOxbOC0IlYZ32Des0CT7O4BDKg/tNOCjCQc85n814wUMZHnCRl8Y4HoYnMOzFbGdOflCGUO/Wmr66IjPTy6kjYmG1ZdDkyTpycc/9RcDDNlouy5oWvyEyu6KvnJslDqM1Aue6uTt0MI/xVZJrMN9g5oh7IpsJJSaaCrUIC7JTNh6kNyltapVLVAwCYnc4l08sfCfA9BINz/0IA8rDZ6DydraYhpemuTFqHRmi7jsKaYhekVVfgymlvmNKORIVH1NjPS4a7afqL8RgABjKRu9hiB/nL4/x7+T74bW3gx3+LK4SXhwkRkM7pklQ1FYxzV8juBkCc7sVRfIsIuUlCwNIcGzc2aU4GyItn6FPyku0lhBmOX6s5SpfH1s1fhoX/1gLseM+w8dwyqM7UqR5qxmcwYvxK+TUU16E6q4ryDJch+8EH5DgGD01xUPBRIGQcMxnrKnSXHmic7TYmhw4lASH7oB2M6C6Z1ig0wNbtlIqEVbozhjAjc5Bgj6Qq1perU1AOSboKmnY4mbKOnDQ4JJNUGZQt2tbM80FOuh5K57T2CjL4pga2O4V7kx1j7SHCgNUUKzpFRkPh6Y/lbHJb5y+kDOy8Ny6J9bSZwj87zoTh+sOFJb8jkpOgzyHTVh55lwJzZ+IlCgd5h6wHWBHKSsW9J153N7XGKnFlRGl/Hc2HScdcpaBme02Ho3xNSBFC2RAIKWFWJA5DiohER//8jL313JB+53jwMDyz",
            "1; DM2PR0301MB0752;\n\t6:R3QRZmGGLJWhBalxGuJlTbL+qRJYDyufiRsqstmPp2/xBg9VSIrIdthQSKVwrH3BqG46SneaHxg2bKeGlwEzNuN3HqohWWyhH97ECFaIw/fD7++2080JbHdlthIDjNX6CGX5PMmq2tdoxJQGiFK8PKwA7M7zhnQYEmFkEL3W1cNF2Q0mp4SPfMY0BT3CFKl0d2GbYq28Fs8oW5epAuXbjndPeccB5yoYmQOOP8CWmyjdPyumbJdpNqnmY7kpBFhcXH4DT96ZxGe5rKMfMMqjgOQNtn57b+wFAuENW4uyu8Zltyf/bRYPBINgRH0h7govZnqFlIwgThWIMYZVMT42t8tDvefHx/KGNwlNz9FJGNdf02U+8T+Qz8QIVxUymn4EX1Bs0YXiwxbCx9GudQWZsyUs9jd4jnqi/JSovdyeHTEA5OeqgUAVdB+WUrMOtpJf;\n\t5:zmc0Sn528pbQdKmz5D+M5q9LxRD8OJOzJAYifPlk9O5Uhq20Xi0cKrYCLxQMNZlR37Yrhs7vFAHEO0GpVuORRSc39WtEBEESiwFsUgFbdDRog/7VOoOc6RhRtj6YalLgBJwk5r+FGES6PKGl0/f3vQf4vAzzusIhWznhgObVZbZ++wVMHeobq9+73jN09jrC;\n\t24:6oFaDND6ImQoBhjEvVIjAmUJGGLoJKdogapTFTu5dP9pfS1GQSfJ6aot6Or2thuO8ctmVFaD4tf4RYqq4z0calDTNlyfvp6/Zpz5WjEVua0=",
            "1; DM2PR0301MB0752;\n\t7:wkwRuoTV373fmmE0v3mMnB/c7du0SMGI8F04w9JvuUCj8WkrkJaOO+lzX2xsQo4O5NPn+qesQPmjJPalEMvlG7/Rh29ItAkkSA/dVwS5V2oGqrO/ex4W66wehvna4HxP9QPNtfjg8x6c9CQnYok6zsKAJ67kwWAbcUDEY06IOrh/Hd+JKzh3U8TMt9jGyTKfaIoEyNQC5W0HQgJj1qYe/L5kNuERRvZLZA7Xm3D4+rHBZOllO7TLXjbhhntGfDWG+AkwOwJYIZT1Po5Gz7BK/egt5bJi6Z8OZ4/BBBlFHQbGrb6nzv/rfOYgrGF+N4NOiTo5mSjWdWC5yd0IHFcbi3c90ER8IqKfvPVkvUBbemOWnYDgQhIxEbsWei/aH26sR5toeyABAU2DYVE+Kmp5aSG2IE+uHvfDJfZPqbQjbaypbeCuW0H7PHsk++5OsA9CtGes1waYHzb0EdEmzxkRmw=="
        ],
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-MS-Office365-Filtering-Correlation-Id": "b22ad1fa-a284-4c45-f51f-08d42d8dd869",
        "X-Microsoft-Antispam": "UriScan:; BCL:0; PCL:0; RULEID:(22001);\n\tSRVR:DM2PR0301MB0752; ",
        "X-Microsoft-Antispam-PRVS": "<DM2PR0301MB075217E24359FF93AF0AC60090960@DM2PR0301MB0752.namprd03.prod.outlook.com>",
        "X-Exchange-Antispam-Report-Test": "UriScan:(185117386973197);",
        "X-Exchange-Antispam-Report-CFA-Test": "BCL:0; PCL:0;\n\tRULEID:(6095060)(601004)(2401047)(13017025)(13024025)(13023025)(13015025)(13018025)(5005006)(8121501046)(10201501046)(3002001)(6055026)(6096035)(20161123561025)(20161123559025)(20161123556025)(20161123563025)(20161123565025);\n\tSRVR:DM2PR0301MB0752; BCL:0; PCL:0; RULEID:(400006);\n\tSRVR:DM2PR0301MB0752; ",
        "X-Forefront-PRVS": "016885DD9B",
        "SpamDiagnosticOutput": "1:99",
        "SpamDiagnosticMetadata": "NSPM",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "26 Dec 2016 12:51:00.8203\n\t(UTC)",
        "X-MS-Exchange-CrossTenant-Id": "5afe0b00-7697-4969-b663-5eab37d5f47e",
        "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e;\n\tIp=[192.88.158.2]; \n\tHelo=[az84smr01.freescale.net]",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DM2PR0301MB0752",
        "Subject": "[dpdk-dev] [PATCH v4 10/12] eal: enable PCI bus and PCI test\n\tframework",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Register a PCI bus with Scan/match and probe callbacks. Necessary changes\nin EAL layer for enabling bus interfaces. PCI devices and drivers now\nreside within the Bus object.\n\nNow that PCI bus handles the scan/probe methods, independent calls to\nPCI scan and probe can be removed from the code.\nPCI device and driver list are also removed.\n\nrte_device and rte_driver list continue to exist. As does the VDEV lists.\n\nChanges to test_pci:\n- use a dummy test_pci_bus for all PCI test driver registrations\n- this reduces the need for cleaning global list\n- add necessary callbacks for invoking scan and probing/matching\n  using EAL PCI scan code\n\nNote: With this patch, all PCI PMDs would cease to work because of lack\n      rte_driver->probe/remove implementations. Next patch would do that.\n\nSigned-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>\n---\n app/test/test_pci.c                             | 154 +++++++++++------\n lib/librte_eal/bsdapp/eal/eal.c                 |   8 +-\n lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +++---\n lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-\n lib/librte_eal/common/eal_common_pci.c          | 212 ++++++++++++++----------\n lib/librte_eal/common/eal_private.h             |  14 +-\n lib/librte_eal/common/include/rte_pci.h         |  53 +++---\n lib/librte_eal/linuxapp/eal/eal.c               |   8 +-\n lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 ++++---\n lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-\n 10 files changed, 332 insertions(+), 240 deletions(-)",
    "diff": "diff --git a/app/test/test_pci.c b/app/test/test_pci.c\nindex f9b84db..e95b758 100644\n--- a/app/test/test_pci.c\n+++ b/app/test/test_pci.c\n@@ -38,6 +38,7 @@\n #include <sys/queue.h>\n \n #include <rte_interrupts.h>\n+#include <rte_bus.h>\n #include <rte_pci.h>\n #include <rte_ethdev.h>\n #include <rte_devargs.h>\n@@ -61,10 +62,18 @@\n \n int test_pci_run = 0; /* value checked by the multiprocess test */\n static unsigned pci_dev_count;\n+static struct rte_bus *pci_bus; /* global reference to a Test PCI bus */\n \n static int my_driver_init(struct rte_pci_driver *dr,\n \t\t\t  struct rte_pci_device *dev);\n \n+/* Test PCI bus. */\n+struct rte_bus test_pci_bus = {\n+\t.name = \"test_pci_bus\",\n+\t.scan = rte_eal_pci_scan,\n+\t.match = rte_eal_pci_match,\n+};\n+\n /* IXGBE NICS */\n struct rte_pci_id my_driver_id[] = {\n \t{RTE_PCI_DEVICE(0x0001, 0x1234)},\n@@ -79,7 +88,9 @@ struct rte_pci_id my_driver_id2[] = {\n \n struct rte_pci_driver my_driver = {\n \t.driver = {\n-\t\t.name = \"test_driver\"\n+\t\t.name = \"test_driver\",\n+\t\t.probe = rte_eal_pci_probe,\n+\t\t.remove = rte_eal_pci_remove,\n \t},\n \t.probe = my_driver_init,\n \t.id_table = my_driver_id,\n@@ -88,7 +99,9 @@ struct rte_pci_driver my_driver = {\n \n struct rte_pci_driver my_driver2 = {\n \t.driver = {\n-\t\t.name = \"test_driver2\"\n+\t\t.name = \"test_driver2\",\n+\t\t.probe = rte_eal_pci_probe,\n+\t\t.remove = rte_eal_pci_remove,\n \t},\n \t.probe = my_driver_init,\n \t.id_table = my_driver_id2,\n@@ -108,14 +121,67 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,\n \treturn 0;\n }\n \n+/* dump devices on the bus */\n+static void\n+do_pci_device_dump(FILE *f)\n+{\n+\tint i;\n+\tstruct rte_pci_device *dev = NULL;\n+\tstruct rte_device *r_dev = NULL;\n+\n+\tTAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {\n+\t\tdev = container_of(r_dev, struct rte_pci_device, device);\n+\n+\t\tfprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,\n+\t\t       dev->addr.devid, dev->addr.function);\n+\t\tfprintf(f, \" - vendor:%x device:%x\\n\", dev->id.vendor_id,\n+\t\t       dev->id.device_id);\n+\n+\t\tfor (i = 0; i != sizeof(dev->mem_resource) /\n+\t\t\tsizeof(dev->mem_resource[0]); i++) {\n+\t\t\tfprintf(f, \"   %16.16\"PRIx64\" %16.16\"PRIx64\"\\n\",\n+\t\t\t\tdev->mem_resource[i].phys_addr,\n+\t\t\t\tdev->mem_resource[i].len);\n+\t\t}\n+\t}\n+}\n+\n+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */\n+static int\n+do_pci_bus_probe(void)\n+{\n+\tint ret;\n+\tstruct rte_device *device;\n+\tstruct rte_driver *driver;\n+\n+\tTAILQ_FOREACH(device, &pci_bus->device_list, next) {\n+\t\tTAILQ_FOREACH(driver, &pci_bus->driver_list, next) {\n+\t\t\tret = pci_bus->match(driver, device);\n+\t\t\tif (!ret) {\n+\t\t\t\tif (!driver->probe)\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tdevice->driver = driver;\n+\t\t\t\tret = driver->probe(driver, device);\n+\t\t\t\tif (ret != 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n static void\n blacklist_all_devices(void)\n {\n \tstruct rte_pci_device *dev = NULL;\n+\tstruct rte_device *device = NULL;\n \tunsigned i = 0;\n \tchar pci_addr_str[16];\n \n-\tTAILQ_FOREACH(dev, &pci_device_list, next) {\n+\tTAILQ_FOREACH(device, &(pci_bus->device_list), next) {\n+\t\tdev = container_of(device, struct rte_pci_device, device);\n \t\tsnprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,\n \t\t\tdev->addr.domain, dev->addr.bus, dev->addr.devid,\n \t\t\tdev->addr.function);\n@@ -142,19 +208,11 @@ static void free_devargs_list(void)\n \t}\n }\n \n-/* backup real devices & drivers (not used for testing) */\n-struct pci_driver_list real_pci_driver_list =\n-\tTAILQ_HEAD_INITIALIZER(real_pci_driver_list);\n-struct pci_device_list real_pci_device_list =\n-\tTAILQ_HEAD_INITIALIZER(real_pci_device_list);\n-\n REGISTER_LINKED_RESOURCE(test_pci_sysfs);\n \n static int\n test_pci_setup(void)\n {\n-\tstruct rte_pci_device *dev;\n-\tstruct rte_pci_driver *dr;\n \tconst struct resource *r;\n \tint ret;\n \n@@ -167,22 +225,19 @@ test_pci_setup(void)\n \tret = setenv(\"SYSFS_PCI_DEVICES\", \"test_pci_sysfs/bus/pci/devices\", 1);\n \tTEST_ASSERT_SUCCESS(ret, \"failed to setenv\");\n \n-\t/* Unregister original devices & drivers lists */\n-\twhile (!TAILQ_EMPTY(&pci_driver_list)) {\n-\t\tdr = TAILQ_FIRST(&pci_driver_list);\n-\t\trte_eal_pci_unregister(dr);\n-\t\tTAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);\n-\t}\n+\t/* Create a new Bus called 'test_pci_bus' */\n+\t/* Bus doesn't exist; Create the test bus */\n+\tprintf(\"Creating a Test PCI bus\\n\");\n+\trte_eal_bus_register(&test_pci_bus);\n+\tpci_bus = &test_pci_bus;\n \n-\twhile (!TAILQ_EMPTY(&pci_device_list)) {\n-\t\tdev = TAILQ_FIRST(&pci_device_list);\n-\t\tTAILQ_REMOVE(&pci_device_list, dev, next);\n-\t\tTAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);\n-\t}\n+\tprintf(\"Scan for Test devices and add to bus\\n\");\n+\tret = pci_bus->scan(pci_bus);\n \n-\tret = rte_eal_pci_scan(NULL);\n \tTEST_ASSERT_SUCCESS(ret, \"failed to scan PCI bus\");\n-\trte_eal_pci_dump(stdout);\n+\n+\tprintf(\"Dump of all devices scanned:\\n\");\n+\tdo_pci_device_dump(stdout);\n \n \treturn 0;\n }\n@@ -190,8 +245,8 @@ test_pci_setup(void)\n static int\n test_pci_cleanup(void)\n {\n-\tstruct rte_pci_device *dev;\n-\tstruct rte_pci_driver *dr;\n+\tstruct rte_device *dev = NULL;\n+\tstruct rte_driver *dr = NULL;\n \tconst struct resource *r;\n \tint ret;\n \n@@ -203,28 +258,23 @@ test_pci_cleanup(void)\n \tret = resource_rm_by_tar(r);\n \tTEST_ASSERT_SUCCESS(ret, \"Failed to delete resource %s\", r->name);\n \n+\tTEST_ASSERT_NOT_NULL(pci_bus, \"Invalid bus specified\");\n+\n \t/*\n \t * FIXME: there is no API in DPDK to free a rte_pci_device so we\n \t * cannot free the devices in the right way. Let's assume that we\n \t * don't care for tests.\n \t */\n-\twhile (!TAILQ_EMPTY(&pci_device_list)) {\n-\t\tdev = TAILQ_FIRST(&pci_device_list);\n-\t\tTAILQ_REMOVE(&pci_device_list, dev, next);\n+\tTAILQ_FOREACH(dev, &(pci_bus->device_list), next) {\n+\t\trte_eal_bus_remove_device(dev);\n+\t\tdev->driver = NULL;\n \t}\n \n-\t/* Restore original devices & drivers lists */\n-\twhile (!TAILQ_EMPTY(&real_pci_driver_list)) {\n-\t\tdr = TAILQ_FIRST(&real_pci_driver_list);\n-\t\tTAILQ_REMOVE(&real_pci_driver_list, dr, next);\n-\t\trte_eal_pci_register(dr);\n+\tTAILQ_FOREACH(dr, &(pci_bus->driver_list), next) {\n+\t\trte_eal_bus_remove_driver(dr);\n \t}\n \n-\twhile (!TAILQ_EMPTY(&real_pci_device_list)) {\n-\t\tdev = TAILQ_FIRST(&real_pci_device_list);\n-\t\tTAILQ_REMOVE(&real_pci_device_list, dev, next);\n-\t\tTAILQ_INSERT_TAIL(&pci_device_list, dev, next);\n-\t}\n+\trte_eal_bus_unregister(pci_bus);\n \n \treturn 0;\n }\n@@ -234,16 +284,19 @@ test_pci_blacklist(void)\n {\n \tstruct rte_devargs_list save_devargs_list;\n \n-\tprintf(\"Dump all devices\\n\");\n-\tTEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),\n-\t\t\t\"pci_driver_list not empty\");\n+\tTEST_ASSERT_NOT_NULL(pci_bus, \"Invalid bus specified\");\n+\n+\tTEST_ASSERT(TAILQ_EMPTY(&pci_bus->driver_list),\n+\t\t    \"PCI Driver list not empty\");\n \n-\trte_eal_pci_register(&my_driver);\n-\trte_eal_pci_register(&my_driver2);\n+\t/* Add test drivers to Bus */\n+\trte_eal_bus_add_driver(pci_bus, &(my_driver.driver));\n+\trte_eal_bus_add_driver(pci_bus, &(my_driver2.driver));\n \n \tpci_dev_count = 0;\n-\tprintf(\"Scan bus\\n\");\n-\trte_eal_pci_probe();\n+\n+\tprintf(\"Probe the Test Bus\\n\");\n+\tdo_pci_bus_probe();\n \n \tif (pci_dev_count == 0) {\n \t\tprintf(\"no device detected\\n\");\n@@ -257,8 +310,8 @@ test_pci_blacklist(void)\n \tblacklist_all_devices();\n \n \tpci_dev_count = 0;\n-\tprintf(\"Scan bus with all devices blacklisted\\n\");\n-\trte_eal_pci_probe();\n+\tprintf(\"Probe bus with all devices blacklisted\\n\");\n+\tdo_pci_bus_probe();\n \n \tfree_devargs_list();\n \tdevargs_list = save_devargs_list;\n@@ -270,8 +323,9 @@ test_pci_blacklist(void)\n \n \ttest_pci_run = 1;\n \n-\trte_eal_pci_unregister(&my_driver);\n-\trte_eal_pci_unregister(&my_driver2);\n+\t/* Clear the test drivers added to Test Bus */\n+\trte_eal_bus_remove_driver(&(my_driver.driver));\n+\trte_eal_bus_remove_driver(&(my_driver2.driver));\n \n \treturn 0;\n }\ndiff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c\nindex 2c223de..f801076 100644\n--- a/lib/librte_eal/bsdapp/eal/eal.c\n+++ b/lib/librte_eal/bsdapp/eal/eal.c\n@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)\n \tif (rte_eal_timer_init() < 0)\n \t\trte_panic(\"Cannot init HPET or TSC timers\\n\");\n \n-\tif (rte_eal_pci_init() < 0)\n-\t\trte_panic(\"Cannot init PCI\\n\");\n-\n \teal_check_mem_on_local_socket();\n \n \tif (eal_plugins_init() < 0)\n@@ -613,10 +610,7 @@ rte_eal_init(int argc, char **argv)\n \trte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);\n \trte_eal_mp_wait_lcore();\n \n-\t/* Probe & Initialize PCI devices */\n-\tif (rte_eal_pci_probe())\n-\t\trte_panic(\"Cannot probe PCI\\n\");\n-\n+\t/* Probe all the buses and devices/drivers on them */\n \tif (rte_eal_bus_probe())\n \t\trte_panic(\"Cannot probe devices\\n\");\n \ndiff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c\nindex 56b506e..2190d0d 100644\n--- a/lib/librte_eal/bsdapp/eal/eal_pci.c\n+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c\n@@ -58,6 +58,7 @@\n \n #include <rte_interrupts.h>\n #include <rte_log.h>\n+#include <rte_bus.h>\n #include <rte_pci.h>\n #include <rte_common.h>\n #include <rte_launch.h>\n@@ -240,7 +241,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n }\n \n static int\n-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)\n+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)\n {\n \tstruct rte_pci_device *dev;\n \tstruct pci_bar_io bar;\n@@ -313,19 +314,23 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)\n \t}\n \n \t/* device is valid, add in list (sorted) */\n-\tif (TAILQ_EMPTY(&pci_device_list)) {\n-\t\tTAILQ_INSERT_TAIL(&pci_device_list, dev, next);\n+\tif (TAILQ_EMPTY(&bus->device_list)) {\n+\t\trte_eal_bus_add_device(bus, &dev->device);\n \t}\n \telse {\n \t\tstruct rte_pci_device *dev2 = NULL;\n+\t\tstruct rte_device *r_dev2;\n \t\tint ret;\n \n-\t\tTAILQ_FOREACH(dev2, &pci_device_list, next) {\n+\t\tTAILQ_FOREACH(r_dev2, &bus->device_list, next) {\n+\t\t\tdev2 = container_of(r_dev2, struct rte_pci_device,\n+\t\t\t\t\t    device);\n \t\t\tret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);\n \t\t\tif (ret > 0)\n \t\t\t\tcontinue;\n \t\t\telse if (ret < 0) {\n-\t\t\t\tTAILQ_INSERT_BEFORE(dev2, dev, next);\n+\t\t\t\trte_eal_bus_insert_device(bus, &dev2->device,\n+\t\t\t\t\t\t\t  &dev->device);\n \t\t\t\treturn 0;\n \t\t\t} else { /* already registered */\n \t\t\t\tdev2->kdrv = dev->kdrv;\n@@ -337,7 +342,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)\n \t\t\t\treturn 0;\n \t\t\t}\n \t\t}\n-\t\tTAILQ_INSERT_TAIL(&pci_device_list, dev, next);\n+\t\trte_eal_bus_add_device(bus, &dev->device);\n \t}\n \n \treturn 0;\n@@ -352,7 +357,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)\n  * list. Call pci_scan_one() for each pci entry found.\n  */\n int\n-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)\n+rte_eal_pci_scan(struct rte_bus *bus)\n {\n \tint fd;\n \tunsigned dev_count = 0;\n@@ -365,6 +370,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)\n \t\t\t.matches = &matches[0],\n \t};\n \n+\t/* for debug purposes, PCI can be disabled */\n+\tif (internal_config.no_pci)\n+\t\treturn 0;\n+\n \tfd = open(\"/dev/pci\", O_RDONLY);\n \tif (fd < 0) {\n \t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n@@ -380,7 +389,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)\n \t\t}\n \n \t\tfor (i = 0; i < conf_io.num_matches; i++)\n-\t\t\tif (pci_scan_one(fd, &matches[i]) < 0)\n+\t\t\tif (pci_scan_one(bus, fd, &matches[i]) < 0)\n \t\t\t\tgoto error;\n \n \t\tdev_count += conf_io.num_matches;\n@@ -398,9 +407,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)\n }\n \n int\n-pci_update_device(const struct rte_pci_addr *addr)\n+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)\n {\n-\tint fd;\n+\tint fd = -1;\n \tstruct pci_conf matches[2];\n \tstruct pci_match_conf match = {\n \t\t.pc_sel = {\n@@ -418,6 +427,9 @@ pci_update_device(const struct rte_pci_addr *addr)\n \t\t.matches = &matches[0],\n \t};\n \n+\tif (!bus)\n+\t\tgoto error;\n+\n \tfd = open(\"/dev/pci\", O_RDONLY);\n \tif (fd < 0) {\n \t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n@@ -433,7 +445,7 @@ pci_update_device(const struct rte_pci_addr *addr)\n \tif (conf_io.num_matches != 1)\n \t\tgoto error;\n \n-\tif (pci_scan_one(fd, &matches[0]) < 0)\n+\tif (pci_scan_one(bus, fd, &matches[0]) < 0)\n \t\tgoto error;\n \n \tclose(fd);\n@@ -659,17 +671,9 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)\n \treturn ret;\n }\n \n-/* Init the PCI EAL subsystem */\n-int\n-rte_eal_pci_init(void)\n-{\n-\t/* for debug purposes, PCI can be disabled */\n-\tif (internal_config.no_pci)\n-\t\treturn 0;\n+struct rte_bus pci_bus = {\n+\t.scan = rte_eal_pci_scan,\n+\t.match = rte_eal_pci_match,\n+};\n \n-\tif (rte_eal_pci_scan(NULL) < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): Cannot scan PCI bus\\n\", __func__);\n-\t\treturn -1;\n-\t}\n-\treturn 0;\n-}\n+RTE_REGISTER_BUS(pci, pci_bus);\ndiff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map\nindex 51115f4..4874902 100644\n--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map\n+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map\n@@ -6,8 +6,6 @@ DPDK_2.0 {\n \teal_parse_sysfs_value;\n \teal_timer_source;\n \tlcore_config;\n-\tpci_device_list;\n-\tpci_driver_list;\n \tper_lcore__lcore_id;\n \tper_lcore__rte_errno;\n \trte_calloc;\n@@ -41,7 +39,6 @@ DPDK_2.0 {\n \trte_eal_mp_wait_lcore;\n \trte_eal_parse_devargs_str;\n \trte_eal_pci_dump;\n-\trte_eal_pci_probe;\n \trte_eal_pci_probe_one;\n \trte_eal_pci_register;\n \trte_eal_pci_scan;\n@@ -188,5 +185,9 @@ DPDK_17.02 {\n \trte_eal_bus_remove_device;\n \trte_eal_bus_remove_driver;\n \trte_eal_bus_unregister;\n+\trte_eal_pci_match;\n+\trte_eal_pci_probe;\n+\trte_eal_pci_remove;\n+\trte_eal_pci_scan;\n \n } DPDK_16.11;\ndiff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c\nindex b7be6aa..ce19b9a 100644\n--- a/lib/librte_eal/common/eal_common_pci.c\n+++ b/lib/librte_eal/common/eal_common_pci.c\n@@ -71,6 +71,7 @@\n \n #include <rte_interrupts.h>\n #include <rte_log.h>\n+#include <rte_bus.h>\n #include <rte_pci.h>\n #include <rte_per_lcore.h>\n #include <rte_memory.h>\n@@ -82,11 +83,6 @@\n \n #include \"eal_private.h\"\n \n-struct pci_driver_list pci_driver_list =\n-\tTAILQ_HEAD_INITIALIZER(pci_driver_list);\n-struct pci_device_list pci_device_list =\n-\tTAILQ_HEAD_INITIALIZER(pci_device_list);\n-\n #define SYSFS_PCI_DEVICES \"/sys/bus/pci/devices\"\n \n const char *pci_get_sysfs_path(void)\n@@ -206,39 +202,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,\n \t\t\t     struct rte_pci_device *dev)\n {\n \tint ret;\n-\tstruct rte_driver *driver;\n-\tstruct rte_device *device;\n-\tstruct rte_pci_addr *loc;\n \n \tif ((dr == NULL) || (dev == NULL))\n \t\treturn -EINVAL;\n \n-\tdriver = &dr->driver;\n-\tdevice = &dev->device;\n-\tloc = &dev->addr;\n-\n-\tRTE_LOG(INFO, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n-\t\t\tloc->domain, loc->bus, loc->devid, loc->function,\n-\t\t\tdev->device.numa_node);\n-\n-\t/* no initialization when blacklisted, return without error */\n-\tif (dev->device.devargs != NULL &&\n-\t\tdev->device.devargs->type ==\n-\t\t\tRTE_DEVTYPE_BLACKLISTED_PCI) {\n-\t\tRTE_LOG(INFO, EAL, \"  Device is blacklisted, not\"\n-\t\t\t\" initializing\\n\");\n-\t\treturn 1;\n-\t}\n-\n-\t/* The device is not blacklisted; Check if driver supports it */\n-\tret = rte_eal_pci_match(driver, device);\n-\tif (ret) {\n-\t\t/* Match of device and driver failed */\n-\t\tRTE_LOG(DEBUG, EAL, \"Driver (%s) doesn't match the device\\n\",\n-\t\t\tdriver->name);\n-\t\treturn 1;\n-\t}\n-\n \tRTE_LOG(INFO, EAL, \"  probe driver: %x:%x %s\\n\", dev->id.vendor_id,\n \t\t\tdev->id.device_id, dr->driver.name);\n \n@@ -271,23 +238,11 @@ static int\n rte_eal_pci_detach_dev(struct rte_pci_driver *dr,\n \t\tstruct rte_pci_device *dev)\n {\n-\tint ret;\n-\tstruct rte_driver *driver = NULL;\n-\tstruct rte_device *device;\n \tstruct rte_pci_addr *loc;\n \n \tif ((dr == NULL) || (dev == NULL))\n \t\treturn -EINVAL;\n \n-\tdriver = &(dr->driver);\n-\tdevice = &(dev->device);\n-\n-\tret = rte_eal_pci_match(driver, device);\n-\tif (ret) {\n-\t\t/* Device and driver don't match */\n-\t\treturn 1;\n-\t}\n-\n \tloc = &dev->addr;\n \n \tRTE_LOG(DEBUG, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n@@ -316,9 +271,9 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,\n  * failed, return 1 if no driver is found for this device.\n  */\n static int\n-pci_probe_all_drivers(struct rte_pci_device *dev)\n+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)\n {\n-\tstruct rte_pci_driver *dr = NULL;\n+\tstruct rte_driver *r_dr = NULL;\n \tint rc = 0;\n \n \tif (dev == NULL)\n@@ -328,8 +283,8 @@ pci_probe_all_drivers(struct rte_pci_device *dev)\n \tif (dev->driver != NULL)\n \t\treturn 0;\n \n-\tTAILQ_FOREACH(dr, &pci_driver_list, next) {\n-\t\trc = rte_eal_pci_probe_one_driver(dr, dev);\n+\tTAILQ_FOREACH(r_dr, &bus->driver_list, next) {\n+\t\trc = rte_eal_pci_probe(r_dr, &dev->device);\n \t\tif (rc < 0)\n \t\t\t/* negative value is an error */\n \t\t\treturn -1;\n@@ -347,15 +302,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev)\n  * failed, return 1 if no driver is found for this device.\n  */\n static int\n-pci_detach_all_drivers(struct rte_pci_device *dev)\n+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)\n {\n \tstruct rte_pci_driver *dr = NULL;\n+\tstruct rte_driver *r_dr = NULL;\n \tint rc = 0;\n \n \tif (dev == NULL)\n \t\treturn -1;\n \n-\tTAILQ_FOREACH(dr, &pci_driver_list, next) {\n+\tTAILQ_FOREACH(r_dr, &bus->driver_list, next) {\n+\t\tdr = container_of(r_dr, struct rte_pci_driver, driver);\n \t\trc = rte_eal_pci_detach_dev(dr, dev);\n \t\tif (rc < 0)\n \t\t\t/* negative value is an error */\n@@ -376,22 +333,31 @@ int\n rte_eal_pci_probe_one(const struct rte_pci_addr *addr)\n {\n \tstruct rte_pci_device *dev = NULL;\n+\tstruct rte_device *r_dev = NULL;\n+\tstruct rte_bus *bus;\n \tint ret = 0;\n \n \tif (addr == NULL)\n \t\treturn -1;\n \n+\tbus = rte_eal_bus_get(\"pci\");\n+\tif (!bus) {\n+\t\tRTE_LOG(ERR, EAL, \"PCI Bus not registered\\n\");\n+\t\treturn -1;\n+\t}\n+\n \t/* update current pci device in global list, kernel bindings might have\n \t * changed since last time we looked at it.\n \t */\n-\tif (pci_update_device(addr) < 0)\n+\tif (pci_update_device(bus, addr) < 0)\n \t\tgoto err_return;\n \n-\tTAILQ_FOREACH(dev, &pci_device_list, next) {\n+\tTAILQ_FOREACH(r_dev, &bus->device_list, next) {\n+\t\tdev = container_of(r_dev, struct rte_pci_device, device);\n \t\tif (rte_eal_compare_pci_addr(&dev->addr, addr))\n \t\t\tcontinue;\n \n-\t\tret = pci_probe_all_drivers(dev);\n+\t\tret = pci_probe_all_drivers(bus, dev);\n \t\tif (ret)\n \t\t\tgoto err_return;\n \t\treturn 0;\n@@ -412,20 +378,29 @@ int\n rte_eal_pci_detach(const struct rte_pci_addr *addr)\n {\n \tstruct rte_pci_device *dev = NULL;\n+\tstruct rte_device *r_dev = NULL;\n+\tstruct rte_bus *bus;\n \tint ret = 0;\n \n \tif (addr == NULL)\n \t\treturn -1;\n \n-\tTAILQ_FOREACH(dev, &pci_device_list, next) {\n+\tbus = rte_eal_bus_get(\"pci\");\n+\tif (!bus) {\n+\t\tRTE_LOG(ERR, EAL, \"PCI Bus is not registered\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tTAILQ_FOREACH(r_dev, &bus->device_list, next) {\n+\t\tdev = container_of(r_dev, struct rte_pci_device, device);\n \t\tif (rte_eal_compare_pci_addr(&dev->addr, addr))\n \t\t\tcontinue;\n \n-\t\tret = pci_detach_all_drivers(dev);\n+\t\tret = pci_detach_all_drivers(bus, dev);\n \t\tif (ret < 0)\n \t\t\tgoto err_return;\n \n-\t\tTAILQ_REMOVE(&pci_device_list, dev, next);\n+\t\trte_eal_bus_remove_device(r_dev);\n \t\tfree(dev);\n \t\treturn 0;\n \t}\n@@ -438,41 +413,73 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)\n \treturn -1;\n }\n \n-/*\n- * Scan the content of the PCI bus, and call the probe() function for\n- * all registered drivers that have a matching entry in its id_table\n- * for discovered devices.\n- */\n int\n-rte_eal_pci_probe(void)\n+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device)\n {\n-\tstruct rte_pci_device *dev = NULL;\n-\tstruct rte_devargs *devargs;\n-\tint probe_all = 0;\n \tint ret = 0;\n+\tstruct rte_devargs *devargs;\n+\tstruct rte_pci_device *pci_dev;\n+\tstruct rte_pci_driver *pci_drv;\n+\tstruct rte_pci_addr *loc;\n \n-\tif (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)\n-\t\tprobe_all = 1;\n+\tif (!driver || !device)\n+\t\treturn -1;\n \n-\tTAILQ_FOREACH(dev, &pci_device_list, next) {\n+\tpci_dev = container_of(device, struct rte_pci_device, device);\n+\tpci_drv = container_of(driver, struct rte_pci_driver, driver);\n \n-\t\t/* set devargs in PCI structure */\n-\t\tdevargs = pci_devargs_lookup(dev);\n-\t\tif (devargs != NULL)\n-\t\t\tdev->device.devargs = devargs;\n+\tloc = &pci_dev->addr;\n \n-\t\t/* probe all or only whitelisted devices */\n-\t\tif (probe_all)\n-\t\t\tret = pci_probe_all_drivers(dev);\n-\t\telse if (devargs != NULL &&\n-\t\t\tdevargs->type == RTE_DEVTYPE_WHITELISTED_PCI)\n-\t\t\tret = pci_probe_all_drivers(dev);\n-\t\tif (ret < 0)\n-\t\t\trte_exit(EXIT_FAILURE, \"Requested device \" PCI_PRI_FMT\n-\t\t\t\t \" cannot be used\\n\", dev->addr.domain, dev->addr.bus,\n-\t\t\t\t dev->addr.devid, dev->addr.function);\n+\tRTE_LOG(INFO, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n+\t\t\tloc->domain, loc->bus, loc->devid, loc->function,\n+\t\t\tpci_dev->device.numa_node);\n+\n+\t/* Fetch the devargs associated with the device */\n+\tdevargs = pci_devargs_lookup(pci_dev);\n+\tif (devargs != NULL)\n+\t\tpci_dev->device.devargs = devargs;\n+\n+\t/* no initialization when blacklisted, return without error */\n+\tif (pci_dev->device.devargs != NULL &&\n+\t    pci_dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {\n+\t\tRTE_LOG(INFO, EAL, \"  Device is blacklisted, not\"\n+\t\t\t\" initializing\\n\");\n+\t\treturn 1;\n \t}\n \n+\tret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Requested device \" PCI_PRI_FMT\n+\t\t\t\" cannot be used\\n\", pci_dev->addr.domain,\n+\t\t\tpci_dev->addr.bus, pci_dev->addr.devid,\n+\t\t\tpci_dev->addr.function);\n+\t\treturn ret;\n+\t}\n+\treturn 0;\n+}\n+\n+int\n+rte_eal_pci_remove(struct rte_device *device)\n+{\n+\tint ret = 0;\n+\tstruct rte_pci_device *pci_dev;\n+\n+\tif (!device)\n+\t\treturn -1;\n+\n+\tpci_dev = container_of(device, struct rte_pci_device, device);\n+\n+\tif (!pci_dev->driver)\n+\t\treturn -1;\n+\n+\tret = rte_eal_pci_detach_dev(pci_dev->driver, pci_dev);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Requested device \" PCI_PRI_FMT\n+\t\t\t\" cannot be used\\n\", pci_dev->addr.domain,\n+\t\t\tpci_dev->addr.bus, pci_dev->addr.devid,\n+\t\t\tpci_dev->addr.function);\n+\t\treturn ret;\n+\t}\n \treturn 0;\n }\n \n@@ -501,8 +508,17 @@ void\n rte_eal_pci_dump(FILE *f)\n {\n \tstruct rte_pci_device *dev = NULL;\n+\tstruct rte_device *r_dev = NULL;\n+\tstruct rte_bus *bus;\n \n-\tTAILQ_FOREACH(dev, &pci_device_list, next) {\n+\tbus = rte_eal_bus_get(\"pci\");\n+\tif (!bus) {\n+\t\tRTE_LOG(ERR, EAL, \"PCI Bus not registered\\n\");\n+\t\treturn;\n+\t}\n+\n+\tTAILQ_FOREACH(r_dev, &bus->device_list, next) {\n+\t\tdev = container_of(r_dev, struct rte_pci_device, device);\n \t\tpci_dump_one_device(f, dev);\n \t}\n }\n@@ -511,14 +527,32 @@ rte_eal_pci_dump(FILE *f)\n void\n rte_eal_pci_register(struct rte_pci_driver *driver)\n {\n-\tTAILQ_INSERT_TAIL(&pci_driver_list, driver, next);\n-\trte_eal_driver_register(&driver->driver);\n+\tstruct rte_bus *bus;\n+\n+\tRTE_VERIFY(driver);\n+\n+\tbus = rte_eal_bus_get(\"pci\");\n+\tif (!bus) {\n+\t\tRTE_LOG(ERR, EAL, \"PCI Bus not registered\\n\");\n+\t\treturn;\n+\t}\n+\n+\trte_eal_bus_add_driver(bus, &driver->driver);\n }\n \n /* unregister a driver */\n void\n rte_eal_pci_unregister(struct rte_pci_driver *driver)\n {\n-\trte_eal_driver_unregister(&driver->driver);\n-\tTAILQ_REMOVE(&pci_driver_list, driver, next);\n+\tstruct rte_bus *bus;\n+\n+\tRTE_VERIFY(driver);\n+\n+\tbus = driver->driver.bus;\n+\tif (!bus) {\n+\t\tRTE_LOG(ERR, EAL, \"PCI Bus not registered\\n\");\n+\t\treturn;\n+\t}\n+\n+\trte_eal_bus_remove_driver(&driver->driver);\n }\ndiff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h\nindex 9e7d8f6..06ec172 100644\n--- a/lib/librte_eal/common/eal_private.h\n+++ b/lib/librte_eal/common/eal_private.h\n@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);\n  */\n int rte_eal_log_init(const char *id, int facility);\n \n-/**\n- * Init the PCI infrastructure\n- *\n- * This function is private to EAL.\n- *\n- * @return\n- *   0 on success, negative on error\n- */\n-int rte_eal_pci_init(void);\n-\n struct rte_pci_driver;\n struct rte_pci_device;\n \n@@ -126,13 +116,15 @@ struct rte_pci_device;\n  *\n  * This function is private to EAL.\n  *\n+ * @param bus\n+ *\tThe PCI bus on which device is connected\n  * @param addr\n  *\tThe PCI Bus-Device-Function address to look for\n  * @return\n  *   - 0 on success.\n  *   - negative on error.\n  */\n-int pci_update_device(const struct rte_pci_addr *addr);\n+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);\n \n /**\n  * Unbind kernel driver for this device\ndiff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h\nindex e5e58dd..1647672 100644\n--- a/lib/librte_eal/common/include/rte_pci.h\n+++ b/lib/librte_eal/common/include/rte_pci.h\n@@ -86,12 +86,6 @@ extern \"C\" {\n #include <rte_interrupts.h>\n #include <rte_dev.h>\n \n-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */\n-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */\n-\n-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */\n-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */\n-\n /** Pathname of PCI devices directory. */\n const char *pci_get_sysfs_path(void);\n \n@@ -376,6 +370,40 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,\n int rte_eal_pci_scan(struct rte_bus *bus);\n \n /**\n+ * Probe callback for the PCI bus\n+ *\n+ * For each matched pair of PCI device and driver on PCI bus, perform devargs\n+ * check, and call a series of callbacks to allocate ethdev/cryptodev instances\n+ * and intializing them.\n+ *\n+ * @param driver\n+ *\tGeneric driver object matched with the device\n+ * @param device\n+ *\tGeneric device object to initialize\n+ * @return\n+ *   - 0 on success.\n+ *   - !0 on error.\n+ */\n+int\n+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device);\n+\n+/**\n+ * Remove callback for the PCI bus\n+ *\n+ * Called when a device needs to be removed from a bus; wraps around the\n+ * PCI specific implementation layered over rte_pci_driver->remove. Default\n+ * handler used by PCI PMDs\n+ *\n+ * @param device\n+ *\trte_device object referring to device to be removed\n+ * @return\n+ *\t- 0 for successful removal\n+ *\t- !0 for failure in removal of device\n+ */\n+int\n+rte_eal_pci_remove(struct rte_device *device);\n+\n+/**\n  * Match the PCI Driver and Device using the ID Table\n  *\n  * @param drv\n@@ -390,19 +418,6 @@ int\n rte_eal_pci_match(struct rte_driver *drv, struct rte_device *dev);\n \n /**\n- * Probe the PCI bus for registered drivers.\n- *\n- * Scan the content of the PCI bus, and call the probe() function for\n- * all registered drivers that have a matching entry in its id_table\n- * for discovered devices.\n- *\n- * @return\n- *   - 0 on success.\n- *   - Negative on error.\n- */\n-int rte_eal_pci_probe(void);\n-\n-/**\n  * Map the PCI device resources in user space virtual memory address\n  *\n  * Note that driver should not call this function when flag\ndiff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c\nindex 1a17891..2a20e90 100644\n--- a/lib/librte_eal/linuxapp/eal/eal.c\n+++ b/lib/librte_eal/linuxapp/eal/eal.c\n@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)\n \tif (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)\n \t\trte_panic(\"Cannot init logs\\n\");\n \n-\tif (rte_eal_pci_init() < 0)\n-\t\trte_panic(\"Cannot init PCI\\n\");\n-\n #ifdef VFIO_PRESENT\n \tif (rte_eal_vfio_setup() < 0)\n \t\trte_panic(\"Cannot init VFIO\\n\");\n@@ -884,10 +881,7 @@ rte_eal_init(int argc, char **argv)\n \trte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);\n \trte_eal_mp_wait_lcore();\n \n-\t/* Probe & Initialize PCI devices */\n-\tif (rte_eal_pci_probe())\n-\t\trte_panic(\"Cannot probe PCI\\n\");\n-\n+\t/* Probe all the buses and devices/drivers on them */\n \tif (rte_eal_bus_probe())\n \t\trte_panic(\"Cannot probe devices\\n\");\n \ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c\nindex 4a0207d..314effa 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c\n@@ -35,6 +35,7 @@\n #include <dirent.h>\n \n #include <rte_log.h>\n+#include <rte_bus.h>\n #include <rte_pci.h>\n #include <rte_eal_memconfig.h>\n #include <rte_malloc.h>\n@@ -228,7 +229,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)\n \n /* Scan one pci sysfs entry, and fill the devices list from it. */\n static int\n-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)\n+pci_scan_one(struct rte_bus *bus, const char *dirname,\n+\t     const struct rte_pci_addr *addr)\n {\n \tchar filename[PATH_MAX];\n \tunsigned long tmp;\n@@ -346,21 +348,23 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)\n \t\tdev->kdrv = RTE_KDRV_NONE;\n \n \t/* device is valid, add in list (sorted) */\n-\tif (TAILQ_EMPTY(&pci_device_list)) {\n-\t\trte_eal_device_insert(&dev->device);\n-\t\tTAILQ_INSERT_TAIL(&pci_device_list, dev, next);\n+\tif (TAILQ_EMPTY(&bus->device_list)) {\n+\t\trte_eal_bus_add_device(bus, &dev->device);\n \t} else {\n \t\tstruct rte_pci_device *dev2;\n+\t\tstruct rte_device *r_dev2;\n \t\tint ret;\n \n-\t\tTAILQ_FOREACH(dev2, &pci_device_list, next) {\n+\t\tTAILQ_FOREACH(r_dev2, &bus->device_list, next) {\n+\t\t\tdev2 = container_of(r_dev2, struct rte_pci_device,\n+\t\t\t\t\t    device);\n \t\t\tret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);\n \t\t\tif (ret > 0)\n \t\t\t\tcontinue;\n \n \t\t\tif (ret < 0) {\n-\t\t\t\tTAILQ_INSERT_BEFORE(dev2, dev, next);\n-\t\t\t\trte_eal_device_insert(&dev->device);\n+\t\t\t\trte_eal_bus_insert_device(bus, &dev2->device,\n+\t\t\t\t\t\t\t  &dev->device);\n \t\t\t} else { /* already registered */\n \t\t\t\tdev2->kdrv = dev->kdrv;\n \t\t\t\tdev2->max_vfs = dev->max_vfs;\n@@ -370,15 +374,14 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)\n \t\t\t}\n \t\t\treturn 0;\n \t\t}\n-\t\trte_eal_device_insert(&dev->device);\n-\t\tTAILQ_INSERT_TAIL(&pci_device_list, dev, next);\n+\t\trte_eal_bus_add_device(bus, &dev->device);\n \t}\n \n \treturn 0;\n }\n \n int\n-pci_update_device(const struct rte_pci_addr *addr)\n+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)\n {\n \tchar filename[PATH_MAX];\n \n@@ -386,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)\n \t\t pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,\n \t\t addr->function);\n \n-\treturn pci_scan_one(filename, addr);\n+\treturn pci_scan_one(bus, filename, addr);\n }\n \n /*\n@@ -440,13 +443,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)\n  * list\n  */\n int\n-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)\n+rte_eal_pci_scan(struct rte_bus *bus_p)\n {\n \tstruct dirent *e;\n \tDIR *dir;\n \tchar dirname[PATH_MAX];\n \tstruct rte_pci_addr addr;\n \n+\tif (!bus_p) {\n+\t\tRTE_LOG(ERR, EAL, \"PCI Bus is not registered\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* for debug purposes, PCI can be disabled */\n+\tif (internal_config.no_pci)\n+\t\treturn 0;\n+\n \tdir = opendir(pci_get_sysfs_path());\n \tif (dir == NULL) {\n \t\tRTE_LOG(ERR, EAL, \"%s(): opendir failed: %s\\n\",\n@@ -465,7 +477,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)\n \n \t\tsnprintf(dirname, sizeof(dirname), \"%s/%s\",\n \t\t\t\tpci_get_sysfs_path(), e->d_name);\n-\t\tif (pci_scan_one(dirname, &addr) < 0)\n+\t\tif (pci_scan_one(bus_p, dirname, &addr) < 0)\n \t\t\tgoto error;\n \t}\n \tclosedir(dir);\n@@ -711,18 +723,9 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)\n \treturn ret;\n }\n \n-/* Init the PCI EAL subsystem */\n-int\n-rte_eal_pci_init(void)\n-{\n-\t/* for debug purposes, PCI can be disabled */\n-\tif (internal_config.no_pci)\n-\t\treturn 0;\n-\n-\tif (rte_eal_pci_scan(NULL) < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): Cannot scan PCI bus\\n\", __func__);\n-\t\treturn -1;\n-\t}\n+struct rte_bus pci_bus = {\n+\t.scan = rte_eal_pci_scan,\n+\t.match = rte_eal_pci_match,\n+};\n \n-\treturn 0;\n-}\n+RTE_REGISTER_BUS(pci, pci_bus);\ndiff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map\nindex abfe93e..239f2fc 100644\n--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map\n+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map\n@@ -6,8 +6,6 @@ DPDK_2.0 {\n \teal_parse_sysfs_value;\n \teal_timer_source;\n \tlcore_config;\n-\tpci_device_list;\n-\tpci_driver_list;\n \tper_lcore__lcore_id;\n \tper_lcore__rte_errno;\n \trte_calloc;\n@@ -41,7 +39,6 @@ DPDK_2.0 {\n \trte_eal_mp_wait_lcore;\n \trte_eal_parse_devargs_str;\n \trte_eal_pci_dump;\n-\trte_eal_pci_probe;\n \trte_eal_pci_probe_one;\n \trte_eal_pci_register;\n \trte_eal_pci_scan;\n@@ -192,5 +189,9 @@ DPDK_17.02 {\n \trte_eal_bus_remove_device;\n \trte_eal_bus_remove_driver;\n \trte_eal_bus_unregister;\n+\trte_eal_pci_match;\n+\trte_eal_pci_probe;\n+\trte_eal_pci_remove;\n+\trte_eal_pci_scan;\n \n } DPDK_16.11;\n",
    "prefixes": [
        "dpdk-dev",
        "v4",
        "10/12"
    ]
}