From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <shreyansh.jain@nxp.com>
Received: from NAM03-DM3-obe.outbound.protection.outlook.com
 (mail-dm3nam03on0040.outbound.protection.outlook.com [104.47.41.40])
 by dpdk.org (Postfix) with ESMTP id 94D886910
 for <dev@dpdk.org>; Fri,  9 Sep 2016 10:44:57 +0200 (CEST)
Received: from BN6PR03CA0042.namprd03.prod.outlook.com (10.175.124.28) by
 BN6PR03MB2436.namprd03.prod.outlook.com (10.168.223.14) with Microsoft SMTP
 Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id
 15.1.609.9; Fri, 9 Sep 2016 08:44:56 +0000
Received: from BY2FFO11FD006.protection.gbl (2a01:111:f400:7c0c::190) by
 BN6PR03CA0042.outlook.office365.com (2603:10b6:404:10c::28) with Microsoft
 SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384)
 id 15.1.599.9 via Frontend Transport; Fri, 9 Sep 2016 08:44:56 +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
 BY2FFO11FD006.mail.protection.outlook.com (10.1.14.127) with Microsoft SMTP
 Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.587.6
 via Frontend Transport; Fri, 9 Sep 2016 08:44:55 +0000
Received: from Tophie.ap.freescale.net ([10.232.14.87])
 by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id u898hoZ0018305;
 Fri, 9 Sep 2016 01:44:53 -0700
From: Shreyansh Jain <shreyansh.jain@nxp.com>
To: <dev@dpdk.org>
CC: <viktorin@rehivetech.com>, <hemant.agrawal@nxp.com>, Shreyansh Jain
 <shreyansh.jain@nxp.com>
Date: Fri, 9 Sep 2016 14:13:50 +0530
Message-ID: <1473410639-10367-7-git-send-email-shreyansh.jain@nxp.com>
X-Mailer: git-send-email 2.7.4
In-Reply-To: <1473410639-10367-1-git-send-email-shreyansh.jain@nxp.com>
References: <1451682326-5834-1-git-send-email-viktorin@rehivetech.com>
 <1473410639-10367-1-git-send-email-shreyansh.jain@nxp.com>
X-EOPAttributedMessage: 0
X-Matching-Connectors: 131178842957484202;
 (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)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(36756003)(47776003)(106466001)(105606002)(19580405001)(8666005)(356003)(110136002)(7846002)(97736004)(8936002)(81156014)(229853001)(48376002)(76176999)(50226002)(19580395003)(2351001)(86362001)(8676002)(5660300001)(50986999)(33646002)(81166006)(77096005)(85426001)(189998001)(92566002)(586003)(104016004)(11100500001)(87936001)(68736007)(305945005)(2950100001)(2906002)(5003940100001)(4326007)(50466002)(626004)(7059030);
 DIR:OUT; SFP:1101; SCL:1; SRVR:BN6PR03MB2436; H:tx30smr01.am.freescale.net;
 FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; 
X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD006;
 1:j4qUVR7amMa/FYjuYjnZvPQGjSC0f3CMW+AL82f+AFFYgddZUaCsDgs2Aow/IJxkZplysuBz4vM0ujQn7AnF1t5+RfnveUKjDHbAhK1/bBHztLKP6o7Jkp2/9sJB3kEDIEQA+2YOUYH3d+rysAOuGmG93M/Gjm8BP9GQhVGGixOVwqxd3RALyOBirj5bV39M2kHQfG83HevS08Npv9n8WdGIo1LORJ/wtZaR8mcGN/VepX/U5wH69W3khjz+CckgYu4xTSeQlVRmERxljMbWfKKuE9mJHUY0D5D9Gn6VxJ6rWI1MrW7EAtLUfDQEsCd93BnZSDPbxQ19DS7EYtnoXDCQHMo/PP0yz93jbRCzt1eveyPGIyZPn1v2wNzBwuLY/3+2KABdFKlwQSg3+3TMfcYP+9CmGoAgSI8iC7WGAaq//IoKBdZ1AJL0HkeJzPI0MaWgV+S1gSQ/Mr4N/t5cnzUErtrnpiVIhzQ04A2gdlPa2zTRt7pt1Uc99peFu2SxF2h0RN7e5vW5/LsDeLUxlrEjLM5sFHM0FbtgvDjTkOXfcu49rZwvGF8YfEqLsdIp8jpkkkWMKaWDM+1VR/jdNhN7bAUKpEgYvtcmlICOErzXjcPXqQDZRDqrWD44Y3yIYADQLGPmIG8KGmrytziKChQ/9pw7zxmESfHxRKJRbClUausIfgN+uk6TgUfkeiSV3nkv0zefgnZ2fX+O9aqwEmWu+NIjuI6OhSe2fnPCWhs=
MIME-Version: 1.0
Content-Type: text/plain
X-MS-Office365-Filtering-Correlation-Id: fe6fb5f8-8d52-4b91-af49-08d3d88d92fb
X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2436;
 2:mshUdcB7tmzGUdbrMPZPUOoS8IKxTwke5NlTOQ9+W6lNxJ/DLQcWMcBj47qFGR47rJZOkjPW/msbEis+50jErtZbojnDS5/gDvuisgJQ6D2SU5hJHQsLfwA3jgvJwfcjpOKhdpemOFHBM/RV4BjUHmvzfbus/JMEMVsAaXhqcucb5QBy3fu6v2I1/BVMmjUl;
 3:XFm/raIlhVvQykZKOPZzaflHQqIva6pxiuSQoFLXiX4ESLblrtbZ7hSTdyzcbOMrKbrhHYF6anwpxyNmKKdOlaW2h2fvqLU18uNcwwwSEMREGgDJltcUvaTf/NwOLO+uIgpbFxgR58/YoBATgXLhSlDwxqz88cI1tbSdouoG8x5OO9+fvl/jZsQ2vnZ07JovTx9L9IJLyB1mxORpJNcmucKcZ1t0v43Jhg5m4DdCtUw=;
 25:xIinjLgXkCMPuBUW/6lONl0mU4SbFPDrwmuR+X4WMtYcm4WwjsVo5Q5JxxG8mN2IhBi3ZaI8kwORr4psMfQh/VHGzUS4uhieMmzAqAaMy/THruwOIGh4tIk4vpc+rdOAuym4CRblS9edCyFoSYjyTYCU/DhNDSGjG1xA/P7FCHBk4hISJcMW6gex8U1ewzDsS2wPCVClHD4ili9ePsXpm2nA8w3+wscwABlQfIyuihlFGZ625egfF5mm2qZFQO75DsTfeyv5DFO9YJMDeOrXN0lJ5ZO+R2fVZ5dSepLZ7eChWbjHD8ARcj8GroYs1uHGDcJpH/zwN4ox8ctWye+n7Hks7Hbb3FgKljUYwE18cbUzs4EKFWknHp+DKPkSk6NHsVEyKvvEgBiTfqGQ6gMw6g==
X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN6PR03MB2436;
X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2436;
 31:k0W65xfbcP5P6Jwl5ZpVxo774ZPFj6J4LXfU0XHNeuYtAv+0D5eAD0TG8utQBrL4d9W9wzO59VQIHAsSgYvqIOmLSVxOnCr/eDQJ8TuJ531hE9vJuXfVrKL7VBQuQU8lCL/tsWTWmHfOItNgNWREyKQOqR2fbQYndomcUucwR4GyVASq/5J+drTrBWvgGtsRvahkHocyTCMXc7UKX0sIz/S/36wtOD1P1MlD2T3NkC8=;
 4:q2JQeBVr/qMMn6D8NakcoQ244e0mb5KGrnPbQk+ajobrXw63Mo2VprHxEkZTPhtYmNAvS8g287MxCTJadc9Jy6gJdghTV/jgtwZ2wDZ47AgqzkSZVA1iKM0WjZkgH+DwU5IjdWEJH+awjF0CaNWeK9/3FID0CHvYWL7rPDz4yQPQHehpczPbAIPhMNwgNgscgXDmNJC5yy5MiKCFo2pF1Mig52FstW+W4xlS/oySWmWABsoXzpvbBJeyWJh2AOXBgWeMRJaAuyXH+XhZNB6yqsbNZmbcML/CTiudhz8CURqyGyUTlhMJcOt7lf3pLF+eKGCBRntH+PxxbxSn9BvUQOJo8Ntf1U8YkryMP8BGrPUyVPGzkVypTYUpm8LffbxGYSuw3SwsSlJWqznsCSpQfHZk6IXXbNzNzomEJcFUqfXt9ngNzM1mEHHgigytAyfE2u1/4wmM3k8otas8t2YyVKWd1N/QI56FmNLmTg+CLWRBRK9Q8HpG4O506u2MVJ+tB7fr6e1S2mZkbj7hHSQ1BRx743wDRleKsvPqS+YRhig=
X-Microsoft-Antispam-PRVS: <BN6PR03MB2436D37828F8B9DBBD4F3E3A90FA0@BN6PR03MB2436.namprd03.prod.outlook.com>
X-Exchange-Antispam-Report-Test: UriScan:(185117386973197);
X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0;
 RULEID:(6040176)(601004)(2401047)(13017025)(13024025)(13023025)(13018025)(13015025)(8121501046)(5005006)(10201501046)(3002001)(6055026);
 SRVR:BN6PR03MB2436; BCL:0; PCL:0; RULEID:(400006); SRVR:BN6PR03MB2436; 
X-Forefront-PRVS: 00603B7EEF
X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN6PR03MB2436;
 23:xLtJC2J0MxyCPiyh293IH9ypZtzaOwrBRjFkZkHaJ?=
 =?us-ascii?Q?SsDmeNIcLBsEAb/cxbjg8CUJLUwbQMUTlETXj253gfmVPOV82Cq6xjPXjWz1?=
 =?us-ascii?Q?zlN59O8bydKz8Tk8DcjXr/FHj+FUX30naX/aSzMpd3r0ijCnMaQMb8tVd0KH?=
 =?us-ascii?Q?t3JfxhwsHSVWprbcEIEFT18tcDCP1tou6pchixG43Klqvq51AIFuvIKrrhDD?=
 =?us-ascii?Q?702ECppJbKKEZMZrkZJhQ+J8knhgM9kMx5rRiu/JLJDIpcWYfN5BPcvRUoq5?=
 =?us-ascii?Q?z9z4Vmb5VoLmjAIm9jZe9NPgyxavMN0314d1c50PxHMM5Wi3DkwFii0wokHE?=
 =?us-ascii?Q?kyUJNRD2UeM3YVUcpuqXNzgdVzNkfw81UyuNN7boa2eWRv5sOQ7BrpMaDe5w?=
 =?us-ascii?Q?MRYXqn38ESAqHUVTZHehuVcEk1uo6IX3vivHEsmgDisdz3s81idaUeLZ+fZi?=
 =?us-ascii?Q?uQMu5ADZn6dYem5/dikDMFO8xCl53v6HqKuJyN1pY2XXzdccFfqJwuQstN07?=
 =?us-ascii?Q?j1kRPiPu0/jWKYFSHNHLlyHVh6FEo0SU5ccPmiz1maKm+YZY5IFRj5rRhpvI?=
 =?us-ascii?Q?KMwHfbTF7ScAWbA230DWlKqAap38Itk1SYX+hmE5721vYt0iSAGY3/TNcKVa?=
 =?us-ascii?Q?fsZs59pfobNIX+KQhMntnQgDKKHH5YFWCA3OMTeyaDnflmf0SuZ3PUuPBx7m?=
 =?us-ascii?Q?/Jstj1Do8Qy2XXuiKPzc1QuDfLDKjqAZoGHNO1Owo7qmh0sUzYQTQ3oCjzDG?=
 =?us-ascii?Q?xZmZaKY1rGqaCHOL+ILaBAeYrOUkOMXsOXGc5yrLQ7P2fOpb2qJaLXqeTp9A?=
 =?us-ascii?Q?3/V1HMX2lHuAnzPGnM94qNTfusMn77WS572THaMP/jd9Y8SU9z2WPigbvAfD?=
 =?us-ascii?Q?7eYvEjZNuFvNChVtpsbefObJKRgQIj9Hb8+5dM9eKPOnGKNsMRxx5FK452lP?=
 =?us-ascii?Q?SCrfxXf7rBtch7FgQ5EBCwdhinOs83FjRIXSeFiTfxrPdgAF0kxFgYgR1rCa?=
 =?us-ascii?Q?JrCGrPEbhn3kOZGqUGqnpe9E7/pF8G9pi+B/iqbUFOt6IEZBgQgaBt3PIjwl?=
 =?us-ascii?Q?36M66tM2E2iZWLE81TOH/2Iy4N3nZHe/FAC9VjuEXBoNNNGoVOmnWw9m5xo0?=
 =?us-ascii?Q?EXk732K5qcXSXWwKwNybnKG+MWmuC89vfqtGKZ96l6Tr4QVleJ3jUTN6OgLy?=
 =?us-ascii?Q?igISvHFjS/Lo9E=3D?=
X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2436;
 6:fpwtgpOJvkX2Bc33jPGykYE9OG0kQMYPaIQENPiDqkzFhdM0KSkwbh3ao8gN0bGn5SzCHSf3lKUhBK5FpMKE7rlOo8/ODJQqt9E8p9GFDYbgNAXXvMFcLZqjVnWoWwKmq1g9/QLfkPfztW7sP3+5AK5TmkqVqP92/sYe2MrN8m2du/yDuvFumWoOSezQ2JqXQs6FPogDwDRZipYHT+4ISMKJoPFKmjR+ch78xyJoF2Mh6zNWUUZhO2O96DvtlbMsB56YxDMu9ItvGEuQ9Zh1ukpiWZjd8gTu7dxqWf8EtpQ=;
 5:aHU9S1AAa4pWMDAlv/XR1Q5CT95HYJsCnIaxa3quFUuKtNIsXFu3osjHb3NbaiKRtJKA+kaLiXN2dpvqXqXvG2MKTnErnY7iYXtrS5VP5UF60lIV3p/6pXMIWw7tusIARnLEXEPEnDjrbSXLk51Ex6gpAKCupjvhn4LL0aOfDws=;
 24:Y07OXfqubtiv/kZ/7VKklZqYj6lP0icMerhbMdthBcq77Tah6d+0GxWNkZe9mP/F05UUndFCWv3w4Mg/4Tyrmew+LRfMxUMIIr6cg1errIA=;
 7:s4YgGUpecLOYEP44qcMh6Se8h8gomZLmWIOQDLeW5m2ybBdxg6UrAQnqc1Afv+OMD3ENyrMMfc3ClU561G4VEGHXZmNzob2csuKGqOdaFXK1G0edvXIoWPw9CxX7/5M5I7jRTDQOYCL5F0q4dBb0wqoOBAvPwUdLlWpFuY8+D7auZPiWSkwiiQcY1jHNj+XgFnb5ziFWnhhdrRiaBqtbA5otrA9TLUQoQaUbcB0NXGd0C3Tk4zPlOVtsZ3SD47MB
SpamDiagnosticOutput: 1:99
SpamDiagnosticMetadata: NSPM
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Sep 2016 08:44:55.5456 (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: BN6PR03MB2436
Subject: [dpdk-dev] [PATCH v3 06/15] eal/soc: implement probing of drivers
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: patches and discussions about DPDK <dev.dpdk.org>
List-Unsubscribe: <http://dpdk.org/ml/options/dev>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Fri, 09 Sep 2016 08:44:58 -0000

Each SoC PMD registers a set of callback for scanning its own bus/infra and
matching devices to drivers when probe is called.
This patch introduces the infra for calls to SoC scan on rte_eal_soc_init()
and match on rte_eal_soc_probe().

Patch also adds test case for scan and probe.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
 app/test/test_soc.c                             | 138 ++++++++++++++-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   4 +
 lib/librte_eal/common/eal_common_soc.c          | 215 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_soc.h         |  51 ++++++
 lib/librte_eal/linuxapp/eal/eal.c               |   5 +
 lib/librte_eal/linuxapp/eal/eal_soc.c           |  16 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   4 +
 7 files changed, 432 insertions(+), 1 deletion(-)

diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index ac03e64..d2b9462 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -87,14 +87,45 @@ static int test_compare_addr(void)
  */
 struct test_wrapper {
 	struct rte_soc_driver soc_drv;
+	struct rte_soc_device soc_dev;
 };
 
+static int empty_pmd0_devinit(struct rte_soc_driver *drv,
+			      struct rte_soc_device *dev);
+static int empty_pmd0_devuninit(struct rte_soc_device *dev);
+static void test_soc_scan_dev0_cb(void);
+static int test_soc_match_dev0_cb(struct rte_soc_driver *drv,
+				  struct rte_soc_device *dev);
+static void test_soc_scan_dev1_cb(void);
+static int test_soc_match_dev1_cb(struct rte_soc_driver *drv,
+				  struct rte_soc_device *dev);
+
+static int
+empty_pmd0_devinit(struct rte_soc_driver *drv __rte_unused,
+		   struct rte_soc_device *dev __rte_unused)
+{
+	return 0;
+}
+
+static int
+empty_pmd0_devuninit(struct rte_soc_device *dev)
+{
+	/* Release the memory associated with dev->addr.name */
+	free(dev->addr.name);
+
+	return 0;
+}
+
 struct test_wrapper empty_pmd0 = {
 	.soc_drv = {
 		.driver = {
 			.name = "empty_pmd0"
 		},
-	},
+		.devinit = empty_pmd0_devinit,
+		.devuninit = empty_pmd0_devuninit,
+		.scan_fn = test_soc_scan_dev0_cb,
+		.match_fn = test_soc_match_dev0_cb,
+	}
 };
 
 struct test_wrapper empty_pmd1 = {
@@ -102,9 +133,54 @@ struct test_wrapper empty_pmd1 = {
 		.driver = {
 			.name = "empty_pmd1"
 		},
+		.scan_fn = test_soc_scan_dev1_cb,
+		.match_fn = test_soc_match_dev1_cb,
 	},
 };
 
+static void
+test_soc_scan_dev0_cb(void)
+{
+	/* SoC's scan would scan devices on its bus and add to
+	 * soc_device_list
+	 */
+	empty_pmd0.soc_dev.addr.name = strdup("empty_pmd0_dev");
+
+	TAILQ_INSERT_TAIL(&soc_device_list, &empty_pmd0.soc_dev, next);
+}
+
+static int
+test_soc_match_dev0_cb(struct rte_soc_driver *drv __rte_unused,
+		       struct rte_soc_device *dev)
+{
+	if (!dev->addr.name || strcmp(dev->addr.name, "empty_pmd0_dev"))
+		return 0;
+
+	return 1;
+}
+
+
+static void
+test_soc_scan_dev1_cb(void)
+{
+	/* SoC's scan would scan devices on its bus and add to
+	 * soc_device_list
+	 */
+	empty_pmd0.soc_dev.addr.name = strdup("empty_pmd1_dev");
+
+	TAILQ_INSERT_TAIL(&soc_device_list, &empty_pmd1.soc_dev, next);
+}
+
+static int
+test_soc_match_dev1_cb(struct rte_soc_driver *drv __rte_unused,
+		       struct rte_soc_device *dev)
+{
+	if (!dev->addr.name || strcmp(dev->addr.name, "empty_pmd1_dev"))
+		return 0;
+
+	return 1;
+}
+
 static int
 count_registered_socdrvs(void)
 {
@@ -148,13 +224,54 @@ test_register_unregister(void)
 	return 0;
 }
 
+/* Test Probe (scan and match) functionality */
+static int
+test_soc_init_and_probe(void)
+{
+	struct rte_soc_driver *drv;
+
+	/* Registering dummy drivers */
+	rte_eal_soc_register(&empty_pmd0.soc_drv);
+	rte_eal_soc_register(&empty_pmd1.soc_drv);
+	/* Assuming that test_register_unregister is working, not verifying
+	 * that drivers are indeed registered
+	*/
+
+	/* rte_eal_soc_init is called by rte_eal_init, which in turn calls the
+	 * scan_fn of each driver.
+	 */
+	TAILQ_FOREACH(drv, &soc_driver_list, next) {
+		if (drv && drv->scan_fn)
+			drv->scan_fn();
+	}
+
+	/* rte_eal_init() would perform other inits here */
+
+	/* Probe would link the SoC devices<=>drivers */
+	rte_eal_soc_probe();
+
+	/* Unregistering dummy drivers */
+	rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+	rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+	free(empty_pmd0.soc_dev.addr.name);
+
+	printf("%s has been successful\n", __func__);
+	return 0;
+}
+
 /* save real devices and drivers until the tests finishes */
 struct soc_driver_list real_soc_driver_list =
 	TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
 
+/* save real devices and drivers until the tests finishes */
+struct soc_device_list real_soc_device_list =
+	TAILQ_HEAD_INITIALIZER(real_soc_device_list);
+
 static int test_soc_setup(void)
 {
 	struct rte_soc_driver *drv;
+	struct rte_soc_device *dev;
 
 	/* no real drivers for the test */
 	while (!TAILQ_EMPTY(&soc_driver_list)) {
@@ -163,12 +280,20 @@ static int test_soc_setup(void)
 		TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
 	}
 
+	/* And, no real devices for the test */
+	while (!TAILQ_EMPTY(&soc_device_list)) {
+		dev = TAILQ_FIRST(&soc_device_list);
+		TAILQ_REMOVE(&soc_device_list, dev, next);
+		TAILQ_INSERT_TAIL(&real_soc_device_list, dev, next);
+	}
+
 	return 0;
 }
 
 static int test_soc_cleanup(void)
 {
 	struct rte_soc_driver *drv;
+	struct rte_soc_device *dev;
 
 	/* bring back real drivers after the test */
 	while (!TAILQ_EMPTY(&real_soc_driver_list)) {
@@ -177,6 +302,13 @@ static int test_soc_cleanup(void)
 		rte_eal_soc_register(drv);
 	}
 
+	/* And, bring back real devices after the test */
+	while (!TAILQ_EMPTY(&real_soc_device_list)) {
+		dev = TAILQ_FIRST(&real_soc_device_list);
+		TAILQ_REMOVE(&real_soc_device_list, dev, next);
+		TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
+	}
+
 	return 0;
 }
 
@@ -192,6 +324,10 @@ test_soc(void)
 	if (test_register_unregister())
 		return -1;
 
+	/* Assuming test_register_unregister has succeeded */
+	if (test_soc_init_and_probe())
+		return -1;
+
 	if (test_soc_cleanup())
 		return -1;
 
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index de38848..3c407be 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -173,5 +173,9 @@ DPDK_16.11 {
 	rte_eal_soc_register;
 	rte_eal_soc_unregister;
 	rte_eal_soc_dump;
+	rte_eal_soc_match;
+	rte_eal_soc_detach;
+	rte_eal_soc_probe;
+	rte_eal_soc_probe_one;
 
 } DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 5dcddc5..bb87a67 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -36,6 +36,8 @@
 #include <sys/queue.h>
 
 #include <rte_log.h>
+#include <rte_common.h>
+#include <rte_soc.h>
 
 #include "eal_private.h"
 
@@ -45,6 +47,213 @@ struct soc_driver_list soc_driver_list =
 struct soc_device_list soc_device_list =
 	TAILQ_HEAD_INITIALIZER(soc_device_list);
 
+/* Default SoC device<->Driver match handler function */
+int
+rte_eal_soc_match(struct rte_soc_driver *drv, struct rte_soc_device *dev)
+{
+	int i, j;
+
+	RTE_VERIFY(drv != NULL && drv->id_table != NULL);
+	RTE_VERIFY(dev != NULL && dev->id != NULL);
+
+	for (i = 0; drv->id_table[i].compatible; ++i) {
+		const char *drv_compat = drv->id_table[i].compatible;
+
+		for (j = 0; dev->id[j].compatible; ++j) {
+			const char *dev_compat = dev->id[j].compatible;
+
+			if (!strcmp(drv_compat, dev_compat))
+				return 0;
+		}
+	}
+
+	return 1;
+}
+
+
+static int
+rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
+			     struct rte_soc_device *dev)
+{
+	int ret = 1;
+
+	ret = drv->match_fn(drv, dev);
+	if (ret) {
+		RTE_LOG(DEBUG, EAL,
+			" match function failed, skipping\n");
+		return ret;
+	}
+
+	dev->driver = drv;
+	RTE_VERIFY(drv->devinit != NULL);
+	return drv->devinit(drv, dev);
+}
+
+static int
+soc_probe_all_drivers(struct rte_soc_device *dev)
+{
+	struct rte_soc_driver *drv = NULL;
+	int rc = 0;
+
+	if (dev == NULL)
+		return -1;
+
+	TAILQ_FOREACH(drv, &soc_driver_list, next) {
+		rc = rte_eal_soc_probe_one_driver(drv, dev);
+		if (rc < 0)
+			/* negative value is an error */
+			return -1;
+		if (rc > 0)
+			/* positive value means driver doesn't support it */
+			continue;
+		return 0;
+	}
+	return 1;
+}
+
+/* If the IDs match, call the devuninit() function of the driver. */
+static int
+rte_eal_soc_detach_dev(struct rte_soc_driver *drv,
+		       struct rte_soc_device *dev)
+{
+	int ret;
+
+	if ((drv == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = drv->match_fn(drv, dev);
+	if (ret) {
+		RTE_LOG(DEBUG, EAL,
+			" match function failed, skipping\n");
+		return ret;
+	}
+
+	RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+		dev->addr.name);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %s\n", drv->driver.name);
+
+	if (drv->devuninit && (drv->devuninit(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	return 0;
+}
+
+/*
+ * Call the devuninit() function of all registered drivers for the given
+ * device if their IDs match.
+ *
+ * @return
+ *       0 when successful
+ *      -1 if deinitialization fails
+ *       1 if no driver is found for this device.
+ */
+static int
+soc_detach_all_drivers(struct rte_soc_device *dev)
+{
+	struct rte_soc_driver *dr = NULL;
+	int rc = 0;
+
+	if (dev == NULL)
+		return -1;
+
+	TAILQ_FOREACH(dr, &soc_driver_list, next) {
+		rc = rte_eal_soc_detach_dev(dr, dev);
+		if (rc < 0)
+			/* negative value is an error */
+			return -1;
+		if (rc > 0)
+			/* positive value means driver doesn't support it */
+			continue;
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * Detach device specified by its SoC address.
+ */
+int
+rte_eal_soc_detach(const struct rte_soc_addr *addr)
+{
+	struct rte_soc_device *dev = NULL;
+	int ret = 0;
+
+	if (addr == NULL)
+		return -1;
+
+	TAILQ_FOREACH(dev, &soc_device_list, next) {
+		if (rte_eal_compare_soc_addr(&dev->addr, addr))
+			continue;
+
+		ret = soc_detach_all_drivers(dev);
+		if (ret < 0)
+			goto err_return;
+
+		TAILQ_REMOVE(&soc_device_list, dev, next);
+		return 0;
+	}
+	return -1;
+
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device %s cannot be used\n",
+		dev->addr.name);
+	return -1;
+}
+
+int
+rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
+{
+	struct rte_soc_device *dev = NULL;
+	int ret = 0;
+
+	if (addr == NULL)
+		return -1;
+
+	/* unlike pci, in case of soc, it the responsibility of the soc driver
+	 * to check during init whether device has been updated since last add.
+	 */
+
+	TAILQ_FOREACH(dev, &soc_device_list, next) {
+		if (rte_eal_compare_soc_addr(&dev->addr, addr))
+			continue;
+
+		ret = soc_probe_all_drivers(dev);
+		if (ret < 0)
+			goto err_return;
+		return 0;
+	}
+	return -1;
+
+err_return:
+	RTE_LOG(WARNING, EAL,
+		"Requested device %s cannot be used\n", addr->name);
+	return -1;
+}
+
+/*
+ * Scan the SoC devices and call the devinit() function for all registered
+ * drivers that have a matching entry in its id_table for discovered devices.
+ */
+int
+rte_eal_soc_probe(void)
+{
+	struct rte_soc_device *dev = NULL;
+	int ret = 0;
+
+	TAILQ_FOREACH(dev, &soc_device_list, next) {
+		ret = soc_probe_all_drivers(dev);
+		if (ret < 0)
+			rte_exit(EXIT_FAILURE, "Requested device %s"
+				 " cannot be used\n", dev->addr.name);
+	}
+
+	return 0;
+}
+
 /* dump one device */
 static int
 soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
@@ -79,6 +288,12 @@ rte_eal_soc_dump(FILE *f)
 void
 rte_eal_soc_register(struct rte_soc_driver *driver)
 {
+	/* For a valid soc driver, match and scan function
+	 * should be provided.
+	 */
+	RTE_VERIFY(driver != NULL);
+	RTE_VERIFY(driver->match_fn != NULL);
+	RTE_VERIFY(driver->scan_fn != NULL);
 	TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
 }
 
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index c6f98eb..bfb49a2 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -97,6 +97,16 @@ typedef int (soc_devinit_t)(struct rte_soc_driver *, struct rte_soc_device *);
 typedef int (soc_devuninit_t)(struct rte_soc_device *);
 
 /**
+ * SoC device scan callback, called from rte_eal_soc_init.
+ */
+typedef void (soc_scan_t)(void);
+
+/**
+ * Custom device<=>driver match callback for SoC
+ */
+typedef int (soc_match_t)(struct rte_soc_driver *, struct rte_soc_device *);
+
+/**
  * A structure describing a SoC driver.
  */
 struct rte_soc_driver {
@@ -104,6 +114,8 @@ struct rte_soc_driver {
 	struct rte_driver driver;          /**< Inherit core driver. */
 	soc_devinit_t *devinit;            /**< Device initialization */
 	soc_devuninit_t *devuninit;        /**< Device uninitialization */
+	soc_scan_t *scan_fn;               /**< Callback for scanning SoC bus*/
+	soc_match_t *match_fn;             /**< Callback to match dev<->drv */
 	const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
 };
 
@@ -146,6 +158,45 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
 }
 
 /**
+ * Default function for matching the Soc driver with device. Each driver can
+ * either use this function or define their own soc matching function.
+ * This function relies on the compatible string extracted from sysfs. But,
+ * a SoC might have different way of identifying its devices. Such SoC can
+ * override match_fn.
+ *
+ * @return
+ * 	 0 on success
+ *	-1 when no match found
+  */
+int
+rte_eal_soc_match(struct rte_soc_driver *drv, struct rte_soc_device *dev);
+
+/**
+ * Probe SoC devices for registered drivers.
+ */
+int rte_eal_soc_probe(void);
+
+/**
+ * Probe the single SoC device.
+ */
+int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
+
+/**
+ * Close the single SoC device.
+ *
+ * Scan the SoC devices and find the SoC device specified by the SoC
+ * address, then call the devuninit() function for registered driver
+ * that has a matching entry in its id_table for discovered device.
+ *
+ * @param addr
+ *	The SoC address to close.
+ * @return
+ *   - 0 on success.
+ *   - Negative on error.
+ */
+int rte_eal_soc_detach(const struct rte_soc_addr *addr);
+
+/**
  * Dump discovered SoC devices.
  */
 void rte_eal_soc_dump(FILE *f);
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 15c8c3d..147b601 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -70,6 +70,7 @@
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
 #include <rte_pci.h>
+#include <rte_soc.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
 #include <rte_common.h>
@@ -881,6 +882,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe & Initialize SoC devices */
+	if (rte_eal_soc_probe())
+		rte_panic("Cannot probe SoC\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 04848b9..5f961c4 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -52,5 +52,21 @@
 int
 rte_eal_soc_init(void)
 {
+	struct rte_soc_driver *drv;
+
+	/* for debug purposes, SoC can be disabled */
+	if (internal_config.no_soc)
+		return 0;
+
+	/* For each registered driver, call their scan routine to perform any
+	 * custom scan for devices (for example, custom buses)
+	 */
+	TAILQ_FOREACH(drv, &soc_driver_list, next) {
+		if (drv && drv->scan_fn) {
+			drv->scan_fn();
+			/* Ignore all errors from this */
+		}
+	}
+
 	return 0;
 }
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b9d1932..adcfe7d 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -179,5 +179,9 @@ DPDK_16.11 {
 	rte_eal_soc_register;
 	rte_eal_soc_unregister;
 	rte_eal_soc_dump;
+	rte_eal_soc_match;
+	rte_eal_soc_detach;
+	rte_eal_soc_probe;
+	rte_eal_soc_probe_one;
 
 } DPDK_16.07;
-- 
2.7.4