All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model
@ 2017-01-16 15:38 Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 1/8] eal/bus: introduce bus abstraction Shreyansh Jain
                   ` (9 more replies)
  0 siblings, 10 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v5: [15]

:: Introduction ::

DPDK has been inherently a PCI inclined framework. Because of this, the
design of device tree (or list) within DPDK is also PCI inclined. A
non-PCI device doesn't have a way of being expressed without using hooks
started from EAL to PMD.

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

        device A1
          |
  +==.===='==============.============+ Bus A.
     |                    `--> driver A11     \
  device A2                `-> driver A12      \______
                                                |CPU |
                                                /`````
        device B1                              /
          |                                   /
  +==.===='==============.============+ Bus B`
     |                    `--> driver B11
  device B2                `-> driver B12


 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

In [15], model assumes that rte_bus would be the base class using which
all the bus implementations would instantiate the objects. This patches
takes a much more basic approach, on the same lines of rte_device/
rte_driver and rte_pci_device/rte_pci_driver.
This is based on various review comments as well as offline (IRC)
discussions.

 - rte_bus is an abstract class which includes basic methods supported by
   all buses.
 - specific implementation, for example for PCI rte_pci_bus, would extend
   this class to form their own buses, with their own bus specific device
   and driver list.
 - 

 +-----------------+
 |rte_pci_bus      |
 |+---------------+|
 ||rte_bus        ||
 |+---------------+|
 +-----------------+

And example implementation would look like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | probe          ||     |
  |                | | attach         ||     |
  |                | | detach         ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+


:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003     : Split the PCI match into a separate function
0004~0005: Introduce bus->scan APIs and integrate with EAL
0006     : Update the Bus and PCI test cases for scanning/probing
0007     : Enable PCI bus and remove code for direct PCI scan/probe from
           EAL
0008     : Add device hotplugging over the bus and introduce PCI helpers


:: Pending Changes/Caveats ::

1. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   Eventual aim is the PCI bus reside in driver/bus/pci

2. Though the implementation for bus is common for Linux and BSD, the PCI
   bus implementation has been done/tested only for Linux.

3. RTE_REGISTER_BUS has been declared with contructor priority of 101
    It is important that Bus is registered *before* drivers are registered.
    Only way I could find to assure that was via 
    __attribute(contructor(priority)) of GCC. I am not sure how it would
    behave on other compilers. Any suggestions?
    - One suggestion from David Marchand was to use global bus object
      handles, which I have not implemented for now. If that is common
      choice, I will change in v3.

:: ToDo list ::

 - Bump to librte_eal version
 - Documentation continues to have references to some _old_ PCI symbols

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html

:: Version Changes ::
v6:
 - Rearchitecture to bring bus object parallel to rte_device/driver
   This majorly includes:
   -- rte_pci_bus class and pci_bus as its object for PCI
   -- bus->attach/detach (hotplugging)
   -- removing bus->match as that is local to an implementation
 - rename symbols rte_eal_bus_* to rte_bus_*
 - restructuring patches (order) for simplicity
 - update to test_pci

v5:
 - Fix checkpatch error in Patch 0003

v4:
 - rebase over master (eac901ce)
 - Fix a bug in test_bus while setup and cleanup
 - rename rte_eal_get_bus to rte_eal_bus_get
 - Add helper (iterator) macros for easy bus,device,driver traversal
 - removed 0001 patch as it is already merged in master
 - fix missing rte_eal_bus_insert_device symbol in map file

v3:
 - rebase over master (c431384c8f)
 - revert patch 0001 changes for checkpatch (container_of macro)
 - qat/rte_qat_cryptodev update for rte_driver->probe
 - test_pci update for using a test_pci_bus for verification
 - some bug fixes based on internal testing.
 -- rte_eal_dev_attach not handling devargs
 -- blacklisting not working

v2:
 - No more bus->probe()
   Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
 - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
   added as glue code between PCI PMDs and PCI Bus
   `-> PMDs are updated to use these new functions as callbacks for
       rte_driver
 - 'default' keyword has been removed from match and scan
 - Fix for incorrect changes in mlx* and nicvf*
 - Checkpatch fixes
 - Some variable checks have been removed from internal functions;
   functions which are externally visible continue to have such checks
 - Some rearrangement of patches:
   -- changes to drivers have been separated from EAL changes (but this
      does make PCI PMDs non-working for a particular patch)

Shreyansh Jain (8):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  pci: split match and probe function
  eal/bus: support for scanning of bus
  eal: introduce bus scan and probe in EAL
  test: update bus and pci unit test cases
  eal: enable PCI bus
  eal: enable hotplugging of devices on bus

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 164 ++++--
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  13 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 140 +++++
 lib/librte_eal/common/eal_common_dev.c          |  56 +-
 lib/librte_eal/common/eal_common_pci.c          | 330 ++++++++----
 lib/librte_eal/common/eal_private.h             |  10 -
 lib/librte_eal/common/include/rte_bus.h         | 206 +++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/common/include/rte_pci.h         | 161 +++++-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  53 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
 20 files changed, 1646 insertions(+), 238 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v6 1/8] eal/bus: introduce bus abstraction
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 2/8] test: add basic bus infrastructure tests Shreyansh Jain
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for EAL.
The model is:
 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' base class which would be extended for
specific implementations. It also introduces Bus registration and
deregistration functions.

An example implementation would be like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | match          ||     |
  |                | | probe          ||     |
  |                | | remove         ||     |
  |                | | ...            ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  10 +++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          |  97 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 111 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  10 +++
 8 files changed, 232 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..c891392
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+/* register a bus */
+void
+rte_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_bus_unregister(struct rte_bus *bus)
+{
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* dump one bus info */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..2250269
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,111 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * RTE PMD Bus Abstraction interfaces
+ *
+ * This file exposes APIs and Interfaces for Bus Abstraction over the devices
+ * drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	const char *name;            /**< Name of the bus */
+};
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_bus_dump(FILE *f);
+
+/** Helper for Bus registration. The constructor has higher priority than
+ * PMD constructors
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b17791f..24c1c00 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -122,6 +122,7 @@ struct rte_driver;
  */
 struct rte_device {
 	TAILQ_ENTRY(rte_device) next; /**< Next device */
+	struct rte_bus *bus;          /**< Device connected to this bus */
 	const struct rte_driver *driver;/**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..aa874a5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..b553b13 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 2/8] test: add basic bus infrastructure tests
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 1/8] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 3/8] pci: split match and probe function Shreyansh Jain
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile                       |   2 +-
 app/test/test.h                         |   2 +
 app/test/test_bus.c                     | 359 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h |   3 +
 4 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 2250269..fe0f69d 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * A structure describing a generic bus.
  */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 3/8] pci: split match and probe function
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 1/8] eal/bus: introduce bus abstraction Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 2/8] test: add basic bus infrastructure tests Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 18:24   ` Stephen Hemminger
  2017-01-16 19:53   ` Ferruh Yigit
  2017-01-16 15:38 ` [PATCH v6 4/8] eal/bus: support for scanning of bus Shreyansh Jain
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
 lib/librte_eal/common/include/rte_pci.h         |  15 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..0d799be 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_pci_match(struct rte_pci_driver *pci_drv,
+		  struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 1;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
-
-		return ret;
+		match = 0;
+		break;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	return match;
 }
 
 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	int ret;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	loc = &dev->addr;
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
 
-		struct rte_pci_addr *loc = &dev->addr;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	}
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* clear driver structure */
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
 		dev->driver = NULL;
-
 		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
 			rte_eal_pci_unmap_device(dev);
+	}
 
-		return 0;
+	return ret;
+}
+
+/*
+ * If vendor/device ID match, call the remove() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
 	}
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	loc = &dev->addr;
+
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
+
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..6c9ec39 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_pci_match(struct rte_pci_driver *pci_drv,
+	      struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b553b13..5ed2589 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,5 +186,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 4/8] eal/bus: support for scanning of bus
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (2 preceding siblings ...)
  2017-01-16 15:38 ` [PATCH v6 3/8] pci: split match and probe function Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 5/8] eal: introduce bus scan and probe in EAL Shreyansh Jain
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c                     | 175 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  18 ++++
 3 files changed, 195 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
+		.scan = scan_fn_for_busA,
 	},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
 	.name = "busB_impl", /* busB */
 	.bus = {
 		.name = "busB",
+		.scan = scan_fn_for_busB,
 	},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map 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 dummy_device *ddev = NULL;
+	struct dummy_bus_map *dbmap = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; bus_map[i].name; i++) {
+		if (!strcmp(bus_map[i].name, bus->name)) {
+			dbmap = &bus_map[i];
+			break;
+		}
+	}
+
+	if (!dbmap)
+		return -1;
+
+	db = dbmap->dbus;
+
+	/* For all the devices in the device tree (bus_map), add device */
+	for (i = 0; dbmap->ddevices[i]; i++) {
+		ddev = dbmap->ddevices[i];
+		TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+		ddev->dev.bus = bus;
+	}
+
+	return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busA") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busB") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+	int i = 0;
 	struct rte_bus *bus_p = NULL;
 
 	/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
 		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
 	}
 
+	/* Initialize the bus lists */
+	for (i = 0; bus_map[i].name; i++) {
+		TAILQ_INIT(&bus_map[i].dbus->device_list);
+		TAILQ_INIT(&bus_map[i].dbus->driver_list);
+	}
+
+	dump_device_tree();
 	return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
 	return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct dummy_device *ddev;
+	struct dummy_bus *dbus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       bus_map[i].name);
+			return -1;
+		}
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			TAILQ_REMOVE(&dbus->device_list, ddev, next);
+		}
+	}
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		dbus = container_of(bus, struct dummy_bus, bus);
+
+		if (!TAILQ_EMPTY(&dbus->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();
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -346,6 +515,12 @@ test_bus(void)
 	if (test_bus_registration())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_bus_unregistration())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index c891392..35baff8 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -51,6 +51,8 @@ rte_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan implemented */
+	RTE_VERIFY(bus->scan);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index fe0f69d..152451c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,11 +60,29 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 extern struct rte_bus_list rte_bus_list;
 
 /**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * Generic bus object passed only as a helper for implementation to find
+ * their respective registered bus object. Implementations can choose not
+ * to use this variable.
+ *
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
+	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 5/8] eal: introduce bus scan and probe in EAL
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (3 preceding siblings ...)
  2017-01-16 15:38 ` [PATCH v6 4/8] eal/bus: support for scanning of bus Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 19:58   ` Ferruh Yigit
  2017-01-16 15:38 ` [PATCH v6 6/8] test: update bus and pci unit test cases Shreyansh Jain
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Each bus implementation defines their own callbacks for scanning bus
and probing devices available on the bus. Enable EAL to call bus specific
scan and probe functions during DPDK initialization.

Existing PCI scan/probe continues to exist. It will removed in subsequent
patches.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  8 +++
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 11 ++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 +
 lib/librte_eal/common/eal_common_bus.c          | 41 +++++++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 33 ++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 39 ++++++++++++++
 lib/librte_eal/common/include/rte_pci.h         | 68 +++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  8 +++
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 15 ++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 +
 10 files changed, 227 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -577,6 +578,9 @@ rte_eal_init(int argc, char **argv)
 		rte_config.master_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +617,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 35baff8..9c91ca6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -53,6 +53,7 @@ rte_bus_register(struct rte_bus *bus)
 	RTE_VERIFY(bus->name && strlen(bus->name));
 	/* A bus should mandatorily have the scan implemented */
 	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
@@ -66,6 +67,46 @@ rte_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* Error in scanning any bus stops the EAL init. */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->probe();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 0d799be..35da451 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -508,3 +509,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+		       struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+	/* Update Bus references */
+	new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+	TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 152451c..f1d4c2c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -77,12 +77,30 @@ extern struct rte_bus_list rte_bus_list;
 typedef int (*rte_bus_scan_t)(void);
 
 /**
+ * Implementation specific probe function which is responsible for linking
+ * devices on that bus with applicable drivers.
+ *
+ * This is called while iterating over each registered bus. Bus object is
+ * passed along assuming this is wrapped around (embedded) by Implementation
+ * specific bus object.
+ *
+ * @param bus
+ *	Generic bus object which was registered with EAL
+ *
+ * @return
+ *	0 for successful probe
+ *	!0 for any error while probing
+ */
+typedef int (*rte_bus_probe_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
+	rte_bus_probe_t probe;       /**< Probe devices on bus */
 };
 
 /**
@@ -104,6 +122,27 @@ void rte_bus_register(struct rte_bus *bus);
 void rte_bus_unregister(struct rte_bus *bus);
 
 /**
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return
+ *	0 in case of success in scanning all buses
+ *	!0 in case of failure to scan
+ */
+int rte_bus_scan(void);
+
+/**
+ * For each device on the bus, perform a driver 'match' and call the
+ * bus's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_bus_probe(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 6c9ec39..a52b390 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *pci_bus;            /**< PCI bus reference */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -523,6 +553,44 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_bus
+ *	PCI Bus reference to which device is to be added
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+			    struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_dev
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..f77ff5c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -844,6 +845,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index e2fc219..300064d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -54,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -723,3 +727,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 5ed2589..6f047c5 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,6 +186,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 6/8] test: update bus and pci unit test cases
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (4 preceding siblings ...)
  2017-01-16 15:38 ` [PATCH v6 5/8] eal: introduce bus scan and probe in EAL Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 15:38 ` [PATCH v6 7/8] eal: enable PCI bus Shreyansh Jain
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++
 app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 266 insertions(+), 50 deletions(-)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 0b6d011..ef7fa89 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -120,12 +120,15 @@ static int scan_fn_for_busB(void);
 
 /* generic implementations wrapped around by above declarations */
 static int generic_scan_fn(struct rte_bus *bus);
+static int generic_probe_fn(void);
+static int dummy_match_fn(struct rte_driver *drv, struct rte_device *dev);
 
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
 		.scan = scan_fn_for_busA,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -134,6 +137,7 @@ struct dummy_bus busB = {
 	.bus = {
 		.name = "busB",
 		.scan = scan_fn_for_busB,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -288,6 +292,46 @@ generic_scan_fn(struct rte_bus *bus)
 	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 match with
+ * @param dev
+ *	device object
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+dummy_match_fn(struct rte_driver *drv __rte_unused, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct dummy_device *ddev = NULL;
+	struct dummy_device *ddev_as_arg;
+	struct dummy_bus *dbus = 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 = dev->bus;
+	dbus = container_of(bus, struct dummy_bus, bus);
+	ddev_as_arg = container_of(dev, struct dummy_device, dev);
+
+	TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+		if (ddev == ddev_as_arg)
+			return 0;
+	}
+
+	return 1;
+}
+
 int
 scan_fn_for_busA(void) {
 	struct dummy_bus_map *dbm;
@@ -504,6 +548,110 @@ test_bus_scan(void)
 	return 0;
 }
 
+/*
+ *
+ */
+static int
+generic_probe_fn(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+	struct dummy_bus *dbus = NULL;
+	struct dummy_device *ddev = NULL;
+	struct dummy_driver *ddrv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device on that bus (bus specific->device_list)
+	 * 3.   for each driver on that bus (bus specific->driver_list)
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+
+		/* Looping over all scanned devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			/* There is a list of drivers within dummy_bus_map.
+			 * In case of PMDs, this would be driver registration
+			 * APIs/list
+			 */
+			for (j = 0; bus_map[i].ddrivers[j]; j++) {
+				ddrv = bus_map[i].ddrivers[j];
+
+				drv = &ddrv->drv;
+				dev = &ddev->dev;
+				ret = dummy_match_fn(drv, dev);
+				if (!ret) {
+					/* As match is generic, it always
+					 * results in dev->drv pointing to
+					 * first driver entry in bus_map[i]
+					 */
+					dev->driver = drv;
+					dev->bus = &dbus->bus;
+				}
+				/* Else, continue */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a bus_map[i]
+	 * should have same driver (first driver entry of bus_map[i])
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		ddrv = bus_map[i].ddrivers[0];
+		drv = &ddrv->drv;
+
+		for (j = 0; bus_map[i].ddevices[j]; j++) {
+			ddev = bus_map[i].ddevices[j];
+			dev = &ddev->dev;
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	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.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i;
+	struct dummy_bus *dbus;
+	struct rte_bus *bus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+		bus = &dbus->bus;
+		ret = bus->probe();
+		if (ret)
+			printf("Probe for %s failed.\n", bus_map[i].name);
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
 
 int
 test_bus(void)
@@ -518,6 +666,10 @@ test_bus(void)
 	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;
 
diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+	struct rte_bus bus;
+	struct test_pci_device_list test_device_list;
+	struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+	.bus = {
+		.name = "test_pci_bus",
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
 	return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+	int i;
+	struct rte_pci_device *dev = NULL;
+
+	TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+		       dev->addr.devid, dev->addr.function);
+		fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+		       dev->id.device_id);
+
+		for (i = 0; i != sizeof(dev->mem_resource) /
+			sizeof(dev->mem_resource[0]); i++) {
+			fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+				dev->mem_resource[i].phys_addr,
+				dev->mem_resource[i].len);
+		}
+	}
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+	int ret;
+	struct rte_pci_device *device;
+	struct rte_pci_driver *driver;
+
+	TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+		TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+			ret = rte_pci_match(driver, device);
+			if (!ret) {
+				if (!driver->probe)
+					continue;
+
+				device->driver = driver;
+				ret = driver->probe(driver, device);
+				if (ret != 0)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
 			dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
 	}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
 	const struct resource *r;
 	int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
 	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
+	TAILQ_INIT(&test_pci_bus.test_device_list);
+	TAILQ_INIT(&test_pci_bus.test_driver_list);
 
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_bus_register(&test_pci_bus.bus);
+	pci_bus = &test_pci_bus;
+
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->bus.scan();
 
-	ret = rte_eal_pci_scan();
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
+
+	printf("Dump of all devices scanned:\n");
+	do_pci_device_dump(stdout);
 
 	return 0;
 }
@@ -190,10 +254,11 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
+	void *temp;
 
 	unsetenv("SYSFS_PCI_DEVICES");
 
@@ -203,28 +268,23 @@ test_pci_cleanup(void)
 	ret = resource_rm_by_tar(r);
 	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
 	/*
 	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+	TAILQ_FOREACH_SAFE(dev, &(test_pci_bus.test_device_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_device_list), dev, next);
+		dev->driver = NULL;
 	}
 
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
+	TAILQ_FOREACH_SAFE(dr, &(test_pci_bus.test_driver_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_driver_list), dr, next);
 	}
 
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
+	rte_bus_unregister(&pci_bus->bus);
 
 	return 0;
 }
@@ -234,16 +294,19 @@ test_pci_blacklist(void)
 {
 	struct rte_devargs_list save_devargs_list;
 
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	TEST_ASSERT(TAILQ_EMPTY(&test_pci_bus.test_driver_list),
+		    "PCI Driver list not empty");
+
+	/* Add test drivers to Bus */
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver, next);
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver2, next);
 
 	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
+
+	printf("Probe the Test Bus\n");
+	do_pci_bus_probe();
 
 	if (pci_dev_count == 0) {
 		printf("no device detected\n");
@@ -257,8 +320,8 @@ test_pci_blacklist(void)
 	blacklist_all_devices();
 
 	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
+	printf("Probe bus with all devices blacklisted\n");
+	do_pci_bus_probe();
 
 	free_devargs_list();
 	devargs_list = save_devargs_list;
@@ -270,8 +333,9 @@ test_pci_blacklist(void)
 
 	test_pci_run = 1;
 
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
+	/* Clear the test drivers added to Test Bus */
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver, next);
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver2, next);
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 7/8] eal: enable PCI bus
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (5 preceding siblings ...)
  2017-01-16 15:38 ` [PATCH v6 6/8] test: update bus and pci unit test cases Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-16 19:58   ` Ferruh Yigit
  2017-01-16 15:38 ` [PATCH v6 8/8] eal: enable hotplugging of devices on bus Shreyansh Jain
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 -----
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 36 ++++++++++++-----------
 lib/librte_eal/common/eal_private.h             | 10 -------
 lib/librte_eal/common/include/rte_pci.h         | 22 +++++---------
 lib/librte_eal/linuxapp/eal/eal.c               |  7 -----
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 38 +++++++------------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 8 files changed, 37 insertions(+), 87 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 35da451..1d283d2 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -342,7 +337,7 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -363,6 +358,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -374,7 +370,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -404,7 +400,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -412,7 +408,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -441,7 +437,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 
 		/* set devargs in PCI structure */
 		devargs = pci_devargs_lookup(dev);
@@ -489,7 +485,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -498,16 +494,22 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = &rte_pci_bus;
 }
 
-/* unregister a driver */
+/* Unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = driver->pci_bus;
+
+	TAILQ_REMOVE(&pci_bus->driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = NULL;
 }
 
 /* Add a PCI device to PCI Bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..68386e8 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index a52b390..5f8d679 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -124,6 +118,9 @@ TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
 /** List of PCI drivers */
 TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
 
+/* Extend PCI bus definition to users */
+extern struct rte_pci_bus rte_pci_bus;
+
 /* PCI Bus iterators */
 #define FOREACH_DEVICE_ON_PCIBUS(p)	\
 		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
@@ -208,8 +205,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -416,17 +411,14 @@ rte_pci_match(struct rte_pci_driver *pci_drv,
 	      struct rte_pci_device *pci_dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index f77ff5c..6bb7fc9 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -884,10 +881,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 300064d..50ad9f7 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -232,7 +232,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_pci_bus *pci_bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -350,21 +351,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&pci_bus->device_list)) {
+		rte_eal_pci_add_device(pci_bus, dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &pci_bus->device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -374,8 +373,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(pci_bus, dev);
 	}
 
 	return 0;
@@ -390,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr);
+	return pci_scan_one(&rte_pci_bus, filename, addr);
 }
 
 /*
@@ -467,7 +466,8 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+
+		if (pci_scan_one(&rte_pci_bus, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -712,22 +712,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 6f047c5..f0e63c3 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v6 8/8] eal: enable hotplugging of devices on bus
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (6 preceding siblings ...)
  2017-01-16 15:38 ` [PATCH v6 7/8] eal: enable PCI bus Shreyansh Jain
@ 2017-01-16 15:38 ` Shreyansh Jain
  2017-01-17  7:24   ` Shreyansh Jain
  2017-01-16 18:27 ` [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Stephen Hemminger
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-16 15:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
 lib/librte_eal/common/eal_common_dev.c  | 56 +++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 82 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 35 ++++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 58 +++++++++++++++++++----
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
 6 files changed, 212 insertions(+), 23 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..17a04d9 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -678,6 +678,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..b363fa9 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(bus, name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(bus, name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 1d283d2..1c205bd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,95 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(struct rte_bus *bus __rte_unused, const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret = -1;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr) == 0) {
+		/* Device doesn't match PCI BDF naming format */
+		return -1;
+	}
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+		}
+	}
+
+	return ret;
+
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(struct rte_bus *bus __rte_unused, const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_pci_addr addr;
 	int ret = 0;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr) == 0) {
+		/* Device doesn't match PCI BDF naming format */
+		return -1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = pci_detach_all_drivers(dev);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index f1d4c2c..5b7ae0c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Bus list exposed */
 extern struct rte_bus_list rte_bus_list;
 
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
@@ -94,6 +96,37 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param bus
+ *	Generic bus object which was registered with EAL
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(struct rte_bus *bus, const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param bus
+ *	Generic bus object which was registered with EAL
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(struct rte_bus *bus, const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -101,6 +134,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 5f8d679..6369584 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -421,6 +421,40 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param bus
+ *	Generic bus object representing PCI bus
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(struct rte_bus *bus, const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param bus
+ *	Generic bus object representing PCI bus
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(struct rte_bus *bus, const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -494,19 +528,27 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
+ * Attach a PCI device on PCI Bus
+ * @param bus
+ *	Generic Bus object for PCI Bus. If passed NULL, PCI bus is extracted
+ *	using Bus APIs.
+ * @param device_name
+ *	Device Name, which would be converted into BDF.
+ */
+int rte_eal_pci_attach(struct rte_bus *bus, const char *device_name);
+
+/**
+ * Detach a single PCI device.
  *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
+ * @param bus
+ *	Generic bus object for PCI bus.
+ * @param device_name
+ *	Device Name, which would be converted into BDF.
  * @return
  *   - 0 on success.
  *   - Negative on error.
  */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
+int rte_eal_pci_detach(struct rte_bus *bus, const char *device_name);
 
 /**
  * Dump the content of the PCI bus.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 50ad9f7..8084996 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -716,6 +716,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 3/8] pci: split match and probe function
  2017-01-16 15:38 ` [PATCH v6 3/8] pci: split match and probe function Shreyansh Jain
@ 2017-01-16 18:24   ` Stephen Hemminger
  2017-01-17 10:10     ` Shreyansh Jain
  2017-01-16 19:53   ` Ferruh Yigit
  1 sibling, 1 reply; 146+ messages in thread
From: Stephen Hemminger @ 2017-01-16 18:24 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev, thomas.monjalon

On Mon, 16 Jan 2017 21:08:22 +0530
Shreyansh Jain <shreyansh.jain@nxp.com> wrote:

> -rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
> +int
> +rte_pci_match(struct rte_pci_driver *pci_drv,
> +		  struct rte_pci_device *pci_dev)

Use const?

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (7 preceding siblings ...)
  2017-01-16 15:38 ` [PATCH v6 8/8] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-16 18:27 ` Stephen Hemminger
  2017-01-17  5:08   ` Shreyansh Jain
  2017-01-17  5:09   ` Shreyansh Jain
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
  9 siblings, 2 replies; 146+ messages in thread
From: Stephen Hemminger @ 2017-01-16 18:27 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev, thomas.monjalon

On Mon, 16 Jan 2017 21:08:19 +0530
Shreyansh Jain <shreyansh.jain@nxp.com> wrote:

> Link to v5: [15]
> 
> :: Introduction ::
> 
> DPDK has been inherently a PCI inclined framework. Because of this, the
> design of device tree (or list) within DPDK is also PCI inclined. A
> non-PCI device doesn't have a way of being expressed without using hooks
> started from EAL to PMD.
> 
> (Check 'Version Changes' section for changes)
> 
> :: Overview of the Proposed Changes ::
> 
> Assuming the below graph for a computing node:
> 
>         device A1
>           |
>   +==.===='==============.============+ Bus A.
>      |                    `--> driver A11     \
>   device A2                `-> driver A12      \______
>                                                 |CPU |
>                                                 /`````
>         device B1                              /
>           |                                   /
>   +==.===='==============.============+ Bus B`
>      |                    `--> driver B11
>   device B2                `-> driver B12
> 
> 
>  - One or more buses are connected to a CPU (or core)
>  - One or more devices are conneted to a Bus
>  - Drivers are running instances which manage one or more devices
>  - Bus is responsible for identifying devices (and interrupt propogation)
>  - Driver is responsible for initializing the device
> 
> In [15], model assumes that rte_bus would be the base class using which
> all the bus implementations would instantiate the objects. This patches
> takes a much more basic approach, on the same lines of rte_device/
> rte_driver and rte_pci_device/rte_pci_driver.
> This is based on various review comments as well as offline (IRC)
> discussions.
> 
>  - rte_bus is an abstract class which includes basic methods supported by
>    all buses.
>  - specific implementation, for example for PCI rte_pci_bus, would extend
>    this class to form their own buses, with their own bus specific device
>    and driver list.
>  - 
> 
>  +-----------------+
>  |rte_pci_bus      |
>  |+---------------+|
>  ||rte_bus        ||
>  |+---------------+|
>  +-----------------+
> 
> And example implementation would look like:
> 
>   .--------------->+-------------------+
>   |                |rte_pci_bus        |
>   |                | +----------------+|
>   |                | |rte_bus         <------.
>   |                | | name           ||     |
>   |                | | scan           ||     |
>   |                | | probe          ||     |
>   |                | | attach         ||     |
>   |                | | detach         ||     |
>   |                | +----------------+|     |
>   |                | pci_driver_list   |     |
>   |  .-------------->pci_device_list   |     |
>   |  |             | ...               |     |
>   |  |             +-------------------+     |
>   |  |                                       |
>   |  +-------------------+                   |
>   |  |rte_pci_device     |                   |
>   '----bus               |                   |
>      | +----------------+|                   |
>      | |rte_device      ||                   |
>      | | bus --------------------------------'
>      | | ...            ||
>      | +----------------+|
>      | ...               |
>      +-------------------+
> 
> 
> :: Brief about Patch Layout ::
> 
> 0001~0002: Introducing the basic Bus model and associated test case
> 0003     : Split the PCI match into a separate function
> 0004~0005: Introduce bus->scan APIs and integrate with EAL
> 0006     : Update the Bus and PCI test cases for scanning/probing
> 0007     : Enable PCI bus and remove code for direct PCI scan/probe from
>            EAL
> 0008     : Add device hotplugging over the bus and introduce PCI helpers
> 
> 
> :: Pending Changes/Caveats ::
> 
> 1. This patchset only moves the PCI into a bus. And, that movement is also
>    currently part of the EAL (lib/librte_eal/linux)
>    Eventual aim is the PCI bus reside in driver/bus/pci
> 
> 2. Though the implementation for bus is common for Linux and BSD, the PCI
>    bus implementation has been done/tested only for Linux.
> 
> 3. RTE_REGISTER_BUS has been declared with contructor priority of 101
>     It is important that Bus is registered *before* drivers are registered.
>     Only way I could find to assure that was via 
>     __attribute(contructor(priority)) of GCC. I am not sure how it would
>     behave on other compilers. Any suggestions?
>     - One suggestion from David Marchand was to use global bus object
>       handles, which I have not implemented for now. If that is common
>       choice, I will change in v3.
> 
> :: ToDo list ::
> 
>  - Bump to librte_eal version
>  - Documentation continues to have references to some _old_ PCI symbols
> 
> :: References ::
> 
> [1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
> [2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
> [3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
> [4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
> [5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
> [6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
> [7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
> [8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
> [9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
> [10] http://dpdk.org/ml/archives/dev/2016-December/051349.html
> [12] http://dpdk.org/ml/archives/dev/2016-December/052092.html
> [13] http://dpdk.org/ml/archives/dev/2016-December/052381.html
> [14] http://dpdk.org/ml/archives/dev/2016-December/053302.html
> [15] http://dpdk.org/ml/archives/dev/2016-December/053315.html
> 
> :: Version Changes ::
> v6:
>  - Rearchitecture to bring bus object parallel to rte_device/driver
>    This majorly includes:
>    -- rte_pci_bus class and pci_bus as its object for PCI
>    -- bus->attach/detach (hotplugging)
>    -- removing bus->match as that is local to an implementation
>  - rename symbols rte_eal_bus_* to rte_bus_*
>  - restructuring patches (order) for simplicity
>  - update to test_pci
> 
> v5:
>  - Fix checkpatch error in Patch 0003
> 
> v4:
>  - rebase over master (eac901ce)
>  - Fix a bug in test_bus while setup and cleanup
>  - rename rte_eal_get_bus to rte_eal_bus_get
>  - Add helper (iterator) macros for easy bus,device,driver traversal
>  - removed 0001 patch as it is already merged in master
>  - fix missing rte_eal_bus_insert_device symbol in map file
> 
> v3:
>  - rebase over master (c431384c8f)
>  - revert patch 0001 changes for checkpatch (container_of macro)
>  - qat/rte_qat_cryptodev update for rte_driver->probe
>  - test_pci update for using a test_pci_bus for verification
>  - some bug fixes based on internal testing.
>  -- rte_eal_dev_attach not handling devargs
>  -- blacklisting not working
> 
> v2:
>  - No more bus->probe()
>    Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
>  - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
>    added as glue code between PCI PMDs and PCI Bus
>    `-> PMDs are updated to use these new functions as callbacks for
>        rte_driver
>  - 'default' keyword has been removed from match and scan
>  - Fix for incorrect changes in mlx* and nicvf*
>  - Checkpatch fixes
>  - Some variable checks have been removed from internal functions;
>    functions which are externally visible continue to have such checks
>  - Some rearrangement of patches:
>    -- changes to drivers have been separated from EAL changes (but this
>       does make PCI PMDs non-working for a particular patch)
> 
> Shreyansh Jain (8):
>   eal/bus: introduce bus abstraction
>   test: add basic bus infrastructure tests
>   pci: split match and probe function
>   eal/bus: support for scanning of bus
>   eal: introduce bus scan and probe in EAL
>   test: update bus and pci unit test cases
>   eal: enable PCI bus
>   eal: enable hotplugging of devices on bus
> 
>  app/test/Makefile                               |   2 +-
>  app/test/test.h                                 |   2 +
>  app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
>  app/test/test_pci.c                             | 164 ++++--
>  lib/librte_eal/bsdapp/eal/Makefile              |   1 +
>  lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
>  lib/librte_eal/bsdapp/eal/eal_pci.c             |  13 +
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
>  lib/librte_eal/common/Makefile                  |   2 +-
>  lib/librte_eal/common/eal_common_bus.c          | 140 +++++
>  lib/librte_eal/common/eal_common_dev.c          |  56 +-
>  lib/librte_eal/common/eal_common_pci.c          | 330 ++++++++----
>  lib/librte_eal/common/eal_private.h             |  10 -
>  lib/librte_eal/common/include/rte_bus.h         | 206 +++++++
>  lib/librte_eal/common/include/rte_dev.h         |   1 +
>  lib/librte_eal/common/include/rte_pci.h         | 161 +++++-
>  lib/librte_eal/linuxapp/eal/Makefile            |   1 +
>  lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
>  lib/librte_eal/linuxapp/eal/eal_pci.c           |  53 +-
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
>  20 files changed, 1646 insertions(+), 238 deletions(-)
>  create mode 100644 app/test/test_bus.c
>  create mode 100644 lib/librte_eal/common/eal_common_bus.c
>  create mode 100644 lib/librte_eal/common/include/rte_bus.h
> 


All this is excellent, but doesn't go far enough to break the assumptions
of 'struct eth_driver'

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 3/8] pci: split match and probe function
  2017-01-16 15:38 ` [PATCH v6 3/8] pci: split match and probe function Shreyansh Jain
  2017-01-16 18:24   ` Stephen Hemminger
@ 2017-01-16 19:53   ` Ferruh Yigit
  2017-01-17  4:54     ` Shreyansh Jain
  1 sibling, 1 reply; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-16 19:53 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
> Matching of PCI device address and driver ID table is being done at two
> discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
> and rte_eal_pci_detach_dev).
> 
> Splitting the matching function into a public fn rte_pci_match.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

<...>

>  /*
> - * If vendor/device ID match, call the remove() function of the
> + * If vendor/device ID match, call the probe() function of the
>   * driver.
>   */
>  static int
> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> -		struct rte_pci_device *dev)
> +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
> +			     struct rte_pci_device *dev)
>  {
> -	const struct rte_pci_id *id_table;
> +	int ret;
> +	struct rte_pci_addr *loc;
>  
>  	if ((dr == NULL) || (dev == NULL))
>  		return -EINVAL;
>  
> -	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
> +	loc = &dev->addr;
>  
> -		/* check if device's identifiers match the driver's ones */
> -		if (id_table->vendor_id != dev->id.vendor_id &&
> -				id_table->vendor_id != PCI_ANY_ID)
> -			continue;
> -		if (id_table->device_id != dev->id.device_id &&
> -				id_table->device_id != PCI_ANY_ID)
> -			continue;
> -		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
> -				id_table->subsystem_vendor_id != PCI_ANY_ID)
> -			continue;
> -		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
> -				id_table->subsystem_device_id != PCI_ANY_ID)
> -			continue;
> +	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
> +			loc->domain, loc->bus, loc->devid, loc->function,
> +			dev->device.numa_node);

This cause bunch of log printed during app startup, what about printing
this log when probed device found?

>  
> -		struct rte_pci_addr *loc = &dev->addr;
> +	/* The device is not blacklisted; Check if driver supports it */
> +	ret = rte_pci_match(dr, dev);
> +	if (ret) {
> +		/* Match of device and driver failed */
> +		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
> +			dr->driver.name);
> +		return 1;
> +	}
> +
> +	/* no initialization when blacklisted, return without error */
> +	if (dev->device.devargs != NULL &&
> +		dev->device.devargs->type ==
> +			RTE_DEVTYPE_BLACKLISTED_PCI) {
> +		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
> +			" initializing\n");
> +		return 1;
> +	}
>  
> -		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
> -				loc->domain, loc->bus, loc->devid,
> -				loc->function, dev->device.numa_node);
> +	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
> +		dev->id.device_id, dr->driver.name);

Same for this one, this line cause printing all registered drivers for
each device during app initialization, only matched one can be logged.

>  
> -		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
> -				dev->id.device_id, dr->driver.name);
> +	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
> +		/* map resources for devices that use igb_uio */
> +		ret = rte_eal_pci_map_device(dev);
> +		if (ret != 0)
> +			return ret;
> +	}
>  
> -		if (dr->remove && (dr->remove(dev) < 0))
> -			return -1;	/* negative value is an error */
> +	/* reference driver structure */
> +	dev->driver = dr;
>  
> -		/* clear driver structure */
> +	/* call the driver probe() function */
> +	ret = dr->probe(dr, dev);
> +	if (ret) {
>  		dev->driver = NULL;
> -
>  		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> -			/* unmap resources for devices that use igb_uio */
>  			rte_eal_pci_unmap_device(dev);
> +	}
>  
> -		return 0;
> +	return ret;
> +}

<...>

> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> index b553b13..5ed2589 100644
> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> @@ -186,5 +186,6 @@ DPDK_17.02 {
>  	rte_bus_dump;
>  	rte_bus_register;
>  	rte_bus_unregister;
> +	rte_pci_match;

I think this is internal API, should library expose this API?

>  
>  } DPDK_16.11;
> 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 5/8] eal: introduce bus scan and probe in EAL
  2017-01-16 15:38 ` [PATCH v6 5/8] eal: introduce bus scan and probe in EAL Shreyansh Jain
@ 2017-01-16 19:58   ` Ferruh Yigit
  2017-01-17  5:03     ` Shreyansh Jain
  2017-01-17 10:13     ` Shreyansh Jain
  0 siblings, 2 replies; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-16 19:58 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
> Each bus implementation defines their own callbacks for scanning bus
> and probing devices available on the bus. Enable EAL to call bus specific
> scan and probe functions during DPDK initialization.
> 
> Existing PCI scan/probe continues to exist. It will removed in subsequent
> patches.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

<...>

> +/* Scan all the buses for registering devices */
> +int
> +rte_bus_scan(void)

I hesitate to make this kind of (not really functional) comments in this
stage of the release, but please feel free to ignore them as your wish.

Previous patch is (4/8) for adding bus scan support, so why not this
function (also .map and .h file part of it) added in prev patch?

And if there is a specific patch for scan, probe can be another one?

> +{
> +	int ret;
> +	struct rte_bus *bus = NULL;
> +
> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +		ret = bus->scan();
> +		if (ret) {
> +			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
> +				bus->name);
> +			/* Error in scanning any bus stops the EAL init. */
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}

<...>

> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 0d799be..35da451 100644
<...>
> +
> +/* Add a PCI device to PCI Bus */
> +void
> +rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
> +		       struct rte_pci_device *pci_dev)

I think more generic approach from previous version was better
(rte_eal_bus_add_device()), but I guess they sacrificed for less
modification.

> +{
> +	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
> +	/* Update Bus references */
> +	pci_dev->device.bus = &pci_bus->bus;
> +}
> +

<...>

>  
> +/**
> + * Structure describing the PCI bus
> + */
> +struct rte_pci_bus {
> +	struct rte_bus bus;               /**< Inherit the generic class */
> +	struct rte_pci_device_list device_list;  /**< List of PCI devices */
> +	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */

Why bus device/driver lists moved from rte_bus? Each bus will need this?
Is it to change as less code as possible?

<...>

> +
> +/**
> + * Insert a PCI device in the PCI Bus at a particular location in the device
> + * list. It also updates the PCI Bus reference of the new devices to be
> + * inserted.

Minor issue in document compilation:

- warning: argument 'pci_dev' of command @param is not found

- parameter 'new_pci_dev' not documented

Similar warnings exists for rte_eal_pci_remove_device() too.

Also following in rte_bus_scan(void) and rte_bus_probe(void)
- warning: argument 'void' of command @param is not found

> + *
> + * @param exist_pci_dev
> + *	Existing PCI device in PCI Bus
> + * @param pci_dev
> + *	PCI device to be added before exist_pci_dev
> + * @return void
> + */
> +void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
> +			       struct rte_pci_device *new_pci_dev);
> +

<...>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 7/8] eal: enable PCI bus
  2017-01-16 15:38 ` [PATCH v6 7/8] eal: enable PCI bus Shreyansh Jain
@ 2017-01-16 19:58   ` Ferruh Yigit
  2017-01-17  5:04     ` Shreyansh Jain
  2017-01-17 10:11     ` Shreyansh Jain
  0 siblings, 2 replies; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-16 19:58 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
> Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---

<...>

> -/* Init the PCI EAL subsystem */
> -int
> -rte_eal_pci_init(void)
> -{
> -	/* for debug purposes, PCI can be disabled */
> -	if (internal_config.no_pci)
> -		return 0;

Are we losing this feature? Should this check moved to rte_eal_pci_scan() ?

<...>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 3/8] pci: split match and probe function
  2017-01-16 19:53   ` Ferruh Yigit
@ 2017-01-17  4:54     ` Shreyansh Jain
  2017-01-17  9:58       ` Ferruh Yigit
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17  4:54 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

Hello Ferruh,

On Tuesday 17 January 2017 01:23 AM, Ferruh Yigit wrote:
> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>> Matching of PCI device address and driver ID table is being done at two
>> discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
>> and rte_eal_pci_detach_dev).
>>
>> Splitting the matching function into a public fn rte_pci_match.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> <...>
>
>>  /*
>> - * If vendor/device ID match, call the remove() function of the
>> + * If vendor/device ID match, call the probe() function of the
>>   * driver.
>>   */
>>  static int
>> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
>> -		struct rte_pci_device *dev)
>> +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
>> +			     struct rte_pci_device *dev)
>>  {
>> -	const struct rte_pci_id *id_table;
>> +	int ret;
>> +	struct rte_pci_addr *loc;
>>
>>  	if ((dr == NULL) || (dev == NULL))
>>  		return -EINVAL;
>>
>> -	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
>> +	loc = &dev->addr;
>>
>> -		/* check if device's identifiers match the driver's ones */
>> -		if (id_table->vendor_id != dev->id.vendor_id &&
>> -				id_table->vendor_id != PCI_ANY_ID)
>> -			continue;
>> -		if (id_table->device_id != dev->id.device_id &&
>> -				id_table->device_id != PCI_ANY_ID)
>> -			continue;
>> -		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
>> -				id_table->subsystem_vendor_id != PCI_ANY_ID)
>> -			continue;
>> -		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
>> -				id_table->subsystem_device_id != PCI_ANY_ID)
>> -			continue;
>> +	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>> +			loc->domain, loc->bus, loc->devid, loc->function,
>> +			dev->device.numa_node);
>
> This cause bunch of log printed during app startup, what about printing
> this log when probed device found?

Only thing I did was move around this log message without adding 
anything new. Maybe earlier it was in some conditional (match) and now 
it isn't. I will check again and move to match-only case.

>
>>
>> -		struct rte_pci_addr *loc = &dev->addr;
>> +	/* The device is not blacklisted; Check if driver supports it */
>> +	ret = rte_pci_match(dr, dev);
>> +	if (ret) {
>> +		/* Match of device and driver failed */
>> +		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
>> +			dr->driver.name);
>> +		return 1;
>> +	}
>> +
>> +	/* no initialization when blacklisted, return without error */
>> +	if (dev->device.devargs != NULL &&
>> +		dev->device.devargs->type ==
>> +			RTE_DEVTYPE_BLACKLISTED_PCI) {
>> +		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
>> +			" initializing\n");
>> +		return 1;
>> +	}
>>
>> -		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>> -				loc->domain, loc->bus, loc->devid,
>> -				loc->function, dev->device.numa_node);
>> +	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
>> +		dev->id.device_id, dr->driver.name);
>
> Same for this one, this line cause printing all registered drivers for
> each device during app initialization, only matched one can be logged.

Same. Will post v7 shortly with only match case printing.
What about DEBUG for all cases?

>
>>
>> -		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
>> -				dev->id.device_id, dr->driver.name);
>> +	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
>> +		/* map resources for devices that use igb_uio */
>> +		ret = rte_eal_pci_map_device(dev);
>> +		if (ret != 0)
>> +			return ret;
>> +	}
>>
>> -		if (dr->remove && (dr->remove(dev) < 0))
>> -			return -1;	/* negative value is an error */
>> +	/* reference driver structure */
>> +	dev->driver = dr;
>>
>> -		/* clear driver structure */
>> +	/* call the driver probe() function */
>> +	ret = dr->probe(dr, dev);
>> +	if (ret) {
>>  		dev->driver = NULL;
>> -
>>  		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
>> -			/* unmap resources for devices that use igb_uio */
>>  			rte_eal_pci_unmap_device(dev);
>> +	}
>>
>> -		return 0;
>> +	return ret;
>> +}
>
> <...>
>
>> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>> index b553b13..5ed2589 100644
>> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>> @@ -186,5 +186,6 @@ DPDK_17.02 {
>>  	rte_bus_dump;
>>  	rte_bus_register;
>>  	rte_bus_unregister;
>> +	rte_pci_match;
>
> I think this is internal API, should library expose this API?

Idea is that pci_match be useable outside of PCI for any other PCI-like 
bus (BDF compliant). For example, one of NXP's devices are very close to 
PCI (but not exactly PCI) and they too rely on BDF for addressing/naming.

>
>>
>>  } DPDK_16.11;
>>
>
>

-
Shreyansh

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 5/8] eal: introduce bus scan and probe in EAL
  2017-01-16 19:58   ` Ferruh Yigit
@ 2017-01-17  5:03     ` Shreyansh Jain
  2017-01-17 23:04       ` Thomas Monjalon
  2017-01-17 10:13     ` Shreyansh Jain
  1 sibling, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17  5:03 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:
> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>> Each bus implementation defines their own callbacks for scanning bus
>> and probing devices available on the bus. Enable EAL to call bus specific
>> scan and probe functions during DPDK initialization.
>>
>> Existing PCI scan/probe continues to exist. It will removed in subsequent
>> patches.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> <...>
>
>> +/* Scan all the buses for registering devices */
>> +int
>> +rte_bus_scan(void)
>
> I hesitate to make this kind of (not really functional) comments in this
> stage of the release, but please feel free to ignore them as your wish.

No issues - any review comment is welcome.

>
> Previous patch is (4/8) for adding bus scan support, so why not this
> function (also .map and .h file part of it) added in prev patch?

Maybe I didn't get your point well, but this is my take:

4/8 is for introducing the scan callbacks into the Bus layer. There is 
no work done for EAL yet in 4/8.

This patch, 5/8, adds functions (not callbacks) and modifications to EAL 
for plugging the bus (with its scan/probe) into EAL.

>
> And if there is a specific patch for scan, probe can be another one?

I agree with this.

>
>> +{
>> +	int ret;
>> +	struct rte_bus *bus = NULL;
>> +
>> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
>> +		ret = bus->scan();
>> +		if (ret) {
>> +			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
>> +				bus->name);
>> +			/* Error in scanning any bus stops the EAL init. */
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>
> <...>
>
>> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
>> index 0d799be..35da451 100644
> <...>
>> +
>> +/* Add a PCI device to PCI Bus */
>> +void
>> +rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
>> +		       struct rte_pci_device *pci_dev)
>
> I think more generic approach from previous version was better
> (rte_eal_bus_add_device()), but I guess they sacrificed for less
> modification.

There was a lot of offline discussions after the reviews were posted 
until v5. From the gist of it, I gathered that smaller 'specific' 
changes are preferred as compared to complete generic approach without 
an upfront usecase.

Also, this change became irrelevant once I moved out the device/driver 
lists from rte_bus to rte_xxx_bus. This is inline with existing model of 
(rte_pci_device->rte_device, rte_pci_driver->rte_driver, 
rte_pci_bus->rte_bus) and having pci_device_list/pci_driver_list private 
to PCI itself.

I guess what is going to happen is that in near future when buses start 
moving to drivers/bus/*, this kind of generic layer would come in.

>
>> +{
>> +	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
>> +	/* Update Bus references */
>> +	pci_dev->device.bus = &pci_bus->bus;
>> +}
>> +
>
> <...>
>
>>
>> +/**
>> + * Structure describing the PCI bus
>> + */
>> +struct rte_pci_bus {
>> +	struct rte_bus bus;               /**< Inherit the generic class */
>> +	struct rte_pci_device_list device_list;  /**< List of PCI devices */
>> +	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
>
> Why bus device/driver lists moved from rte_bus? Each bus will need this?
> Is it to change as less code as possible?

Yes, to move towards a minimal change.
Also, in sync with existing 'pci_device_list/pci_driver_list'.

>
> <...>
>
>> +
>> +/**
>> + * Insert a PCI device in the PCI Bus at a particular location in the device
>> + * list. It also updates the PCI Bus reference of the new devices to be
>> + * inserted.
>
> Minor issue in document compilation:
>
> - warning: argument 'pci_dev' of command @param is not found
>
> - parameter 'new_pci_dev' not documented
>
> Similar warnings exists for rte_eal_pci_remove_device() too.
>
> Also following in rte_bus_scan(void) and rte_bus_probe(void)
> - warning: argument 'void' of command @param is not found

I will fix and post v7 very shortly.

>
>> + *
>> + * @param exist_pci_dev
>> + *	Existing PCI device in PCI Bus
>> + * @param pci_dev
>> + *	PCI device to be added before exist_pci_dev
>> + * @return void
>> + */
>> +void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
>> +			       struct rte_pci_device *new_pci_dev);
>> +
>
> <...>
>
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 7/8] eal: enable PCI bus
  2017-01-16 19:58   ` Ferruh Yigit
@ 2017-01-17  5:04     ` Shreyansh Jain
  2017-01-17 10:11     ` Shreyansh Jain
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17  5:04 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:
> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>> Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> ---
>
> <...>
>
>> -/* Init the PCI EAL subsystem */
>> -int
>> -rte_eal_pci_init(void)
>> -{
>> -	/* for debug purposes, PCI can be disabled */
>> -	if (internal_config.no_pci)
>> -		return 0;
>
> Are we losing this feature? Should this check moved to rte_eal_pci_scan() ?

Yes, that is miss from my side. v5 had this, but I missed in v6 in all 
that code movement. I will add that to rte_eal_pci_scan.
Thanks for highlighting.

>
> <...>
>
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model
  2017-01-16 18:27 ` [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Stephen Hemminger
@ 2017-01-17  5:08   ` Shreyansh Jain
  2017-01-17  5:09   ` Shreyansh Jain
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17  5:08 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: david.marchand, dev, thomas.monjalon

On Monday 16 January 2017 11:57 PM, Stephen Hemminger wrote:
> On Mon, 16 Jan 2017 21:08:19 +0530
> Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>
>> Link to v5: [15]
>>
>> :: Introduction ::
>>
>> DPDK has been inherently a PCI inclined framework. Because of this, the
>> design of device tree (or list) within DPDK is also PCI inclined. A
>> non-PCI device doesn't have a way of being expressed without using hooks
>> started from EAL to PMD.
>>
>> (Check 'Version Changes' section for changes)
>>
>> :: Overview of the Proposed Changes ::
>>
>> Assuming the below graph for a computing node:
>>
>>         device A1
>>           |
>>   +==.===='==============.============+ Bus A.
>>      |                    `--> driver A11     \
>>   device A2                `-> driver A12      \______
>>                                                 |CPU |
>>                                                 /`````
>>         device B1                              /
>>           |                                   /
>>   +==.===='==============.============+ Bus B`
>>      |                    `--> driver B11
>>   device B2                `-> driver B12
>>
>>
>>  - One or more buses are connected to a CPU (or core)
>>  - One or more devices are conneted to a Bus
>>  - Drivers are running instances which manage one or more devices
>>  - Bus is responsible for identifying devices (and interrupt propogation)
>>  - Driver is responsible for initializing the device
>>
>> In [15], model assumes that rte_bus would be the base class using which
>> all the bus implementations would instantiate the objects. This patches
>> takes a much more basic approach, on the same lines of rte_device/
>> rte_driver and rte_pci_device/rte_pci_driver.
>> This is based on various review comments as well as offline (IRC)
>> discussions.
>>
>>  - rte_bus is an abstract class which includes basic methods supported by
>>    all buses.
>>  - specific implementation, for example for PCI rte_pci_bus, would extend
>>    this class to form their own buses, with their own bus specific device
>>    and driver list.
>>  -
>>
>>  +-----------------+
>>  |rte_pci_bus      |
>>  |+---------------+|
>>  ||rte_bus        ||
>>  |+---------------+|
>>  +-----------------+
>>
>> And example implementation would look like:
>>
>>   .--------------->+-------------------+
>>   |                |rte_pci_bus        |
>>   |                | +----------------+|
>>   |                | |rte_bus         <------.
>>   |                | | name           ||     |
>>   |                | | scan           ||     |
>>   |                | | probe          ||     |
>>   |                | | attach         ||     |
>>   |                | | detach         ||     |
>>   |                | +----------------+|     |
>>   |                | pci_driver_list   |     |
>>   |  .-------------->pci_device_list   |     |
>>   |  |             | ...               |     |
>>   |  |             +-------------------+     |
>>   |  |                                       |
>>   |  +-------------------+                   |
>>   |  |rte_pci_device     |                   |
>>   '----bus               |                   |
>>      | +----------------+|                   |
>>      | |rte_device      ||                   |
>>      | | bus --------------------------------'
>>      | | ...            ||
>>      | +----------------+|
>>      | ...               |
>>      +-------------------+
>>
>>
>> :: Brief about Patch Layout ::
>>
>> 0001~0002: Introducing the basic Bus model and associated test case
>> 0003     : Split the PCI match into a separate function
>> 0004~0005: Introduce bus->scan APIs and integrate with EAL
>> 0006     : Update the Bus and PCI test cases for scanning/probing
>> 0007     : Enable PCI bus and remove code for direct PCI scan/probe from
>>            EAL
>> 0008     : Add device hotplugging over the bus and introduce PCI helpers
>>
>>
>> :: Pending Changes/Caveats ::
>>
>> 1. This patchset only moves the PCI into a bus. And, that movement is also
>>    currently part of the EAL (lib/librte_eal/linux)
>>    Eventual aim is the PCI bus reside in driver/bus/pci
>>
>> 2. Though the implementation for bus is common for Linux and BSD, the PCI
>>    bus implementation has been done/tested only for Linux.
>>
>> 3. RTE_REGISTER_BUS has been declared with contructor priority of 101
>>     It is important that Bus is registered *before* drivers are registered.
>>     Only way I could find to assure that was via
>>     __attribute(contructor(priority)) of GCC. I am not sure how it would
>>     behave on other compilers. Any suggestions?
>>     - One suggestion from David Marchand was to use global bus object
>>       handles, which I have not implemented for now. If that is common
>>       choice, I will change in v3.
>>
>> :: ToDo list ::
>>
>>  - Bump to librte_eal version
>>  - Documentation continues to have references to some _old_ PCI symbols
>>
>> :: References ::
>>
>> [1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
>> [2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
>> [3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
>> [4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
>> [5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
>> [6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
>> [7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
>> [8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
>> [9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
>> [10] http://dpdk.org/ml/archives/dev/2016-December/051349.html
>> [12] http://dpdk.org/ml/archives/dev/2016-December/052092.html
>> [13] http://dpdk.org/ml/archives/dev/2016-December/052381.html
>> [14] http://dpdk.org/ml/archives/dev/2016-December/053302.html
>> [15] http://dpdk.org/ml/archives/dev/2016-December/053315.html
>>
>> :: Version Changes ::
>> v6:
>>  - Rearchitecture to bring bus object parallel to rte_device/driver
>>    This majorly includes:
>>    -- rte_pci_bus class and pci_bus as its object for PCI
>>    -- bus->attach/detach (hotplugging)
>>    -- removing bus->match as that is local to an implementation
>>  - rename symbols rte_eal_bus_* to rte_bus_*
>>  - restructuring patches (order) for simplicity
>>  - update to test_pci
>>
>> v5:
>>  - Fix checkpatch error in Patch 0003
>>
>> v4:
>>  - rebase over master (eac901ce)
>>  - Fix a bug in test_bus while setup and cleanup
>>  - rename rte_eal_get_bus to rte_eal_bus_get
>>  - Add helper (iterator) macros for easy bus,device,driver traversal
>>  - removed 0001 patch as it is already merged in master
>>  - fix missing rte_eal_bus_insert_device symbol in map file
>>
>> v3:
>>  - rebase over master (c431384c8f)
>>  - revert patch 0001 changes for checkpatch (container_of macro)
>>  - qat/rte_qat_cryptodev update for rte_driver->probe
>>  - test_pci update for using a test_pci_bus for verification
>>  - some bug fixes based on internal testing.
>>  -- rte_eal_dev_attach not handling devargs
>>  -- blacklisting not working
>>
>> v2:
>>  - No more bus->probe()
>>    Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
>>  - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
>>    added as glue code between PCI PMDs and PCI Bus
>>    `-> PMDs are updated to use these new functions as callbacks for
>>        rte_driver
>>  - 'default' keyword has been removed from match and scan
>>  - Fix for incorrect changes in mlx* and nicvf*
>>  - Checkpatch fixes
>>  - Some variable checks have been removed from internal functions;
>>    functions which are externally visible continue to have such checks
>>  - Some rearrangement of patches:
>>    -- changes to drivers have been separated from EAL changes (but this
>>       does make PCI PMDs non-working for a particular patch)
>>
>> Shreyansh Jain (8):
>>   eal/bus: introduce bus abstraction
>>   test: add basic bus infrastructure tests
>>   pci: split match and probe function
>>   eal/bus: support for scanning of bus
>>   eal: introduce bus scan and probe in EAL
>>   test: update bus and pci unit test cases
>>   eal: enable PCI bus
>>   eal: enable hotplugging of devices on bus
>>
>>  app/test/Makefile                               |   2 +-
>>  app/test/test.h                                 |   2 +
>>  app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
>>  app/test/test_pci.c                             | 164 ++++--
>>  lib/librte_eal/bsdapp/eal/Makefile              |   1 +
>>  lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
>>  lib/librte_eal/bsdapp/eal/eal_pci.c             |  13 +
>>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
>>  lib/librte_eal/common/Makefile                  |   2 +-
>>  lib/librte_eal/common/eal_common_bus.c          | 140 +++++
>>  lib/librte_eal/common/eal_common_dev.c          |  56 +-
>>  lib/librte_eal/common/eal_common_pci.c          | 330 ++++++++----
>>  lib/librte_eal/common/eal_private.h             |  10 -
>>  lib/librte_eal/common/include/rte_bus.h         | 206 +++++++
>>  lib/librte_eal/common/include/rte_dev.h         |   1 +
>>  lib/librte_eal/common/include/rte_pci.h         | 161 +++++-
>>  lib/librte_eal/linuxapp/eal/Makefile            |   1 +
>>  lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
>>  lib/librte_eal/linuxapp/eal/eal_pci.c           |  53 +-
>>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
>>  20 files changed, 1646 insertions(+), 238 deletions(-)
>>  create mode 100644 app/test/test_bus.c
>>  create mode 100644 lib/librte_eal/common/eal_common_bus.c
>>  create mode 100644 lib/librte_eal/common/include/rte_bus.h
>>
>
>
> All this is excellent, but doesn't go far enough to break the assumptions
> of 'struct eth_driver'
>

That true. But, this is the first step. Next would be:
  - unlinking eth_device from pci_device (already upstream by Jan)
  - unlinking eth_driver from pci_driver dependency
  - Same steps for cryptodev (I will pick this next)
  - moving buses to drivers/bus

And some more minor changes making PCI just one bus exposing services; 
eth_device/eth_driver being just a type of device provided by DPDK 
without any linkage to bus actual device belongs to.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model
  2017-01-16 18:27 ` [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Stephen Hemminger
  2017-01-17  5:08   ` Shreyansh Jain
@ 2017-01-17  5:09   ` Shreyansh Jain
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17  5:09 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: david.marchand, dev, thomas.monjalon

On Monday 16 January 2017 11:57 PM, Stephen Hemminger wrote:
> On Mon, 16 Jan 2017 21:08:19 +0530
> Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>
>> Link to v5: [15]
>>
>> :: Introduction ::
>>
>> DPDK has been inherently a PCI inclined framework. Because of this, the
>> design of device tree (or list) within DPDK is also PCI inclined. A
>> non-PCI device doesn't have a way of being expressed without using hooks
>> started from EAL to PMD.
>>
>> (Check 'Version Changes' section for changes)
>>
>> :: Overview of the Proposed Changes ::
>>
>> Assuming the below graph for a computing node:
>>
>>         device A1
>>           |
>>   +==.===='==============.============+ Bus A.
>>      |                    `--> driver A11     \
>>   device A2                `-> driver A12      \______
>>                                                 |CPU |
>>                                                 /`````
>>         device B1                              /
>>           |                                   /
>>   +==.===='==============.============+ Bus B`
>>      |                    `--> driver B11
>>   device B2                `-> driver B12
>>
>>
>>  - One or more buses are connected to a CPU (or core)
>>  - One or more devices are conneted to a Bus
>>  - Drivers are running instances which manage one or more devices
>>  - Bus is responsible for identifying devices (and interrupt propogation)
>>  - Driver is responsible for initializing the device
>>
>> In [15], model assumes that rte_bus would be the base class using which
>> all the bus implementations would instantiate the objects. This patches
>> takes a much more basic approach, on the same lines of rte_device/
>> rte_driver and rte_pci_device/rte_pci_driver.
>> This is based on various review comments as well as offline (IRC)
>> discussions.
>>
>>  - rte_bus is an abstract class which includes basic methods supported by
>>    all buses.
>>  - specific implementation, for example for PCI rte_pci_bus, would extend
>>    this class to form their own buses, with their own bus specific device
>>    and driver list.
>>  -
>>
>>  +-----------------+
>>  |rte_pci_bus      |
>>  |+---------------+|
>>  ||rte_bus        ||
>>  |+---------------+|
>>  +-----------------+
>>
>> And example implementation would look like:
>>
>>   .--------------->+-------------------+
>>   |                |rte_pci_bus        |
>>   |                | +----------------+|
>>   |                | |rte_bus         <------.
>>   |                | | name           ||     |
>>   |                | | scan           ||     |
>>   |                | | probe          ||     |
>>   |                | | attach         ||     |
>>   |                | | detach         ||     |
>>   |                | +----------------+|     |
>>   |                | pci_driver_list   |     |
>>   |  .-------------->pci_device_list   |     |
>>   |  |             | ...               |     |
>>   |  |             +-------------------+     |
>>   |  |                                       |
>>   |  +-------------------+                   |
>>   |  |rte_pci_device     |                   |
>>   '----bus               |                   |
>>      | +----------------+|                   |
>>      | |rte_device      ||                   |
>>      | | bus --------------------------------'
>>      | | ...            ||
>>      | +----------------+|
>>      | ...               |
>>      +-------------------+
>>
>>
>> :: Brief about Patch Layout ::
>>
>> 0001~0002: Introducing the basic Bus model and associated test case
>> 0003     : Split the PCI match into a separate function
>> 0004~0005: Introduce bus->scan APIs and integrate with EAL
>> 0006     : Update the Bus and PCI test cases for scanning/probing
>> 0007     : Enable PCI bus and remove code for direct PCI scan/probe from
>>            EAL
>> 0008     : Add device hotplugging over the bus and introduce PCI helpers
>>
>>
>> :: Pending Changes/Caveats ::
>>
>> 1. This patchset only moves the PCI into a bus. And, that movement is also
>>    currently part of the EAL (lib/librte_eal/linux)
>>    Eventual aim is the PCI bus reside in driver/bus/pci
>>
>> 2. Though the implementation for bus is common for Linux and BSD, the PCI
>>    bus implementation has been done/tested only for Linux.
>>
>> 3. RTE_REGISTER_BUS has been declared with contructor priority of 101
>>     It is important that Bus is registered *before* drivers are registered.
>>     Only way I could find to assure that was via
>>     __attribute(contructor(priority)) of GCC. I am not sure how it would
>>     behave on other compilers. Any suggestions?
>>     - One suggestion from David Marchand was to use global bus object
>>       handles, which I have not implemented for now. If that is common
>>       choice, I will change in v3.
>>
>> :: ToDo list ::
>>
>>  - Bump to librte_eal version
>>  - Documentation continues to have references to some _old_ PCI symbols
>>
>> :: References ::
>>
>> [1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
>> [2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
>> [3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
>> [4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
>> [5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
>> [6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
>> [7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
>> [8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
>> [9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
>> [10] http://dpdk.org/ml/archives/dev/2016-December/051349.html
>> [12] http://dpdk.org/ml/archives/dev/2016-December/052092.html
>> [13] http://dpdk.org/ml/archives/dev/2016-December/052381.html
>> [14] http://dpdk.org/ml/archives/dev/2016-December/053302.html
>> [15] http://dpdk.org/ml/archives/dev/2016-December/053315.html
>>
>> :: Version Changes ::
>> v6:
>>  - Rearchitecture to bring bus object parallel to rte_device/driver
>>    This majorly includes:
>>    -- rte_pci_bus class and pci_bus as its object for PCI
>>    -- bus->attach/detach (hotplugging)
>>    -- removing bus->match as that is local to an implementation
>>  - rename symbols rte_eal_bus_* to rte_bus_*
>>  - restructuring patches (order) for simplicity
>>  - update to test_pci
>>
>> v5:
>>  - Fix checkpatch error in Patch 0003
>>
>> v4:
>>  - rebase over master (eac901ce)
>>  - Fix a bug in test_bus while setup and cleanup
>>  - rename rte_eal_get_bus to rte_eal_bus_get
>>  - Add helper (iterator) macros for easy bus,device,driver traversal
>>  - removed 0001 patch as it is already merged in master
>>  - fix missing rte_eal_bus_insert_device symbol in map file
>>
>> v3:
>>  - rebase over master (c431384c8f)
>>  - revert patch 0001 changes for checkpatch (container_of macro)
>>  - qat/rte_qat_cryptodev update for rte_driver->probe
>>  - test_pci update for using a test_pci_bus for verification
>>  - some bug fixes based on internal testing.
>>  -- rte_eal_dev_attach not handling devargs
>>  -- blacklisting not working
>>
>> v2:
>>  - No more bus->probe()
>>    Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
>>  - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
>>    added as glue code between PCI PMDs and PCI Bus
>>    `-> PMDs are updated to use these new functions as callbacks for
>>        rte_driver
>>  - 'default' keyword has been removed from match and scan
>>  - Fix for incorrect changes in mlx* and nicvf*
>>  - Checkpatch fixes
>>  - Some variable checks have been removed from internal functions;
>>    functions which are externally visible continue to have such checks
>>  - Some rearrangement of patches:
>>    -- changes to drivers have been separated from EAL changes (but this
>>       does make PCI PMDs non-working for a particular patch)
>>
>> Shreyansh Jain (8):
>>   eal/bus: introduce bus abstraction
>>   test: add basic bus infrastructure tests
>>   pci: split match and probe function
>>   eal/bus: support for scanning of bus
>>   eal: introduce bus scan and probe in EAL
>>   test: update bus and pci unit test cases
>>   eal: enable PCI bus
>>   eal: enable hotplugging of devices on bus
>>
>>  app/test/Makefile                               |   2 +-
>>  app/test/test.h                                 |   2 +
>>  app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
>>  app/test/test_pci.c                             | 164 ++++--
>>  lib/librte_eal/bsdapp/eal/Makefile              |   1 +
>>  lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
>>  lib/librte_eal/bsdapp/eal/eal_pci.c             |  13 +
>>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
>>  lib/librte_eal/common/Makefile                  |   2 +-
>>  lib/librte_eal/common/eal_common_bus.c          | 140 +++++
>>  lib/librte_eal/common/eal_common_dev.c          |  56 +-
>>  lib/librte_eal/common/eal_common_pci.c          | 330 ++++++++----
>>  lib/librte_eal/common/eal_private.h             |  10 -
>>  lib/librte_eal/common/include/rte_bus.h         | 206 +++++++
>>  lib/librte_eal/common/include/rte_dev.h         |   1 +
>>  lib/librte_eal/common/include/rte_pci.h         | 161 +++++-
>>  lib/librte_eal/linuxapp/eal/Makefile            |   1 +
>>  lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
>>  lib/librte_eal/linuxapp/eal/eal_pci.c           |  53 +-
>>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
>>  20 files changed, 1646 insertions(+), 238 deletions(-)
>>  create mode 100644 app/test/test_bus.c
>>  create mode 100644 lib/librte_eal/common/eal_common_bus.c
>>  create mode 100644 lib/librte_eal/common/include/rte_bus.h
>>
>
>
> All this is excellent, but doesn't go far enough to break the assumptions
> of 'struct eth_driver'
>

That is true. But, this is the first step of many steps. Next would be:
  - unlinking eth_device from pci_device (already upstream by Jan)
  - unlinking eth_driver from pci_driver dependency
  - Same steps for cryptodev (I will pick this next)
  - moving buses to drivers/bus

And some more minor changes making PCI just one bus exposing services; 
eth_device/eth_driver being just a type of device provided by DPDK 
without any linkage to bus actual device belongs to.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 8/8] eal: enable hotplugging of devices on bus
  2017-01-16 15:38 ` [PATCH v6 8/8] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-17  7:24   ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17  7:24 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon

On Monday 16 January 2017 09:08 PM, Shreyansh Jain wrote:
> Given a bus, attach and detach callbacks allow the implementation to
> handles calls from EAL for attaching or detaching a named device.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
>  lib/librte_eal/common/eal_common_dev.c  | 56 +++++++++++++++++-----
>  lib/librte_eal/common/eal_common_pci.c  | 82 +++++++++++++++++++++++++++++++--
>  lib/librte_eal/common/include/rte_bus.h | 35 ++++++++++++++
>  lib/librte_eal/common/include/rte_pci.h | 58 +++++++++++++++++++----
>  lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
>  6 files changed, 212 insertions(+), 23 deletions(-)
>
> diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
> index 48bfe24..17a04d9 100644
> --- a/lib/librte_eal/bsdapp/eal/eal_pci.c
> +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
> @@ -678,6 +678,8 @@ struct rte_pci_bus rte_pci_bus = {
>  	.bus = {
>  		.scan = rte_eal_pci_scan,
>  		.probe = rte_eal_pci_probe,
> +		.attach = rte_eal_pci_attach,
> +		.detach = rte_eal_pci_detach,
>  	},
>  	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
>  	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
> diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
> index 4f3b493..b363fa9 100644
> --- a/lib/librte_eal/common/eal_common_dev.c
> +++ b/lib/librte_eal/common/eal_common_dev.c
> @@ -38,6 +38,7 @@
>  #include <sys/queue.h>
>
>  #include <rte_dev.h>
> +#include <rte_bus.h>
>  #include <rte_devargs.h>
>  #include <rte_debug.h>
>  #include <rte_devargs.h>
> @@ -106,23 +107,37 @@ rte_eal_dev_init(void)
>
>  int rte_eal_dev_attach(const char *name, const char *devargs)
>  {
> -	struct rte_pci_addr addr;
> +	int ret = 1;
> +	struct rte_bus *bus;
>
>  	if (name == NULL || devargs == NULL) {
>  		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
>  		return -EINVAL;
>  	}
>
> -	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
> -		if (rte_eal_pci_probe_one(&addr) < 0)
> +	FOREACH_BUS(bus) {
> +		if (!bus->attach) {
> +			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
> +				" attach.\n", bus->name);
> +			continue;
> +		}
> +		ret = bus->attach(bus, name);
> +		if (!ret) /* device successfully attached */
> +			return ret;
> +		if (ret > 0) /* device not found on bus */
> +			continue;
> +		else
>  			goto err;
> +	}
>
> -	} else {
> -		if (rte_eal_vdev_init(name, devargs))
> +	if (ret > 0) {
> +		/* In case the device was not found on any bus, search VDEV */
> +		ret = rte_eal_vdev_init(name, devargs);
> +		if (ret)
>  			goto err;
>  	}
>
> -	return 0;
> +	return ret;
>
>  err:
>  	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
> @@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
>
>  int rte_eal_dev_detach(const char *name)
>  {
> -	struct rte_pci_addr addr;
> +	int ret = 1;
> +	struct rte_bus *bus;
>
>  	if (name == NULL) {
>  		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
>  		return -EINVAL;
>  	}
>
> -	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
> -		if (rte_eal_pci_detach(&addr) < 0)
> +	FOREACH_BUS(bus) {
> +		if (!bus->detach) {
> +			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
> +				" detach.\n", bus->name);
> +			continue;
> +		}
> +
> +		ret = bus->detach(bus, name);
> +		if (!ret) /* device successfully detached */
> +			return ret;
> +		if (ret > 0) /* device not found on the bus */
> +			continue;
> +		else
>  			goto err;
> -	} else {
> -		if (rte_eal_vdev_uninit(name))
> +	}
> +
> +	if (ret > 0) {
> +		/* In case the device was not found on any bus, search VDEV */
> +		ret = rte_eal_vdev_uninit(name);
> +		if (ret)
>  			goto err;
>  	}
> -	return 0;
> +
> +	return ret;
>
>  err:
>  	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 1d283d2..1c205bd 100644
> --- a/lib/librte_eal/common/eal_common_pci.c
> +++ b/lib/librte_eal/common/eal_common_pci.c
> @@ -389,19 +389,95 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
>  }
>
>  /*
> + * Attach device specific by its name
> + */
> +int
> +rte_eal_pci_attach(struct rte_bus *bus __rte_unused, const char *device_name)
> +{
> +	struct rte_pci_device *dev = NULL;
> +	struct rte_pci_driver *drv = NULL;
> +	struct rte_pci_addr addr;
> +	int ret = -1;
> +
> +	if (!device_name)
> +		return -1;
> +
> +	memset(&addr, 0, sizeof(addr));
> +	if (eal_parse_pci_DomBDF(device_name, &addr) == 0) {
> +		/* Device doesn't match PCI BDF naming format */
> +		return -1;
> +	}
> +
> +	FOREACH_DEVICE_ON_PCIBUS(dev) {
> +		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
> +			continue;
> +
> +		FOREACH_DRIVER_ON_PCIBUS(drv) {
> +			ret = rte_pci_match(drv, dev);
> +			if (ret) {
> +				/* Match of device and driver failed */
> +				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
> +					" the device (%s)\n", drv->driver.name,
> +					device_name);
> +				continue;
> +			}
> +
> +			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
> +				dev->id.vendor_id, dev->id.device_id,
> +				drv->driver.name);
> +
> +			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
> +				/* map resources for devices that use
> +				 * igb_uio
> +				 */
> +				ret = rte_eal_pci_map_device(dev);
> +				if (ret != 0)
> +					goto err_return;
> +			}
> +
> +			/* reference driver structure */
> +			dev->driver = drv;
> +
> +			/* call the driver probe() function */
> +			ret = drv->probe(drv, dev);
> +			if (ret) {
> +				dev->driver = NULL;
> +				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> +					rte_eal_pci_unmap_device(dev);
> +			}
> +		}
> +	}
> +
> +	return ret;
> +
> +err_return:
> +	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
> +			" cannot be used\n", dev->addr.domain, dev->addr.bus,
> +			dev->addr.devid, dev->addr.function);
> +	return -1;
> +}
> +
> +/*
>   * Detach device specified by its pci address.
>   */
>  int
> -rte_eal_pci_detach(const struct rte_pci_addr *addr)
> +rte_eal_pci_detach(struct rte_bus *bus __rte_unused, const char *device_name)
>  {
>  	struct rte_pci_device *dev = NULL;
> +	struct rte_pci_addr addr;
>  	int ret = 0;
>
> -	if (addr == NULL)
> +	if (!device_name)
>  		return -1;
>
> +	memset(&addr, 0, sizeof(addr));
> +	if (eal_parse_pci_DomBDF(device_name, &addr) == 0) {
> +		/* Device doesn't match PCI BDF naming format */
> +		return -1;
> +	}
> +
>  	FOREACH_DEVICE_ON_PCIBUS(dev) {
> -		if (rte_eal_compare_pci_addr(&dev->addr, addr))
> +		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
>  			continue;
>
>  		ret = pci_detach_all_drivers(dev);
> diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
> index f1d4c2c..5b7ae0c 100644
> --- a/lib/librte_eal/common/include/rte_bus.h
> +++ b/lib/librte_eal/common/include/rte_bus.h
> @@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
>  /* Bus list exposed */
>  extern struct rte_bus_list rte_bus_list;
>
> +#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
> +
>  /**
>   * Bus specific scan for devices attached on the bus.
>   * For each bus object, the scan would be reponsible for finding devices and
> @@ -94,6 +96,37 @@ typedef int (*rte_bus_scan_t)(void);
>  typedef int (*rte_bus_probe_t)(void);
>
>  /**
> + * Attach a device to a bus, assuming it is 'connected' to the bus.
> + * A bus is responsible for scanning for devices. Attaching a new device is
> + * for reenabling the device after being detached/removed.
> + *
> + * @param bus
> + *	Generic bus object which was registered with EAL
> + * @param device_name
> + *	Name of the device to attach.
> + *
> + * @return
> + *	0 for successful attach
> + *	!0 for unsuccessful attach (or incorrect device name)
> + */
> +typedef int (*rte_bus_attach_t)(struct rte_bus *bus, const char *device_name);
> +
> +/**
> + * Detach a named device from a bus. Implementation would check the existence
> + * of device on the bus and detach it.
> + *
> + * @param bus
> + *	Generic bus object which was registered with EAL
> + * @param device_name
> + *	Name of the device to detach
> + *
> + * @return
> + *	0 for successful detaching
> + *	!0 if device not found or can't detach
> + */
> +typedef int (*rte_bus_detach_t)(struct rte_bus *bus, const char *device_name);
> +
> +/**
>   * A structure describing a generic bus.
>   */
>  struct rte_bus {
> @@ -101,6 +134,8 @@ struct rte_bus {
>  	const char *name;            /**< Name of the bus */
>  	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
>  	rte_bus_probe_t probe;       /**< Probe devices on bus */
> +	rte_bus_attach_t attach;     /**< Attach a named device */
> +	rte_bus_detach_t detach;     /**< Detach a named device */
>  };
>
>  /**
> diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
> index 5f8d679..6369584 100644
> --- a/lib/librte_eal/common/include/rte_pci.h
> +++ b/lib/librte_eal/common/include/rte_pci.h
> @@ -421,6 +421,40 @@ int
>  rte_eal_pci_probe(void);
>
>  /**
> + * Search and attach a PCI device to PCI Bus
> + * Implements rte_bus->attach
> + *
> + * @param bus
> + *	Generic bus object representing PCI bus
> + * @param device_name
> + *	Name of the device to search and attach
> + *
> + * @return
> + *	0 for successful removal of device
> + *	>0 if device not found on bus
> + *	<0 in case of error in removal.
> + */
> +int
> +rte_eal_pci_attach(struct rte_bus *bus, const char *device_name);

The first argument, rte_bus, is not required. I will remove this in v7.

> +
> +/**
> + * Search and detach a PCI device from PCI Bus
> + * Implements rte_bus->detach
> + *
> + * @param bus
> + *	Generic bus object representing PCI bus
> + * @param device_name
> + *	Name of the device to search and detach
> + *
> + * @return
> + *	0 for successful detaching of device
> + *	>0 if device not found on bus
> + *	<0 in case of error in removal.
> + */
> +int
> +rte_eal_pci_detach(struct rte_bus *bus, const char *device_name);

Same as above, rte_bus argument is not required and will be removed in v7.

> +
> +/**
>   * Map the PCI device resources in user space virtual memory address
>   *
>   * Note that driver should not call this function when flag
> @@ -494,19 +528,27 @@ void pci_unmap_resource(void *requested_addr, size_t size);
>  int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
>
>  /**
> - * Close the single PCI device.
> - *
> - * Scan the content of the PCI bus, and find the pci device specified by pci
> - * address, then call the remove() function for registered driver that has a
> - * matching entry in its id_table for discovered device.
> + * Attach a PCI device on PCI Bus
> + * @param bus
> + *	Generic Bus object for PCI Bus. If passed NULL, PCI bus is extracted
> + *	using Bus APIs.
> + * @param device_name
> + *	Device Name, which would be converted into BDF.
> + */
> +int rte_eal_pci_attach(struct rte_bus *bus, const char *device_name);
> +
> +/**
> + * Detach a single PCI device.
>   *
> - * @param addr
> - *	The PCI Bus-Device-Function address to close.
> + * @param bus
> + *	Generic bus object for PCI bus.
> + * @param device_name
> + *	Device Name, which would be converted into BDF.
>   * @return
>   *   - 0 on success.
>   *   - Negative on error.
>   */
> -int rte_eal_pci_detach(const struct rte_pci_addr *addr);
> +int rte_eal_pci_detach(struct rte_bus *bus, const char *device_name);
>
>  /**
>   * Dump the content of the PCI bus.
> diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
> index 50ad9f7..8084996 100644
> --- a/lib/librte_eal/linuxapp/eal/eal_pci.c
> +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
> @@ -716,6 +716,8 @@ struct rte_pci_bus rte_pci_bus = {
>  	.bus = {
>  		.scan = rte_eal_pci_scan,
>  		.probe = rte_eal_pci_probe,
> +		.attach = rte_eal_pci_attach,
> +		.detach = rte_eal_pci_detach,
>  	},
>  	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
>  	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 3/8] pci: split match and probe function
  2017-01-17  4:54     ` Shreyansh Jain
@ 2017-01-17  9:58       ` Ferruh Yigit
  2017-01-17 10:14         ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-17  9:58 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/17/2017 4:54 AM, Shreyansh Jain wrote:
> Hello Ferruh,
> 
> On Tuesday 17 January 2017 01:23 AM, Ferruh Yigit wrote:
>> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>>> Matching of PCI device address and driver ID table is being done at two
>>> discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
>>> and rte_eal_pci_detach_dev).
>>>
>>> Splitting the matching function into a public fn rte_pci_match.
>>>
>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>
>> <...>
>>
>>>  /*
>>> - * If vendor/device ID match, call the remove() function of the
>>> + * If vendor/device ID match, call the probe() function of the
>>>   * driver.
>>>   */
>>>  static int
>>> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
>>> -		struct rte_pci_device *dev)
>>> +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
>>> +			     struct rte_pci_device *dev)
>>>  {
>>> -	const struct rte_pci_id *id_table;
>>> +	int ret;
>>> +	struct rte_pci_addr *loc;
>>>
>>>  	if ((dr == NULL) || (dev == NULL))
>>>  		return -EINVAL;
>>>
>>> -	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
>>> +	loc = &dev->addr;
>>>
>>> -		/* check if device's identifiers match the driver's ones */
>>> -		if (id_table->vendor_id != dev->id.vendor_id &&
>>> -				id_table->vendor_id != PCI_ANY_ID)
>>> -			continue;
>>> -		if (id_table->device_id != dev->id.device_id &&
>>> -				id_table->device_id != PCI_ANY_ID)
>>> -			continue;
>>> -		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
>>> -				id_table->subsystem_vendor_id != PCI_ANY_ID)
>>> -			continue;
>>> -		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
>>> -				id_table->subsystem_device_id != PCI_ANY_ID)
>>> -			continue;
>>> +	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>>> +			loc->domain, loc->bus, loc->devid, loc->function,
>>> +			dev->device.numa_node);
>>
>> This cause bunch of log printed during app startup, what about printing
>> this log when probed device found?
> 
> Only thing I did was move around this log message without adding 
> anything new. Maybe earlier it was in some conditional (match) and now 
> it isn't. I will check again and move to match-only case.
> 
>>
>>>
>>> -		struct rte_pci_addr *loc = &dev->addr;
>>> +	/* The device is not blacklisted; Check if driver supports it */
>>> +	ret = rte_pci_match(dr, dev);
>>> +	if (ret) {
>>> +		/* Match of device and driver failed */
>>> +		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
>>> +			dr->driver.name);
>>> +		return 1;
>>> +	}
>>> +
>>> +	/* no initialization when blacklisted, return without error */
>>> +	if (dev->device.devargs != NULL &&
>>> +		dev->device.devargs->type ==
>>> +			RTE_DEVTYPE_BLACKLISTED_PCI) {
>>> +		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
>>> +			" initializing\n");
>>> +		return 1;
>>> +	}
>>>
>>> -		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>>> -				loc->domain, loc->bus, loc->devid,
>>> -				loc->function, dev->device.numa_node);
>>> +	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
>>> +		dev->id.device_id, dr->driver.name);
>>
>> Same for this one, this line cause printing all registered drivers for
>> each device during app initialization, only matched one can be logged.
> 
> Same. Will post v7 shortly with only match case printing.
> What about DEBUG for all cases?

I would prefer existing behavior, INFO level for successfully probed
device and driver, but no strong opinion.

> 
>>
>>>
>>> -		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
>>> -				dev->id.device_id, dr->driver.name);
>>> +	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
>>> +		/* map resources for devices that use igb_uio */
>>> +		ret = rte_eal_pci_map_device(dev);
>>> +		if (ret != 0)
>>> +			return ret;
>>> +	}
>>>
>>> -		if (dr->remove && (dr->remove(dev) < 0))
>>> -			return -1;	/* negative value is an error */
>>> +	/* reference driver structure */
>>> +	dev->driver = dr;
>>>
>>> -		/* clear driver structure */
>>> +	/* call the driver probe() function */
>>> +	ret = dr->probe(dr, dev);
>>> +	if (ret) {
>>>  		dev->driver = NULL;
>>> -
>>>  		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
>>> -			/* unmap resources for devices that use igb_uio */
>>>  			rte_eal_pci_unmap_device(dev);
>>> +	}
>>>
>>> -		return 0;
>>> +	return ret;
>>> +}
>>
>> <...>
>>
>>> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>>> index b553b13..5ed2589 100644
>>> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>>> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>>> @@ -186,5 +186,6 @@ DPDK_17.02 {
>>>  	rte_bus_dump;
>>>  	rte_bus_register;
>>>  	rte_bus_unregister;
>>> +	rte_pci_match;
>>
>> I think this is internal API, should library expose this API?
> 
> Idea is that pci_match be useable outside of PCI for any other PCI-like 
> bus (BDF compliant). For example, one of NXP's devices are very close to 
> PCI (but not exactly PCI) and they too rely on BDF for addressing/naming.

OK.

> 
>>
>>>
>>>  } DPDK_16.11;
>>>
>>
>>
> 
> -
> Shreyansh
> 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v7 0/9] Introducing EAL Bus-Device-Driver Model
  2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (8 preceding siblings ...)
  2017-01-16 18:27 ` [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Stephen Hemminger
@ 2017-01-17 10:09 ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
                     ` (10 more replies)
  9 siblings, 11 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v6: [16]

:: Introduction ::

DPDK has been inherently a PCI inclined framework. Because of this, the
design of device tree (or list) within DPDK is also PCI inclined. A
non-PCI device doesn't have a way of being expressed without using hooks
started from EAL to PMD.

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

        device A1
          |
  +==.===='==============.============+ Bus A.
     |                    `--> driver A11     \
  device A2                `-> driver A12      \______
                                                |CPU |
                                                /`````
        device B1                              /
          |                                   /
  +==.===='==============.============+ Bus B`
     |                    `--> driver B11
  device B2                `-> driver B12


 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

In [15], model assumes that rte_bus would be the base class using which
all the bus implementations would instantiate the objects. This patches
takes a much more basic approach, on the same lines of rte_device/
rte_driver and rte_pci_device/rte_pci_driver.
This is based on various review comments as well as offline (IRC)
discussions.

 - rte_bus is an abstract class which includes basic methods supported by
   all buses.
 - specific implementation, for example for PCI rte_pci_bus, would extend
   this class to form their own buses, with their own bus specific device
   and driver list.
 - 

 +-----------------+
 |rte_pci_bus      |
 |+---------------+|
 ||rte_bus        ||
 |+---------------+|
 +-----------------+

And example implementation would look like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | probe          ||     |
  |                | | attach         ||     |
  |                | | detach         ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+


:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003     : Split the PCI match into a separate function
0004~0005: Introduce bus->scan/probe callbacks
0006     : Integrate bus with EAL, without removing existing PCI probe/
           scan from EAL
0007     : Update the Bus and PCI test cases for scanning/probing
0008     : Enable PCI bus and remove code for direct PCI scan/probe from
           EAL
0009     : Add device hotplugging over the bus and introduce PCI helpers


:: Pending Changes/Caveats ::

1. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   Eventual aim is the PCI bus reside in driver/bus/pci

2. Though the implementation for bus is common for Linux and BSD, the PCI
   bus implementation has been done/tested only for Linux.

3. RTE_REGISTER_BUS has been declared with contructor priority of 101
    It is important that Bus is registered *before* drivers are registered.
    Only way I could find to assure that was via 
    __attribute(contructor(priority)) of GCC. I am not sure how it would
    behave on other compilers. Any suggestions?
    - One suggestion from David Marchand was to use global bus object
      handles, which I have not implemented for now. If that is common
      choice, I will change in v3.
4. Hotplugging has been introduced over Bus with a caveat - it would only
   work for ports/NICs already scanned and available in the bus list.

:: ToDo list ::

 - Bump to librte_eal version
 - Documentation continues to have references to some _old_ PCI symbols

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html - v1
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html - v2
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html - v3
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html - v4
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html - v5
[16] http://dpdk.org/ml/archives/dev/2017-January/055120.html  - v6

:: Version Changes ::
v7:
 - update to rte_pci_match for const parameters
 - remove unnecessary log messages in probe; moved _after_ matching
   of device and driver
 - bug fixes in attach/detach methods
 - PCI disable for debugging was missed (from rte_eal_pci_init) in v6
 - Split patch 5 into two: one for scan handler, another for integration
   with EAL

v6:
 - Rearchitecture to bring bus object parallel to rte_device/driver
   This majorly includes:
   -- rte_pci_bus class and pci_bus as its object for PCI
   -- bus->attach/detach (hotplugging)
   -- removing bus->match as that is local to an implementation
 - rename symbols rte_eal_bus_* to rte_bus_*
 - restructuring patches (order) for simplicity
 - update to test_pci

v5:
 - Fix checkpatch error in Patch 0003

v4:
 - rebase over master (eac901ce)
 - Fix a bug in test_bus while setup and cleanup
 - rename rte_eal_get_bus to rte_eal_bus_get
 - Add helper (iterator) macros for easy bus,device,driver traversal
 - removed 0001 patch as it is already merged in master
 - fix missing rte_eal_bus_insert_device symbol in map file

v3:
 - rebase over master (c431384c8f)
 - revert patch 0001 changes for checkpatch (container_of macro)
 - qat/rte_qat_cryptodev update for rte_driver->probe
 - test_pci update for using a test_pci_bus for verification
 - some bug fixes based on internal testing.
 -- rte_eal_dev_attach not handling devargs
 -- blacklisting not working

v2:
 - No more bus->probe()
   Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
 - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
   added as glue code between PCI PMDs and PCI Bus
   `-> PMDs are updated to use these new functions as callbacks for
       rte_driver
 - 'default' keyword has been removed from match and scan
 - Fix for incorrect changes in mlx* and nicvf*
 - Checkpatch fixes
 - Some variable checks have been removed from internal functions;
   functions which are externally visible continue to have such checks
 - Some rearrangement of patches:
   -- changes to drivers have been separated from EAL changes (but this
      does make PCI PMDs non-working for a particular patch)

Shreyansh Jain (9):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  pci: split match and probe function
  eal/bus: support for scanning of bus
  eal/bus: introduce support for bus probing
  eal: integrate bus scan and probe with EAL
  test: update bus and pci unit test cases
  eal: enable PCI bus
  eal: enable hotplugging of devices on bus

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 164 ++++--
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  17 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 140 +++++
 lib/librte_eal/common/eal_common_dev.c          |  56 +-
 lib/librte_eal/common/eal_common_pci.c          | 334 ++++++++----
 lib/librte_eal/common/eal_private.h             |  10 -
 lib/librte_eal/common/include/rte_bus.h         | 200 +++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/common/include/rte_pci.h         | 148 ++++-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
 20 files changed, 1632 insertions(+), 245 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v7 1/9] eal/bus: introduce bus abstraction
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 2/9] test: add basic bus infrastructure tests Shreyansh Jain
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for EAL.
The model is:
 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' base class which would be extended for
specific implementations. It also introduces Bus registration and
deregistration functions.

An example implementation would be like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | match          ||     |
  |                | | probe          ||     |
  |                | | remove         ||     |
  |                | | ...            ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  10 +++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          |  97 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 111 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  10 +++
 8 files changed, 232 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..c891392
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+/* register a bus */
+void
+rte_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_bus_unregister(struct rte_bus *bus)
+{
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* dump one bus info */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..2250269
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,111 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * RTE PMD Bus Abstraction interfaces
+ *
+ * This file exposes APIs and Interfaces for Bus Abstraction over the devices
+ * drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	const char *name;            /**< Name of the bus */
+};
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_bus_dump(FILE *f);
+
+/** Helper for Bus registration. The constructor has higher priority than
+ * PMD constructors
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b17791f..24c1c00 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -122,6 +122,7 @@ struct rte_driver;
  */
 struct rte_device {
 	TAILQ_ENTRY(rte_device) next; /**< Next device */
+	struct rte_bus *bus;          /**< Device connected to this bus */
 	const struct rte_driver *driver;/**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..aa874a5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..b553b13 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 2/9] test: add basic bus infrastructure tests
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 3/9] pci: split match and probe function Shreyansh Jain
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile                       |   2 +-
 app/test/test.h                         |   2 +
 app/test/test_bus.c                     | 359 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h |   3 +
 4 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 2250269..fe0f69d 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * A structure describing a generic bus.
  */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 3/9] pci: split match and probe function
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 2/9] test: add basic bus infrastructure tests Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 4/9] eal/bus: support for scanning of bus Shreyansh Jain
                     ` (7 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
 lib/librte_eal/common/include/rte_pci.h         |  15 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 1;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
-
-		return ret;
+		match = 0;
+		break;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	return match;
 }
 
 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	int ret;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	loc = &dev->addr;
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	}
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* clear driver structure */
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
 		dev->driver = NULL;
-
 		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
 			rte_eal_pci_unmap_device(dev);
+	}
 
-		return 0;
+	return ret;
+}
+
+/*
+ * If vendor/device ID match, call the remove() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
 	}
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	loc = &dev->addr;
+
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
+
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..adc20b9 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b553b13..5ed2589 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,5 +186,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 4/9] eal/bus: support for scanning of bus
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (2 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 3/9] pci: split match and probe function Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
                     ` (6 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c                     | 175 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  18 ++++
 3 files changed, 195 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
+		.scan = scan_fn_for_busA,
 	},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
 	.name = "busB_impl", /* busB */
 	.bus = {
 		.name = "busB",
+		.scan = scan_fn_for_busB,
 	},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map 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 dummy_device *ddev = NULL;
+	struct dummy_bus_map *dbmap = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; bus_map[i].name; i++) {
+		if (!strcmp(bus_map[i].name, bus->name)) {
+			dbmap = &bus_map[i];
+			break;
+		}
+	}
+
+	if (!dbmap)
+		return -1;
+
+	db = dbmap->dbus;
+
+	/* For all the devices in the device tree (bus_map), add device */
+	for (i = 0; dbmap->ddevices[i]; i++) {
+		ddev = dbmap->ddevices[i];
+		TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+		ddev->dev.bus = bus;
+	}
+
+	return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busA") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busB") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+	int i = 0;
 	struct rte_bus *bus_p = NULL;
 
 	/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
 		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
 	}
 
+	/* Initialize the bus lists */
+	for (i = 0; bus_map[i].name; i++) {
+		TAILQ_INIT(&bus_map[i].dbus->device_list);
+		TAILQ_INIT(&bus_map[i].dbus->driver_list);
+	}
+
+	dump_device_tree();
 	return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
 	return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct dummy_device *ddev;
+	struct dummy_bus *dbus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       bus_map[i].name);
+			return -1;
+		}
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			TAILQ_REMOVE(&dbus->device_list, ddev, next);
+		}
+	}
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		dbus = container_of(bus, struct dummy_bus, bus);
+
+		if (!TAILQ_EMPTY(&dbus->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();
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -346,6 +515,12 @@ test_bus(void)
 	if (test_bus_registration())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_bus_unregistration())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index c891392..35baff8 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -51,6 +51,8 @@ rte_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan implemented */
+	RTE_VERIFY(bus->scan);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index fe0f69d..152451c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,11 +60,29 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 extern struct rte_bus_list rte_bus_list;
 
 /**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * Generic bus object passed only as a helper for implementation to find
+ * their respective registered bus object. Implementations can choose not
+ * to use this variable.
+ *
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
+	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 5/9] eal/bus: introduce support for bus probing
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (3 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 4/9] eal/bus: support for scanning of bus Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

This patch introduces the callback which would be implemented for PCI
in subsequent patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 35baff8..9c4b014 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -53,6 +53,7 @@ rte_bus_register(struct rte_bus *bus)
 	RTE_VERIFY(bus->name && strlen(bus->name));
 	/* A bus should mandatorily have the scan implemented */
 	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 152451c..eb5c677 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -77,12 +77,30 @@ extern struct rte_bus_list rte_bus_list;
 typedef int (*rte_bus_scan_t)(void);
 
 /**
+ * Implementation specific probe function which is responsible for linking
+ * devices on that bus with applicable drivers.
+ *
+ * This is called while iterating over each registered bus. Bus object is
+ * passed along assuming this is wrapped around (embedded) by Implementation
+ * specific bus object.
+ *
+ * @param bus
+ *	Generic bus object which was registered with EAL
+ *
+ * @return
+ *	0 for successful probe
+ *	!0 for any error while probing
+ */
+typedef int (*rte_bus_probe_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
+	rte_bus_probe_t probe;       /**< Probe devices on bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 6/9] eal: integrate bus scan and probe with EAL
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (4 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 7/9] test: update bus and pci unit test cases Shreyansh Jain
                     ` (4 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Each bus implementation defines their own callbacks for scanning its bus
and probing devices available on the bus. Enable EAL to call bus specific
scan and probe functions during DPDK initialization.

Existing PCI scan/probe continues to exist. It will removed in subsequent
patches.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  8 +++
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 11 ++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 +
 lib/librte_eal/common/eal_common_bus.c          | 40 +++++++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 33 ++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 19 +++++++
 lib/librte_eal/common/include/rte_pci.h         | 68 +++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  8 +++
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 15 ++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 +
 10 files changed, 206 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -577,6 +578,9 @@ rte_eal_init(int argc, char **argv)
 		rte_config.master_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +617,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 9c4b014..9c91ca6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -67,6 +67,46 @@ rte_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* Error in scanning any bus stops the EAL init. */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->probe();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..5f2cab5 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -508,3 +509,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+		       struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+	/* Update Bus references */
+	new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+	TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index eb5c677..9a93454 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -122,6 +122,25 @@ void rte_bus_register(struct rte_bus *bus);
 void rte_bus_unregister(struct rte_bus *bus);
 
 /**
+ * Scan all the buses attached to the framework.
+ *
+ * @return
+ *	0 in case of success in scanning all buses
+ *	!0 in case of failure to scan
+ */
+int rte_bus_scan(void);
+
+/**
+ * For each device on the bus, perform a driver 'match' and call the
+ * bus's probe for device initialization.
+ *
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_bus_probe(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..05cf693 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *pci_bus;            /**< PCI bus reference */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -523,6 +553,44 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_bus
+ *	PCI Bus reference to which device is to be added
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+			    struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..f77ff5c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -844,6 +845,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index e2fc219..300064d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -54,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -723,3 +727,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 5ed2589..6f047c5 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,6 +186,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 7/9] test: update bus and pci unit test cases
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (5 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 8/9] eal: enable PCI bus Shreyansh Jain
                     ` (3 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++
 app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 266 insertions(+), 50 deletions(-)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 0b6d011..ef7fa89 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -120,12 +120,15 @@ static int scan_fn_for_busB(void);
 
 /* generic implementations wrapped around by above declarations */
 static int generic_scan_fn(struct rte_bus *bus);
+static int generic_probe_fn(void);
+static int dummy_match_fn(struct rte_driver *drv, struct rte_device *dev);
 
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
 		.scan = scan_fn_for_busA,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -134,6 +137,7 @@ struct dummy_bus busB = {
 	.bus = {
 		.name = "busB",
 		.scan = scan_fn_for_busB,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -288,6 +292,46 @@ generic_scan_fn(struct rte_bus *bus)
 	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 match with
+ * @param dev
+ *	device object
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+dummy_match_fn(struct rte_driver *drv __rte_unused, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct dummy_device *ddev = NULL;
+	struct dummy_device *ddev_as_arg;
+	struct dummy_bus *dbus = 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 = dev->bus;
+	dbus = container_of(bus, struct dummy_bus, bus);
+	ddev_as_arg = container_of(dev, struct dummy_device, dev);
+
+	TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+		if (ddev == ddev_as_arg)
+			return 0;
+	}
+
+	return 1;
+}
+
 int
 scan_fn_for_busA(void) {
 	struct dummy_bus_map *dbm;
@@ -504,6 +548,110 @@ test_bus_scan(void)
 	return 0;
 }
 
+/*
+ *
+ */
+static int
+generic_probe_fn(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+	struct dummy_bus *dbus = NULL;
+	struct dummy_device *ddev = NULL;
+	struct dummy_driver *ddrv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device on that bus (bus specific->device_list)
+	 * 3.   for each driver on that bus (bus specific->driver_list)
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+
+		/* Looping over all scanned devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			/* There is a list of drivers within dummy_bus_map.
+			 * In case of PMDs, this would be driver registration
+			 * APIs/list
+			 */
+			for (j = 0; bus_map[i].ddrivers[j]; j++) {
+				ddrv = bus_map[i].ddrivers[j];
+
+				drv = &ddrv->drv;
+				dev = &ddev->dev;
+				ret = dummy_match_fn(drv, dev);
+				if (!ret) {
+					/* As match is generic, it always
+					 * results in dev->drv pointing to
+					 * first driver entry in bus_map[i]
+					 */
+					dev->driver = drv;
+					dev->bus = &dbus->bus;
+				}
+				/* Else, continue */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a bus_map[i]
+	 * should have same driver (first driver entry of bus_map[i])
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		ddrv = bus_map[i].ddrivers[0];
+		drv = &ddrv->drv;
+
+		for (j = 0; bus_map[i].ddevices[j]; j++) {
+			ddev = bus_map[i].ddevices[j];
+			dev = &ddev->dev;
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	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.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i;
+	struct dummy_bus *dbus;
+	struct rte_bus *bus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+		bus = &dbus->bus;
+		ret = bus->probe();
+		if (ret)
+			printf("Probe for %s failed.\n", bus_map[i].name);
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
 
 int
 test_bus(void)
@@ -518,6 +666,10 @@ test_bus(void)
 	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;
 
diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+	struct rte_bus bus;
+	struct test_pci_device_list test_device_list;
+	struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+	.bus = {
+		.name = "test_pci_bus",
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
 	return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+	int i;
+	struct rte_pci_device *dev = NULL;
+
+	TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+		       dev->addr.devid, dev->addr.function);
+		fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+		       dev->id.device_id);
+
+		for (i = 0; i != sizeof(dev->mem_resource) /
+			sizeof(dev->mem_resource[0]); i++) {
+			fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+				dev->mem_resource[i].phys_addr,
+				dev->mem_resource[i].len);
+		}
+	}
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+	int ret;
+	struct rte_pci_device *device;
+	struct rte_pci_driver *driver;
+
+	TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+		TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+			ret = rte_pci_match(driver, device);
+			if (!ret) {
+				if (!driver->probe)
+					continue;
+
+				device->driver = driver;
+				ret = driver->probe(driver, device);
+				if (ret != 0)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
 			dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
 	}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
 	const struct resource *r;
 	int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
 	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
+	TAILQ_INIT(&test_pci_bus.test_device_list);
+	TAILQ_INIT(&test_pci_bus.test_driver_list);
 
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_bus_register(&test_pci_bus.bus);
+	pci_bus = &test_pci_bus;
+
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->bus.scan();
 
-	ret = rte_eal_pci_scan();
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
+
+	printf("Dump of all devices scanned:\n");
+	do_pci_device_dump(stdout);
 
 	return 0;
 }
@@ -190,10 +254,11 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
+	void *temp;
 
 	unsetenv("SYSFS_PCI_DEVICES");
 
@@ -203,28 +268,23 @@ test_pci_cleanup(void)
 	ret = resource_rm_by_tar(r);
 	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
 	/*
 	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+	TAILQ_FOREACH_SAFE(dev, &(test_pci_bus.test_device_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_device_list), dev, next);
+		dev->driver = NULL;
 	}
 
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
+	TAILQ_FOREACH_SAFE(dr, &(test_pci_bus.test_driver_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_driver_list), dr, next);
 	}
 
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
+	rte_bus_unregister(&pci_bus->bus);
 
 	return 0;
 }
@@ -234,16 +294,19 @@ test_pci_blacklist(void)
 {
 	struct rte_devargs_list save_devargs_list;
 
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	TEST_ASSERT(TAILQ_EMPTY(&test_pci_bus.test_driver_list),
+		    "PCI Driver list not empty");
+
+	/* Add test drivers to Bus */
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver, next);
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver2, next);
 
 	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
+
+	printf("Probe the Test Bus\n");
+	do_pci_bus_probe();
 
 	if (pci_dev_count == 0) {
 		printf("no device detected\n");
@@ -257,8 +320,8 @@ test_pci_blacklist(void)
 	blacklist_all_devices();
 
 	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
+	printf("Probe bus with all devices blacklisted\n");
+	do_pci_bus_probe();
 
 	free_devargs_list();
 	devargs_list = save_devargs_list;
@@ -270,8 +333,9 @@ test_pci_blacklist(void)
 
 	test_pci_run = 1;
 
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
+	/* Clear the test drivers added to Test Bus */
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver, next);
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver2, next);
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 8/9] eal: enable PCI bus
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (6 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 7/9] test: update bus and pci unit test cases Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:09   ` [PATCH v7 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 -----
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  4 +++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 36 +++++++++++----------
 lib/librte_eal/common/eal_private.h             | 10 ------
 lib/librte_eal/common/include/rte_pci.h         | 22 +++++--------
 lib/librte_eal/linuxapp/eal/eal.c               |  7 -----
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 42 +++++++++----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 45 insertions(+), 87 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 5f2cab5..d8c1350 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -342,7 +337,7 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -363,6 +358,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -374,7 +370,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -404,7 +400,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -412,7 +408,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -441,7 +437,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 
 		/* set devargs in PCI structure */
 		devargs = pci_devargs_lookup(dev);
@@ -489,7 +485,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -498,16 +494,22 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = &rte_pci_bus;
 }
 
-/* unregister a driver */
+/* Unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = driver->pci_bus;
+
+	TAILQ_REMOVE(&pci_bus->driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = NULL;
 }
 
 /* Add a PCI device to PCI Bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..68386e8 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 05cf693..53793f3 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -124,6 +118,9 @@ TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
 /** List of PCI drivers */
 TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
 
+/* Extend PCI bus definition to users */
+extern struct rte_pci_bus rte_pci_bus;
+
 /* PCI Bus iterators */
 #define FOREACH_DEVICE_ON_PCIBUS(p)	\
 		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
@@ -208,8 +205,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -416,17 +411,14 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,
 	      const struct rte_pci_device *pci_dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index f77ff5c..6bb7fc9 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -884,10 +881,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 300064d..51522af 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -232,7 +232,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_pci_bus *pci_bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -350,21 +351,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&pci_bus->device_list)) {
+		rte_eal_pci_add_device(pci_bus, dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &pci_bus->device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -374,8 +373,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(pci_bus, dev);
 	}
 
 	return 0;
@@ -390,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr);
+	return pci_scan_one(&rte_pci_bus, filename, addr);
 }
 
 /*
@@ -451,6 +450,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -467,7 +470,8 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+
+		if (pci_scan_one(&rte_pci_bus, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -712,22 +716,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 6f047c5..f0e63c3 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v7 9/9] eal: enable hotplugging of devices on bus
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (7 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 8/9] eal: enable PCI bus Shreyansh Jain
@ 2017-01-17 10:09   ` Shreyansh Jain
  2017-01-17 10:47     ` Ferruh Yigit
  2017-01-17 10:50   ` [PATCH v7 0/9] Introducing EAL Bus-Device-Driver Model Ferruh Yigit
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
  10 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:09 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
 lib/librte_eal/common/eal_common_dev.c  | 56 ++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 86 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 45 +++++++++++------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
 6 files changed, 192 insertions(+), 30 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index d8c1350..f4866da 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,99 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret = -1;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return -1;
+	}
+
+	if (pci_update_device(&addr) < 0)
+		goto err_return;
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+			return ret;
+		}
+	}
+
+	return ret;
+
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_pci_addr addr;
 	int ret = 0;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return -1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = pci_detach_all_drivers(dev);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 9a93454..7d93430 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Bus list exposed */
 extern struct rte_bus_list rte_bus_list;
 
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
@@ -94,6 +96,33 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -101,6 +130,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 53793f3..820b9df 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -421,6 +421,36 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -494,21 +524,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
-
-/**
  * Dump the content of the PCI bus.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 51522af..4c562c5 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -720,6 +720,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 3/8] pci: split match and probe function
  2017-01-16 18:24   ` Stephen Hemminger
@ 2017-01-17 10:10     ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:10 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: david.marchand, dev, thomas.monjalon

On Monday 16 January 2017 11:54 PM, Stephen Hemminger wrote:
> On Mon, 16 Jan 2017 21:08:22 +0530
> Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>
>> -rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
>> +int
>> +rte_pci_match(struct rte_pci_driver *pci_drv,
>> +		  struct rte_pci_device *pci_dev)
>
> Use const?
>

Done in v7. Thanks

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 7/8] eal: enable PCI bus
  2017-01-16 19:58   ` Ferruh Yigit
  2017-01-17  5:04     ` Shreyansh Jain
@ 2017-01-17 10:11     ` Shreyansh Jain
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:11 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:
> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>> Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> ---
>
> <...>
>
>> -/* Init the PCI EAL subsystem */
>> -int
>> -rte_eal_pci_init(void)
>> -{
>> -	/* for debug purposes, PCI can be disabled */
>> -	if (internal_config.no_pci)
>> -		return 0;
>
> Are we losing this feature? Should this check moved to rte_eal_pci_scan() ?
>
> <...>
>
>

Fixed in v7. Thanks for comments.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 5/8] eal: introduce bus scan and probe in EAL
  2017-01-16 19:58   ` Ferruh Yigit
  2017-01-17  5:03     ` Shreyansh Jain
@ 2017-01-17 10:13     ` Shreyansh Jain
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:13 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

Just an update on things fixed/updated in v7 against these comments:

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:
> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>> Each bus implementation defines their own callbacks for scanning bus
>> and probing devices available on the bus. Enable EAL to call bus specific
>> scan and probe functions during DPDK initialization.
>>
>> Existing PCI scan/probe continues to exist. It will removed in subsequent
>> patches.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> <...>
>
>> +/* Scan all the buses for registering devices */
>> +int
>> +rte_bus_scan(void)
>
> I hesitate to make this kind of (not really functional) comments in this
> stage of the release, but please feel free to ignore them as your wish.
>
> Previous patch is (4/8) for adding bus scan support, so why not this
> function (also .map and .h file part of it) added in prev patch?
>
> And if there is a specific patch for scan, probe can be another one?

v7 Contains a split patch for introducing probe handler and introducing
scan and probe in EAL.

>
>> +{
>> +	int ret;
>> +	struct rte_bus *bus = NULL;
>> +
>> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
>> +		ret = bus->scan();
>> +		if (ret) {
>> +			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
>> +				bus->name);
>> +			/* Error in scanning any bus stops the EAL init. */
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>
> <...>
>
>> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
>> index 0d799be..35da451 100644
> <...>
>> +
>> +/* Add a PCI device to PCI Bus */
>> +void
>> +rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
>> +		       struct rte_pci_device *pci_dev)
>
> I think more generic approach from previous version was better
> (rte_eal_bus_add_device()), but I guess they sacrificed for less
> modification.
>
>> +{
>> +	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
>> +	/* Update Bus references */
>> +	pci_dev->device.bus = &pci_bus->bus;
>> +}
>> +
>
> <...>
>
>>
>> +/**
>> + * Structure describing the PCI bus
>> + */
>> +struct rte_pci_bus {
>> +	struct rte_bus bus;               /**< Inherit the generic class */
>> +	struct rte_pci_device_list device_list;  /**< List of PCI devices */
>> +	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
>
> Why bus device/driver lists moved from rte_bus? Each bus will need this?
> Is it to change as less code as possible?
>
> <...>
>
>> +
>> +/**
>> + * Insert a PCI device in the PCI Bus at a particular location in the device
>> + * list. It also updates the PCI Bus reference of the new devices to be
>> + * inserted.
>
> Minor issue in document compilation:
>
> - warning: argument 'pci_dev' of command @param is not found
>
> - parameter 'new_pci_dev' not documented
>
> Similar warnings exists for rte_eal_pci_remove_device() too.
>
> Also following in rte_bus_scan(void) and rte_bus_probe(void)
> - warning: argument 'void' of command @param is not found

Pushed v7 to ML. 'make doc' is not reporting any warn/error now.
Thanks for pointing it out.

>
>> + *
>> + * @param exist_pci_dev
>> + *	Existing PCI device in PCI Bus
>> + * @param pci_dev
>> + *	PCI device to be added before exist_pci_dev
>> + * @return void
>> + */
>> +void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
>> +			       struct rte_pci_device *new_pci_dev);
>> +
>
> <...>
>
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 3/8] pci: split match and probe function
  2017-01-17  9:58       ` Ferruh Yigit
@ 2017-01-17 10:14         ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 10:14 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

On Tuesday 17 January 2017 03:28 PM, Ferruh Yigit wrote:
> On 1/17/2017 4:54 AM, Shreyansh Jain wrote:
>> Hello Ferruh,
>>
>> On Tuesday 17 January 2017 01:23 AM, Ferruh Yigit wrote:
>>> On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
>>>> Matching of PCI device address and driver ID table is being done at two
>>>> discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
>>>> and rte_eal_pci_detach_dev).
>>>>
>>>> Splitting the matching function into a public fn rte_pci_match.
>>>>
>>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>>
>>> <...>
>>>
>>>>  /*
>>>> - * If vendor/device ID match, call the remove() function of the
>>>> + * If vendor/device ID match, call the probe() function of the
>>>>   * driver.
>>>>   */
>>>>  static int
>>>> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
>>>> -		struct rte_pci_device *dev)
>>>> +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
>>>> +			     struct rte_pci_device *dev)
>>>>  {
>>>> -	const struct rte_pci_id *id_table;
>>>> +	int ret;
>>>> +	struct rte_pci_addr *loc;
>>>>
>>>>  	if ((dr == NULL) || (dev == NULL))
>>>>  		return -EINVAL;
>>>>
>>>> -	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
>>>> +	loc = &dev->addr;
>>>>
>>>> -		/* check if device's identifiers match the driver's ones */
>>>> -		if (id_table->vendor_id != dev->id.vendor_id &&
>>>> -				id_table->vendor_id != PCI_ANY_ID)
>>>> -			continue;
>>>> -		if (id_table->device_id != dev->id.device_id &&
>>>> -				id_table->device_id != PCI_ANY_ID)
>>>> -			continue;
>>>> -		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
>>>> -				id_table->subsystem_vendor_id != PCI_ANY_ID)
>>>> -			continue;
>>>> -		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
>>>> -				id_table->subsystem_device_id != PCI_ANY_ID)
>>>> -			continue;
>>>> +	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>>>> +			loc->domain, loc->bus, loc->devid, loc->function,
>>>> +			dev->device.numa_node);
>>>
>>> This cause bunch of log printed during app startup, what about printing
>>> this log when probed device found?
>>
>> Only thing I did was move around this log message without adding
>> anything new. Maybe earlier it was in some conditional (match) and now
>> it isn't. I will check again and move to match-only case.
>>
>>>
>>>>
>>>> -		struct rte_pci_addr *loc = &dev->addr;
>>>> +	/* The device is not blacklisted; Check if driver supports it */
>>>> +	ret = rte_pci_match(dr, dev);
>>>> +	if (ret) {
>>>> +		/* Match of device and driver failed */
>>>> +		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
>>>> +			dr->driver.name);
>>>> +		return 1;
>>>> +	}
>>>> +
>>>> +	/* no initialization when blacklisted, return without error */
>>>> +	if (dev->device.devargs != NULL &&
>>>> +		dev->device.devargs->type ==
>>>> +			RTE_DEVTYPE_BLACKLISTED_PCI) {
>>>> +		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
>>>> +			" initializing\n");
>>>> +		return 1;
>>>> +	}
>>>>
>>>> -		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>>>> -				loc->domain, loc->bus, loc->devid,
>>>> -				loc->function, dev->device.numa_node);
>>>> +	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
>>>> +		dev->id.device_id, dr->driver.name);
>>>
>>> Same for this one, this line cause printing all registered drivers for
>>> each device during app initialization, only matched one can be logged.
>>
>> Same. Will post v7 shortly with only match case printing.
>> What about DEBUG for all cases?
>
> I would prefer existing behavior, INFO level for successfully probed
> device and driver, but no strong opinion.

Reverted to existing behavior. It was a miss from my side. I had moved
this log message _before_ matching unlike the original code.
Pushed v7 to ML.

>
>>
>>>
>>>>
>>>> -		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
>>>> -				dev->id.device_id, dr->driver.name);
>>>> +	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
>>>> +		/* map resources for devices that use igb_uio */
>>>> +		ret = rte_eal_pci_map_device(dev);
>>>> +		if (ret != 0)
>>>> +			return ret;
>>>> +	}
>>>>
>>>> -		if (dr->remove && (dr->remove(dev) < 0))
>>>> -			return -1;	/* negative value is an error */
>>>> +	/* reference driver structure */
>>>> +	dev->driver = dr;
>>>>
>>>> -		/* clear driver structure */
>>>> +	/* call the driver probe() function */
>>>> +	ret = dr->probe(dr, dev);
>>>> +	if (ret) {
>>>>  		dev->driver = NULL;
>>>> -
>>>>  		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
>>>> -			/* unmap resources for devices that use igb_uio */
>>>>  			rte_eal_pci_unmap_device(dev);
>>>> +	}
>>>>
>>>> -		return 0;
>>>> +	return ret;
>>>> +}
>>>
>>> <...>
>>>
>>>> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>>>> index b553b13..5ed2589 100644
>>>> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>>>> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>>>> @@ -186,5 +186,6 @@ DPDK_17.02 {
>>>>  	rte_bus_dump;
>>>>  	rte_bus_register;
>>>>  	rte_bus_unregister;
>>>> +	rte_pci_match;
>>>
>>> I think this is internal API, should library expose this API?
>>
>> Idea is that pci_match be useable outside of PCI for any other PCI-like
>> bus (BDF compliant). For example, one of NXP's devices are very close to
>> PCI (but not exactly PCI) and they too rely on BDF for addressing/naming.
>
> OK.
>
>>
>>>
>>>>
>>>>  } DPDK_16.11;
>>>>
>>>
>>>
>>
>> -
>> Shreyansh
>>
>
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v7 9/9] eal: enable hotplugging of devices on bus
  2017-01-17 10:09   ` [PATCH v7 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-17 10:47     ` Ferruh Yigit
  2017-01-17 11:04       ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-17 10:47 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/17/2017 10:09 AM, Shreyansh Jain wrote:
> Given a bus, attach and detach callbacks allow the implementation to
> handles calls from EAL for attaching or detaching a named device.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

<...>

> +/**
> + * Search and detach a PCI device from PCI Bus
> + * Implements rte_bus->detach
> + *
> + * @param device_name
> + *	Name of the device to search and detach
> + *
> + * @return
> + *	0 for successful detaching of device
> + *	>0 if device not found on bus
> + *	<0 in case of error in removal.

These are the return values expected by rte_eal_dev_detach(), but
rte_eal_pci_detach() is not following these right now, which is causing
failure on detaching virtual devices.

Fix is not complex, it may be an option to fix this as a separate patch
after this patchset applied.

> + */
> +int
> +rte_eal_pci_detach(const char *device_name);
> +
> +/**

<...>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v7 0/9] Introducing EAL Bus-Device-Driver Model
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (8 preceding siblings ...)
  2017-01-17 10:09   ` [PATCH v7 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-17 10:50   ` Ferruh Yigit
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
  10 siblings, 0 replies; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-17 10:50 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/17/2017 10:09 AM, Shreyansh Jain wrote:

<...>

> Shreyansh Jain (9):
>   eal/bus: introduce bus abstraction
>   test: add basic bus infrastructure tests
>   pci: split match and probe function
>   eal/bus: support for scanning of bus
>   eal/bus: introduce support for bus probing
>   eal: integrate bus scan and probe with EAL
>   test: update bus and pci unit test cases
>   eal: enable PCI bus
>   eal: enable hotplugging of devices on bus
> 

Apart from issue mentioned in patch v7 9/9,

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v7 9/9] eal: enable hotplugging of devices on bus
  2017-01-17 10:47     ` Ferruh Yigit
@ 2017-01-17 11:04       ` Shreyansh Jain
  2017-01-17 13:40         ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 11:04 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

Hi Ferruh,

> -----Original Message-----
> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Tuesday, January 17, 2017 4:18 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>; david.marchand@6wind.com
> Cc: dev@dpdk.org; thomas.monjalon@6wind.com
> Subject: Re: [dpdk-dev] [PATCH v7 9/9] eal: enable hotplugging of devices on
> bus
> 
> On 1/17/2017 10:09 AM, Shreyansh Jain wrote:
> > Given a bus, attach and detach callbacks allow the implementation to
> > handles calls from EAL for attaching or detaching a named device.
> >
> > Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> 
> <...>
> 
> > +/**
> > + * Search and detach a PCI device from PCI Bus
> > + * Implements rte_bus->detach
> > + *
> > + * @param device_name
> > + *	Name of the device to search and detach
> > + *
> > + * @return
> > + *	0 for successful detaching of device
> > + *	>0 if device not found on bus
> > + *	<0 in case of error in removal.
> 
> These are the return values expected by rte_eal_dev_detach(), but
> rte_eal_pci_detach() is not following these right now, which is causing
> failure on detaching virtual devices.
> 
> Fix is not complex, it may be an option to fix this as a separate patch
> after this patchset applied.

Ok. I will have a look and fix it.
If possible I will push v8; keeping it pending is lower preference for me.

> 
> > + */
> > +int
> > +rte_eal_pci_detach(const char *device_name);
> > +
> > +/**
> 
> <...>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v8 0/9] Introducing EAL Bus-Device-Driver Model
  2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
                     ` (9 preceding siblings ...)
  2017-01-17 10:50   ` [PATCH v7 0/9] Introducing EAL Bus-Device-Driver Model Ferruh Yigit
@ 2017-01-17 13:37   ` Shreyansh Jain
  2017-01-17 13:37     ` [PATCH v8 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
                       ` (9 more replies)
  10 siblings, 10 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v7: [17]

:: Introduction ::

DPDK has been inherently a PCI inclined framework. Because of this, the
design of device tree (or list) within DPDK is also PCI inclined. A
non-PCI device doesn't have a way of being expressed without using hooks
started from EAL to PMD.

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

        device A1
          |
  +==.===='==============.============+ Bus A.
     |                    `--> driver A11     \
  device A2                `-> driver A12      \______
                                                |CPU |
                                                /`````
        device B1                              /
          |                                   /
  +==.===='==============.============+ Bus B`
     |                    `--> driver B11
  device B2                `-> driver B12


 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

In [15], model assumes that rte_bus would be the base class using which
all the bus implementations would instantiate the objects. This patches
takes a much more basic approach, on the same lines of rte_device/
rte_driver and rte_pci_device/rte_pci_driver.
This is based on various review comments as well as offline (IRC)
discussions.

 - rte_bus is an abstract class which includes basic methods supported by
   all buses.
 - specific implementation, for example for PCI rte_pci_bus, would extend
   this class to form their own buses, with their own bus specific device
   and driver list.
 - 

 +-----------------+
 |rte_pci_bus      |
 |+---------------+|
 ||rte_bus        ||
 |+---------------+|
 +-----------------+

And example implementation would look like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | probe          ||     |
  |                | | attach         ||     |
  |                | | detach         ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+


:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003     : Split the PCI match into a separate function
0004~0005: Introduce bus->scan APIs and integrate with EAL
0006     : Update the Bus and PCI test cases for scanning/probing
0007     : Enable PCI bus and remove code for direct PCI scan/probe from
           EAL
0008     : Add device hotplugging over the bus and introduce PCI helpers


:: Pending Changes/Caveats ::

1. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   Eventual aim is the PCI bus reside in driver/bus/pci

2. Though the implementation for bus is common for Linux and BSD, the PCI
   bus implementation has been done/tested only for Linux.

3. RTE_REGISTER_BUS has been declared with contructor priority of 101
    It is important that Bus is registered *before* drivers are registered.
    Only way I could find to assure that was via 
    __attribute(contructor(priority)) of GCC. I am not sure how it would
    behave on other compilers. Any suggestions?
    - One suggestion from David Marchand was to use global bus object
      handles, which I have not implemented for now. If that is common
      choice, I will change in v3.
4. Hotplugging has been introduced over Bus with a caveat - it would only
   work for ports/NICs already scanned and available in the bus list.

:: ToDo list ::

 - Bump to librte_eal version
 - Documentation continues to have references to some _old_ PCI symbols

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html - v1
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html - v2
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html - v3
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html - v4
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html - v5
[16] http://dpdk.org/ml/archives/dev/2017-January/055120.html  - v6
[17] http://dpdk.org/ml/archives/dev/2017-January/055320.html  - v7

:: Version Changes ::
v8:
 - fix return value bug in rte_eal_pci_attach and rte_eal_pci_detach

v7:
 - update to rte_pci_match for const parameters
 - remove unnecessary log messages in probe; moved _after_ matching
   of device and driver
 - bug fixes in attach/detach methods
 - PCI disable for debugging was missed (from rte_eal_pci_init) in v6

v6:
 - Rearchitecture to bring bus object parallel to rte_device/driver
   This majorly includes:
   -- rte_pci_bus class and pci_bus as its object for PCI
   -- bus->attach/detach (hotplugging)
   -- removing bus->match as that is local to an implementation
 - rename symbols rte_eal_bus_* to rte_bus_*
 - restructuring patches (order) for simplicity
 - update to test_pci

v5:
 - Fix checkpatch error in Patch 0003

v4:
 - rebase over master (eac901ce)
 - Fix a bug in test_bus while setup and cleanup
 - rename rte_eal_get_bus to rte_eal_bus_get
 - Add helper (iterator) macros for easy bus,device,driver traversal
 - removed 0001 patch as it is already merged in master
 - fix missing rte_eal_bus_insert_device symbol in map file

v3:
 - rebase over master (c431384c8f)
 - revert patch 0001 changes for checkpatch (container_of macro)
 - qat/rte_qat_cryptodev update for rte_driver->probe
 - test_pci update for using a test_pci_bus for verification
 - some bug fixes based on internal testing.
 -- rte_eal_dev_attach not handling devargs
 -- blacklisting not working

v2:
 - No more bus->probe()
   Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
 - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
   added as glue code between PCI PMDs and PCI Bus
   `-> PMDs are updated to use these new functions as callbacks for
       rte_driver
 - 'default' keyword has been removed from match and scan
 - Fix for incorrect changes in mlx* and nicvf*
 - Checkpatch fixes
 - Some variable checks have been removed from internal functions;
   functions which are externally visible continue to have such checks
 - Some rearrangement of patches:
   -- changes to drivers have been separated from EAL changes (but this
      does make PCI PMDs non-working for a particular patch)

Shreyansh Jain (9):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  pci: split match and probe function
  eal/bus: support for scanning of bus
  eal/bus: introduce support for bus probing
  eal: integrate bus scan and probe with EAL
  test: update bus and pci unit test cases
  eal: enable PCI bus
  eal: enable hotplugging of devices on bus

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 164 ++++--
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  17 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 140 +++++
 lib/librte_eal/common/eal_common_dev.c          |  56 +-
 lib/librte_eal/common/eal_common_pci.c          | 337 ++++++++----
 lib/librte_eal/common/eal_private.h             |  10 -
 lib/librte_eal/common/include/rte_bus.h         | 200 +++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/common/include/rte_pci.h         | 148 ++++-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
 20 files changed, 1633 insertions(+), 247 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v8 1/9] eal/bus: introduce bus abstraction
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:19       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 2/9] test: add basic bus infrastructure tests Shreyansh Jain
                       ` (8 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for EAL.
The model is:
 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' base class which would be extended for
specific implementations. It also introduces Bus registration and
deregistration functions.

An example implementation would be like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | match          ||     |
  |                | | probe          ||     |
  |                | | remove         ||     |
  |                | | ...            ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  10 +++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          |  97 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 111 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  10 +++
 8 files changed, 232 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..c891392
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+/* register a bus */
+void
+rte_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_bus_unregister(struct rte_bus *bus)
+{
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* dump one bus info */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..2250269
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,111 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * RTE PMD Bus Abstraction interfaces
+ *
+ * This file exposes APIs and Interfaces for Bus Abstraction over the devices
+ * drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	const char *name;            /**< Name of the bus */
+};
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_bus_dump(FILE *f);
+
+/** Helper for Bus registration. The constructor has higher priority than
+ * PMD constructors
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b17791f..24c1c00 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -122,6 +122,7 @@ struct rte_driver;
  */
 struct rte_device {
 	TAILQ_ENTRY(rte_device) next; /**< Next device */
+	struct rte_bus *bus;          /**< Device connected to this bus */
 	const struct rte_driver *driver;/**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..aa874a5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..b553b13 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 2/9] test: add basic bus infrastructure tests
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
  2017-01-17 13:37     ` [PATCH v8 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:23       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 3/9] pci: split match and probe function Shreyansh Jain
                       ` (7 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/Makefile                       |   2 +-
 app/test/test.h                         |   2 +
 app/test/test_bus.c                     | 359 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h |   3 +
 4 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 2250269..fe0f69d 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * A structure describing a generic bus.
  */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 3/9] pci: split match and probe function
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
  2017-01-17 13:37     ` [PATCH v8 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
  2017-01-17 13:37     ` [PATCH v8 2/9] test: add basic bus infrastructure tests Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:31       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 4/9] eal/bus: support for scanning of bus Shreyansh Jain
                       ` (6 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
 lib/librte_eal/common/include/rte_pci.h         |  15 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 1;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
-
-		return ret;
+		match = 0;
+		break;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	return match;
 }
 
 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	int ret;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	loc = &dev->addr;
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	}
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* clear driver structure */
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
 		dev->driver = NULL;
-
 		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
 			rte_eal_pci_unmap_device(dev);
+	}
 
-		return 0;
+	return ret;
+}
+
+/*
+ * If vendor/device ID match, call the remove() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
 	}
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	loc = &dev->addr;
+
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
+
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..adc20b9 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b553b13..5ed2589 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,5 +186,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 4/9] eal/bus: support for scanning of bus
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (2 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 3/9] pci: split match and probe function Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:37       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
                       ` (5 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_bus.c                     | 175 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  18 ++++
 3 files changed, 195 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
+		.scan = scan_fn_for_busA,
 	},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
 	.name = "busB_impl", /* busB */
 	.bus = {
 		.name = "busB",
+		.scan = scan_fn_for_busB,
 	},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map 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 dummy_device *ddev = NULL;
+	struct dummy_bus_map *dbmap = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; bus_map[i].name; i++) {
+		if (!strcmp(bus_map[i].name, bus->name)) {
+			dbmap = &bus_map[i];
+			break;
+		}
+	}
+
+	if (!dbmap)
+		return -1;
+
+	db = dbmap->dbus;
+
+	/* For all the devices in the device tree (bus_map), add device */
+	for (i = 0; dbmap->ddevices[i]; i++) {
+		ddev = dbmap->ddevices[i];
+		TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+		ddev->dev.bus = bus;
+	}
+
+	return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busA") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busB") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+	int i = 0;
 	struct rte_bus *bus_p = NULL;
 
 	/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
 		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
 	}
 
+	/* Initialize the bus lists */
+	for (i = 0; bus_map[i].name; i++) {
+		TAILQ_INIT(&bus_map[i].dbus->device_list);
+		TAILQ_INIT(&bus_map[i].dbus->driver_list);
+	}
+
+	dump_device_tree();
 	return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
 	return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct dummy_device *ddev;
+	struct dummy_bus *dbus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       bus_map[i].name);
+			return -1;
+		}
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			TAILQ_REMOVE(&dbus->device_list, ddev, next);
+		}
+	}
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		dbus = container_of(bus, struct dummy_bus, bus);
+
+		if (!TAILQ_EMPTY(&dbus->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();
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -346,6 +515,12 @@ test_bus(void)
 	if (test_bus_registration())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_bus_unregistration())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index c891392..35baff8 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -51,6 +51,8 @@ rte_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan implemented */
+	RTE_VERIFY(bus->scan);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index fe0f69d..152451c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,11 +60,29 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 extern struct rte_bus_list rte_bus_list;
 
 /**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * Generic bus object passed only as a helper for implementation to find
+ * their respective registered bus object. Implementations can choose not
+ * to use this variable.
+ *
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
+	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 5/9] eal/bus: introduce support for bus probing
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (3 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 4/9] eal/bus: support for scanning of bus Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:38       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
                       ` (4 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

This patch introduces the callback which would be implemented for PCI
in subsequent patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 35baff8..9c4b014 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -53,6 +53,7 @@ rte_bus_register(struct rte_bus *bus)
 	RTE_VERIFY(bus->name && strlen(bus->name));
 	/* A bus should mandatorily have the scan implemented */
 	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 152451c..eb5c677 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -77,12 +77,30 @@ extern struct rte_bus_list rte_bus_list;
 typedef int (*rte_bus_scan_t)(void);
 
 /**
+ * Implementation specific probe function which is responsible for linking
+ * devices on that bus with applicable drivers.
+ *
+ * This is called while iterating over each registered bus. Bus object is
+ * passed along assuming this is wrapped around (embedded) by Implementation
+ * specific bus object.
+ *
+ * @param bus
+ *	Generic bus object which was registered with EAL
+ *
+ * @return
+ *	0 for successful probe
+ *	!0 for any error while probing
+ */
+typedef int (*rte_bus_probe_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
+	rte_bus_probe_t probe;       /**< Probe devices on bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 6/9] eal: integrate bus scan and probe with EAL
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (4 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:44       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 7/9] test: update bus and pci unit test cases Shreyansh Jain
                       ` (3 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Each bus implementation defines their own callbacks for scanning its bus
and probing devices available on the bus. Enable EAL to call bus specific
scan and probe functions during DPDK initialization.

Existing PCI scan/probe continues to exist. It will removed in subsequent
patches.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  8 +++
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 11 ++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 +
 lib/librte_eal/common/eal_common_bus.c          | 40 +++++++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 33 ++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 19 +++++++
 lib/librte_eal/common/include/rte_pci.h         | 68 +++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  8 +++
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 15 ++++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 +
 10 files changed, 206 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -577,6 +578,9 @@ rte_eal_init(int argc, char **argv)
 		rte_config.master_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +617,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 9c4b014..9c91ca6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -67,6 +67,46 @@ rte_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* Error in scanning any bus stops the EAL init. */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->probe();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..5f2cab5 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -508,3 +509,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+		       struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+	/* Update Bus references */
+	new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+	TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index eb5c677..9a93454 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -122,6 +122,25 @@ void rte_bus_register(struct rte_bus *bus);
 void rte_bus_unregister(struct rte_bus *bus);
 
 /**
+ * Scan all the buses attached to the framework.
+ *
+ * @return
+ *	0 in case of success in scanning all buses
+ *	!0 in case of failure to scan
+ */
+int rte_bus_scan(void);
+
+/**
+ * For each device on the bus, perform a driver 'match' and call the
+ * bus's probe for device initialization.
+ *
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_bus_probe(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..05cf693 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *pci_bus;            /**< PCI bus reference */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -523,6 +553,44 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_bus
+ *	PCI Bus reference to which device is to be added
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+			    struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..f77ff5c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -844,6 +845,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index e2fc219..300064d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -54,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -723,3 +727,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 5ed2589..6f047c5 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,6 +186,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 7/9] test: update bus and pci unit test cases
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (5 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:46       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 8/9] eal: enable PCI bus Shreyansh Jain
                       ` (2 subsequent siblings)
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_bus.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++
 app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 266 insertions(+), 50 deletions(-)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 0b6d011..ef7fa89 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -120,12 +120,15 @@ static int scan_fn_for_busB(void);
 
 /* generic implementations wrapped around by above declarations */
 static int generic_scan_fn(struct rte_bus *bus);
+static int generic_probe_fn(void);
+static int dummy_match_fn(struct rte_driver *drv, struct rte_device *dev);
 
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
 		.scan = scan_fn_for_busA,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -134,6 +137,7 @@ struct dummy_bus busB = {
 	.bus = {
 		.name = "busB",
 		.scan = scan_fn_for_busB,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -288,6 +292,46 @@ generic_scan_fn(struct rte_bus *bus)
 	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 match with
+ * @param dev
+ *	device object
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+dummy_match_fn(struct rte_driver *drv __rte_unused, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct dummy_device *ddev = NULL;
+	struct dummy_device *ddev_as_arg;
+	struct dummy_bus *dbus = 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 = dev->bus;
+	dbus = container_of(bus, struct dummy_bus, bus);
+	ddev_as_arg = container_of(dev, struct dummy_device, dev);
+
+	TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+		if (ddev == ddev_as_arg)
+			return 0;
+	}
+
+	return 1;
+}
+
 int
 scan_fn_for_busA(void) {
 	struct dummy_bus_map *dbm;
@@ -504,6 +548,110 @@ test_bus_scan(void)
 	return 0;
 }
 
+/*
+ *
+ */
+static int
+generic_probe_fn(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+	struct dummy_bus *dbus = NULL;
+	struct dummy_device *ddev = NULL;
+	struct dummy_driver *ddrv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device on that bus (bus specific->device_list)
+	 * 3.   for each driver on that bus (bus specific->driver_list)
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+
+		/* Looping over all scanned devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			/* There is a list of drivers within dummy_bus_map.
+			 * In case of PMDs, this would be driver registration
+			 * APIs/list
+			 */
+			for (j = 0; bus_map[i].ddrivers[j]; j++) {
+				ddrv = bus_map[i].ddrivers[j];
+
+				drv = &ddrv->drv;
+				dev = &ddev->dev;
+				ret = dummy_match_fn(drv, dev);
+				if (!ret) {
+					/* As match is generic, it always
+					 * results in dev->drv pointing to
+					 * first driver entry in bus_map[i]
+					 */
+					dev->driver = drv;
+					dev->bus = &dbus->bus;
+				}
+				/* Else, continue */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a bus_map[i]
+	 * should have same driver (first driver entry of bus_map[i])
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		ddrv = bus_map[i].ddrivers[0];
+		drv = &ddrv->drv;
+
+		for (j = 0; bus_map[i].ddevices[j]; j++) {
+			ddev = bus_map[i].ddevices[j];
+			dev = &ddev->dev;
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	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.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i;
+	struct dummy_bus *dbus;
+	struct rte_bus *bus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+		bus = &dbus->bus;
+		ret = bus->probe();
+		if (ret)
+			printf("Probe for %s failed.\n", bus_map[i].name);
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
 
 int
 test_bus(void)
@@ -518,6 +666,10 @@ test_bus(void)
 	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;
 
diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+	struct rte_bus bus;
+	struct test_pci_device_list test_device_list;
+	struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+	.bus = {
+		.name = "test_pci_bus",
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
 	return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+	int i;
+	struct rte_pci_device *dev = NULL;
+
+	TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+		       dev->addr.devid, dev->addr.function);
+		fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+		       dev->id.device_id);
+
+		for (i = 0; i != sizeof(dev->mem_resource) /
+			sizeof(dev->mem_resource[0]); i++) {
+			fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+				dev->mem_resource[i].phys_addr,
+				dev->mem_resource[i].len);
+		}
+	}
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+	int ret;
+	struct rte_pci_device *device;
+	struct rte_pci_driver *driver;
+
+	TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+		TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+			ret = rte_pci_match(driver, device);
+			if (!ret) {
+				if (!driver->probe)
+					continue;
+
+				device->driver = driver;
+				ret = driver->probe(driver, device);
+				if (ret != 0)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
 			dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
 	}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
 	const struct resource *r;
 	int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
 	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
+	TAILQ_INIT(&test_pci_bus.test_device_list);
+	TAILQ_INIT(&test_pci_bus.test_driver_list);
 
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_bus_register(&test_pci_bus.bus);
+	pci_bus = &test_pci_bus;
+
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->bus.scan();
 
-	ret = rte_eal_pci_scan();
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
+
+	printf("Dump of all devices scanned:\n");
+	do_pci_device_dump(stdout);
 
 	return 0;
 }
@@ -190,10 +254,11 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
+	void *temp;
 
 	unsetenv("SYSFS_PCI_DEVICES");
 
@@ -203,28 +268,23 @@ test_pci_cleanup(void)
 	ret = resource_rm_by_tar(r);
 	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
 	/*
 	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+	TAILQ_FOREACH_SAFE(dev, &(test_pci_bus.test_device_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_device_list), dev, next);
+		dev->driver = NULL;
 	}
 
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
+	TAILQ_FOREACH_SAFE(dr, &(test_pci_bus.test_driver_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_driver_list), dr, next);
 	}
 
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
+	rte_bus_unregister(&pci_bus->bus);
 
 	return 0;
 }
@@ -234,16 +294,19 @@ test_pci_blacklist(void)
 {
 	struct rte_devargs_list save_devargs_list;
 
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	TEST_ASSERT(TAILQ_EMPTY(&test_pci_bus.test_driver_list),
+		    "PCI Driver list not empty");
+
+	/* Add test drivers to Bus */
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver, next);
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver2, next);
 
 	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
+
+	printf("Probe the Test Bus\n");
+	do_pci_bus_probe();
 
 	if (pci_dev_count == 0) {
 		printf("no device detected\n");
@@ -257,8 +320,8 @@ test_pci_blacklist(void)
 	blacklist_all_devices();
 
 	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
+	printf("Probe bus with all devices blacklisted\n");
+	do_pci_bus_probe();
 
 	free_devargs_list();
 	devargs_list = save_devargs_list;
@@ -270,8 +333,9 @@ test_pci_blacklist(void)
 
 	test_pci_run = 1;
 
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
+	/* Clear the test drivers added to Test Bus */
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver, next);
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver2, next);
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 8/9] eal: enable PCI bus
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (6 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 7/9] test: update bus and pci unit test cases Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 23:57       ` Thomas Monjalon
  2017-01-17 13:37     ` [PATCH v8 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 -----
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  4 +++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 36 +++++++++++----------
 lib/librte_eal/common/eal_private.h             | 10 ------
 lib/librte_eal/common/include/rte_pci.h         | 22 +++++--------
 lib/librte_eal/linuxapp/eal/eal.c               |  7 -----
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 42 +++++++++----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 45 insertions(+), 87 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 5f2cab5..d8c1350 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -342,7 +337,7 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -363,6 +358,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -374,7 +370,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -404,7 +400,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -412,7 +408,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -441,7 +437,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 
 		/* set devargs in PCI structure */
 		devargs = pci_devargs_lookup(dev);
@@ -489,7 +485,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -498,16 +494,22 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = &rte_pci_bus;
 }
 
-/* unregister a driver */
+/* Unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = driver->pci_bus;
+
+	TAILQ_REMOVE(&pci_bus->driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = NULL;
 }
 
 /* Add a PCI device to PCI Bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..68386e8 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 05cf693..53793f3 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -124,6 +118,9 @@ TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
 /** List of PCI drivers */
 TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
 
+/* Extend PCI bus definition to users */
+extern struct rte_pci_bus rte_pci_bus;
+
 /* PCI Bus iterators */
 #define FOREACH_DEVICE_ON_PCIBUS(p)	\
 		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
@@ -208,8 +205,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -416,17 +411,14 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,
 	      const struct rte_pci_device *pci_dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index f77ff5c..6bb7fc9 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -884,10 +881,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 300064d..51522af 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -232,7 +232,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_pci_bus *pci_bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -350,21 +351,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&pci_bus->device_list)) {
+		rte_eal_pci_add_device(pci_bus, dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &pci_bus->device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -374,8 +373,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(pci_bus, dev);
 	}
 
 	return 0;
@@ -390,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr);
+	return pci_scan_one(&rte_pci_bus, filename, addr);
 }
 
 /*
@@ -451,6 +450,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -467,7 +470,8 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+
+		if (pci_scan_one(&rte_pci_bus, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -712,22 +716,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 6f047c5..f0e63c3 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v8 9/9] eal: enable hotplugging of devices on bus
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (7 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 8/9] eal: enable PCI bus Shreyansh Jain
@ 2017-01-17 13:37     ` Shreyansh Jain
  2017-01-17 15:17       ` Ferruh Yigit
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  9 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
 lib/librte_eal/common/eal_common_dev.c  | 56 ++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 89 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 45 +++++++++++------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
 6 files changed, 193 insertions(+), 32 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index d8c1350..8eed8d1 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
+	if (pci_update_device(&addr) < 0)
+		goto err_return;
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+			return ret;
+		}
+	}
+
+	return 1;
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
-	int ret = 0;
+	struct rte_pci_addr addr;
+	int ret = 1;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = pci_detach_all_drivers(dev);
@@ -412,8 +491,8 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		free(dev);
 		return 0;
 	}
-	return -1;
 
+	return ret;
 err_return:
 	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
 			" cannot be used\n", dev->addr.domain, dev->addr.bus,
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 9a93454..7d93430 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Bus list exposed */
 extern struct rte_bus_list rte_bus_list;
 
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
@@ -94,6 +96,33 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -101,6 +130,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 53793f3..820b9df 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -421,6 +421,36 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -494,21 +524,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
-
-/**
  * Dump the content of the PCI bus.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 51522af..4c562c5 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -720,6 +720,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* Re: [PATCH v7 9/9] eal: enable hotplugging of devices on bus
  2017-01-17 11:04       ` Shreyansh Jain
@ 2017-01-17 13:40         ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-17 13:40 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

Hello Ferruh,

On Tuesday 17 January 2017 04:34 PM, Shreyansh Jain wrote:
> Hi Ferruh,
>
>> -----Original Message-----
>> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
>> Sent: Tuesday, January 17, 2017 4:18 PM
>> To: Shreyansh Jain <shreyansh.jain@nxp.com>; david.marchand@6wind.com
>> Cc: dev@dpdk.org; thomas.monjalon@6wind.com
>> Subject: Re: [dpdk-dev] [PATCH v7 9/9] eal: enable hotplugging of devices on
>> bus
>>
>> On 1/17/2017 10:09 AM, Shreyansh Jain wrote:
>>> Given a bus, attach and detach callbacks allow the implementation to
>>> handles calls from EAL for attaching or detaching a named device.
>>>
>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>
>> <...>
>>
>>> +/**
>>> + * Search and detach a PCI device from PCI Bus
>>> + * Implements rte_bus->detach
>>> + *
>>> + * @param device_name
>>> + *	Name of the device to search and detach
>>> + *
>>> + * @return
>>> + *	0 for successful detaching of device
>>> + *	>0 if device not found on bus
>>> + *	<0 in case of error in removal.
>>
>> These are the return values expected by rte_eal_dev_detach(), but
>> rte_eal_pci_detach() is not following these right now, which is causing
>> failure on detaching virtual devices.
>>
>> Fix is not complex, it may be an option to fix this as a separate patch
>> after this patchset applied.
>
> Ok. I will have a look and fix it.
> If possible I will push v8; keeping it pending is lower preference for me.

I have sent a v8 to fix this (issue was indeed there). I have not used
reviewed-by from you on v8 9/9.

>
>>
>>> + */
>>> +int
>>> +rte_eal_pci_detach(const char *device_name);
>>> +
>>> +/**
>>
>> <...>
>
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 9/9] eal: enable hotplugging of devices on bus
  2017-01-17 13:37     ` [PATCH v8 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-17 15:17       ` Ferruh Yigit
  0 siblings, 0 replies; 146+ messages in thread
From: Ferruh Yigit @ 2017-01-17 15:17 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/17/2017 1:37 PM, Shreyansh Jain wrote:
> Given a bus, attach and detach callbacks allow the implementation to
> handles calls from EAL for attaching or detaching a named device.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v6 5/8] eal: introduce bus scan and probe in EAL
  2017-01-17  5:03     ` Shreyansh Jain
@ 2017-01-17 23:04       ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:04 UTC (permalink / raw)
  To: Shreyansh Jain, Ferruh Yigit; +Cc: david.marchand, dev

2017-01-17 10:33, Shreyansh Jain:
> On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:
> > On 1/16/2017 3:38 PM, Shreyansh Jain wrote:
> >> +/* Add a PCI device to PCI Bus */
> >> +void
> >> +rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
> >> +                   struct rte_pci_device *pci_dev)
> >
> > I think more generic approach from previous version was better
> > (rte_eal_bus_add_device()), but I guess they sacrificed for less
> > modification.
> 
> There was a lot of offline discussions after the reviews were posted 
> until v5. From the gist of it, I gathered that smaller 'specific' 
> changes are preferred as compared to complete generic approach without 
> an upfront usecase.

Yes I discussed (a lot) this approach with Shreyansh.

> Also, this change became irrelevant once I moved out the device/driver 
> lists from rte_bus to rte_xxx_bus. This is inline with existing model of 
> (rte_pci_device->rte_device, rte_pci_driver->rte_driver, 
> rte_pci_bus->rte_bus) and having pci_device_list/pci_driver_list private 
> to PCI itself.
> 
> I guess what is going to happen is that in near future when buses start 
> moving to drivers/bus/*, this kind of generic layer would come in.

I think there will be no use case requiring a unique list of all rte_device(s).
Being generic and wrapping stuff with abstract classes is not always a benefit.
That's why, this version is more focused on specialized objects.

Experience with this layering will tell us wether it is a good design or not.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 1/9] eal/bus: introduce bus abstraction
  2017-01-17 13:37     ` [PATCH v8 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-17 23:19       ` Thomas Monjalon
  2017-01-18  5:12         ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:19 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> +void
> +rte_bus_register(struct rte_bus *bus)
> +{
> +	RTE_VERIFY(bus);
> +	RTE_VERIFY(bus->name && strlen(bus->name));
> +
> +	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> +	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);

I think it should be a debug log.

> +/* unregister a bus */
> +void
> +rte_bus_unregister(struct rte_bus *bus)

I appreciate the effort for commenting, but I think the function name
is self describing.

> +/**
> + * @file
> + *
> + * RTE PMD Bus Abstraction interfaces

RTE PMD?
I would say "DPDK device bus interface"

> +DPDK_17.02 {
> +	global:
> +
> +	rte_bus_list;

Why the bus list is exported?
If it is for testing purpose, I wonder wether it is worth to do it.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
  2017-01-17 13:37     ` [PATCH v8 2/9] test: add basic bus infrastructure tests Shreyansh Jain
@ 2017-01-17 23:23       ` Thomas Monjalon
  2017-01-18  5:13         ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:23 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> +REGISTER_TEST_COMMAND(bus_autotest, test_bus);

You should add it to app/test/autotest_data.py

> +/* Bus list exposed */
> +extern struct rte_bus_list rte_bus_list;

I think it should be possible to write a test without the real list
of registered bus.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 3/9] pci: split match and probe function
  2017-01-17 13:37     ` [PATCH v8 3/9] pci: split match and probe function Shreyansh Jain
@ 2017-01-17 23:31       ` Thomas Monjalon
  2017-01-18  6:17         ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:31 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> +static int
> +rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> +               struct rte_pci_device *dev)
> +{
> +       int ret;
> +       struct rte_pci_addr *loc;
> +
> +       if ((dr == NULL) || (dev == NULL))
> +               return -EINVAL;
> +
> +       ret = rte_pci_match(dr, dev);

I do not understand this function.
The driver should be known by the device at this stage.
Why specifying a driver as parameter?

I know it is not new in this series, but
pci_detach_all_drivers(struct rte_pci_device *dev) makes no sense to me.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 4/9] eal/bus: support for scanning of bus
  2017-01-17 13:37     ` [PATCH v8 4/9] eal/bus: support for scanning of bus Shreyansh Jain
@ 2017-01-17 23:37       ` Thomas Monjalon
  2017-01-18  5:15         ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:37 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> + * Generic bus object passed only as a helper for implementation to find
> + * their respective registered bus object. Implementations can choose not
> + * to use this variable.

I think this comment is obsolete.

> + *
> + * @return
> + *     0 for successful scan
> + *     !0 (<0) for unsuccessful scan with error value

What do you mean with !0 (<0) ?
I guess <0 is enough.

> + */
> +typedef int (*rte_bus_scan_t)(void);
> 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 5/9] eal/bus: introduce support for bus probing
  2017-01-17 13:37     ` [PATCH v8 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
@ 2017-01-17 23:38       ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:38 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> + * This is called while iterating over each registered bus. Bus object is
> + * passed along assuming this is wrapped around (embedded) by Implementation
> + * specific bus object.
> + *
> + * @param bus
> + *     Generic bus object which was registered with EAL

No param bus here.

> + *
> + * @return
> + *     0 for successful probe
> + *     !0 for any error while probing
> + */
> +typedef int (*rte_bus_probe_t)(void);
> 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 6/9] eal: integrate bus scan and probe with EAL
  2017-01-17 13:37     ` [PATCH v8 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2017-01-17 23:44       ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:44 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> Each bus implementation defines their own callbacks for scanning its bus
> and probing devices available on the bus. Enable EAL to call bus specific
> scan and probe functions during DPDK initialization.
> 
> Existing PCI scan/probe continues to exist. It will removed in subsequent
> patches.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> ---
>  lib/librte_eal/bsdapp/eal/eal.c                 |  8 +++
>  lib/librte_eal/bsdapp/eal/eal_pci.c             | 11 ++++
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 +
>  lib/librte_eal/common/eal_common_bus.c          | 40 +++++++++++++++
>  lib/librte_eal/common/eal_common_pci.c          | 33 ++++++++++++
>  lib/librte_eal/common/include/rte_bus.h         | 19 +++++++
>  lib/librte_eal/common/include/rte_pci.h         | 68 +++++++++++++++++++++++++
>  lib/librte_eal/linuxapp/eal/eal.c               |  8 +++
>  lib/librte_eal/linuxapp/eal/eal_pci.c           | 15 ++++++
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 +
>  10 files changed, 206 insertions(+)

You can make 2 patches here:
- 1 patch for generic functions
- 1 patch for PCI implementation

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 7/9] test: update bus and pci unit test cases
  2017-01-17 13:37     ` [PATCH v8 7/9] test: update bus and pci unit test cases Shreyansh Jain
@ 2017-01-17 23:46       ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:46 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> ---
>  app/test/test_bus.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++
>  app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
>  2 files changed, 266 insertions(+), 50 deletions(-)

You can split in 2 patches (generic and PCI)
and squash them with their respective implementation in EAL.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 8/9] eal: enable PCI bus
  2017-01-17 13:37     ` [PATCH v8 8/9] eal: enable PCI bus Shreyansh Jain
@ 2017-01-17 23:57       ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-17 23:57 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-17 19:07, Shreyansh Jain:
> -       /* Probe & Initialize PCI devices */
> -       if (rte_eal_pci_probe())
> -               rte_panic("Cannot probe PCI\n");
> -
>         /* Probe all the buses and devices/drivers on them */
>         if (rte_bus_probe())
>                 rte_panic("Cannot probe devices\n");
> 

I like reading this :)
It is a good step.
A next step could be removing rte_bus_probe() and do it from
the scan functions, after letting the application manage the
blacklist via a callback.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 1/9] eal/bus: introduce bus abstraction
  2017-01-17 23:19       ` Thomas Monjalon
@ 2017-01-18  5:12         ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18  5:12 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, January 18, 2017 4:50 AM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v8 1/9] eal/bus: introduce bus abstraction
> 
> 2017-01-17 19:07, Shreyansh Jain:
> > +void
> > +rte_bus_register(struct rte_bus *bus)
> > +{
> > +	RTE_VERIFY(bus);
> > +	RTE_VERIFY(bus->name && strlen(bus->name));
> > +
> > +	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> > +	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
> 
> I think it should be a debug log.

I thought it should be visible to user/app which buses exists parallel to the information about the detected devices.

But, no strong opinion on this - I will change in v9.

> 
> > +/* unregister a bus */
> > +void
> > +rte_bus_unregister(struct rte_bus *bus)
> 
> I appreciate the effort for commenting, but I think the function name
> is self describing.

Ok. I will remove the comment. (as well as similar occurences. 

> 
> > +/**
> > + * @file
> > + *
> > + * RTE PMD Bus Abstraction interfaces
> 
> RTE PMD?
> I would say "DPDK device bus interface"

Yes, that is an oversight. PMD is irrelevant here.

> 
> > +DPDK_17.02 {
> > +	global:
> > +
> > +	rte_bus_list;
> 
> Why the bus list is exported?
> If it is for testing purpose, I wonder wether it is worth to do it.

I have modeled the test cases on the lines of test_pci and it worked on actual pci device lists. Though, it is very much possible to not even touch the actual lists (in either, bus or pci test cases).

I can easily remove the usage of actual list in test_bus.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
  2017-01-17 23:23       ` Thomas Monjalon
@ 2017-01-18  5:13         ` Shreyansh Jain
  2017-01-18  6:56           ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18  5:13 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, January 18, 2017 4:54 AM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
> 
> 2017-01-17 19:07, Shreyansh Jain:
> > +REGISTER_TEST_COMMAND(bus_autotest, test_bus);
> 
> You should add it to app/test/autotest_data.py

Ok. I will do that.

> 
> > +/* Bus list exposed */
> > +extern struct rte_bus_list rte_bus_list;
> 
> I think it should be possible to write a test without the real list
> of registered bus.

Yes, it is possible. I just modeled it on test_pci assuming that is a kind of expected/standard. But, it seems probably it is not. I will change the tests.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 4/9] eal/bus: support for scanning of bus
  2017-01-17 23:37       ` Thomas Monjalon
@ 2017-01-18  5:15         ` Shreyansh Jain
  2017-01-18  7:32           ` Thomas Monjalon
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18  5:15 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, January 18, 2017 5:07 AM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v8 4/9] eal/bus: support for scanning of bus
> 
> 2017-01-17 19:07, Shreyansh Jain:
> > + * Generic bus object passed only as a helper for implementation to find
> > + * their respective registered bus object. Implementations can choose not
> > + * to use this variable.
> 
> I think this comment is obsolete.
 
I will remove it.

> 
> > + *
> > + * @return
> > + *     0 for successful scan
> > + *     !0 (<0) for unsuccessful scan with error value
> 
> What do you mean with !0 (<0) ?
> I guess <0 is enough.
> 
 
Only to highlight that only '-ve' values would be returned. I will change it to !0 only.

> > + */
> > +typedef int (*rte_bus_scan_t)(void);
> >
> 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 3/9] pci: split match and probe function
  2017-01-17 23:31       ` Thomas Monjalon
@ 2017-01-18  6:17         ` Shreyansh Jain
  2017-01-18  7:31           ` Thomas Monjalon
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18  6:17 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, January 18, 2017 5:02 AM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v8 3/9] pci: split match and probe function
> 
> 2017-01-17 19:07, Shreyansh Jain:
> > +static int
> > +rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> > +               struct rte_pci_device *dev)
> > +{
> > +       int ret;
> > +       struct rte_pci_addr *loc;
> > +
> > +       if ((dr == NULL) || (dev == NULL))
> > +               return -EINVAL;
> > +
> > +       ret = rte_pci_match(dr, dev);
> 
> I do not understand this function.
> The driver should be known by the device at this stage.
> Why specifying a driver as parameter?
> 
> I know it is not new in this series, but
> pci_detach_all_drivers(struct rte_pci_device *dev) makes no sense to me.

>From what I understand, pci_detach_all_drivers is simply a wrapper over the PCI driver list, calling rte_eal_pci_detach_dev for each driver. Considering that all it does is iterate, it is not functionally required.

But, let me clarify one more thing: There is a possibility that rte_pci_device->pci_driver be directly used in case of detach rather than searching for a driver. This is assuming that before 'detach', a pci_device would link to a valid pci_driver. Is there some caveat in this assumption?

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
  2017-01-18  5:13         ` Shreyansh Jain
@ 2017-01-18  6:56           ` Shreyansh Jain
  2017-01-18  7:28             ` Thomas Monjalon
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18  6:56 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Shreyansh Jain
> Sent: Wednesday, January 18, 2017 10:42 AM
> To: 'Thomas Monjalon' <thomas.monjalon@6wind.com>
> Cc: dev@dpdk.org
> Subject: RE: [PATCH v8 2/9] test: add basic bus infrastructure tests
> 
> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > Sent: Wednesday, January 18, 2017 4:54 AM
> > To: Shreyansh Jain <shreyansh.jain@nxp.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
> >
> > 2017-01-17 19:07, Shreyansh Jain:
> > > +REGISTER_TEST_COMMAND(bus_autotest, test_bus);
> >
> > You should add it to app/test/autotest_data.py
> 
> Ok. I will do that.
> 
> >
> > > +/* Bus list exposed */
> > > +extern struct rte_bus_list rte_bus_list;
> >
> > I think it should be possible to write a test without the real list
> > of registered bus.
> 
> Yes, it is possible. I just modeled it on test_pci assuming that is a kind of
> expected/standard. But, it seems probably it is not. I will change the tests.

After sending out this mail I realized the real reason for using the actual lists. Functions like rte_eal_pci_register (for PCI) or rte_bus_register (for Bus), use global lists for registration. Test cases calls these functions for registering dummy device/bus.

One way is to not worry about adding these test/dummy devices/buses to original list as they would be unregistered anyway. But, risk is of impacting running list assuming multiple cases need to be run from same application/binary context.

Another way is to rewrite these functions locally in test case, but that also means not testing these global registration/de-registration functions.

Former method would continue to have symbols exported. Later is not testing some entry/exit functions of a sub-system.

You still interested in this change?

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
  2017-01-18  6:56           ` Shreyansh Jain
@ 2017-01-18  7:28             ` Thomas Monjalon
  2017-01-18  8:42               ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-18  7:28 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-18 06:56, Shreyansh Jain:
> > > > +/* Bus list exposed */
> > > > +extern struct rte_bus_list rte_bus_list;
> > >
> > > I think it should be possible to write a test without the real list
> > > of registered bus.
> > 
> > Yes, it is possible. I just modeled it on test_pci assuming that is a kind of
> > expected/standard. But, it seems probably it is not. I will change the tests.
> 
> After sending out this mail I realized the real reason for using the actual lists. Functions like rte_eal_pci_register (for PCI) or rte_bus_register (for Bus), use global lists for registration. Test cases calls these functions for registering dummy device/bus.

Why access to the bus list is externally required?
I feel there is something wrong here. It should be private in PCI.

> One way is to not worry about adding these test/dummy devices/buses to original list as they would be unregistered anyway. But, risk is of impacting running list assuming multiple cases need to be run from same application/binary context.
> 
> Another way is to rewrite these functions locally in test case, but that also means not testing these global registration/de-registration functions.
> 
> Former method would continue to have symbols exported. Later is not testing some entry/exit functions of a sub-system.
> 
> You still interested in this change?

I would prefer you do not lose time with testing at this stage.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 3/9] pci: split match and probe function
  2017-01-18  6:17         ` Shreyansh Jain
@ 2017-01-18  7:31           ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-18  7:31 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-18 06:17, Shreyansh Jain:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > 2017-01-17 19:07, Shreyansh Jain:
> > > +static int
> > > +rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> > > +               struct rte_pci_device *dev)
> > > +{
> > > +       int ret;
> > > +       struct rte_pci_addr *loc;
> > > +
> > > +       if ((dr == NULL) || (dev == NULL))
> > > +               return -EINVAL;
> > > +
> > > +       ret = rte_pci_match(dr, dev);
> > 
> > I do not understand this function.
> > The driver should be known by the device at this stage.
> > Why specifying a driver as parameter?
> > 
> > I know it is not new in this series, but
> > pci_detach_all_drivers(struct rte_pci_device *dev) makes no sense to me.
> 
> From what I understand, pci_detach_all_drivers is simply a wrapper over the PCI driver list, calling rte_eal_pci_detach_dev for each driver. Considering that all it does is iterate, it is not functionally required.
> 
> But, let me clarify one more thing: There is a possibility that rte_pci_device->pci_driver be directly used in case of detach rather than searching for a driver. This is assuming that before 'detach', a pci_device would link to a valid pci_driver. Is there some caveat in this assumption?

I would say it it always true.
But seeing this code existing makes me hesitates.
I suggest to go with this assumption for RC1 and remove this loop.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 4/9] eal/bus: support for scanning of bus
  2017-01-18  5:15         ` Shreyansh Jain
@ 2017-01-18  7:32           ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-18  7:32 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-18 05:15, Shreyansh Jain:
> > > + *
> > > + * @return
> > > + *     0 for successful scan
> > > + *     !0 (<0) for unsuccessful scan with error value
> > 
> > What do you mean with !0 (<0) ?
> > I guess <0 is enough.
> > 
>  
> Only to highlight that only '-ve' values would be returned. I will change it to !0 only.

What is -ve?
Why not specifying <0 if errors are always negative?

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v8 2/9] test: add basic bus infrastructure tests
  2017-01-18  7:28             ` Thomas Monjalon
@ 2017-01-18  8:42               ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18  8:42 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

On Wednesday 18 January 2017 12:58 PM, Thomas Monjalon wrote:
> 2017-01-18 06:56, Shreyansh Jain:
>>>>> +/* Bus list exposed */
>>>>> +extern struct rte_bus_list rte_bus_list;
>>>>
>>>> I think it should be possible to write a test without the real list
>>>> of registered bus.
>>>
>>> Yes, it is possible. I just modeled it on test_pci assuming that is a kind of
>>> expected/standard. But, it seems probably it is not. I will change the tests.
>>
>> After sending out this mail I realized the real reason for using the actual lists. Functions like rte_eal_pci_register (for PCI) or rte_bus_register (for Bus), use global lists for registration. Test cases calls these functions for registering dummy device/bus.
>
> Why access to the bus list is externally required?
> I feel there is something wrong here. It should be private in PCI.

When I stated rte_eal_pci_register required global lists, I meant in 
previous code base (pre bus), the pci_device_list and pci_driver_list
were public because registration function used them and test cases used
the registration function.

>
>> One way is to not worry about adding these test/dummy devices/buses to original list as they would be unregistered anyway. But, risk is of impacting running list assuming multiple cases need to be run from same application/binary context.
>>
>> Another way is to rewrite these functions locally in test case, but that also means not testing these global registration/de-registration functions.
>>
>> Former method would continue to have symbols exported. Later is not testing some entry/exit functions of a sub-system.
>>
>> You still interested in this change?
>
> I would prefer you do not lose time with testing at this stage.
>

Ok. I will leave it as it is for now.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model
  2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
                       ` (8 preceding siblings ...)
  2017-01-17 13:37     ` [PATCH v8 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-18 10:37     ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
                         ` (13 more replies)
  9 siblings, 14 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v8: [18]

:: Introduction ::

DPDK has been inherently a PCI inclined framework. Because of this, the
design of device tree (or list) within DPDK is also PCI inclined. A
non-PCI device doesn't have a way of being expressed without using hooks
started from EAL to PMD.

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

        device A1
          |
  +==.===='==============.============+ Bus A.
     |                    `--> driver A11     \
  device A2                `-> driver A12      \______
                                                |CPU |
                                                /`````
        device B1                              /
          |                                   /
  +==.===='==============.============+ Bus B`
     |                    `--> driver B11
  device B2                `-> driver B12


 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

In [15], model assumes that rte_bus would be the base class using which
all the bus implementations would instantiate the objects. This patches
takes a much more basic approach, on the same lines of rte_device/
rte_driver and rte_pci_device/rte_pci_driver.
This is based on various review comments as well as offline (IRC)
discussions.

 - rte_bus is an abstract class which includes basic methods supported by
   all buses.
 - specific implementation, for example for PCI rte_pci_bus, would extend
   this class to form their own buses, with their own bus specific device
   and driver list.
 - 

 +-----------------+
 |rte_pci_bus      |
 |+---------------+|
 ||rte_bus        ||
 |+---------------+|
 +-----------------+

And example implementation would look like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | probe          ||     |
  |                | | attach         ||     |
  |                | | detach         ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+


:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003     : Split the PCI match into a separate function
0004     : Remove an unnecessary loop over drivers in device detach
0005~0006: Introduce bus->scan and bus->probe APIs
0007     : Integrate the bus with EAL, without removing existing device
           driver init/scan model.
0008     : Add PCI Bus over Bus patches introduced earlier
0009~0010: Update the Bus and PCI test cases for scanning/probing
0011     : Enable PCI bus and remove code for direct PCI scan/probe from
           EAL
0012     : Add device hotplugging over the bus and introduce PCI helpers


:: Pending Changes/Caveats ::

1. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   Eventual aim is the PCI bus reside in driver/bus/pci

2. Though the implementation for bus is common for Linux and BSD, the PCI
   bus implementation has been done/tested only for Linux.

3. RTE_REGISTER_BUS has been declared with contructor priority of 101
    It is important that Bus is registered *before* drivers are registered.
    Only way I could find to assure that was via 
    __attribute(contructor(priority)) of GCC. I am not sure how it would
    behave on other compilers. Any suggestions?
    - One suggestion from David Marchand was to use global bus object
      handles, which I have not implemented for now. If that is common
      choice, I will change in v3.
4. Hotplugging has been introduced over Bus with a caveat - it would only
   work for ports/NICs already scanned and available in the bus list.

:: ToDo list ::

 - Bump to librte_eal version
 - Documentation continues to have references to some _old_ PCI symbols

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html - v1
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html - v2
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html - v3
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html - v4
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html - v5
[16] http://dpdk.org/ml/archives/dev/2017-January/055120.html  - v6
[17] http://dpdk.org/ml/archives/dev/2017-January/055320.html  - v7
[18] http://dpdk.org/ml/archives/dev/2017-January/055398.html  - v8

:: Version Changes ::
v9:
 - Removed comments over function definitions
 - Documentation fixes as per review comments
 - Split the test_pci and test_bus patches
 - Split the patches for generic bus changes and PCI level bus changes
 - Add bus_autotest as entry into autotest_data.py

v8:
 - fix return value bug in rte_eal_pci_attach and rte_eal_pci_detach

v7:
 - update to rte_pci_match for const parameters
 - remove unnecessary log messages in probe; moved _after_ matching
   of device and driver
 - bug fixes in attach/detach methods
 - PCI disable for debugging was missed (from rte_eal_pci_init) in v6

v6:
 - Rearchitecture to bring bus object parallel to rte_device/driver
   This majorly includes:
   -- rte_pci_bus class and pci_bus as its object for PCI
   -- bus->attach/detach (hotplugging)
   -- removing bus->match as that is local to an implementation
 - rename symbols rte_eal_bus_* to rte_bus_*
 - restructuring patches (order) for simplicity
 - update to test_pci

v5:
 - Fix checkpatch error in Patch 0003

v4:
 - rebase over master (eac901ce)
 - Fix a bug in test_bus while setup and cleanup
 - rename rte_eal_get_bus to rte_eal_bus_get
 - Add helper (iterator) macros for easy bus,device,driver traversal
 - removed 0001 patch as it is already merged in master
 - fix missing rte_eal_bus_insert_device symbol in map file

v3:
 - rebase over master (c431384c8f)
 - revert patch 0001 changes for checkpatch (container_of macro)
 - qat/rte_qat_cryptodev update for rte_driver->probe
 - test_pci update for using a test_pci_bus for verification
 - some bug fixes based on internal testing.
 -- rte_eal_dev_attach not handling devargs
 -- blacklisting not working

v2:
 - No more bus->probe()
   Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
 - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
   added as glue code between PCI PMDs and PCI Bus
   `-> PMDs are updated to use these new functions as callbacks for
       rte_driver
 - 'default' keyword has been removed from match and scan
 - Fix for incorrect changes in mlx* and nicvf*
 - Checkpatch fixes
 - Some variable checks have been removed from internal functions;
   functions which are externally visible continue to have such checks
 - Some rearrangement of patches:
   -- changes to drivers have been separated from EAL changes (but this
      does make PCI PMDs non-working for a particular patch)

Shreyansh Jain (12):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  pci: split match and probe function
  eal: remove loop over drivers in device detach
  eal/bus: support for scanning of bus
  eal/bus: introduce support for bus probing
  eal: integrate bus scan and probe with EAL
  eal/pci: add support for PCI bus
  test: add test cases for scan and probe on BUS
  test: add Bus based scan and probe test cases for PCI
  eal: enable PCI bus
  eal: enable hotplugging of devices on bus

 app/test/Makefile                               |   2 +-
 app/test/autotest_data.py                       |   6 +
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 164 ++++--
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  17 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 138 +++++
 lib/librte_eal/common/eal_common_dev.c          |  56 +-
 lib/librte_eal/common/eal_common_pci.c          | 374 ++++++++-----
 lib/librte_eal/common/eal_private.h             |  10 -
 lib/librte_eal/common/include/rte_bus.h         | 191 +++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/common/include/rte_pci.h         | 148 ++++-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
 21 files changed, 1636 insertions(+), 276 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v9 01/12] eal/bus: introduce bus abstraction
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:46         ` Thomas Monjalon
  2017-01-18 10:37       ` [PATCH v9 02/12] test: add basic bus infrastructure tests Shreyansh Jain
                         ` (12 subsequent siblings)
  13 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for EAL.
The model is:
 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' base class which would be extended for
specific implementations. It also introduces Bus registration and
deregistration functions.

An example implementation would be like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | match          ||     |
  |                | | probe          ||     |
  |                | | remove         ||     |
  |                | | ...            ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  10 +++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          |  95 ++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 111 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  10 +++
 8 files changed, 230 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..6e09448
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,95 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+void
+rte_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+void
+rte_bus_unregister(struct rte_bus *bus)
+{
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* Dump information of a single bus */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..2dc9bef
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,111 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * DPDK device bus interface
+ *
+ * This file exposes APIs and Interfaces for Bus Abstraction over the devices
+ * and drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	const char *name;            /**< Name of the bus */
+};
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_bus_dump(FILE *f);
+
+/** Helper for Bus registration. The constructor has higher priority than
+ * PMD constructors
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b17791f..24c1c00 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -122,6 +122,7 @@ struct rte_driver;
  */
 struct rte_device {
 	TAILQ_ENTRY(rte_device) next; /**< Next device */
+	struct rte_bus *bus;          /**< Device connected to this bus */
 	const struct rte_driver *driver;/**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..aa874a5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..b553b13 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,13 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 02/12] test: add basic bus infrastructure tests
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 03/12] pci: split match and probe function Shreyansh Jain
                         ` (11 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/Makefile                       |   2 +-
 app/test/autotest_data.py               |   6 +
 app/test/test.h                         |   2 +
 app/test/test_bus.c                     | 359 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h |   3 +
 5 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0cd598b..ea8f9ca 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -239,6 +239,12 @@ def per_sockets(num):
                 "Func":    default_autotest,
                 "Report":  None,
             },
+            {
+                "Name":    "Bus autotest",
+                "Command": "bus_autotest",
+                "Func":    default_autotest,
+                "Report":  None,
+            },
         ]
     },
     {
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 2dc9bef..204e576 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * A structure describing a generic bus.
  */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 03/12] pci: split match and probe function
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 02/12] test: add basic bus infrastructure tests Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 04/12] eal: remove loop over drivers in device detach Shreyansh Jain
                         ` (10 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
 lib/librte_eal/common/include/rte_pci.h         |  15 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 1;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
-
-		return ret;
+		match = 0;
+		break;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	return match;
 }
 
 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	int ret;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	loc = &dev->addr;
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	}
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* clear driver structure */
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
 		dev->driver = NULL;
-
 		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
 			rte_eal_pci_unmap_device(dev);
+	}
 
-		return 0;
+	return ret;
+}
+
+/*
+ * If vendor/device ID match, call the remove() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
 	}
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	loc = &dev->addr;
+
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
+
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..adc20b9 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b553b13..5ed2589 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,5 +186,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 04/12] eal: remove loop over drivers in device detach
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (2 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 03/12] pci: split match and probe function Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:41         ` Shreyansh Jain
  2017-01-18 11:12         ` Thomas Monjalon
  2017-01-18 10:37       ` [PATCH v9 05/12] eal/bus: support for scanning of bus Shreyansh Jain
                         ` (9 subsequent siblings)
  13 siblings, 2 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

Removing pci_detach_all_drivers and restructuring rte_eal_pci_detach
and rte_eal_pci_detach_dev to work without looping over driver list.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_pci.c | 41 +++++++++-------------------------
 1 file changed, 10 insertions(+), 31 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..7548ab0 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -259,15 +259,17 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_detach_dev(struct rte_pci_device *dev)
 {
 	int ret;
 	struct rte_pci_addr *loc;
+	struct rte_pci_driver *dr;
 
-	if ((dr == NULL) || (dev == NULL))
+	if ((dev == NULL))
 		return -EINVAL;
 
+	dr = dev->driver;
+
 	ret = rte_pci_match(dr, dev);
 	if (ret) {
 		/* Device and driver don't match */
@@ -328,33 +330,6 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 }
 
 /*
- * If vendor/device ID match, call the remove() function of all
- * registered driver for the given device. Return -1 if initialization
- * failed, return 1 if no driver is found for this device.
- */
-static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
-{
-	struct rte_pci_driver *dr = NULL;
-	int rc = 0;
-
-	if (dev == NULL)
-		return -1;
-
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_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;
-}
-
-/*
  * Find the pci device specified by pci address, then invoke probe function of
  * the driver of the devive.
  */
@@ -407,9 +382,13 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = rte_eal_pci_detach_dev(dev);
 		if (ret < 0)
+			/* negative value is an error */
 			goto err_return;
+		if (ret > 0)
+			/* positive value means driver doesn't support it */
+			continue;
 
 		TAILQ_REMOVE(&pci_device_list, dev, next);
 		free(dev);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 05/12] eal/bus: support for scanning of bus
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (3 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 04/12] eal: remove loop over drivers in device detach Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 06/12] eal/bus: introduce support for bus probing Shreyansh Jain
                         ` (8 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_bus.c                     | 175 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  14 +++
 3 files changed, 191 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
+		.scan = scan_fn_for_busA,
 	},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
 	.name = "busB_impl", /* busB */
 	.bus = {
 		.name = "busB",
+		.scan = scan_fn_for_busB,
 	},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map 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 dummy_device *ddev = NULL;
+	struct dummy_bus_map *dbmap = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; bus_map[i].name; i++) {
+		if (!strcmp(bus_map[i].name, bus->name)) {
+			dbmap = &bus_map[i];
+			break;
+		}
+	}
+
+	if (!dbmap)
+		return -1;
+
+	db = dbmap->dbus;
+
+	/* For all the devices in the device tree (bus_map), add device */
+	for (i = 0; dbmap->ddevices[i]; i++) {
+		ddev = dbmap->ddevices[i];
+		TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+		ddev->dev.bus = bus;
+	}
+
+	return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busA") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busB") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+	int i = 0;
 	struct rte_bus *bus_p = NULL;
 
 	/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
 		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
 	}
 
+	/* Initialize the bus lists */
+	for (i = 0; bus_map[i].name; i++) {
+		TAILQ_INIT(&bus_map[i].dbus->device_list);
+		TAILQ_INIT(&bus_map[i].dbus->driver_list);
+	}
+
+	dump_device_tree();
 	return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
 	return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct dummy_device *ddev;
+	struct dummy_bus *dbus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       bus_map[i].name);
+			return -1;
+		}
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			TAILQ_REMOVE(&dbus->device_list, ddev, next);
+		}
+	}
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		dbus = container_of(bus, struct dummy_bus, bus);
+
+		if (!TAILQ_EMPTY(&dbus->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();
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -346,6 +515,12 @@ test_bus(void)
 	if (test_bus_registration())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_bus_unregistration())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 6e09448..aaba10a 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -50,6 +50,8 @@ rte_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan implemented */
+	RTE_VERIFY(bus->scan);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 204e576..ba7d866 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,11 +60,25 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 extern struct rte_bus_list rte_bus_list;
 
 /**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @return
+ *	0 for successful scan
+ *	<0 for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
+	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 06/12] eal/bus: introduce support for bus probing
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (4 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 05/12] eal/bus: support for scanning of bus Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 07/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
                         ` (7 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

This patch introduces the callback which would be implemented for PCI
in subsequent patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index aaba10a..3f529e6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -52,6 +52,7 @@ rte_bus_register(struct rte_bus *bus)
 	RTE_VERIFY(bus->name && strlen(bus->name));
 	/* A bus should mandatorily have the scan implemented */
 	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index ba7d866..17583ad 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -73,12 +73,25 @@ extern struct rte_bus_list rte_bus_list;
 typedef int (*rte_bus_scan_t)(void);
 
 /**
+ * Implementation specific probe function which is responsible for linking
+ * devices on that bus with applicable drivers.
+ *
+ * This is called while iterating over each registered bus.
+ *
+ * @return
+ *	0 for successful probe
+ *	!0 for any error while probing
+ */
+typedef int (*rte_bus_probe_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
+	rte_bus_probe_t probe;       /**< Probe devices on bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 07/12] eal: integrate bus scan and probe with EAL
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (5 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 06/12] eal/bus: introduce support for bus probing Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 08/12] eal/pci: add support for PCI bus Shreyansh Jain
                         ` (6 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Add functions for scanning all the buses and performing probe on all
the buses on EAL initialization.

Presently, no bus exists - in subseqent patches, PCI bus would be
introduced.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 +++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 ++
 lib/librte_eal/common/eal_common_bus.c          | 40 +++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 19 ++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  8 +++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 ++
 6 files changed, 78 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..f0abd82 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -577,6 +577,9 @@ rte_eal_init(int argc, char **argv)
 		rte_config.master_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +616,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 3f529e6..ead9a22 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -65,6 +65,46 @@ rte_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* Error in scanning any bus stops the EAL init. */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->probe();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* Dump information of a single bus */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 17583ad..4b4bb36 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -113,6 +113,25 @@ void rte_bus_register(struct rte_bus *bus);
 void rte_bus_unregister(struct rte_bus *bus);
 
 /**
+ * Scan all the buses attached to the framework.
+ *
+ * @return
+ *	0 in case of success in scanning all buses
+ *	!0 in case of failure to scan
+ */
+int rte_bus_scan(void);
+
+/**
+ * For each device on the bus, perform a driver 'match' and call the
+ * bus's probe for device initialization.
+ *
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_bus_probe(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..f77ff5c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -844,6 +845,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 5ed2589..6f047c5 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,6 +186,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 08/12] eal/pci: add support for PCI bus
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (6 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 07/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 09/12] test: add test cases for scan and probe on BUS Shreyansh Jain
                         ` (5 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

EAL continues to have direct PCI init/scan calls as well. These would be
removed in subsequent patches to enable bus only PCI devices.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  1 +
 lib/librte_eal/bsdapp/eal/eal_pci.c     | 11 ++++++
 lib/librte_eal/common/eal_common_pci.c  | 33 ++++++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 68 +++++++++++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 15 ++++++++
 5 files changed, 128 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index f0abd82..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 7548ab0..d2699bd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -487,3 +488,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+		       struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+	/* Update Bus references */
+	new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+	TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..05cf693 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *pci_bus;            /**< PCI bus reference */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -523,6 +553,44 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_bus
+ *	PCI Bus reference to which device is to be added
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+			    struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index e2fc219..300064d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -54,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -723,3 +727,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 09/12] test: add test cases for scan and probe on BUS
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (7 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 08/12] eal/pci: add support for PCI bus Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 10/12] test: add Bus based scan and probe test cases for PCI Shreyansh Jain
                         ` (4 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_bus.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 0b6d011..ef7fa89 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -120,12 +120,15 @@ static int scan_fn_for_busB(void);
 
 /* generic implementations wrapped around by above declarations */
 static int generic_scan_fn(struct rte_bus *bus);
+static int generic_probe_fn(void);
+static int dummy_match_fn(struct rte_driver *drv, struct rte_device *dev);
 
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
 		.scan = scan_fn_for_busA,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -134,6 +137,7 @@ struct dummy_bus busB = {
 	.bus = {
 		.name = "busB",
 		.scan = scan_fn_for_busB,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -288,6 +292,46 @@ generic_scan_fn(struct rte_bus *bus)
 	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 match with
+ * @param dev
+ *	device object
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+dummy_match_fn(struct rte_driver *drv __rte_unused, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct dummy_device *ddev = NULL;
+	struct dummy_device *ddev_as_arg;
+	struct dummy_bus *dbus = 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 = dev->bus;
+	dbus = container_of(bus, struct dummy_bus, bus);
+	ddev_as_arg = container_of(dev, struct dummy_device, dev);
+
+	TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+		if (ddev == ddev_as_arg)
+			return 0;
+	}
+
+	return 1;
+}
+
 int
 scan_fn_for_busA(void) {
 	struct dummy_bus_map *dbm;
@@ -504,6 +548,110 @@ test_bus_scan(void)
 	return 0;
 }
 
+/*
+ *
+ */
+static int
+generic_probe_fn(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+	struct dummy_bus *dbus = NULL;
+	struct dummy_device *ddev = NULL;
+	struct dummy_driver *ddrv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device on that bus (bus specific->device_list)
+	 * 3.   for each driver on that bus (bus specific->driver_list)
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+
+		/* Looping over all scanned devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			/* There is a list of drivers within dummy_bus_map.
+			 * In case of PMDs, this would be driver registration
+			 * APIs/list
+			 */
+			for (j = 0; bus_map[i].ddrivers[j]; j++) {
+				ddrv = bus_map[i].ddrivers[j];
+
+				drv = &ddrv->drv;
+				dev = &ddev->dev;
+				ret = dummy_match_fn(drv, dev);
+				if (!ret) {
+					/* As match is generic, it always
+					 * results in dev->drv pointing to
+					 * first driver entry in bus_map[i]
+					 */
+					dev->driver = drv;
+					dev->bus = &dbus->bus;
+				}
+				/* Else, continue */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a bus_map[i]
+	 * should have same driver (first driver entry of bus_map[i])
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		ddrv = bus_map[i].ddrivers[0];
+		drv = &ddrv->drv;
+
+		for (j = 0; bus_map[i].ddevices[j]; j++) {
+			ddev = bus_map[i].ddevices[j];
+			dev = &ddev->dev;
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	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.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i;
+	struct dummy_bus *dbus;
+	struct rte_bus *bus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+		bus = &dbus->bus;
+		ret = bus->probe();
+		if (ret)
+			printf("Probe for %s failed.\n", bus_map[i].name);
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
 
 int
 test_bus(void)
@@ -518,6 +666,10 @@ test_bus(void)
 	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;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 10/12] test: add Bus based scan and probe test cases for PCI
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (8 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 09/12] test: add test cases for scan and probe on BUS Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:37       ` [PATCH v9 11/12] eal: enable PCI bus Shreyansh Jain
                         ` (3 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 114 insertions(+), 50 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+	struct rte_bus bus;
+	struct test_pci_device_list test_device_list;
+	struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+	.bus = {
+		.name = "test_pci_bus",
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
 	return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+	int i;
+	struct rte_pci_device *dev = NULL;
+
+	TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+		       dev->addr.devid, dev->addr.function);
+		fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+		       dev->id.device_id);
+
+		for (i = 0; i != sizeof(dev->mem_resource) /
+			sizeof(dev->mem_resource[0]); i++) {
+			fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+				dev->mem_resource[i].phys_addr,
+				dev->mem_resource[i].len);
+		}
+	}
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+	int ret;
+	struct rte_pci_device *device;
+	struct rte_pci_driver *driver;
+
+	TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+		TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+			ret = rte_pci_match(driver, device);
+			if (!ret) {
+				if (!driver->probe)
+					continue;
+
+				device->driver = driver;
+				ret = driver->probe(driver, device);
+				if (ret != 0)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
 			dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
 	}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
 	const struct resource *r;
 	int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
 	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
+	TAILQ_INIT(&test_pci_bus.test_device_list);
+	TAILQ_INIT(&test_pci_bus.test_driver_list);
 
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_bus_register(&test_pci_bus.bus);
+	pci_bus = &test_pci_bus;
+
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->bus.scan();
 
-	ret = rte_eal_pci_scan();
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
+
+	printf("Dump of all devices scanned:\n");
+	do_pci_device_dump(stdout);
 
 	return 0;
 }
@@ -190,10 +254,11 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
+	void *temp;
 
 	unsetenv("SYSFS_PCI_DEVICES");
 
@@ -203,28 +268,23 @@ test_pci_cleanup(void)
 	ret = resource_rm_by_tar(r);
 	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
 	/*
 	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+	TAILQ_FOREACH_SAFE(dev, &(test_pci_bus.test_device_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_device_list), dev, next);
+		dev->driver = NULL;
 	}
 
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
+	TAILQ_FOREACH_SAFE(dr, &(test_pci_bus.test_driver_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_driver_list), dr, next);
 	}
 
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
+	rte_bus_unregister(&pci_bus->bus);
 
 	return 0;
 }
@@ -234,16 +294,19 @@ test_pci_blacklist(void)
 {
 	struct rte_devargs_list save_devargs_list;
 
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	TEST_ASSERT(TAILQ_EMPTY(&test_pci_bus.test_driver_list),
+		    "PCI Driver list not empty");
+
+	/* Add test drivers to Bus */
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver, next);
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver2, next);
 
 	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
+
+	printf("Probe the Test Bus\n");
+	do_pci_bus_probe();
 
 	if (pci_dev_count == 0) {
 		printf("no device detected\n");
@@ -257,8 +320,8 @@ test_pci_blacklist(void)
 	blacklist_all_devices();
 
 	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
+	printf("Probe bus with all devices blacklisted\n");
+	do_pci_bus_probe();
 
 	free_devargs_list();
 	devargs_list = save_devargs_list;
@@ -270,8 +333,9 @@ test_pci_blacklist(void)
 
 	test_pci_run = 1;
 
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
+	/* Clear the test drivers added to Test Bus */
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver, next);
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver2, next);
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 11/12] eal: enable PCI bus
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (9 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 10/12] test: add Bus based scan and probe test cases for PCI Shreyansh Jain
@ 2017-01-18 10:37       ` Shreyansh Jain
  2017-01-18 10:38       ` [PATCH v9 12/12] eal: enable hotplugging of devices on bus Shreyansh Jain
                         ` (2 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:37 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 -----
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  4 +++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 34 ++++++++++----------
 lib/librte_eal/common/eal_private.h             | 10 ------
 lib/librte_eal/common/include/rte_pci.h         | 22 +++++--------
 lib/librte_eal/linuxapp/eal/eal.c               |  7 -----
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 42 +++++++++----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 44 insertions(+), 86 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index d2699bd..a17ecaf 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -317,7 +312,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -338,6 +333,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -349,7 +345,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -379,7 +375,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -391,7 +387,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 			/* positive value means driver doesn't support it */
 			continue;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -420,7 +416,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 
 		/* set devargs in PCI structure */
 		devargs = pci_devargs_lookup(dev);
@@ -468,7 +464,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -477,16 +473,22 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = &rte_pci_bus;
 }
 
-/* unregister a driver */
+/* Unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = driver->pci_bus;
+
+	TAILQ_REMOVE(&pci_bus->driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = NULL;
 }
 
 /* Add a PCI device to PCI Bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..68386e8 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 05cf693..53793f3 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -124,6 +118,9 @@ TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
 /** List of PCI drivers */
 TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
 
+/* Extend PCI bus definition to users */
+extern struct rte_pci_bus rte_pci_bus;
+
 /* PCI Bus iterators */
 #define FOREACH_DEVICE_ON_PCIBUS(p)	\
 		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
@@ -208,8 +205,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -416,17 +411,14 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,
 	      const struct rte_pci_device *pci_dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index f77ff5c..6bb7fc9 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -884,10 +881,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 300064d..51522af 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -232,7 +232,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_pci_bus *pci_bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -350,21 +351,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&pci_bus->device_list)) {
+		rte_eal_pci_add_device(pci_bus, dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &pci_bus->device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -374,8 +373,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(pci_bus, dev);
 	}
 
 	return 0;
@@ -390,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr);
+	return pci_scan_one(&rte_pci_bus, filename, addr);
 }
 
 /*
@@ -451,6 +450,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -467,7 +470,8 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+
+		if (pci_scan_one(&rte_pci_bus, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -712,22 +716,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 6f047c5..f0e63c3 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v9 12/12] eal: enable hotplugging of devices on bus
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (10 preceding siblings ...)
  2017-01-18 10:37       ` [PATCH v9 11/12] eal: enable PCI bus Shreyansh Jain
@ 2017-01-18 10:38       ` Shreyansh Jain
  2017-01-18 11:10       ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:38 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
 lib/librte_eal/common/eal_common_dev.c  | 56 ++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 89 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 45 +++++++++++------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
 6 files changed, 193 insertions(+), 32 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index a17ecaf..e4f37f3 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -364,19 +364,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
+	if (pci_update_device(&addr) < 0)
+		goto err_return;
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+			return ret;
+		}
+	}
+
+	return 1;
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
-	int ret = 0;
+	struct rte_pci_addr addr;
+	int ret = 1;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = rte_eal_pci_detach_dev(dev);
@@ -391,8 +470,8 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		free(dev);
 		return 0;
 	}
-	return -1;
 
+	return ret;
 err_return:
 	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
 			" cannot be used\n", dev->addr.domain, dev->addr.bus,
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 4b4bb36..1214908 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Bus list exposed */
 extern struct rte_bus_list rte_bus_list;
 
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
@@ -85,6 +87,33 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -92,6 +121,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 53793f3..820b9df 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -421,6 +421,36 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -494,21 +524,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
-
-/**
  * Dump the content of the PCI bus.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 51522af..4c562c5 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -720,6 +720,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* Re: [PATCH v9 04/12] eal: remove loop over drivers in device detach
  2017-01-18 10:37       ` [PATCH v9 04/12] eal: remove loop over drivers in device detach Shreyansh Jain
@ 2017-01-18 10:41         ` Shreyansh Jain
  2017-01-18 11:12         ` Thomas Monjalon
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:41 UTC (permalink / raw)
  To: thomas.monjalon; +Cc: david.marchand, dev

Thomas,

On Wednesday 18 January 2017 04:07 PM, Shreyansh Jain wrote:
> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 4f155c6..7548ab0 100644
> --- a/lib/librte_eal/common/eal_common_pci.c
> +++ b/lib/librte_eal/common/eal_common_pci.c
> @@ -259,15 +259,17 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
>   * driver.
>   */
>  static int
> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> -		struct rte_pci_device *dev)
> +rte_eal_pci_detach_dev(struct rte_pci_device *dev)
>  {
>  	int ret;
>  	struct rte_pci_addr *loc;
> +	struct rte_pci_driver *dr;
>
> -	if ((dr == NULL) || (dev == NULL))
> +	if ((dev == NULL))

There is a checkpatch warning here which missed my check (double
paranthesis). Let me know if you want me to send v10 for this.
Or, if there is anything major, I will send it along with that.

>  		return -EINVAL;
>
> +	dr = dev->driver;
> +
>  	ret = rte_pci_match(dr, dev);
>  	if (ret) {

-
Shreyansh

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v9 01/12] eal/bus: introduce bus abstraction
  2017-01-18 10:37       ` [PATCH v9 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-18 10:46         ` Thomas Monjalon
  2017-01-18 10:52           ` Shreyansh Jain
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-18 10:46 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-18 16:07, Shreyansh Jain:
> +void
> +rte_bus_register(struct rte_bus *bus)
> +{
> +	RTE_VERIFY(bus);
> +	RTE_VERIFY(bus->name && strlen(bus->name));
> +
> +	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> +	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
> +}
> +
> +void
> +rte_bus_unregister(struct rte_bus *bus)
> +{
> +	TAILQ_REMOVE(&rte_bus_list, bus, next);
> +	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
> +}

This log should be DEBUG, consistently with "register" one.

> +DPDK_17.02 {
> +	global:
> +
> +	rte_bus_list;

So finally, is it an useful symbol?
Could it be removed from this patch?

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v9 01/12] eal/bus: introduce bus abstraction
  2017-01-18 10:46         ` Thomas Monjalon
@ 2017-01-18 10:52           ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 10:52 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, January 18, 2017 4:16 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v9 01/12] eal/bus: introduce bus abstraction
> 
> 2017-01-18 16:07, Shreyansh Jain:
> > +void
> > +rte_bus_register(struct rte_bus *bus)
> > +{
> > +	RTE_VERIFY(bus);
> > +	RTE_VERIFY(bus->name && strlen(bus->name));
> > +
> > +	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> > +	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
> > +}
> > +
> > +void
> > +rte_bus_unregister(struct rte_bus *bus)
> > +{
> > +	TAILQ_REMOVE(&rte_bus_list, bus, next);
> > +	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
> > +}
> 
> This log should be DEBUG, consistently with "register" one.
 
:(
Obvious miss.
I will change it.

> 
> > +DPDK_17.02 {
> > +	global:
> > +
> > +	rte_bus_list;
> 
> So finally, is it an useful symbol?
> Could it be removed from this patch?

It is required until test_bus is re-written.
I can move this to next patch (which introduces test_bus).

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (11 preceding siblings ...)
  2017-01-18 10:38       ` [PATCH v9 12/12] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-18 11:10       ` Thomas Monjalon
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
  13 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-18 11:10 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-18 16:07, Shreyansh Jain:
> :: ToDo list ::
> 
>  - Bump to librte_eal version

Please, could you update doc/guides/rel_notes/deprecation.rst in v10?
It is also the opportunity to update the EAL abiver.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v9 04/12] eal: remove loop over drivers in device detach
  2017-01-18 10:37       ` [PATCH v9 04/12] eal: remove loop over drivers in device detach Shreyansh Jain
  2017-01-18 10:41         ` Shreyansh Jain
@ 2017-01-18 11:12         ` Thomas Monjalon
  2017-01-18 12:15           ` Shreyansh Jain
  1 sibling, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-18 11:12 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-18 16:07, Shreyansh Jain:
> +       dr = dev->driver;
> +
>         ret = rte_pci_match(dr, dev);
> 

I think you don't need to match driver anymore.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v9 04/12] eal: remove loop over drivers in device detach
  2017-01-18 11:12         ` Thomas Monjalon
@ 2017-01-18 12:15           ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 12:15 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, January 18, 2017 4:43 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [PATCH v9 04/12] eal: remove loop over drivers in device detach
> 
> 2017-01-18 16:07, Shreyansh Jain:
> > +       dr = dev->driver;
> > +
> >         ret = rte_pci_match(dr, dev);
> >
> 
> I think you don't need to match driver anymore.

:(
I really need to have a strong shot of caffeine.
Will send out in v10.
 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v10 00/13] Introducing EAL Bus-Device-Driver Model
  2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (12 preceding siblings ...)
  2017-01-18 11:10       ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
@ 2017-01-18 14:05       ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 01/13] eal/bus: introduce bus abstraction Shreyansh Jain
                           ` (13 more replies)
  13 siblings, 14 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v9: [19]

:: Introduction ::

DPDK has been inherently a PCI inclined framework. Because of this, the
design of device tree (or list) within DPDK is also PCI inclined. A
non-PCI device doesn't have a way of being expressed without using hooks
started from EAL to PMD.

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

        device A1
          |
  +==.===='==============.============+ Bus A.
     |                    `--> driver A11     \
  device A2                `-> driver A12      \______
                                                |CPU |
                                                /`````
        device B1                              /
          |                                   /
  +==.===='==============.============+ Bus B`
     |                    `--> driver B11
  device B2                `-> driver B12


 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

In [15], model assumes that rte_bus would be the base class using which
all the bus implementations would instantiate the objects. This patches
takes a much more basic approach, on the same lines of rte_device/
rte_driver and rte_pci_device/rte_pci_driver.
This is based on various review comments as well as offline (IRC)
discussions.

 - rte_bus is an abstract class which includes basic methods supported by
   all buses.
 - specific implementation, for example for PCI rte_pci_bus, would extend
   this class to form their own buses, with their own bus specific device
   and driver list.
 - 

 +-----------------+
 |rte_pci_bus      |
 |+---------------+|
 ||rte_bus        ||
 |+---------------+|
 +-----------------+

And example implementation would look like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | probe          ||     |
  |                | | attach         ||     |
  |                | | detach         ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+


:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003     : Split the PCI match into a separate function
0004     : Remove an unnecessary loop over drivers in device detach
0005~0006: Introduce bus->scan and bus->probe APIs
0007     : Integrate the bus with EAL, without removing existing device
           driver init/scan model.
0008     : Add PCI Bus over Bus patches introduced earlier
0009~0010: Update the Bus and PCI test cases for scanning/probing
0011     : Enable PCI bus and remove code for direct PCI scan/probe from
           EAL
0012     : Add device hotplugging over the bus and introduce PCI helpers
0013     : Remove the deprecation notice for rte_bus


:: Pending Changes/Caveats ::

1. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   Eventual aim is the PCI bus reside in driver/bus/pci

2. Though the implementation for bus is common for Linux and BSD, the PCI
   bus implementation has been done/tested only for Linux.

3. RTE_REGISTER_BUS has been declared with contructor priority of 101
    It is important that Bus is registered *before* drivers are registered.
    Only way I could find to assure that was via 
    __attribute(contructor(priority)) of GCC. I am not sure how it would
    behave on other compilers. Any suggestions?
    - One suggestion from David Marchand was to use global bus object
      handles, which I have not implemented for now. If that is common
      choice, I will change in v3.
4. Hotplugging has been introduced over Bus with a caveat - it would only
   work for ports/NICs already scanned and available in the bus list.

:: ToDo list ::

 - Bump to librte_eal version
 - Documentation continues to have references to some _old_ PCI symbols

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html - v1
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html - v2
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html - v3
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html - v4
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html - v5
[16] http://dpdk.org/ml/archives/dev/2017-January/055120.html  - v6
[17] http://dpdk.org/ml/archives/dev/2017-January/055320.html  - v7
[18] http://dpdk.org/ml/archives/dev/2017-January/055398.html  - v8
[19] http://dpdk.org/ml/archives/dev/2017-January/055621.html  - v9

:: Version Changes ::
v10:
 - bump to librte_eal LIBABIVER
 - remove an unnecessary call to rte_pci_match
 - INFO->DEBUG movement of a log message
 - Checkpatch issue fix
 - deprecation notice removal for rte_bus

v9:
 - Removed comments over function definitions
 - Documentation fixes as per review comments
 - Split the test_pci and test_bus patches
 - Split the patches for generic bus changes and PCI level bus changes
 - Add bus_autotest as entry into autotest_data.py

v8:
 - fix return value bug in rte_eal_pci_attach and rte_eal_pci_detach

v7:
 - update to rte_pci_match for const parameters
 - remove unnecessary log messages in probe; moved _after_ matching
   of device and driver
 - bug fixes in attach/detach methods
 - PCI disable for debugging was missed (from rte_eal_pci_init) in v6

v6:
 - Rearchitecture to bring bus object parallel to rte_device/driver
   This majorly includes:
   -- rte_pci_bus class and pci_bus as its object for PCI
   -- bus->attach/detach (hotplugging)
   -- removing bus->match as that is local to an implementation
 - rename symbols rte_eal_bus_* to rte_bus_*
 - restructuring patches (order) for simplicity
 - update to test_pci

v5:
 - Fix checkpatch error in Patch 0003

v4:
 - rebase over master (eac901ce)
 - Fix a bug in test_bus while setup and cleanup
 - rename rte_eal_get_bus to rte_eal_bus_get
 - Add helper (iterator) macros for easy bus,device,driver traversal
 - removed 0001 patch as it is already merged in master
 - fix missing rte_eal_bus_insert_device symbol in map file

v3:
 - rebase over master (c431384c8f)
 - revert patch 0001 changes for checkpatch (container_of macro)
 - qat/rte_qat_cryptodev update for rte_driver->probe
 - test_pci update for using a test_pci_bus for verification
 - some bug fixes based on internal testing.
 -- rte_eal_dev_attach not handling devargs
 -- blacklisting not working

v2:
 - No more bus->probe()
   Now, rte_eal_bus_probe() calls rte_driver->probe based on match output
 - new functions, rte_eal_pci_probe and rte_eal_pci_remove have been
   added as glue code between PCI PMDs and PCI Bus
   `-> PMDs are updated to use these new functions as callbacks for
       rte_driver
 - 'default' keyword has been removed from match and scan
 - Fix for incorrect changes in mlx* and nicvf*
 - Checkpatch fixes
 - Some variable checks have been removed from internal functions;
   functions which are externally visible continue to have such checks
 - Some rearrangement of patches:
   -- changes to drivers have been separated from EAL changes (but this
      does make PCI PMDs non-working for a particular patch)

Shreyansh Jain (13):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  pci: split match and probe function
  eal: remove loop over drivers in device detach
  eal/bus: support for scanning of bus
  eal/bus: introduce support for bus probing
  eal: integrate bus scan and probe with EAL
  eal/pci: add support for PCI bus
  test: add test cases for scan and probe on BUS
  test: add Bus based scan and probe test cases for PCI
  eal: enable PCI bus
  eal: enable hotplugging of devices on bus
  doc: remove deprecation notice for rte_bus

 app/test/Makefile                               |   2 +-
 app/test/autotest_data.py                       |   6 +
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 686 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 164 ++++--
 doc/guides/rel_notes/deprecation.rst            |   5 -
 lib/librte_eal/bsdapp/eal/Makefile              |   3 +-
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  17 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 138 +++++
 lib/librte_eal/common/eal_common_dev.c          |  56 +-
 lib/librte_eal/common/eal_common_pci.c          | 368 ++++++++-----
 lib/librte_eal/common/eal_private.h             |  10 -
 lib/librte_eal/common/include/rte_bus.h         | 191 +++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/common/include/rte_pci.h         | 148 ++++-
 lib/librte_eal/linuxapp/eal/Makefile            |   3 +-
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
 22 files changed, 1631 insertions(+), 284 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v10 01/13] eal/bus: introduce bus abstraction
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 02/13] test: add basic bus infrastructure tests Shreyansh Jain
                           ` (12 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for EAL.
The model is:
 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' base class which would be extended for
specific implementations. It also introduces Bus registration and
deregistration functions.

An example implementation would be like:

  .--------------->+-------------------+
  |                |rte_pci_bus        |
  |                | +----------------+|
  |                | |rte_bus         <------.
  |                | | name           ||     |
  |                | | scan           ||     |
  |                | | match          ||     |
  |                | | probe          ||     |
  |                | | remove         ||     |
  |                | | ...            ||     |
  |                | +----------------+|     |
  |                | pci_driver_list   |     |
  |  .-------------->pci_device_list   |     |
  |  |             | ...               |     |
  |  |             +-------------------+     |
  |  |                                       |
  |  +-------------------+                   |
  |  |rte_pci_device     |                   |
  '----bus               |                   |
     | +----------------+|                   |
     | |rte_device      ||                   |
     | | bus --------------------------------'
     | | ...            ||
     | +----------------+|
     | ...               |
     +-------------------+

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/Makefile              |   3 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   9 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          |  95 ++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 111 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   1 +
 lib/librte_eal/linuxapp/eal/Makefile            |   3 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   9 ++
 8 files changed, 230 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..63c1fda 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -48,7 +48,7 @@ LDLIBS += -lgcc_s
 
 EXPORT_MAP := rte_eal_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 # specific to bsdapp exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..12298f2 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,12 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..49b3516
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,95 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+void
+rte_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+void
+rte_bus_unregister(struct rte_bus *bus)
+{
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* Dump information of a single bus */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..2dc9bef
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,111 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * DPDK device bus interface
+ *
+ * This file exposes APIs and Interfaces for Bus Abstraction over the devices
+ * and drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	const char *name;            /**< Name of the bus */
+};
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_bus_dump(FILE *f);
+
+/** Helper for Bus registration. The constructor has higher priority than
+ * PMD constructors
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b17791f..24c1c00 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -122,6 +122,7 @@ struct rte_driver;
  */
 struct rte_device {
 	TAILQ_ENTRY(rte_device) next; /**< Next device */
+	struct rte_bus *bus;          /**< Device connected to this bus */
 	const struct rte_driver *driver;/**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..88fdc43 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -37,7 +37,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..d996cbc 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,12 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 02/13] test: add basic bus infrastructure tests
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 01/13] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 03/13] pci: split match and probe function Shreyansh Jain
                           ` (11 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/Makefile                               |   2 +-
 app/test/autotest_data.py                       |   6 +
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 359 ++++++++++++++++++++++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/include/rte_bus.h         |   3 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 7 files changed, 373 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0cd598b..ea8f9ca 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -239,6 +239,12 @@ def per_sockets(num):
                 "Func":    default_autotest,
                 "Report":  None,
             },
+            {
+                "Name":    "Bus autotest",
+                "Command": "bus_autotest",
+                "Func":    default_autotest,
+                "Report":  None,
+            },
         ]
     },
     {
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 12298f2..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -178,6 +178,7 @@ DPDK_16.11 {
 DPDK_17.02 {
 	global:
 
+	rte_bus_list;
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 2dc9bef..204e576 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * A structure describing a generic bus.
  */
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index d996cbc..b553b13 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -182,6 +182,7 @@ DPDK_16.11 {
 DPDK_17.02 {
 	global:
 
+	rte_bus_list;
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 03/13] pci: split match and probe function
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 01/13] eal/bus: introduce bus abstraction Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 02/13] test: add basic bus infrastructure tests Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 04/13] eal: remove loop over drivers in device detach Shreyansh Jain
                           ` (10 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
 lib/librte_eal/common/include/rte_pci.h         |  15 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 1;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
-
-		return ret;
+		match = 0;
+		break;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	return match;
 }
 
 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	int ret;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	loc = &dev->addr;
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	}
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* clear driver structure */
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
 		dev->driver = NULL;
-
 		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
 			rte_eal_pci_unmap_device(dev);
+	}
 
-		return 0;
+	return ret;
+}
+
+/*
+ * If vendor/device ID match, call the remove() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
 	}
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	loc = &dev->addr;
+
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
+
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..adc20b9 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b553b13..5ed2589 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,5 +186,6 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 04/13] eal: remove loop over drivers in device detach
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (2 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 03/13] pci: split match and probe function Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 05/13] eal/bus: support for scanning of bus Shreyansh Jain
                           ` (9 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

Removing pci_detach_all_drivers and restructuring rte_eal_pci_detach
and rte_eal_pci_detach_dev to work without looping over driver list.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_pci.c | 47 +++++++---------------------------
 1 file changed, 9 insertions(+), 38 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..8b4ae2d 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -259,21 +259,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_detach_dev(struct rte_pci_device *dev)
 {
-	int ret;
 	struct rte_pci_addr *loc;
+	struct rte_pci_driver *dr;
 
-	if ((dr == NULL) || (dev == NULL))
+	if (dev == NULL)
 		return -EINVAL;
 
-	ret = rte_pci_match(dr, dev);
-	if (ret) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
+	dr = dev->driver;
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -328,33 +322,6 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 }
 
 /*
- * If vendor/device ID match, call the remove() function of all
- * registered driver for the given device. Return -1 if initialization
- * failed, return 1 if no driver is found for this device.
- */
-static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
-{
-	struct rte_pci_driver *dr = NULL;
-	int rc = 0;
-
-	if (dev == NULL)
-		return -1;
-
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_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;
-}
-
-/*
  * Find the pci device specified by pci address, then invoke probe function of
  * the driver of the devive.
  */
@@ -407,9 +374,13 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = rte_eal_pci_detach_dev(dev);
 		if (ret < 0)
+			/* negative value is an error */
 			goto err_return;
+		if (ret > 0)
+			/* positive value means driver doesn't support it */
+			continue;
 
 		TAILQ_REMOVE(&pci_device_list, dev, next);
 		free(dev);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 05/13] eal/bus: support for scanning of bus
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (3 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 04/13] eal: remove loop over drivers in device detach Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 06/13] eal/bus: introduce support for bus probing Shreyansh Jain
                           ` (8 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_bus.c                     | 175 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  14 +++
 3 files changed, 191 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
+		.scan = scan_fn_for_busA,
 	},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
 	.name = "busB_impl", /* busB */
 	.bus = {
 		.name = "busB",
+		.scan = scan_fn_for_busB,
 	},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map 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 dummy_device *ddev = NULL;
+	struct dummy_bus_map *dbmap = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; bus_map[i].name; i++) {
+		if (!strcmp(bus_map[i].name, bus->name)) {
+			dbmap = &bus_map[i];
+			break;
+		}
+	}
+
+	if (!dbmap)
+		return -1;
+
+	db = dbmap->dbus;
+
+	/* For all the devices in the device tree (bus_map), add device */
+	for (i = 0; dbmap->ddevices[i]; i++) {
+		ddev = dbmap->ddevices[i];
+		TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+		ddev->dev.bus = bus;
+	}
+
+	return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busA") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busB") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+	int i = 0;
 	struct rte_bus *bus_p = NULL;
 
 	/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
 		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
 	}
 
+	/* Initialize the bus lists */
+	for (i = 0; bus_map[i].name; i++) {
+		TAILQ_INIT(&bus_map[i].dbus->device_list);
+		TAILQ_INIT(&bus_map[i].dbus->driver_list);
+	}
+
+	dump_device_tree();
 	return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
 	return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct dummy_device *ddev;
+	struct dummy_bus *dbus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       bus_map[i].name);
+			return -1;
+		}
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			TAILQ_REMOVE(&dbus->device_list, ddev, next);
+		}
+	}
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		dbus = container_of(bus, struct dummy_bus, bus);
+
+		if (!TAILQ_EMPTY(&dbus->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();
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -346,6 +515,12 @@ test_bus(void)
 	if (test_bus_registration())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_bus_unregistration())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 49b3516..d5d6beb 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -50,6 +50,8 @@ rte_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan implemented */
+	RTE_VERIFY(bus->scan);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 204e576..ba7d866 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,11 +60,25 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 extern struct rte_bus_list rte_bus_list;
 
 /**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @return
+ *	0 for successful scan
+ *	<0 for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
+	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 06/13] eal/bus: introduce support for bus probing
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (4 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 05/13] eal/bus: support for scanning of bus Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 07/13] eal: integrate bus scan and probe with EAL Shreyansh Jain
                           ` (7 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

This patch introduces the callback which would be implemented for PCI
in subsequent patch.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index d5d6beb..205ddb6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -52,6 +52,7 @@ rte_bus_register(struct rte_bus *bus)
 	RTE_VERIFY(bus->name && strlen(bus->name));
 	/* A bus should mandatorily have the scan implemented */
 	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index ba7d866..17583ad 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -73,12 +73,25 @@ extern struct rte_bus_list rte_bus_list;
 typedef int (*rte_bus_scan_t)(void);
 
 /**
+ * Implementation specific probe function which is responsible for linking
+ * devices on that bus with applicable drivers.
+ *
+ * This is called while iterating over each registered bus.
+ *
+ * @return
+ *	0 for successful probe
+ *	!0 for any error while probing
+ */
+typedef int (*rte_bus_probe_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
+	rte_bus_probe_t probe;       /**< Probe devices on bus */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 07/13] eal: integrate bus scan and probe with EAL
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (5 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 06/13] eal/bus: introduce support for bus probing Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 08/13] eal/pci: add support for PCI bus Shreyansh Jain
                           ` (6 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Add functions for scanning all the buses and performing probe on all
the buses on EAL initialization.

Presently, no bus exists - in subseqent patches, PCI bus would be
introduced.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 +++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 ++
 lib/librte_eal/common/eal_common_bus.c          | 40 +++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 19 ++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  8 +++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 ++
 6 files changed, 78 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..f0abd82 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -577,6 +577,9 @@ rte_eal_init(int argc, char **argv)
 		rte_config.master_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +616,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 205ddb6..089fcd6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -65,6 +65,46 @@ rte_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(DEBUG, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* Error in scanning any bus stops the EAL init. */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->probe();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* Dump information of a single bus */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 17583ad..4b4bb36 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -113,6 +113,25 @@ void rte_bus_register(struct rte_bus *bus);
 void rte_bus_unregister(struct rte_bus *bus);
 
 /**
+ * Scan all the buses attached to the framework.
+ *
+ * @return
+ *	0 in case of success in scanning all buses
+ *	!0 in case of failure to scan
+ */
+int rte_bus_scan(void);
+
+/**
+ * For each device on the bus, perform a driver 'match' and call the
+ * bus's probe for device initialization.
+ *
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_bus_probe(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..f77ff5c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -844,6 +845,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 5ed2589..6f047c5 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -186,6 +186,8 @@ DPDK_17.02 {
 	rte_bus_dump;
 	rte_bus_register;
 	rte_bus_unregister;
+	rte_bus_probe;
+	rte_bus_scan;
 	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 08/13] eal/pci: add support for PCI bus
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (6 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 07/13] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 09/13] test: add test cases for scan and probe on BUS Shreyansh Jain
                           ` (5 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

EAL continues to have direct PCI init/scan calls as well. These would be
removed in subsequent patches to enable bus only PCI devices.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  1 +
 lib/librte_eal/bsdapp/eal/eal_pci.c     | 11 ++++++
 lib/librte_eal/common/eal_common_pci.c  | 33 ++++++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 68 +++++++++++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 15 ++++++++
 5 files changed, 128 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index f0abd82..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 8b4ae2d..4cde957 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -479,3 +480,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+		       struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+	/* Update Bus references */
+	new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+	TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+	/* Update Bus references */
+	pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..05cf693 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *pci_bus;            /**< PCI bus reference */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -523,6 +553,44 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_bus
+ *	PCI Bus reference to which device is to be added
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+			    struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index e2fc219..300064d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -54,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -723,3 +727,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 09/13] test: add test cases for scan and probe on BUS
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (7 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 08/13] eal/pci: add support for PCI bus Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 10/13] test: add Bus based scan and probe test cases for PCI Shreyansh Jain
                           ` (4 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_bus.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 0b6d011..ef7fa89 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -120,12 +120,15 @@ static int scan_fn_for_busB(void);
 
 /* generic implementations wrapped around by above declarations */
 static int generic_scan_fn(struct rte_bus *bus);
+static int generic_probe_fn(void);
+static int dummy_match_fn(struct rte_driver *drv, struct rte_device *dev);
 
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
 		.scan = scan_fn_for_busA,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -134,6 +137,7 @@ struct dummy_bus busB = {
 	.bus = {
 		.name = "busB",
 		.scan = scan_fn_for_busB,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -288,6 +292,46 @@ generic_scan_fn(struct rte_bus *bus)
 	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 match with
+ * @param dev
+ *	device object
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+dummy_match_fn(struct rte_driver *drv __rte_unused, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct dummy_device *ddev = NULL;
+	struct dummy_device *ddev_as_arg;
+	struct dummy_bus *dbus = 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 = dev->bus;
+	dbus = container_of(bus, struct dummy_bus, bus);
+	ddev_as_arg = container_of(dev, struct dummy_device, dev);
+
+	TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+		if (ddev == ddev_as_arg)
+			return 0;
+	}
+
+	return 1;
+}
+
 int
 scan_fn_for_busA(void) {
 	struct dummy_bus_map *dbm;
@@ -504,6 +548,110 @@ test_bus_scan(void)
 	return 0;
 }
 
+/*
+ *
+ */
+static int
+generic_probe_fn(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+	struct dummy_bus *dbus = NULL;
+	struct dummy_device *ddev = NULL;
+	struct dummy_driver *ddrv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device on that bus (bus specific->device_list)
+	 * 3.   for each driver on that bus (bus specific->driver_list)
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+
+		/* Looping over all scanned devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			/* There is a list of drivers within dummy_bus_map.
+			 * In case of PMDs, this would be driver registration
+			 * APIs/list
+			 */
+			for (j = 0; bus_map[i].ddrivers[j]; j++) {
+				ddrv = bus_map[i].ddrivers[j];
+
+				drv = &ddrv->drv;
+				dev = &ddev->dev;
+				ret = dummy_match_fn(drv, dev);
+				if (!ret) {
+					/* As match is generic, it always
+					 * results in dev->drv pointing to
+					 * first driver entry in bus_map[i]
+					 */
+					dev->driver = drv;
+					dev->bus = &dbus->bus;
+				}
+				/* Else, continue */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a bus_map[i]
+	 * should have same driver (first driver entry of bus_map[i])
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		ddrv = bus_map[i].ddrivers[0];
+		drv = &ddrv->drv;
+
+		for (j = 0; bus_map[i].ddevices[j]; j++) {
+			ddev = bus_map[i].ddevices[j];
+			dev = &ddev->dev;
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	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.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i;
+	struct dummy_bus *dbus;
+	struct rte_bus *bus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+		bus = &dbus->bus;
+		ret = bus->probe();
+		if (ret)
+			printf("Probe for %s failed.\n", bus_map[i].name);
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
 
 int
 test_bus(void)
@@ -518,6 +666,10 @@ test_bus(void)
 	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;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 10/13] test: add Bus based scan and probe test cases for PCI
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (8 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 09/13] test: add test cases for scan and probe on BUS Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 11/13] eal: enable PCI bus Shreyansh Jain
                           ` (3 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 114 insertions(+), 50 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+	struct rte_bus bus;
+	struct test_pci_device_list test_device_list;
+	struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+	.bus = {
+		.name = "test_pci_bus",
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
 	return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+	int i;
+	struct rte_pci_device *dev = NULL;
+
+	TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+		       dev->addr.devid, dev->addr.function);
+		fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+		       dev->id.device_id);
+
+		for (i = 0; i != sizeof(dev->mem_resource) /
+			sizeof(dev->mem_resource[0]); i++) {
+			fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+				dev->mem_resource[i].phys_addr,
+				dev->mem_resource[i].len);
+		}
+	}
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+	int ret;
+	struct rte_pci_device *device;
+	struct rte_pci_driver *driver;
+
+	TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+		TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+			ret = rte_pci_match(driver, device);
+			if (!ret) {
+				if (!driver->probe)
+					continue;
+
+				device->driver = driver;
+				ret = driver->probe(driver, device);
+				if (ret != 0)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
 			dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
 	}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
 	const struct resource *r;
 	int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
 	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
+	TAILQ_INIT(&test_pci_bus.test_device_list);
+	TAILQ_INIT(&test_pci_bus.test_driver_list);
 
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_bus_register(&test_pci_bus.bus);
+	pci_bus = &test_pci_bus;
+
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->bus.scan();
 
-	ret = rte_eal_pci_scan();
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
+
+	printf("Dump of all devices scanned:\n");
+	do_pci_device_dump(stdout);
 
 	return 0;
 }
@@ -190,10 +254,11 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
+	void *temp;
 
 	unsetenv("SYSFS_PCI_DEVICES");
 
@@ -203,28 +268,23 @@ test_pci_cleanup(void)
 	ret = resource_rm_by_tar(r);
 	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
 	/*
 	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+	TAILQ_FOREACH_SAFE(dev, &(test_pci_bus.test_device_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_device_list), dev, next);
+		dev->driver = NULL;
 	}
 
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
+	TAILQ_FOREACH_SAFE(dr, &(test_pci_bus.test_driver_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_driver_list), dr, next);
 	}
 
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
+	rte_bus_unregister(&pci_bus->bus);
 
 	return 0;
 }
@@ -234,16 +294,19 @@ test_pci_blacklist(void)
 {
 	struct rte_devargs_list save_devargs_list;
 
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	TEST_ASSERT(TAILQ_EMPTY(&test_pci_bus.test_driver_list),
+		    "PCI Driver list not empty");
+
+	/* Add test drivers to Bus */
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver, next);
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver2, next);
 
 	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
+
+	printf("Probe the Test Bus\n");
+	do_pci_bus_probe();
 
 	if (pci_dev_count == 0) {
 		printf("no device detected\n");
@@ -257,8 +320,8 @@ test_pci_blacklist(void)
 	blacklist_all_devices();
 
 	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
+	printf("Probe bus with all devices blacklisted\n");
+	do_pci_bus_probe();
 
 	free_devargs_list();
 	devargs_list = save_devargs_list;
@@ -270,8 +333,9 @@ test_pci_blacklist(void)
 
 	test_pci_run = 1;
 
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
+	/* Clear the test drivers added to Test Bus */
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver, next);
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver2, next);
 
 	return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 11/13] eal: enable PCI bus
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (9 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 10/13] test: add Bus based scan and probe test cases for PCI Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 12/13] eal: enable hotplugging of devices on bus Shreyansh Jain
                           ` (2 subsequent siblings)
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 -----
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  4 +++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 34 ++++++++++----------
 lib/librte_eal/common/eal_private.h             | 10 ------
 lib/librte_eal/common/include/rte_pci.h         | 22 +++++--------
 lib/librte_eal/linuxapp/eal/eal.c               |  7 -----
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 42 +++++++++----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 44 insertions(+), 86 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4cde957..ca7c0ce 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -309,7 +304,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -330,6 +325,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -341,7 +337,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -371,7 +367,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -383,7 +379,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 			/* positive value means driver doesn't support it */
 			continue;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -412,7 +408,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 
 		/* set devargs in PCI structure */
 		devargs = pci_devargs_lookup(dev);
@@ -460,7 +456,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -469,16 +465,22 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = &rte_pci_bus;
 }
 
-/* unregister a driver */
+/* Unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_pci_bus *pci_bus;
+
+	pci_bus = driver->pci_bus;
+
+	TAILQ_REMOVE(&pci_bus->driver_list, driver, next);
+	/* Update Bus references */
+	driver->pci_bus = NULL;
 }
 
 /* Add a PCI device to PCI Bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..68386e8 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 05cf693..53793f3 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -124,6 +118,9 @@ TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
 /** List of PCI drivers */
 TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
 
+/* Extend PCI bus definition to users */
+extern struct rte_pci_bus rte_pci_bus;
+
 /* PCI Bus iterators */
 #define FOREACH_DEVICE_ON_PCIBUS(p)	\
 		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
@@ -208,8 +205,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -416,17 +411,14 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,
 	      const struct rte_pci_device *pci_dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index f77ff5c..6bb7fc9 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -884,10 +881,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	/* Probe all the buses and devices/drivers on them */
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 300064d..51522af 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -232,7 +232,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_pci_bus *pci_bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -350,21 +351,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&pci_bus->device_list)) {
+		rte_eal_pci_add_device(pci_bus, dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &pci_bus->device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -374,8 +373,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(pci_bus, dev);
 	}
 
 	return 0;
@@ -390,7 +389,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr);
+	return pci_scan_one(&rte_pci_bus, filename, addr);
 }
 
 /*
@@ -451,6 +450,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -467,7 +470,8 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+
+		if (pci_scan_one(&rte_pci_bus, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -712,22 +716,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 6f047c5..f0e63c3 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 12/13] eal: enable hotplugging of devices on bus
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (10 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 11/13] eal: enable PCI bus Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-18 14:05         ` [PATCH v10 13/13] doc: remove deprecation notice for rte_bus Shreyansh Jain
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
 lib/librte_eal/common/eal_common_dev.c  | 56 ++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 89 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 45 +++++++++++------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
 6 files changed, 193 insertions(+), 32 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index ca7c0ce..7991645 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -356,19 +356,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
+	if (pci_update_device(&addr) < 0)
+		goto err_return;
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+			return ret;
+		}
+	}
+
+	return 1;
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
-	int ret = 0;
+	struct rte_pci_addr addr;
+	int ret = 1;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = rte_eal_pci_detach_dev(dev);
@@ -383,8 +462,8 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		free(dev);
 		return 0;
 	}
-	return -1;
 
+	return ret;
 err_return:
 	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
 			" cannot be used\n", dev->addr.domain, dev->addr.bus,
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 4b4bb36..1214908 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Bus list exposed */
 extern struct rte_bus_list rte_bus_list;
 
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
@@ -85,6 +87,33 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -92,6 +121,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 53793f3..820b9df 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -421,6 +421,36 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -494,21 +524,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
-
-/**
  * Dump the content of the PCI bus.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 51522af..4c562c5 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -720,6 +720,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v10 13/13] doc: remove deprecation notice for rte_bus
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (11 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 12/13] eal: enable hotplugging of devices on bus Shreyansh Jain
@ 2017-01-18 14:05         ` Shreyansh Jain
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
  13 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-01-18 14:05 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 doc/guides/rel_notes/deprecation.rst | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 291e03d..60d2bad 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -13,11 +13,6 @@ Deprecation Notices
   has exposed, like the way we have done with uio-pci-generic. This change
   targets release 17.02.
 
-* ABI/API changes are planned for 17.02: ``rte_device``, ``rte_driver`` will be
-  impacted because of introduction of a new ``rte_bus`` hierarchy. This would
-  also impact the way devices are identified by EAL. A bus-device-driver model
-  will be introduced providing a hierarchical view of devices.
-
 * ``eth_driver`` is planned to be removed in 17.02. This currently serves as
   a placeholder for PMDs to register themselves. Changes for ``rte_bus`` will
   provide a way to handle device initialization currently being done in
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 00/13] rte_bus + rte_pci_bus
  2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
                           ` (12 preceding siblings ...)
  2017-01-18 14:05         ` [PATCH v10 13/13] doc: remove deprecation notice for rte_bus Shreyansh Jain
@ 2017-01-19  4:45         ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 01/13] bus: introduce bus abstraction Thomas Monjalon
                             ` (14 more replies)
  13 siblings, 15 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

I've continued the work done by Shreyansh for bus abstraction
and PCI implementation.
This change has two benefits:
  - ease future introduction of new bus
  - clean existing buses (only PCI here)
The same kind of work must be done on VDEV in order to move
these implementations as bus drivers.

changes in v11:
- fixes for BSD
- remove useless bus object retrieving
- remove useless bus reference in rte_device
- some rewording and patch reordering

Unfortunately, it is not ready to be integrated in 17.02.
More specifically:
  - the tests need some review/rework
  - the PCI implementation requires more work
  - the documentation must be updated

However there are some new buses waiting for the bus abstraction,
which is simple and good enough.
That's why I have isolated the generic bus model in first patches
and will apply them in 17.02-rc1. It will allow to base new buses
on top of rte_bus.


Shreyansh Jain (13):
  bus: introduce bus abstraction
  bus: add scanning
  bus: add probing
  app/test: check bus registration
  app/test: check bus scan
  app/test: check bus probe
  pci: split match and probe
  pci: remove loop over drivers in device detach
  pci: add bus driver
  app/test: add PCI bus driver
  pci: use bus driver for scan/probe
  pci: use bus driver for attach/detach
  doc: remove deprecation notice for rte_bus

 MAINTAINERS                                     |   1 +
 app/test/Makefile                               |   2 +-
 app/test/autotest_data.py                       |   6 +
 app/test/test.h                                 |   1 +
 app/test/test_bus.c                             | 678 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 164 ++++--
 doc/guides/rel_notes/deprecation.rst            |   5 -
 doc/guides/rel_notes/release_17_02.rst          |   2 +-
 lib/librte_eal/bsdapp/eal/Makefile              |   3 +-
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  43 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 133 +++++
 lib/librte_eal/common/eal_common_dev.c          |  56 +-
 lib/librte_eal/common/eal_common_pci.c          | 350 +++++++-----
 lib/librte_eal/common/eal_private.h             |  10 -
 lib/librte_eal/common/include/rte_bus.h         | 192 +++++++
 lib/librte_eal/common/include/rte_pci.h         | 142 ++++-
 lib/librte_eal/linuxapp/eal/Makefile            |   3 +-
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  50 +-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 +-
 23 files changed, 1600 insertions(+), 299 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.0

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v11 01/13] bus: introduce bus abstraction
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 02/13] bus: add scanning Thomas Monjalon
                             ` (13 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

This patch introduces the rte_bus abstraction for EAL.
The model is:
 - One or more devices are connected to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' base class which would be extended for
specific implementations. It also introduces Bus registration and
deregistration functions.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   9 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          |  92 +++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 112 ++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   9 ++
 7 files changed, 225 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..12298f2 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,12 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index b34dce9..a5bd108 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..e9b1470
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,92 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+void
+rte_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+void
+rte_bus_unregister(struct rte_bus *bus)
+{
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(DEBUG, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* Dump information of a single bus */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..b8ea5ae
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,112 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * DPDK device bus interface
+ *
+ * This file exposes API and interfaces for bus abstraction
+ * over the devices and drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	const char *name;            /**< Name of the bus */
+};
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	 A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_bus_dump(FILE *f);
+
+/**
+ * Helper for Bus registration.
+ * The constructor has higher priority than PMD constructors.
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..aa874a5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..d996cbc 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,12 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_dump;
+	rte_bus_register;
+	rte_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 02/13] bus: add scanning
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 01/13] bus: introduce bus abstraction Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 03/13] bus: add probing Thomas Monjalon
                             ` (12 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  3 +++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  1 +
 lib/librte_eal/common/eal_common_bus.c          | 21 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 23 +++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  4 ++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  1 +
 6 files changed, 53 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..be5d295 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -577,6 +577,9 @@ rte_eal_init(int argc, char **argv)
 		rte_config.master_lcore, thread_id, cpuset,
 		ret == 0 ? "" : "...");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 12298f2..931afeb 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -180,6 +180,7 @@ DPDK_17.02 {
 
 	rte_bus_dump;
 	rte_bus_register;
+	rte_bus_scan;
 	rte_bus_unregister;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index e9b1470..ef10390 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -47,6 +47,8 @@ rte_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan implemented */
+	RTE_VERIFY(bus->scan);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
@@ -59,6 +61,25 @@ rte_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(DEBUG, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registered devices */
+int
+rte_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* Dump information of a single bus */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index b8ea5ae..b01930a 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -57,11 +57,25 @@ extern "C" {
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
 /**
+ * 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.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @return
+ *	0 for successful scan
+ *	<0 for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
+	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
@@ -83,6 +97,15 @@ void rte_bus_register(struct rte_bus *bus);
 void rte_bus_unregister(struct rte_bus *bus);
 
 /**
+ * Scan all the buses.
+ *
+ * @return
+ *   0 in case of success in scanning all buses
+ *  !0 in case of failure to scan
+ */
+int rte_bus_scan(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..1d2a16a 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -844,6 +845,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index d996cbc..c238381 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -184,6 +184,7 @@ DPDK_17.02 {
 
 	rte_bus_dump;
 	rte_bus_register;
+	rte_bus_scan;
 	rte_bus_unregister;
 
 } DPDK_16.11;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 03/13] bus: add probing
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 01/13] bus: introduce bus abstraction Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 02/13] bus: add scanning Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 04/13] app/test: check bus registration Thomas Monjalon
                             ` (11 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  4 ++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  1 +
 lib/librte_eal/common/eal_common_bus.c          | 20 ++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 23 +++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c               |  4 ++++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  1 +
 6 files changed, 53 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index be5d295..534aeea 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -612,6 +612,10 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	/* Probe & Initialize PCI devices */
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 931afeb..2cf1ac8 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -179,6 +179,7 @@ DPDK_17.02 {
 	global:
 
 	rte_bus_dump;
+	rte_bus_probe;
 	rte_bus_register;
 	rte_bus_scan;
 	rte_bus_unregister;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index ef10390..4638e78 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -49,6 +49,7 @@ rte_bus_register(struct rte_bus *bus)
 	RTE_VERIFY(bus->name && strlen(bus->name));
 	/* A bus should mandatorily have the scan implemented */
 	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->probe);
 
 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
 	RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
@@ -80,6 +81,25 @@ rte_bus_scan(void)
 	return 0;
 }
 
+/* Probe all devices of all buses */
+int
+rte_bus_probe(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->probe();
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+				bus->name);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* Dump information of a single bus */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index b01930a..7c36969 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -70,12 +70,25 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 typedef int (*rte_bus_scan_t)(void);
 
 /**
+ * Implementation specific probe function which is responsible for linking
+ * devices on that bus with applicable drivers.
+ *
+ * This is called while iterating over each registered bus.
+ *
+ * @return
+ *	0 for successful probe
+ *	!0 for any error while probing
+ */
+typedef int (*rte_bus_probe_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
+	rte_bus_probe_t probe;       /**< Probe devices on bus */
 };
 
 /**
@@ -106,6 +119,16 @@ void rte_bus_unregister(struct rte_bus *bus);
 int rte_bus_scan(void);
 
 /**
+ * For each device on the buses, perform a driver 'match' and call the
+ * driver-specific probe for device initialization.
+ *
+ * @return
+ *	 0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_bus_probe(void);
+
+/**
  * Dump information of all the buses registered with EAL.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 1d2a16a..bf6b818 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -884,6 +884,10 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
+	/* Probe all the buses and devices/drivers on them */
+	if (rte_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	/* Probe & Initialize PCI devices */
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index c238381..3c68ff5 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -183,6 +183,7 @@ DPDK_17.02 {
 	global:
 
 	rte_bus_dump;
+	rte_bus_probe;
 	rte_bus_register;
 	rte_bus_scan;
 	rte_bus_unregister;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 04/13] app/test: check bus registration
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (2 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 03/13] bus: add probing Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 05/13] app/test: check bus scan Thomas Monjalon
                             ` (10 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 MAINTAINERS                                     |   1 +
 app/test/Makefile                               |   2 +-
 app/test/autotest_data.py                       |   6 +
 app/test/test.h                                 |   1 +
 app/test/test_bus.c                             | 355 ++++++++++++++++++++++++
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/include/rte_bus.h         |   3 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 8 files changed, 369 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f071138..6c87f33 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -89,6 +89,7 @@ F: lib/librte_eal/common/include/generic/
 F: doc/guides/prog_guide/env_abstraction_layer.rst
 F: app/test/test_alarm.c
 F: app/test/test_atomic.c
+F: app/test/test_bus.c
 F: app/test/test_byteorder.c
 F: app/test/test_common.c
 F: app/test/test_cpuflags.c
diff --git a/app/test/Makefile b/app/test/Makefile
index 9de301f..48235ad 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0cd598b..ab08a64 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -204,6 +204,12 @@ def per_sockets(num):
         "Tests":
         [
             {
+                "Name":    "Bus autotest",
+                "Command": "bus_autotest",
+                "Func":    default_autotest,
+                "Report":  None,
+            },
+            {
                 "Name":    "PCI autotest",
                 "Command": "pci_autotest",
                 "Func":    default_autotest,
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..9be88a7 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -233,6 +233,7 @@ extern const char *prgname;
 
 int commands_init(void);
 
+int test_bus(void);
 int test_pci(void);
 int test_pci_run;
 
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..e2a58fa
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,355 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2cf1ac8..a3d9fac 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -178,6 +178,7 @@ DPDK_16.11 {
 DPDK_17.02 {
 	global:
 
+	rte_bus_list;
 	rte_bus_dump;
 	rte_bus_probe;
 	rte_bus_register;
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 7c36969..19954f4 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+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
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 3c68ff5..69e0e7b 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -182,6 +182,7 @@ DPDK_16.11 {
 DPDK_17.02 {
 	global:
 
+	rte_bus_list;
 	rte_bus_dump;
 	rte_bus_probe;
 	rte_bus_register;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 05/13] app/test: check bus scan
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (3 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 04/13] app/test: check bus registration Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 06/13] app/test: check bus probe Thomas Monjalon
                             ` (9 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index e2a58fa..de4f1ab 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
+		.scan = scan_fn_for_busA,
 	},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
 	.name = "busB_impl", /* busB */
 	.bus = {
 		.name = "busB",
+		.scan = scan_fn_for_busB,
 	},
 };
 
@@ -222,9 +239,80 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map 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 dummy_device *ddev = NULL;
+	struct dummy_bus_map *dbmap = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; bus_map[i].name; i++) {
+		if (!strcmp(bus_map[i].name, bus->name)) {
+			dbmap = &bus_map[i];
+			break;
+		}
+	}
+
+	if (!dbmap)
+		return -1;
+
+	db = dbmap->dbus;
+
+	/* For all the devices in the device tree (bus_map), add device */
+	for (i = 0; dbmap->ddevices[i]; i++) {
+		ddev = dbmap->ddevices[i];
+		TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+	}
+
+	return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busA") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+	struct dummy_bus_map *dbm;
+
+	dbm = &bus_map[0];
+	while (dbm) {
+		if (strcmp(dbm->name, "busB") == 0)
+			return generic_scan_fn(&dbm->dbus->bus);
+		dbm++;
+	}
+	return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+	int i = 0;
 	struct rte_bus *bus_p = NULL;
 
 	/* Preserve the original bus list before executing test */
@@ -234,6 +322,13 @@ test_bus_setup(void)
 		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
 	}
 
+	/* Initialize the bus lists */
+	for (i = 0; bus_map[i].name; i++) {
+		TAILQ_INIT(&bus_map[i].dbus->device_list);
+		TAILQ_INIT(&bus_map[i].dbus->driver_list);
+	}
+
+	dump_device_tree();
 	return 0;
 }
 
@@ -332,6 +427,79 @@ test_bus_unregistration(void)
 	return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct dummy_device *ddev;
+	struct dummy_bus *dbus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       bus_map[i].name);
+			return -1;
+		}
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			TAILQ_REMOVE(&dbus->device_list, ddev, next);
+		}
+	}
+
+	for (i = 0; bus_map[i].name; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		dbus = container_of(bus, struct dummy_bus, bus);
+
+		if (!TAILQ_EMPTY(&dbus->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();
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -342,6 +510,12 @@ test_bus(void)
 	if (test_bus_registration())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_bus_unregistration())
 		return -1;
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 06/13] app/test: check bus probe
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (4 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 05/13] app/test: check bus scan Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 07/13] pci: split match and probe Thomas Monjalon
                             ` (8 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index de4f1ab..a3220f3 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -120,12 +120,15 @@ static int scan_fn_for_busB(void);
 
 /* generic implementations wrapped around by above declarations */
 static int generic_scan_fn(struct rte_bus *bus);
+static int generic_probe_fn(void);
+static int dummy_match_fn(struct rte_driver *drv, struct rte_device *dev);
 
 struct dummy_bus busA = {
 	.name = "busA_impl", /* busA */
 	.bus = {
 		.name = "busA",
 		.scan = scan_fn_for_busA,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -134,6 +137,7 @@ struct dummy_bus busB = {
 	.bus = {
 		.name = "busB",
 		.scan = scan_fn_for_busB,
+		.probe = generic_probe_fn,
 	},
 };
 
@@ -283,6 +287,44 @@ generic_scan_fn(struct rte_bus *bus)
 	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 match with
+ * @param dev
+ *	device object
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+dummy_match_fn(struct rte_driver *drv __rte_unused, struct rte_device *dev)
+{
+	struct dummy_device *ddev = NULL;
+	struct dummy_device *ddev_as_arg;
+	struct dummy_bus *dbus = 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. */
+	dbus = &busA; /* FIXME: bus cannot be retrieved without knowing the driver */
+	ddev_as_arg = container_of(dev, struct dummy_device, dev);
+
+	TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+		if (ddev == ddev_as_arg)
+			return 0;
+	}
+
+	return 1;
+}
+
 int
 scan_fn_for_busA(void) {
 	struct dummy_bus_map *dbm;
@@ -499,6 +541,109 @@ test_bus_scan(void)
 	return 0;
 }
 
+/*
+ *
+ */
+static int
+generic_probe_fn(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+	struct dummy_bus *dbus = NULL;
+	struct dummy_device *ddev = NULL;
+	struct dummy_driver *ddrv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device on that bus (bus specific->device_list)
+	 * 3.   for each driver on that bus (bus specific->driver_list)
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+
+		/* Looping over all scanned devices */
+		TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+			/* There is a list of drivers within dummy_bus_map.
+			 * In case of PMDs, this would be driver registration
+			 * APIs/list
+			 */
+			for (j = 0; bus_map[i].ddrivers[j]; j++) {
+				ddrv = bus_map[i].ddrivers[j];
+
+				drv = &ddrv->drv;
+				dev = &ddev->dev;
+				ret = dummy_match_fn(drv, dev);
+				if (!ret) {
+					/* As match is generic, it always
+					 * results in dev->drv pointing to
+					 * first driver entry in bus_map[i]
+					 */
+					dev->driver = drv;
+				}
+				/* Else, continue */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a bus_map[i]
+	 * should have same driver (first driver entry of bus_map[i])
+	 */
+	for (i = 0; bus_map[i].name; i++) {
+		ddrv = bus_map[i].ddrivers[0];
+		drv = &ddrv->drv;
+
+		for (j = 0; bus_map[i].ddevices[j]; j++) {
+			ddev = bus_map[i].ddevices[j];
+			dev = &ddev->dev;
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	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.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i;
+	struct dummy_bus *dbus;
+	struct rte_bus *bus;
+
+	for (i = 0; bus_map[i].name; i++) {
+		/* get bus pointer from bus_map itself */
+		dbus = bus_map[i].dbus;
+		bus = &dbus->bus;
+		ret = bus->probe();
+		if (ret)
+			printf("Probe for %s failed.\n", bus_map[i].name);
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
 
 int
 test_bus(void)
@@ -513,6 +658,10 @@ test_bus(void)
 	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;
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 07/13] pci: split match and probe
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (5 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 06/13] app/test: check bus probe Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-02-15 10:45             ` Jan Blunck
  2017-01-19  4:45           ` [PATCH v11 08/13] pci: remove loop over drivers in device detach Thomas Monjalon
                             ` (7 subsequent siblings)
  14 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
 lib/librte_eal/common/include/rte_pci.h         |  15 ++
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
 4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index a3d9fac..afa1643 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -184,5 +184,6 @@ DPDK_17.02 {
 	rte_bus_register;
 	rte_bus_scan;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 1;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
-
-		return ret;
+		match = 0;
+		break;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	return match;
 }
 
 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	int ret;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	loc = &dev->addr;
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	}
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	/* reference driver structure */
+	dev->driver = dr;
 
-		/* clear driver structure */
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
 		dev->driver = NULL;
-
 		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
 			rte_eal_pci_unmap_device(dev);
+	}
 
-		return 0;
+	return ret;
+}
+
+/*
+ * If vendor/device ID match, call the remove() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	ret = rte_pci_match(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
 	}
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	loc = &dev->addr;
+
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
+
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..adc20b9 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 69e0e7b..b557e7c 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -188,5 +188,6 @@ DPDK_17.02 {
 	rte_bus_register;
 	rte_bus_scan;
 	rte_bus_unregister;
+	rte_pci_match;
 
 } DPDK_16.11;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 08/13] pci: remove loop over drivers in device detach
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (6 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 07/13] pci: split match and probe Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 09/13] pci: add bus driver Thomas Monjalon
                             ` (6 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

Removing pci_detach_all_drivers and restructuring rte_eal_pci_detach
and rte_eal_pci_detach_dev to work without looping over driver list.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_pci.c | 47 +++++++---------------------------
 1 file changed, 9 insertions(+), 38 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..8b4ae2d 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -259,21 +259,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_detach_dev(struct rte_pci_device *dev)
 {
-	int ret;
 	struct rte_pci_addr *loc;
+	struct rte_pci_driver *dr;
 
-	if ((dr == NULL) || (dev == NULL))
+	if (dev == NULL)
 		return -EINVAL;
 
-	ret = rte_pci_match(dr, dev);
-	if (ret) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
+	dr = dev->driver;
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -328,33 +322,6 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 }
 
 /*
- * If vendor/device ID match, call the remove() function of all
- * registered driver for the given device. Return -1 if initialization
- * failed, return 1 if no driver is found for this device.
- */
-static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
-{
-	struct rte_pci_driver *dr = NULL;
-	int rc = 0;
-
-	if (dev == NULL)
-		return -1;
-
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_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;
-}
-
-/*
  * Find the pci device specified by pci address, then invoke probe function of
  * the driver of the devive.
  */
@@ -407,9 +374,13 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = rte_eal_pci_detach_dev(dev);
 		if (ret < 0)
+			/* negative value is an error */
 			goto err_return;
+		if (ret > 0)
+			/* positive value means driver doesn't support it */
+			continue;
 
 		TAILQ_REMOVE(&pci_device_list, dev, next);
 		free(dev);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 09/13] pci: add bus driver
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (7 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 08/13] pci: remove loop over drivers in device detach Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-02-15 10:42             ` Jan Blunck
  2017-01-19  4:45           ` [PATCH v11 10/13] app/test: add PCI " Thomas Monjalon
                             ` (5 subsequent siblings)
  14 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

EAL continues to have direct PCI init/scan calls as well. These would be
removed in subsequent patches to enable bus only PCI devices.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  1 +
 lib/librte_eal/bsdapp/eal/eal_pci.c     | 11 ++++++
 lib/librte_eal/common/eal_common_pci.c  | 25 +++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 65 +++++++++++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 12 ++++++
 5 files changed, 114 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 534aeea..ee7c9de 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 8b4ae2d..c53e2bd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -87,6 +88,8 @@ struct pci_driver_list pci_driver_list =
 struct pci_device_list pci_device_list =
 	TAILQ_HEAD_INITIALIZER(pci_device_list);
 
+extern struct rte_pci_bus rte_pci_bus;
+
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -479,3 +482,25 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a device to PCI bus */
+void
+rte_eal_pci_add_device(struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&rte_pci_bus.device_list, pci_dev, next);
+}
+
+/* Insert a device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+}
+
+/* Remove a device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	TAILQ_REMOVE(&rte_pci_bus.device_list, pci_dev, next);
+}
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..957cddb 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *bus;                /**< PCI bus reference. */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -523,6 +553,41 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index e2fc219..c40814d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -723,3 +724,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 10/13] app/test: add PCI bus driver
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (8 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 09/13] pci: add bus driver Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 11/13] pci: use bus driver for scan/probe Thomas Monjalon
                             ` (4 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 app/test/test_pci.c | 164 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 114 insertions(+), 50 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
+#include <rte_tailq.h>
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+	struct rte_bus bus;
+	struct test_pci_device_list test_device_list;
+	struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+	.bus = {
+		.name = "test_pci_bus",
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
 	return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+	int i;
+	struct rte_pci_device *dev = NULL;
+
+	TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+		       dev->addr.devid, dev->addr.function);
+		fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+		       dev->id.device_id);
+
+		for (i = 0; i != sizeof(dev->mem_resource) /
+			sizeof(dev->mem_resource[0]); i++) {
+			fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+				dev->mem_resource[i].phys_addr,
+				dev->mem_resource[i].len);
+		}
+	}
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+	int ret;
+	struct rte_pci_device *device;
+	struct rte_pci_driver *driver;
+
+	TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+		TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+			ret = rte_pci_match(driver, device);
+			if (!ret) {
+				if (!driver->probe)
+					continue;
+
+				device->driver = driver;
+				ret = driver->probe(driver, device);
+				if (ret != 0)
+					return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
 			dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
 	}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
 	const struct resource *r;
 	int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
 	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
 
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
+	TAILQ_INIT(&test_pci_bus.test_device_list);
+	TAILQ_INIT(&test_pci_bus.test_driver_list);
 
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_bus_register(&test_pci_bus.bus);
+	pci_bus = &test_pci_bus;
+
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->bus.scan();
 
-	ret = rte_eal_pci_scan();
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
+
+	printf("Dump of all devices scanned:\n");
+	do_pci_device_dump(stdout);
 
 	return 0;
 }
@@ -190,10 +254,11 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
+	void *temp;
 
 	unsetenv("SYSFS_PCI_DEVICES");
 
@@ -203,28 +268,23 @@ test_pci_cleanup(void)
 	ret = resource_rm_by_tar(r);
 	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
 
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
+
 	/*
 	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+	TAILQ_FOREACH_SAFE(dev, &(test_pci_bus.test_device_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_device_list), dev, next);
+		dev->driver = NULL;
 	}
 
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
+	TAILQ_FOREACH_SAFE(dr, &(test_pci_bus.test_driver_list), next, temp) {
+		TAILQ_REMOVE(&(test_pci_bus.test_driver_list), dr, next);
 	}
 
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
+	rte_bus_unregister(&pci_bus->bus);
 
 	return 0;
 }
@@ -234,16 +294,19 @@ test_pci_blacklist(void)
 {
 	struct rte_devargs_list save_devargs_list;
 
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
+	TEST_ASSERT_NOT_NULL(pci_bus, "Invalid bus specified");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	TEST_ASSERT(TAILQ_EMPTY(&test_pci_bus.test_driver_list),
+		    "PCI Driver list not empty");
+
+	/* Add test drivers to Bus */
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver, next);
+	TAILQ_INSERT_TAIL(&test_pci_bus.test_driver_list, &my_driver2, next);
 
 	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
+
+	printf("Probe the Test Bus\n");
+	do_pci_bus_probe();
 
 	if (pci_dev_count == 0) {
 		printf("no device detected\n");
@@ -257,8 +320,8 @@ test_pci_blacklist(void)
 	blacklist_all_devices();
 
 	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
+	printf("Probe bus with all devices blacklisted\n");
+	do_pci_bus_probe();
 
 	free_devargs_list();
 	devargs_list = save_devargs_list;
@@ -270,8 +333,9 @@ test_pci_blacklist(void)
 
 	test_pci_run = 1;
 
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
+	/* Clear the test drivers added to Test Bus */
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver, next);
+	TAILQ_REMOVE(&(test_pci_bus.test_driver_list), &my_driver2, next);
 
 	return 0;
 }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 11/13] pci: use bus driver for scan/probe
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (9 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 10/13] app/test: add PCI " Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19  4:45           ` [PATCH v11 12/13] pci: use bus driver for attach/detach Thomas Monjalon
                             ` (3 subsequent siblings)
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 |  7 -----
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 32 ++++++++-------------
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 26 +++++++----------
 lib/librte_eal/common/eal_private.h             | 10 -------
 lib/librte_eal/common/include/rte_pci.h         | 19 +++----------
 lib/librte_eal/linuxapp/eal/eal.c               |  7 -----
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 38 +++++++++----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 41 insertions(+), 102 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index ee7c9de..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -617,10 +614,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..103ad70 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -87,6 +87,9 @@
  * enabling bus master.
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 /* Map pci device */
 int
 rte_eal_pci_map_device(struct rte_pci_device *dev)
@@ -313,19 +316,19 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 	}
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+		rte_eal_pci_add_device(dev);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 			else if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
+				rte_eal_pci_insert_device(dev2, dev);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -337,7 +340,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_pci_add_device(dev);
 	}
 
 	return 0;
@@ -365,6 +368,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -659,21 +666,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index afa1643..c7c2a05 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index c53e2bd..5149e6e 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 extern struct rte_pci_bus rte_pci_bus;
 
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
@@ -311,7 +306,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -332,6 +327,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -343,7 +339,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -373,7 +369,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -385,7 +381,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 			/* positive value means driver doesn't support it */
 			continue;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -414,7 +410,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 
 		/* set devargs in PCI structure */
 		devargs = pci_devargs_lookup(dev);
@@ -462,7 +458,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -471,16 +467,16 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	driver->bus = &rte_pci_bus;
 }
 
 /* unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	TAILQ_REMOVE(&rte_pci_bus.driver_list, driver, next);
+	driver->bus = NULL;
 }
 
 /* Add a device to PCI bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..68386e8 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 957cddb..bab8df4 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -208,8 +202,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -416,17 +408,14 @@ rte_pci_match(const struct rte_pci_driver *pci_drv,
 	      const struct rte_pci_device *pci_dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index bf6b818..6bb7fc9 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -888,10 +885,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_bus_probe())
 		rte_panic("Cannot probe devices\n");
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index c40814d..d6f9855 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -55,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -347,21 +350,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+		rte_eal_pci_add_device(dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -371,8 +372,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(dev);
 	}
 
 	return 0;
@@ -448,6 +449,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -464,6 +469,7 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
+
 		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
@@ -709,22 +715,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b557e7c..84dfbe7 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 12/13] pci: use bus driver for attach/detach
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (10 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 11/13] pci: use bus driver for scan/probe Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-02-15 11:08             ` Jan Blunck
  2017-01-19  4:45           ` [PATCH v11 13/13] doc: remove deprecation notice for rte_bus Thomas Monjalon
                             ` (2 subsequent siblings)
  14 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
 lib/librte_eal/common/eal_common_dev.c  | 56 ++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 89 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 45 +++++++++++------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
 6 files changed, 193 insertions(+), 32 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 103ad70..38a75af 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -670,6 +670,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 5149e6e..6866b04 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -358,19 +358,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
+	if (pci_update_device(&addr) < 0)
+		goto err_return;
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+			return ret;
+		}
+	}
+
+	return 1;
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
-	int ret = 0;
+	struct rte_pci_addr addr;
+	int ret = 1;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = rte_eal_pci_detach_dev(dev);
@@ -385,8 +464,8 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		free(dev);
 		return 0;
 	}
-	return -1;
 
+	return ret;
 err_return:
 	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
 			" cannot be used\n", dev->addr.domain, dev->addr.bus,
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 19954f4..9a096ec 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Bus list exposed */
 extern struct rte_bus_list rte_bus_list;
 
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
@@ -85,6 +87,33 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -92,6 +121,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index bab8df4..215d732 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -418,6 +418,36 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -491,21 +521,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
-
-/**
  * Dump the content of the PCI bus.
  *
  * @param f
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index d6f9855..01f0c9a 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -719,6 +719,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v11 13/13] doc: remove deprecation notice for rte_bus
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (11 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 12/13] pci: use bus driver for attach/detach Thomas Monjalon
@ 2017-01-19  4:45           ` Thomas Monjalon
  2017-01-19 17:40             ` Mcnamara, John
  2017-01-19  4:50           ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
  14 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:45 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 doc/guides/rel_notes/deprecation.rst   | 5 -----
 doc/guides/rel_notes/release_17_02.rst | 2 +-
 lib/librte_eal/bsdapp/eal/Makefile     | 2 +-
 lib/librte_eal/linuxapp/eal/Makefile   | 2 +-
 4 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 755dc65..a9b0aef 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -13,11 +13,6 @@ Deprecation Notices
   has exposed, like the way we have done with uio-pci-generic. This change
   targets release 17.02.
 
-* ABI/API changes are planned for 17.02: ``rte_device``, ``rte_driver`` will be
-  impacted because of introduction of a new ``rte_bus`` hierarchy. This would
-  also impact the way devices are identified by EAL. A bus-device-driver model
-  will be introduced providing a hierarchical view of devices.
-
 * ``eth_driver`` is planned to be removed in 17.02. This currently serves as
   a placeholder for PMDs to register themselves. Changes for ``rte_bus`` will
   provide a way to handle device initialization currently being done in
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 0ecd720..666f386 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -326,7 +326,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cmdline.so.2
      librte_cryptodev.so.2
      librte_distributor.so.1
-     librte_eal.so.3
+   + librte_eal.so.4
    + librte_ethdev.so.6
      librte_hash.so.2
      librte_ip_frag.so.1
diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index cce99f7..63c1fda 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -48,7 +48,7 @@ LDLIBS += -lgcc_s
 
 EXPORT_MAP := rte_eal_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 # specific to bsdapp exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index aa874a5..88fdc43 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -37,7 +37,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 00/13] rte_bus + rte_pci_bus
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (12 preceding siblings ...)
  2017-01-19  4:45           ` [PATCH v11 13/13] doc: remove deprecation notice for rte_bus Thomas Monjalon
@ 2017-01-19  4:50           ` Thomas Monjalon
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
  14 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-01-19  4:50 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

2017-01-19 05:45, Thomas Monjalon:
> Unfortunately, it is not ready to be integrated in 17.02.
> More specifically:
>   - the tests need some review/rework
>   - the PCI implementation requires more work
>   - the documentation must be updated
> 
> However there are some new buses waiting for the bus abstraction,
> which is simple and good enough.
> That's why I have isolated the generic bus model in first patches
> and will apply them in 17.02-rc1. It will allow to base new buses
> on top of rte_bus.
> 
> 
> Shreyansh Jain (13):
>   bus: introduce bus abstraction
>   bus: add scanning
>   bus: add probing

First 3 patches applied.

I'll continue to work with Shreyansh on PCI implementation.
Some help is required to convert VDEV into a bus driver.

>   app/test: check bus registration
>   app/test: check bus scan
>   app/test: check bus probe
>   pci: split match and probe
>   pci: remove loop over drivers in device detach
>   pci: add bus driver
>   app/test: add PCI bus driver
>   pci: use bus driver for scan/probe
>   pci: use bus driver for attach/detach
>   doc: remove deprecation notice for rte_bus

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 13/13] doc: remove deprecation notice for rte_bus
  2017-01-19  4:45           ` [PATCH v11 13/13] doc: remove deprecation notice for rte_bus Thomas Monjalon
@ 2017-01-19 17:40             ` Mcnamara, John
  0 siblings, 0 replies; 146+ messages in thread
From: Mcnamara, John @ 2017-01-19 17:40 UTC (permalink / raw)
  To: Thomas Monjalon, Shreyansh Jain; +Cc: dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon
> Sent: Thursday, January 19, 2017 4:45 AM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v11 13/13] doc: remove deprecation notice for
> rte_bus
> 
> From: Shreyansh Jain <shreyansh.jain@nxp.com>
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

Acked-by: John McNamara <john.mcnamara@intel.com>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 09/13] pci: add bus driver
  2017-01-19  4:45           ` [PATCH v11 09/13] pci: add bus driver Thomas Monjalon
@ 2017-02-15 10:42             ` Jan Blunck
  2017-02-15 11:20               ` Thomas Monjalon
  0 siblings, 1 reply; 146+ messages in thread
From: Jan Blunck @ 2017-02-15 10:42 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Shreyansh Jain, dev

On Thu, Jan 19, 2017 at 5:45 AM, Thomas Monjalon
<thomas.monjalon@6wind.com> wrote:
> From: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> Based on EAL Bus APIs, PCI bus callbacks and support functions are
> introduced in this patch.
>
> EAL continues to have direct PCI init/scan calls as well. These would be
> removed in subsequent patches to enable bus only PCI devices.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
> ---
>  lib/librte_eal/bsdapp/eal/eal.c         |  1 +
>  lib/librte_eal/bsdapp/eal/eal_pci.c     | 11 ++++++
>  lib/librte_eal/common/eal_common_pci.c  | 25 +++++++++++++
>  lib/librte_eal/common/include/rte_pci.h | 65 +++++++++++++++++++++++++++++++++
>  lib/librte_eal/linuxapp/eal/eal_pci.c   | 12 ++++++
>  5 files changed, 114 insertions(+)
>
> diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
> index 534aeea..ee7c9de 100644
> --- a/lib/librte_eal/bsdapp/eal/eal.c
> +++ b/lib/librte_eal/bsdapp/eal/eal.c
> @@ -64,6 +64,7 @@
>  #include <rte_string_fns.h>
>  #include <rte_cpuflags.h>
>  #include <rte_interrupts.h>
> +#include <rte_bus.h>
>  #include <rte_pci.h>
>  #include <rte_dev.h>
>  #include <rte_devargs.h>
> diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
> index 3a5c315..48bfe24 100644
> --- a/lib/librte_eal/bsdapp/eal/eal_pci.c
> +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
> @@ -673,3 +673,14 @@ rte_eal_pci_init(void)
>         }
>         return 0;
>  }
> +
> +struct rte_pci_bus rte_pci_bus = {
> +       .bus = {
> +               .scan = rte_eal_pci_scan,
> +               .probe = rte_eal_pci_probe,
> +       },
> +       .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
> +       .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
> +};
> +
> +RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 8b4ae2d..c53e2bd 100644
> --- a/lib/librte_eal/common/eal_common_pci.c
> +++ b/lib/librte_eal/common/eal_common_pci.c
> @@ -71,6 +71,7 @@
>
>  #include <rte_interrupts.h>
>  #include <rte_log.h>
> +#include <rte_bus.h>
>  #include <rte_pci.h>
>  #include <rte_per_lcore.h>
>  #include <rte_memory.h>
> @@ -87,6 +88,8 @@ struct pci_driver_list pci_driver_list =
>  struct pci_device_list pci_device_list =
>         TAILQ_HEAD_INITIALIZER(pci_device_list);
>
> +extern struct rte_pci_bus rte_pci_bus;
> +
>  #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
>
>  const char *pci_get_sysfs_path(void)
> @@ -479,3 +482,25 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
>         rte_eal_driver_unregister(&driver->driver);
>         TAILQ_REMOVE(&pci_driver_list, driver, next);
>  }
> +
> +/* Add a device to PCI bus */
> +void
> +rte_eal_pci_add_device(struct rte_pci_device *pci_dev)
> +{
> +       TAILQ_INSERT_TAIL(&rte_pci_bus.device_list, pci_dev, next);
> +}
> +
> +/* Insert a device into a predefined position in PCI bus */
> +void
> +rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
> +                         struct rte_pci_device *new_pci_dev)
> +{
> +       TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
> +}
> +
> +/* Remove a device from PCI bus */
> +void
> +rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
> +{
> +       TAILQ_REMOVE(&rte_pci_bus.device_list, pci_dev, next);
> +}
> diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
> index adc20b9..957cddb 100644
> --- a/lib/librte_eal/common/include/rte_pci.h
> +++ b/lib/librte_eal/common/include/rte_pci.h
> @@ -85,6 +85,7 @@ extern "C" {
>  #include <rte_debug.h>
>  #include <rte_interrupts.h>
>  #include <rte_dev.h>
> +#include <rte_bus.h>
>
>  TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
>  TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
> @@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
>  /** Maximum number of PCI resources. */
>  #define PCI_MAX_RESOURCE 6
>
> +/** Name of PCI Bus */
> +#define PCI_BUS_NAME "PCI"
> +
> +/* Forward declarations */
> +struct rte_pci_device;
> +struct rte_pci_driver;
> +
> +/** List of PCI devices */
> +TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
> +/** List of PCI drivers */
> +TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
> +
> +/* PCI Bus iterators */
> +#define FOREACH_DEVICE_ON_PCIBUS(p)    \
> +               TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
> +
> +#define FOREACH_DRIVER_ON_PCIBUS(p)    \
> +               TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
> +
>  /**
>   * A structure describing an ID for a PCI driver. Each driver provides a
>   * table of these IDs for each device that it supports.
> @@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
>  struct rte_pci_driver {
>         TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
>         struct rte_driver driver;               /**< Inherit core driver. */
> +       struct rte_pci_bus *bus;                /**< PCI bus reference. */
>         pci_probe_t *probe;                     /**< Device Probe function. */
>         pci_remove_t *remove;                   /**< Device Remove function. */
>         const struct rte_pci_id *id_table;      /**< ID table, NULL terminated. */
>         uint32_t drv_flags;                     /**< Flags contolling handling of device. */
>  };
>
> +/**
> + * Structure describing the PCI bus
> + */
> +struct rte_pci_bus {
> +       struct rte_bus bus;               /**< Inherit the generic class */
> +       struct rte_pci_device_list device_list;  /**< List of PCI devices */
> +       struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
> +};
> +
>  /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
>  #define RTE_PCI_DRV_NEED_MAPPING 0x0001
>  /** Device driver supports link state interrupt */
> @@ -523,6 +553,41 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
>  void rte_eal_pci_unregister(struct rte_pci_driver *driver);
>
>  /**
> + * Add a PCI device to the PCI Bus (append to PCI Device list). This function
> + * also updates the bus references of the PCI Device (and the generic device
> + * object embedded within.
> + *
> + * @param pci_dev
> + *     PCI device to add
> + * @return void
> + */
> +void rte_eal_pci_add_device(struct rte_pci_device *pci_dev);
> +

Who would be the user of this?

>From my understanding a device will show up on the bus if:
1. bus->scan() finds it
2. bus->attach(devargs) explicitly adds it to the whitelist

Both methods shouldn't require us to expose the API outside of eal.

> +/**
> + * Insert a PCI device in the PCI Bus at a particular location in the device
> + * list. It also updates the PCI Bus reference of the new devices to be
> + * inserted.
> + *
> + * @param exist_pci_dev
> + *     Existing PCI device in PCI Bus
> + * @param new_pci_dev
> + *     PCI device to be added before exist_pci_dev
> + * @return void
> + */
> +void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
> +                              struct rte_pci_device *new_pci_dev);
> +
> +/**
> + * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
> + * in the PCI device object as well as the generic device object.
> + *
> + * @param pci_device
> + *     PCI device to be removed from PCI Bus
> + * @return void
> + */
> +void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
> +
> +/**
>   * Read PCI config space.
>   *
>   * @param device
> diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
> index e2fc219..c40814d 100644
> --- a/lib/librte_eal/linuxapp/eal/eal_pci.c
> +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
> @@ -35,6 +35,7 @@
>  #include <dirent.h>
>
>  #include <rte_log.h>
> +#include <rte_bus.h>
>  #include <rte_pci.h>
>  #include <rte_eal_memconfig.h>
>  #include <rte_malloc.h>
> @@ -723,3 +724,14 @@ rte_eal_pci_init(void)
>
>         return 0;
>  }
> +
> +struct rte_pci_bus rte_pci_bus = {
> +       .bus = {
> +               .scan = rte_eal_pci_scan,
> +               .probe = rte_eal_pci_probe,
> +       },
> +       .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
> +       .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),

I don't see why this is necessary and I believe it makes people think
we might want to model topology. It's better to keep it simple and
have it locally in eal_common_pci.c.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 07/13] pci: split match and probe
  2017-01-19  4:45           ` [PATCH v11 07/13] pci: split match and probe Thomas Monjalon
@ 2017-02-15 10:45             ` Jan Blunck
  2017-02-15 11:22               ` Thomas Monjalon
  2017-02-15 11:30               ` Shreyansh Jain
  0 siblings, 2 replies; 146+ messages in thread
From: Jan Blunck @ 2017-02-15 10:45 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Shreyansh Jain, dev

On Thu, Jan 19, 2017 at 5:45 AM, Thomas Monjalon
<thomas.monjalon@6wind.com> wrote:
> From: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> Matching of PCI device address and driver ID table is being done at two
> discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
> and rte_eal_pci_detach_dev).
>
> Splitting the matching function into a public fn rte_pci_match.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> ---
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
>  lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
>  lib/librte_eal/common/include/rte_pci.h         |  15 ++
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
>  4 files changed, 121 insertions(+), 85 deletions(-)
>
> diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> index a3d9fac..afa1643 100644
> --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> @@ -184,5 +184,6 @@ DPDK_17.02 {
>         rte_bus_register;
>         rte_bus_scan;
>         rte_bus_unregister;
> +       rte_pci_match;
>
>  } DPDK_16.11;
> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 72547bd..4f155c6 100644
> --- a/lib/librte_eal/common/eal_common_pci.c
> +++ b/lib/librte_eal/common/eal_common_pci.c
> @@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
>                                 requested_addr);
>  }
>
> -/*
> - * If vendor/device ID match, call the probe() function of the
> - * driver.
> - */
> -static int
> -rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
> +int
> +rte_pci_match(const struct rte_pci_driver *pci_drv,
> +             const struct rte_pci_device *pci_dev)
>  {
> -       int ret;
> +       int match = 1;
>         const struct rte_pci_id *id_table;
>
> -       for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
> +       if (!pci_drv || !pci_dev || !pci_drv->id_table) {
> +               RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
> +               return -1;
> +       }
>
> +       for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
> +            id_table++) {
>                 /* check if device's identifiers match the driver's ones */
> -               if (id_table->vendor_id != dev->id.vendor_id &&
> +               if (id_table->vendor_id != pci_dev->id.vendor_id &&
>                                 id_table->vendor_id != PCI_ANY_ID)
>                         continue;
> -               if (id_table->device_id != dev->id.device_id &&
> +               if (id_table->device_id != pci_dev->id.device_id &&
>                                 id_table->device_id != PCI_ANY_ID)
>                         continue;
> -               if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
> -                               id_table->subsystem_vendor_id != PCI_ANY_ID)
> +               if (id_table->subsystem_vendor_id !=
> +                   pci_dev->id.subsystem_vendor_id &&
> +                   id_table->subsystem_vendor_id != PCI_ANY_ID)
>                         continue;
> -               if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
> -                               id_table->subsystem_device_id != PCI_ANY_ID)
> +               if (id_table->subsystem_device_id !=
> +                   pci_dev->id.subsystem_device_id &&
> +                   id_table->subsystem_device_id != PCI_ANY_ID)
>                         continue;
> -               if (id_table->class_id != dev->id.class_id &&
> +               if (id_table->class_id != pci_dev->id.class_id &&
>                                 id_table->class_id != RTE_CLASS_ANY_ID)
>                         continue;
>
> -               struct rte_pci_addr *loc = &dev->addr;
> -
> -               RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
> -                               loc->domain, loc->bus, loc->devid, loc->function,
> -                               dev->device.numa_node);
> -
> -               /* no initialization when blacklisted, return without error */
> -               if (dev->device.devargs != NULL &&
> -                       dev->device.devargs->type ==
> -                               RTE_DEVTYPE_BLACKLISTED_PCI) {
> -                       RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
> -                       return 1;
> -               }
> -
> -               RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
> -                               dev->id.device_id, dr->driver.name);
> -
> -               if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
> -                       /* map resources for devices that use igb_uio */
> -                       ret = rte_eal_pci_map_device(dev);
> -                       if (ret != 0)
> -                               return ret;
> -               }
> -
> -               /* reference driver structure */
> -               dev->driver = dr;
> -
> -               /* call the driver probe() function */
> -               ret = dr->probe(dr, dev);
> -               if (ret) {
> -                       dev->driver = NULL;
> -                       if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> -                               rte_eal_pci_unmap_device(dev);
> -               }
> -
> -               return ret;
> +               match = 0;
> +               break;
>         }
> -       /* return positive value if driver doesn't support this device */
> -       return 1;
> +
> +       return match;
>  }
>
>  /*
> - * If vendor/device ID match, call the remove() function of the
> + * If vendor/device ID match, call the probe() function of the
>   * driver.
>   */
>  static int
> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> -               struct rte_pci_device *dev)
> +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
> +                            struct rte_pci_device *dev)
>  {
> -       const struct rte_pci_id *id_table;
> +       int ret;
> +       struct rte_pci_addr *loc;
>
>         if ((dr == NULL) || (dev == NULL))
>                 return -EINVAL;
>
> -       for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
> +       loc = &dev->addr;
>
> -               /* check if device's identifiers match the driver's ones */
> -               if (id_table->vendor_id != dev->id.vendor_id &&
> -                               id_table->vendor_id != PCI_ANY_ID)
> -                       continue;
> -               if (id_table->device_id != dev->id.device_id &&
> -                               id_table->device_id != PCI_ANY_ID)
> -                       continue;
> -               if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
> -                               id_table->subsystem_vendor_id != PCI_ANY_ID)
> -                       continue;
> -               if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
> -                               id_table->subsystem_device_id != PCI_ANY_ID)
> -                       continue;
> +       /* The device is not blacklisted; Check if driver supports it */
> +       ret = rte_pci_match(dr, dev);
> +       if (ret) {
> +               /* Match of device and driver failed */
> +               RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
> +                       dr->driver.name);
> +               return 1;
> +       }
>
> -               struct rte_pci_addr *loc = &dev->addr;
> +       RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
> +                       loc->domain, loc->bus, loc->devid, loc->function,
> +                       dev->device.numa_node);
> +
> +       /* no initialization when blacklisted, return without error */
> +       if (dev->device.devargs != NULL &&
> +               dev->device.devargs->type ==
> +                       RTE_DEVTYPE_BLACKLISTED_PCI) {
> +               RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
> +                       " initializing\n");
> +               return 1;
> +       }
>
> -               RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
> -                               loc->domain, loc->bus, loc->devid,
> -                               loc->function, dev->device.numa_node);
> +       RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
> +               dev->id.device_id, dr->driver.name);
>
> -               RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
> -                               dev->id.device_id, dr->driver.name);
> +       if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
> +               /* map resources for devices that use igb_uio */
> +               ret = rte_eal_pci_map_device(dev);
> +               if (ret != 0)
> +                       return ret;
> +       }
>
> -               if (dr->remove && (dr->remove(dev) < 0))
> -                       return -1;      /* negative value is an error */
> +       /* reference driver structure */
> +       dev->driver = dr;
>
> -               /* clear driver structure */
> +       /* call the driver probe() function */
> +       ret = dr->probe(dr, dev);
> +       if (ret) {
>                 dev->driver = NULL;
> -
>                 if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> -                       /* unmap resources for devices that use igb_uio */
>                         rte_eal_pci_unmap_device(dev);
> +       }
>
> -               return 0;
> +       return ret;
> +}
> +
> +/*
> + * If vendor/device ID match, call the remove() function of the
> + * driver.
> + */
> +static int
> +rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
> +               struct rte_pci_device *dev)
> +{
> +       int ret;
> +       struct rte_pci_addr *loc;
> +
> +       if ((dr == NULL) || (dev == NULL))
> +               return -EINVAL;
> +
> +       ret = rte_pci_match(dr, dev);
> +       if (ret) {
> +               /* Device and driver don't match */
> +               return 1;
>         }
>
> -       /* return positive value if driver doesn't support this device */
> -       return 1;
> +       loc = &dev->addr;
> +
> +       RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
> +                       loc->domain, loc->bus, loc->devid,
> +                       loc->function, dev->device.numa_node);
> +
> +       RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
> +                       dev->id.device_id, dr->driver.name);
> +
> +       if (dr->remove && (dr->remove(dev) < 0))
> +               return -1;      /* negative value is an error */
> +
> +       /* clear driver structure */
> +       dev->driver = NULL;
> +
> +       if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> +               /* unmap resources for devices that use igb_uio */
> +               rte_eal_pci_unmap_device(dev);
> +
> +       return 0;
>  }
>
>  /*
> diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
> index 8557e47..adc20b9 100644
> --- a/lib/librte_eal/common/include/rte_pci.h
> +++ b/lib/librte_eal/common/include/rte_pci.h
> @@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
>  int rte_eal_pci_scan(void);
>
>  /**
> + * Match the PCI Driver and Device using the ID Table
> + *
> + * @param pci_drv
> + *     PCI driver from which ID table would be extracted
> + * @param pci_dev
> + *     PCI device to match against the driver
> + * @return
> + *     0 for successful match
> + *     !0 for unsuccessful match
> + */
> +int
> +rte_pci_match(const struct rte_pci_driver *pci_drv,
> +             const struct rte_pci_device *pci_dev);

I don't think this symbol needs to be exported and visible outside of EAL.

> +
> +/**
>   * Probe the PCI bus for registered drivers.
>   *
>   * Scan the content of the PCI bus, and call the probe() function for
> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> index 69e0e7b..b557e7c 100644
> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> @@ -188,5 +188,6 @@ DPDK_17.02 {
>         rte_bus_register;
>         rte_bus_scan;
>         rte_bus_unregister;
> +       rte_pci_match;
>
>  } DPDK_16.11;
> --
> 2.7.0
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 12/13] pci: use bus driver for attach/detach
  2017-01-19  4:45           ` [PATCH v11 12/13] pci: use bus driver for attach/detach Thomas Monjalon
@ 2017-02-15 11:08             ` Jan Blunck
  2017-02-15 11:26               ` Thomas Monjalon
  0 siblings, 1 reply; 146+ messages in thread
From: Jan Blunck @ 2017-02-15 11:08 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Shreyansh Jain, dev

On Thu, Jan 19, 2017 at 5:45 AM, Thomas Monjalon
<thomas.monjalon@6wind.com> wrote:
> From: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> Given a bus, attach and detach callbacks allow the implementation to
> handles calls from EAL for attaching or detaching a named device.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
> ---
>  lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 +
>  lib/librte_eal/common/eal_common_dev.c  | 56 ++++++++++++++++-----
>  lib/librte_eal/common/eal_common_pci.c  | 89 +++++++++++++++++++++++++++++++--
>  lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++
>  lib/librte_eal/common/include/rte_pci.h | 45 +++++++++++------
>  lib/librte_eal/linuxapp/eal/eal_pci.c   |  2 +
>  6 files changed, 193 insertions(+), 32 deletions(-)
>
> diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
> index 103ad70..38a75af 100644
> --- a/lib/librte_eal/bsdapp/eal/eal_pci.c
> +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
> @@ -670,6 +670,8 @@ struct rte_pci_bus rte_pci_bus = {
>         .bus = {
>                 .scan = rte_eal_pci_scan,
>                 .probe = rte_eal_pci_probe,
> +               .attach = rte_eal_pci_attach,
> +               .detach = rte_eal_pci_detach,
>         },
>         .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
>         .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
> diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
> index 4f3b493..97d0cf5 100644
> --- a/lib/librte_eal/common/eal_common_dev.c
> +++ b/lib/librte_eal/common/eal_common_dev.c
> @@ -38,6 +38,7 @@
>  #include <sys/queue.h>
>
>  #include <rte_dev.h>
> +#include <rte_bus.h>
>  #include <rte_devargs.h>
>  #include <rte_debug.h>
>  #include <rte_devargs.h>
> @@ -106,23 +107,37 @@ rte_eal_dev_init(void)
>
>  int rte_eal_dev_attach(const char *name, const char *devargs)
>  {
> -       struct rte_pci_addr addr;
> +       int ret = 1;
> +       struct rte_bus *bus;
>
>         if (name == NULL || devargs == NULL) {
>                 RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
>                 return -EINVAL;
>         }
>
> -       if (eal_parse_pci_DomBDF(name, &addr) == 0) {
> -               if (rte_eal_pci_probe_one(&addr) < 0)
> +       FOREACH_BUS(bus) {
> +               if (!bus->attach) {
> +                       RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
> +                               " attach.\n", bus->name);
> +                       continue;
> +               }
> +               ret = bus->attach(name);

Enforcing a globally unique naming scheme for the low-level device
makes this complicated for users. There are buses that enumerate the
devices just by an integer so we will have conflicts.

I think it is better to change the signature of rte_eal_dev_attach()
instead and find the correct bus based on its name. Also I believe the
API is more user friendly if we pass the complete (raw) devargs string
instead of the name/args pair.


> +               if (!ret) /* device successfully attached */
> +                       return ret;
> +               if (ret > 0) /* device not found on bus */
> +                       continue;
> +               else
>                         goto err;
> +       }
>
> -       } else {
> -               if (rte_eal_vdev_init(name, devargs))
> +       if (ret > 0) {
> +               /* In case the device was not found on any bus, search VDEV */
> +               ret = rte_eal_vdev_init(name, devargs);
> +               if (ret)
>                         goto err;
>         }
>
> -       return 0;
> +       return ret;
>
>  err:
>         RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
> @@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
>
>  int rte_eal_dev_detach(const char *name)
>  {
> -       struct rte_pci_addr addr;
> +       int ret = 1;
> +       struct rte_bus *bus;
>
>         if (name == NULL) {
>                 RTE_LOG(ERR, EAL, "Invalid device provided.\n");
>                 return -EINVAL;
>         }
>
> -       if (eal_parse_pci_DomBDF(name, &addr) == 0) {
> -               if (rte_eal_pci_detach(&addr) < 0)
> +       FOREACH_BUS(bus) {
> +               if (!bus->detach) {
> +                       RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
> +                               " detach.\n", bus->name);
> +                       continue;
> +               }
> +
> +               ret = bus->detach(name);
> +               if (!ret) /* device successfully detached */
> +                       return ret;
> +               if (ret > 0) /* device not found on the bus */
> +                       continue;
> +               else
>                         goto err;
> -       } else {
> -               if (rte_eal_vdev_uninit(name))
> +       }
> +
> +       if (ret > 0) {
> +               /* In case the device was not found on any bus, search VDEV */
> +               ret = rte_eal_vdev_uninit(name);
> +               if (ret)
>                         goto err;
>         }
> -       return 0;
> +
> +       return ret;
>
>  err:
>         RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
> index 5149e6e..6866b04 100644
> --- a/lib/librte_eal/common/eal_common_pci.c
> +++ b/lib/librte_eal/common/eal_common_pci.c
> @@ -358,19 +358,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
>  }
>
>  /*
> + * Attach device specific by its name
> + */
> +int
> +rte_eal_pci_attach(const char *device_name)
> +{
> +       struct rte_pci_device *dev = NULL;
> +       struct rte_pci_driver *drv = NULL;
> +       struct rte_pci_addr addr;
> +       int ret;
> +
> +       if (!device_name)
> +               return -1;
> +
> +       memset(&addr, 0, sizeof(addr));
> +       if (eal_parse_pci_DomBDF(device_name, &addr)) {
> +               /* Device doesn't match PCI BDF naming format */
> +               return 1;
> +       }
> +
> +       if (pci_update_device(&addr) < 0)
> +               goto err_return;
> +
> +       FOREACH_DEVICE_ON_PCIBUS(dev) {
> +               if (rte_eal_compare_pci_addr(&dev->addr, &addr))
> +                       continue;
> +
> +               FOREACH_DRIVER_ON_PCIBUS(drv) {
> +                       ret = rte_pci_match(drv, dev);
> +                       if (ret) {
> +                               /* Match of device and driver failed */
> +                               RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
> +                                       " the device (%s)\n", drv->driver.name,
> +                                       device_name);
> +                               continue;
> +                       }
> +
> +                       RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
> +                               dev->id.vendor_id, dev->id.device_id,
> +                               drv->driver.name);
> +
> +                       if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
> +                               /* map resources for devices that use
> +                                * igb_uio
> +                                */
> +                               ret = rte_eal_pci_map_device(dev);
> +                               if (ret != 0)
> +                                       goto err_return;
> +                       }
> +
> +                       /* reference driver structure */
> +                       dev->driver = drv;
> +
> +                       /* call the driver probe() function */
> +                       ret = drv->probe(drv, dev);
> +                       if (ret) {
> +                               dev->driver = NULL;
> +                               if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
> +                                       rte_eal_pci_unmap_device(dev);
> +                       }
> +                       return ret;
> +               }
> +       }
> +
> +       return 1;
> +err_return:
> +       RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
> +                       " cannot be used\n", dev->addr.domain, dev->addr.bus,
> +                       dev->addr.devid, dev->addr.function);
> +       return -1;
> +}
> +
> +/*
>   * Detach device specified by its pci address.
>   */
>  int
> -rte_eal_pci_detach(const struct rte_pci_addr *addr)
> +rte_eal_pci_detach(const char *device_name)
>  {
>         struct rte_pci_device *dev = NULL;
> -       int ret = 0;
> +       struct rte_pci_addr addr;
> +       int ret = 1;
>
> -       if (addr == NULL)
> +       if (!device_name)
>                 return -1;
>
> +       memset(&addr, 0, sizeof(addr));
> +       if (eal_parse_pci_DomBDF(device_name, &addr)) {
> +               /* Device doesn't match PCI BDF naming format */
> +               return 1;
> +       }
> +
>         FOREACH_DEVICE_ON_PCIBUS(dev) {
> -               if (rte_eal_compare_pci_addr(&dev->addr, addr))
> +               if (rte_eal_compare_pci_addr(&dev->addr, &addr))
>                         continue;
>
>                 ret = rte_eal_pci_detach_dev(dev);
> @@ -385,8 +464,8 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
>                 free(dev);
>                 return 0;
>         }
> -       return -1;
>
> +       return ret;
>  err_return:
>         RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
>                         " cannot be used\n", dev->addr.domain, dev->addr.bus,
> diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
> index 19954f4..9a096ec 100644
> --- a/lib/librte_eal/common/include/rte_bus.h
> +++ b/lib/librte_eal/common/include/rte_bus.h
> @@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
>  /* Bus list exposed */
>  extern struct rte_bus_list rte_bus_list;
>
> +#define FOREACH_BUS(bus_p)     TAILQ_FOREACH(bus_p, &rte_bus_list, next)
> +
>  /**
>   * Bus specific scan for devices attached on the bus.
>   * For each bus object, the scan would be reponsible for finding devices and
> @@ -85,6 +87,33 @@ typedef int (*rte_bus_scan_t)(void);
>  typedef int (*rte_bus_probe_t)(void);
>
>  /**
> + * Attach a device to a bus, assuming it is 'connected' to the bus.
> + * A bus is responsible for scanning for devices. Attaching a new device is
> + * for reenabling the device after being detached/removed.
> + *
> + * @param device_name
> + *     Name of the device to attach.
> + *
> + * @return
> + *     0 for successful attach
> + *     !0 for unsuccessful attach (or incorrect device name)
> + */
> +typedef int (*rte_bus_attach_t)(const char *device_name);
> +
> +/**
> + * Detach a named device from a bus. Implementation would check the existence
> + * of device on the bus and detach it.
> + *
> + * @param device_name
> + *     Name of the device to detach
> + *
> + * @return
> + *     0 for successful detaching
> + *     !0 if device not found or can't detach
> + */
> +typedef int (*rte_bus_detach_t)(const char *device_name);
> +
> +/**
>   * A structure describing a generic bus.
>   */
>  struct rte_bus {
> @@ -92,6 +121,8 @@ struct rte_bus {
>         const char *name;            /**< Name of the bus */
>         rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
>         rte_bus_probe_t probe;       /**< Probe devices on bus */
> +       rte_bus_attach_t attach;     /**< Attach a named device */
> +       rte_bus_detach_t detach;     /**< Detach a named device */
>  };
>
>  /**
> diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
> index bab8df4..215d732 100644
> --- a/lib/librte_eal/common/include/rte_pci.h
> +++ b/lib/librte_eal/common/include/rte_pci.h
> @@ -418,6 +418,36 @@ int
>  rte_eal_pci_probe(void);
>
>  /**
> + * Search and attach a PCI device to PCI Bus
> + * Implements rte_bus->attach
> + *
> + * @param device_name
> + *     Name of the device to search and attach
> + *
> + * @return
> + *     0 for successful removal of device
> + *     >0 if device not found on bus
> + *     <0 in case of error in removal.
> + */
> +int
> +rte_eal_pci_attach(const char *device_name);
> +
> +/**
> + * Search and detach a PCI device from PCI Bus
> + * Implements rte_bus->detach
> + *
> + * @param device_name
> + *     Name of the device to search and detach
> + *
> + * @return
> + *     0 for successful detaching of device
> + *     >0 if device not found on bus
> + *     <0 in case of error in removal.
> + */
> +int
> +rte_eal_pci_detach(const char *device_name);
> +
> +/**
>   * Map the PCI device resources in user space virtual memory address
>   *
>   * Note that driver should not call this function when flag
> @@ -491,21 +521,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
>  int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
>
>  /**
> - * Close the single PCI device.
> - *
> - * Scan the content of the PCI bus, and find the pci device specified by pci
> - * address, then call the remove() function for registered driver that has a
> - * matching entry in its id_table for discovered device.
> - *
> - * @param addr
> - *     The PCI Bus-Device-Function address to close.
> - * @return
> - *   - 0 on success.
> - *   - Negative on error.
> - */
> -int rte_eal_pci_detach(const struct rte_pci_addr *addr);
> -
> -/**
>   * Dump the content of the PCI bus.
>   *
>   * @param f
> diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
> index d6f9855..01f0c9a 100644
> --- a/lib/librte_eal/linuxapp/eal/eal_pci.c
> +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
> @@ -719,6 +719,8 @@ struct rte_pci_bus rte_pci_bus = {
>         .bus = {
>                 .scan = rte_eal_pci_scan,
>                 .probe = rte_eal_pci_probe,
> +               .attach = rte_eal_pci_attach,
> +               .detach = rte_eal_pci_detach,
>         },
>         .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
>         .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
> --
> 2.7.0
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 09/13] pci: add bus driver
  2017-02-15 10:42             ` Jan Blunck
@ 2017-02-15 11:20               ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-02-15 11:20 UTC (permalink / raw)
  To: Jan Blunck; +Cc: Shreyansh Jain, dev

2017-02-15 11:42, Jan Blunck:
> >  /**
> > + * Add a PCI device to the PCI Bus (append to PCI Device list). This function
> > + * also updates the bus references of the PCI Device (and the generic device
> > + * object embedded within.
> > + *
> > + * @param pci_dev
> > + *     PCI device to add
> > + * @return void
> > + */
> > +void rte_eal_pci_add_device(struct rte_pci_device *pci_dev);
> > +
> 
> Who would be the user of this?
> 
> From my understanding a device will show up on the bus if:
> 1. bus->scan() finds it
> 2. bus->attach(devargs) explicitly adds it to the whitelist
> 
> Both methods shouldn't require us to expose the API outside of eal.

I agree

> > +struct rte_pci_bus rte_pci_bus = {
> > +       .bus = {
> > +               .scan = rte_eal_pci_scan,
> > +               .probe = rte_eal_pci_probe,
> > +       },
> > +       .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
> > +       .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
> 
> I don't see why this is necessary and I believe it makes people think
> we might want to model topology. It's better to keep it simple and
> have it locally in eal_common_pci.c.

I agree

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 07/13] pci: split match and probe
  2017-02-15 10:45             ` Jan Blunck
@ 2017-02-15 11:22               ` Thomas Monjalon
  2017-02-15 11:52                 ` Shreyansh Jain
  2017-02-15 11:30               ` Shreyansh Jain
  1 sibling, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-02-15 11:22 UTC (permalink / raw)
  To: Jan Blunck, Shreyansh Jain; +Cc: dev

2017-02-15 11:45, Jan Blunck:
> >  /**
> > + * Match the PCI Driver and Device using the ID Table
> > + *
> > + * @param pci_drv
> > + *     PCI driver from which ID table would be extracted
> > + * @param pci_dev
> > + *     PCI device to match against the driver
> > + * @return
> > + *     0 for successful match
> > + *     !0 for unsuccessful match
> > + */
> > +int
> > +rte_pci_match(const struct rte_pci_driver *pci_drv,
> > +             const struct rte_pci_device *pci_dev);
> 
> I don't think this symbol needs to be exported and visible outside of EAL.

If I remember well, Shreyansh wants to re-use it for its own bus which
is closed to PCI.
I think it is weird and we could look for another way to re-use some code.
Shreyansh?

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 12/13] pci: use bus driver for attach/detach
  2017-02-15 11:08             ` Jan Blunck
@ 2017-02-15 11:26               ` Thomas Monjalon
  2017-02-15 11:39                 ` Jan Blunck
  0 siblings, 1 reply; 146+ messages in thread
From: Thomas Monjalon @ 2017-02-15 11:26 UTC (permalink / raw)
  To: Jan Blunck; +Cc: Shreyansh Jain, dev

2017-02-15 12:08, Jan Blunck:
> >  int rte_eal_dev_attach(const char *name, const char *devargs)
> >  {
> > -       struct rte_pci_addr addr;
> > +       int ret = 1;
> > +       struct rte_bus *bus;
> >
> >         if (name == NULL || devargs == NULL) {
> >                 RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
> >                 return -EINVAL;
> >         }
> >
> > -       if (eal_parse_pci_DomBDF(name, &addr) == 0) {
> > -               if (rte_eal_pci_probe_one(&addr) < 0)
> > +       FOREACH_BUS(bus) {
> > +               if (!bus->attach) {
> > +                       RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
> > +                               " attach.\n", bus->name);
> > +                       continue;
> > +               }
> > +               ret = bus->attach(name);
> 
> Enforcing a globally unique naming scheme for the low-level device
> makes this complicated for users. There are buses that enumerate the
> devices just by an integer so we will have conflicts.
> 
> I think it is better to change the signature of rte_eal_dev_attach()
> instead and find the correct bus based on its name. Also I believe the
> API is more user friendly if we pass the complete (raw) devargs string
> instead of the name/args pair.

I thought we could have a bus prefix in the name so there is no conflict.
How do you imagine the full devargs?

> > +               if (!ret) /* device successfully attached */
> > +                       return ret;
> > +               if (ret > 0) /* device not found on bus */
> > +                       continue;
> > +               else
> >                         goto err;
> > +       }
> 

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 07/13] pci: split match and probe
  2017-02-15 10:45             ` Jan Blunck
  2017-02-15 11:22               ` Thomas Monjalon
@ 2017-02-15 11:30               ` Shreyansh Jain
  1 sibling, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-02-15 11:30 UTC (permalink / raw)
  To: Jan Blunck, Thomas Monjalon; +Cc: dev

On Wednesday 15 February 2017 04:15 PM, Jan Blunck wrote:
> On Thu, Jan 19, 2017 at 5:45 AM, Thomas Monjalon
> <thomas.monjalon@6wind.com> wrote:
>> From: Shreyansh Jain <shreyansh.jain@nxp.com>
>>
>> Matching of PCI device address and driver ID table is being done at two
>> discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
>> and rte_eal_pci_detach_dev).
>>
>> Splitting the matching function into a public fn rte_pci_match.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
>> ---
>>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   1 +
>>  lib/librte_eal/common/eal_common_pci.c          | 189 +++++++++++++-----------
>>  lib/librte_eal/common/include/rte_pci.h         |  15 ++
>>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |   1 +
>>  4 files changed, 121 insertions(+), 85 deletions(-)
>>
>> diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
>> index a3d9fac..afa1643 100644
>> --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
>> +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
>> @@ -184,5 +184,6 @@ DPDK_17.02 {
>>         rte_bus_register;
>>         rte_bus_scan;
>>         rte_bus_unregister;
>> +       rte_pci_match;
>>
>>  } DPDK_16.11;
>> diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
>> index 72547bd..4f155c6 100644
>> --- a/lib/librte_eal/common/eal_common_pci.c
>> +++ b/lib/librte_eal/common/eal_common_pci.c
>> @@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
>>                                 requested_addr);
>>  }
>>
>> -/*
>> - * If vendor/device ID match, call the probe() function of the
>> - * driver.
>> - */
>> -static int
>> -rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
>> +int
>> +rte_pci_match(const struct rte_pci_driver *pci_drv,
>> +             const struct rte_pci_device *pci_dev)
>>  {
>> -       int ret;
>> +       int match = 1;
>>         const struct rte_pci_id *id_table;
>>
>> -       for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
>> +       if (!pci_drv || !pci_dev || !pci_drv->id_table) {
>> +               RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
>> +               return -1;
>> +       }
>>
>> +       for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
>> +            id_table++) {
>>                 /* check if device's identifiers match the driver's ones */
>> -               if (id_table->vendor_id != dev->id.vendor_id &&
>> +               if (id_table->vendor_id != pci_dev->id.vendor_id &&
>>                                 id_table->vendor_id != PCI_ANY_ID)
>>                         continue;
>> -               if (id_table->device_id != dev->id.device_id &&
>> +               if (id_table->device_id != pci_dev->id.device_id &&
>>                                 id_table->device_id != PCI_ANY_ID)
>>                         continue;
>> -               if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
>> -                               id_table->subsystem_vendor_id != PCI_ANY_ID)
>> +               if (id_table->subsystem_vendor_id !=
>> +                   pci_dev->id.subsystem_vendor_id &&
>> +                   id_table->subsystem_vendor_id != PCI_ANY_ID)
>>                         continue;
>> -               if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
>> -                               id_table->subsystem_device_id != PCI_ANY_ID)
>> +               if (id_table->subsystem_device_id !=
>> +                   pci_dev->id.subsystem_device_id &&
>> +                   id_table->subsystem_device_id != PCI_ANY_ID)
>>                         continue;
>> -               if (id_table->class_id != dev->id.class_id &&
>> +               if (id_table->class_id != pci_dev->id.class_id &&
>>                                 id_table->class_id != RTE_CLASS_ANY_ID)
>>                         continue;
>>
>> -               struct rte_pci_addr *loc = &dev->addr;
>> -
>> -               RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>> -                               loc->domain, loc->bus, loc->devid, loc->function,
>> -                               dev->device.numa_node);
>> -
>> -               /* no initialization when blacklisted, return without error */
>> -               if (dev->device.devargs != NULL &&
>> -                       dev->device.devargs->type ==
>> -                               RTE_DEVTYPE_BLACKLISTED_PCI) {
>> -                       RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
>> -                       return 1;
>> -               }
>> -
>> -               RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
>> -                               dev->id.device_id, dr->driver.name);
>> -
>> -               if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
>> -                       /* map resources for devices that use igb_uio */
>> -                       ret = rte_eal_pci_map_device(dev);
>> -                       if (ret != 0)
>> -                               return ret;
>> -               }
>> -
>> -               /* reference driver structure */
>> -               dev->driver = dr;
>> -
>> -               /* call the driver probe() function */
>> -               ret = dr->probe(dr, dev);
>> -               if (ret) {
>> -                       dev->driver = NULL;
>> -                       if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
>> -                               rte_eal_pci_unmap_device(dev);
>> -               }
>> -
>> -               return ret;
>> +               match = 0;
>> +               break;
>>         }
>> -       /* return positive value if driver doesn't support this device */
>> -       return 1;
>> +
>> +       return match;
>>  }
>>
>>  /*
>> - * If vendor/device ID match, call the remove() function of the
>> + * If vendor/device ID match, call the probe() function of the
>>   * driver.
>>   */
>>  static int
>> -rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
>> -               struct rte_pci_device *dev)
>> +rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
>> +                            struct rte_pci_device *dev)
>>  {
>> -       const struct rte_pci_id *id_table;
>> +       int ret;
>> +       struct rte_pci_addr *loc;
>>
>>         if ((dr == NULL) || (dev == NULL))
>>                 return -EINVAL;
>>
>> -       for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
>> +       loc = &dev->addr;
>>
>> -               /* check if device's identifiers match the driver's ones */
>> -               if (id_table->vendor_id != dev->id.vendor_id &&
>> -                               id_table->vendor_id != PCI_ANY_ID)
>> -                       continue;
>> -               if (id_table->device_id != dev->id.device_id &&
>> -                               id_table->device_id != PCI_ANY_ID)
>> -                       continue;
>> -               if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
>> -                               id_table->subsystem_vendor_id != PCI_ANY_ID)
>> -                       continue;
>> -               if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
>> -                               id_table->subsystem_device_id != PCI_ANY_ID)
>> -                       continue;
>> +       /* The device is not blacklisted; Check if driver supports it */
>> +       ret = rte_pci_match(dr, dev);
>> +       if (ret) {
>> +               /* Match of device and driver failed */
>> +               RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
>> +                       dr->driver.name);
>> +               return 1;
>> +       }
>>
>> -               struct rte_pci_addr *loc = &dev->addr;
>> +       RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>> +                       loc->domain, loc->bus, loc->devid, loc->function,
>> +                       dev->device.numa_node);
>> +
>> +       /* no initialization when blacklisted, return without error */
>> +       if (dev->device.devargs != NULL &&
>> +               dev->device.devargs->type ==
>> +                       RTE_DEVTYPE_BLACKLISTED_PCI) {
>> +               RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
>> +                       " initializing\n");
>> +               return 1;
>> +       }
>>
>> -               RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>> -                               loc->domain, loc->bus, loc->devid,
>> -                               loc->function, dev->device.numa_node);
>> +       RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
>> +               dev->id.device_id, dr->driver.name);
>>
>> -               RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
>> -                               dev->id.device_id, dr->driver.name);
>> +       if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
>> +               /* map resources for devices that use igb_uio */
>> +               ret = rte_eal_pci_map_device(dev);
>> +               if (ret != 0)
>> +                       return ret;
>> +       }
>>
>> -               if (dr->remove && (dr->remove(dev) < 0))
>> -                       return -1;      /* negative value is an error */
>> +       /* reference driver structure */
>> +       dev->driver = dr;
>>
>> -               /* clear driver structure */
>> +       /* call the driver probe() function */
>> +       ret = dr->probe(dr, dev);
>> +       if (ret) {
>>                 dev->driver = NULL;
>> -
>>                 if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
>> -                       /* unmap resources for devices that use igb_uio */
>>                         rte_eal_pci_unmap_device(dev);
>> +       }
>>
>> -               return 0;
>> +       return ret;
>> +}
>> +
>> +/*
>> + * If vendor/device ID match, call the remove() function of the
>> + * driver.
>> + */
>> +static int
>> +rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
>> +               struct rte_pci_device *dev)
>> +{
>> +       int ret;
>> +       struct rte_pci_addr *loc;
>> +
>> +       if ((dr == NULL) || (dev == NULL))
>> +               return -EINVAL;
>> +
>> +       ret = rte_pci_match(dr, dev);
>> +       if (ret) {
>> +               /* Device and driver don't match */
>> +               return 1;
>>         }
>>
>> -       /* return positive value if driver doesn't support this device */
>> -       return 1;
>> +       loc = &dev->addr;
>> +
>> +       RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
>> +                       loc->domain, loc->bus, loc->devid,
>> +                       loc->function, dev->device.numa_node);
>> +
>> +       RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
>> +                       dev->id.device_id, dr->driver.name);
>> +
>> +       if (dr->remove && (dr->remove(dev) < 0))
>> +               return -1;      /* negative value is an error */
>> +
>> +       /* clear driver structure */
>> +       dev->driver = NULL;
>> +
>> +       if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
>> +               /* unmap resources for devices that use igb_uio */
>> +               rte_eal_pci_unmap_device(dev);
>> +
>> +       return 0;
>>  }
>>
>>  /*
>> diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
>> index 8557e47..adc20b9 100644
>> --- a/lib/librte_eal/common/include/rte_pci.h
>> +++ b/lib/librte_eal/common/include/rte_pci.h
>> @@ -371,6 +371,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
>>  int rte_eal_pci_scan(void);
>>
>>  /**
>> + * Match the PCI Driver and Device using the ID Table
>> + *
>> + * @param pci_drv
>> + *     PCI driver from which ID table would be extracted
>> + * @param pci_dev
>> + *     PCI device to match against the driver
>> + * @return
>> + *     0 for successful match
>> + *     !0 for unsuccessful match
>> + */
>> +int
>> +rte_pci_match(const struct rte_pci_driver *pci_drv,
>> +             const struct rte_pci_device *pci_dev);
>
> I don't think this symbol needs to be exported and visible outside of EAL.

Agree.
2 reasons why this exists:
1. Initial RFC has match as a callback. That doesn't exist now.
2. Earlier the idea was that other buses/device-types might use this
    function (buses which are PCI like), but that is not a good
    assumption.

>
>> +
>> +/**
>>   * Probe the PCI bus for registered drivers.
>>   *
>>   * Scan the content of the PCI bus, and call the probe() function for
>> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>> index 69e0e7b..b557e7c 100644
>> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
>> @@ -188,5 +188,6 @@ DPDK_17.02 {
>>         rte_bus_register;
>>         rte_bus_scan;
>>         rte_bus_unregister;
>> +       rte_pci_match;
>>
>>  } DPDK_16.11;
>> --
>> 2.7.0
>>
>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 12/13] pci: use bus driver for attach/detach
  2017-02-15 11:26               ` Thomas Monjalon
@ 2017-02-15 11:39                 ` Jan Blunck
  2017-02-15 14:04                   ` [RFC] eal: use busname and devargs to attach devices Jan Blunck
  0 siblings, 1 reply; 146+ messages in thread
From: Jan Blunck @ 2017-02-15 11:39 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Shreyansh Jain, dev

On Wed, Feb 15, 2017 at 12:26 PM, Thomas Monjalon
<thomas.monjalon@6wind.com> wrote:
> 2017-02-15 12:08, Jan Blunck:
>> >  int rte_eal_dev_attach(const char *name, const char *devargs)
>> >  {
>> > -       struct rte_pci_addr addr;
>> > +       int ret = 1;
>> > +       struct rte_bus *bus;
>> >
>> >         if (name == NULL || devargs == NULL) {
>> >                 RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
>> >                 return -EINVAL;
>> >         }
>> >
>> > -       if (eal_parse_pci_DomBDF(name, &addr) == 0) {
>> > -               if (rte_eal_pci_probe_one(&addr) < 0)
>> > +       FOREACH_BUS(bus) {
>> > +               if (!bus->attach) {
>> > +                       RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
>> > +                               " attach.\n", bus->name);
>> > +                       continue;
>> > +               }
>> > +               ret = bus->attach(name);
>>
>> Enforcing a globally unique naming scheme for the low-level device
>> makes this complicated for users. There are buses that enumerate the
>> devices just by an integer so we will have conflicts.
>>
>> I think it is better to change the signature of rte_eal_dev_attach()
>> instead and find the correct bus based on its name. Also I believe the
>> API is more user friendly if we pass the complete (raw) devargs string
>> instead of the name/args pair.
>
> I thought we could have a bus prefix in the name so there is no conflict.

Which raises the question of which separator to use. There are some
buses like "xen" and "xen-backend" that might clash with a simple
prefix. Also it makes is awkward to use for the case where the user is
iterating over OS filesystem data structures (directories and files):
the user probably has busname and device identification already
separate and needs to snprintf() into another buffer for our API just
for us to call sscanf() to extract the busname ...

> How do you imagine the full devargs?

I'll send a patch.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v11 07/13] pci: split match and probe
  2017-02-15 11:22               ` Thomas Monjalon
@ 2017-02-15 11:52                 ` Shreyansh Jain
  0 siblings, 0 replies; 146+ messages in thread
From: Shreyansh Jain @ 2017-02-15 11:52 UTC (permalink / raw)
  To: Thomas Monjalon, Jan Blunck; +Cc: dev


> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, February 15, 2017 4:53 PM
> To: Jan Blunck <jblunck@infradead.org>; Shreyansh Jain
> <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v11 07/13] pci: split match and probe
> 
> 2017-02-15 11:45, Jan Blunck:
> > >  /**
> > > + * Match the PCI Driver and Device using the ID Table
> > > + *
> > > + * @param pci_drv
> > > + *     PCI driver from which ID table would be extracted
> > > + * @param pci_dev
> > > + *     PCI device to match against the driver
> > > + * @return
> > > + *     0 for successful match
> > > + *     !0 for unsuccessful match
> > > + */
> > > +int
> > > +rte_pci_match(const struct rte_pci_driver *pci_drv,
> > > +             const struct rte_pci_device *pci_dev);
> >
> > I don't think this symbol needs to be exported and visible outside of EAL.
> 
> If I remember well, Shreyansh wants to re-use it for its own bus which
> is closed to PCI.
> I think it is weird and we could look for another way to re-use some code.
> Shreyansh?

>From what I recall pci_match _was_ exported was because:
1. earlier match was a callback for bus. Which is not the case now
2. idea was that some other Buses might be able to re-use this. NXP DPAA2 implementation (in early stages).

I don't think this is needed anymore.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [RFC] eal: use busname and devargs to attach devices
  2017-02-15 11:39                 ` Jan Blunck
@ 2017-02-15 14:04                   ` Jan Blunck
  0 siblings, 0 replies; 146+ messages in thread
From: Jan Blunck @ 2017-02-15 14:04 UTC (permalink / raw)
  To: dev; +Cc: david.marchand, shreyansh.jain

Using just the device name to attach a device on the EAL level is not enough
for a unique identification of the bus it should get attached to. Therefore
lets change rte_eal_dev_attach() introduced in 16.11 to take the busname and
the raw devargs string.

Signed-off-by: Jan Blunck <jblunck@infradead.org>
---
 lib/librte_eal/common/eal_common_dev.c | 61 ++++++++++++++++++++++++++--------
 lib/librte_ether/rte_ethdev.c          | 17 +---------
 2 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4bde430..bf41a94 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -37,6 +37,7 @@
 #include <inttypes.h>
 #include <sys/queue.h>
 
+#include <rte_bus.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
@@ -76,29 +77,63 @@ void rte_eal_device_remove(struct rte_device *dev)
 	TAILQ_REMOVE(&dev_device_list, dev, next);
 }
 
-int rte_eal_dev_attach(const char *name, const char *devargs)
+int rte_eal_dev_attach(const char *busname, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	struct rte_bus *bus;
+	rte_bus_attach_t attach;
+	int ret;
 
-	if (name == NULL || devargs == NULL) {
+	if (busname == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
-			goto err;
+	if (!busname) {
+		char *name, *args;
+		struct rte_pci_addr addr;
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
-			goto err;
+		/*
+		 * We default to virtual device but lets check for PCI device format for
+		 * backwards compatibility reasons.
+		 */
+		busname = "virtual";
+
+		if (rte_eal_parse_devargs_str(devargs, &name, &args))
+			return -EINVAL;
+
+		if (eal_parse_pci_DomBDF(name, &addr) == 0) {
+			RTE_LOG(ERR, EAL, "Deprectated\n");
+			busname = "pci";
+		}
+
+		free(name);
+		free(args);
 	}
 
-	return 0;
+	bus = rte_bus_find_by_name(busname);
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "Can't find bus (%s)\n", busname);
+		return -EINVAL;
+	}
 
-err:
-	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
-	return -EINVAL;
+	attach = bus->attach;
+	if (!attach) {
+		RTE_LOG(ERR, EAL, "Function not supported\n");
+		return -ENOTSUP;
+	}
+
+	ret = attach(devargs);
+	if (ret) {
+		RTE_LOG(ERR, EAL, "Attaching device to bus failed \n");
+		return ret;
+	}
+
+	/*
+	 * Probing might fail because some devices are not claimed by any driver
+	 * but we don't care: the device is properly attached at this point.
+	 */
+	(void)bus->probe();
+	return 0;
 }
 
 int rte_eal_dev_detach(const char *name)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index eb0a94a..bbebc8f 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -474,29 +474,16 @@ rte_eth_dev_attach(const char *devargs, uint8_t *port_id)
 {
 	int ret = -1;
 	int current = rte_eth_dev_count();
-	char *name = NULL;
-	char *args = NULL;
 
 	if ((devargs == NULL) || (port_id == NULL)) {
 		ret = -EINVAL;
 		goto err;
 	}
 
-	/* parse devargs, then retrieve device name and args */
-	if (rte_eal_parse_devargs_str(devargs, &name, &args))
-		goto err;
-
-	ret = rte_eal_dev_attach(name, args);
+	ret = rte_eal_dev_attach(NULL, devargs);
 	if (ret < 0)
 		goto err;
 
-	/* no point looking at the port count if no port exists */
-	if (!rte_eth_dev_count()) {
-		RTE_LOG(ERR, EAL, "No port found for device (%s)\n", name);
-		ret = -1;
-		goto err;
-	}
-
 	/* if nothing happened, there is a bug here, since some driver told us
 	 * it did attach a device, but did not create a port.
 	 */
@@ -509,8 +496,6 @@ rte_eth_dev_attach(const char *devargs, uint8_t *port_id)
 	ret = 0;
 
 err:
-	free(name);
-	free(args);
 	return ret;
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v12 0/5] rte_bus_pci
  2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
                             ` (13 preceding siblings ...)
  2017-01-19  4:50           ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
@ 2017-04-07 15:28           ` Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 1/5] pci: split match and probe Gaetan Rivet
                               ` (5 more replies)
  14 siblings, 6 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-07 15:28 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain, Thomas Monjalon, Jan Blunck

I have rebased the work done by Shreyansh and Thomas to follow
the bus abstraction introduced in v17.02 for the PCI bus
implementation.
This series is only a partial version of the previous one, because
some of the patches have already been integrated, and others still
need rework.

changes in v12:
  - Change the rte_pci_match function semantic to match its name.
  - Make the rte_pci_match function private.
  - Removed the PCI tests. They cannot follow the bus implementation
    anymore, and it is an opportunity to update their original design.

Additional work is needed:
  - The PCI bus should be moved to the relevant bus sub-directory.
  - The documentation must be updated.

But this version should allow for the PCI bus implementation to be
integrated in v17.05-rc2.

Gaetan Rivet (1):
  test: remove pci tests

Shreyansh Jain (4):
  pci: split match and probe
  pci: remove loop over drivers in device detach
  pci: add bus driver
  pci: use bus driver for scan/probe

 MAINTAINERS                                        |   2 -
 lib/librte_eal/bsdapp/eal/eal.c                    |  14 -
 lib/librte_eal/bsdapp/eal/eal_pci.c                |  42 +--
 lib/librte_eal/bsdapp/eal/rte_eal_version.map      |   2 -
 lib/librte_eal/common/eal_common_pci.c             | 260 +++++++++--------
 lib/librte_eal/common/eal_private.h                |  10 -
 lib/librte_eal/common/include/rte_pci.h            |  84 +++++-
 lib/librte_eal/linuxapp/eal/eal.c                  |  14 -
 lib/librte_eal/linuxapp/eal/eal_pci.c              |  46 +--
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   2 -
 test/test/Makefile                                 |   2 -
 test/test/test.h                                   |   3 -
 test/test/test_mp_secondary.c                      |  17 --
 test/test/test_pci.c                               | 322 ---------------------
 .../bus/pci/devices/0000:01:00.0/class             |   1 -
 .../bus/pci/devices/0000:01:00.0/config            | Bin 64 -> 0 bytes
 .../devices/0000:01:00.0/consistent_dma_mask_bits  |   1 -
 .../bus/pci/devices/0000:01:00.0/device            |   1 -
 .../bus/pci/devices/0000:01:00.0/dma_mask_bits     |   1 -
 .../bus/pci/devices/0000:01:00.0/enable            |   1 -
 .../bus/pci/devices/0000:01:00.0/irq               |   1 -
 .../bus/pci/devices/0000:01:00.0/modalias          |   1 -
 .../bus/pci/devices/0000:01:00.0/msi_bus           |   1 -
 .../bus/pci/devices/0000:01:00.0/numa_node         |   1 -
 .../bus/pci/devices/0000:01:00.0/resource          |  13 -
 .../bus/pci/devices/0000:01:00.0/sriov_numvfs      |   1 -
 .../bus/pci/devices/0000:01:00.0/sriov_totalvfs    |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:00.0/uevent            |   6 -
 .../bus/pci/devices/0000:01:00.0/vendor            |   1 -
 .../bus/pci/devices/0000:01:02.0/class             |   1 -
 .../bus/pci/devices/0000:01:02.0/device            |   1 -
 .../bus/pci/devices/0000:01:02.0/resource          |  13 -
 .../bus/pci/devices/0000:01:02.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:02.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:02.0/vendor            |   1 -
 .../bus/pci/devices/0000:02:ab.0/class             |   1 -
 .../bus/pci/devices/0000:02:ab.0/device            |   1 -
 .../bus/pci/devices/0000:02:ab.0/resource          |  13 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:02:ab.0/vendor            |   1 -
 43 files changed, 251 insertions(+), 638 deletions(-)
 delete mode 100644 test/test/test_pci.c
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor

-- 
2.1.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v12 1/5] pci: split match and probe
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
@ 2017-04-07 15:28             ` Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 2/5] pci: remove loop over drivers in device detach Gaetan Rivet
                               ` (4 subsequent siblings)
  5 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-07 15:28 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Refactor the match logic as a single function.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/common/eal_common_pci.c | 176 ++++++++++++++++++---------------
 1 file changed, 98 insertions(+), 78 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 1ab92c9..83a81c4 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -154,73 +154,108 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 /*
- * If vendor/device ID match, call the probe() function of the
- * driver.
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	1 for successful match
+ *	0 for unsuccessful match
  */
 static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
+		return 1;
+	}
 
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
+	return 0;
+}
 
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
+/*
+ * If vendor/device ID match, call the probe() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
 
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio or VFIO */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
+	loc = &dev->addr;
 
-		/* reference driver structure */
-		dev->driver = dr;
+	/* The device is not blacklisted; Check if driver supports it */
+	if (!rte_pci_match(dr, dev)) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		return ret;
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	/* reference driver structure */
+	dev->driver = dr;
+
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
+		dev->driver = NULL;
+		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+			rte_eal_pci_unmap_device(dev);
+	}
+
+	return ret;
 }
 
 /*
@@ -231,51 +266,36 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
+	if (!rte_pci_match(dr, dev)) {
+		/* Device and driver don't match */
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	loc = &dev->addr;
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
 
-		/* clear driver structure */
-		dev->driver = NULL;
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
-			rte_eal_pci_unmap_device(dev);
+	/* clear driver structure */
+	dev->driver = NULL;
 
-		return 0;
-	}
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	return 0;
 }
 
 /*
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v12 2/5] pci: remove loop over drivers in device detach
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 1/5] pci: split match and probe Gaetan Rivet
@ 2017-04-07 15:28             ` Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 3/5] pci: add bus driver Gaetan Rivet
                               ` (3 subsequent siblings)
  5 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-07 15:28 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain

From: Shreyansh Jain <shreyansh.jain@nxp.com>

rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

Removing pci_detach_all_drivers and restructuring rte_eal_pci_detach
and rte_eal_pci_detach_dev to work without looping over driver list.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/common/eal_common_pci.c | 45 +++++++---------------------------
 1 file changed, 9 insertions(+), 36 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 83a81c4..498a3bb 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -263,19 +263,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_detach_dev(struct rte_pci_device *dev)
 {
 	struct rte_pci_addr *loc;
+	struct rte_pci_driver *dr;
 
-	if ((dr == NULL) || (dev == NULL))
+	if (dev == NULL)
 		return -EINVAL;
 
-	if (!rte_pci_match(dr, dev)) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
+	dr = dev->driver;
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -330,33 +326,6 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 }
 
 /*
- * If vendor/device ID match, call the remove() function of all
- * registered driver for the given device. Return -1 if initialization
- * failed, return 1 if no driver is found for this device.
- */
-static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
-{
-	struct rte_pci_driver *dr = NULL;
-	int rc = 0;
-
-	if (dev == NULL)
-		return -1;
-
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_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;
-}
-
-/*
  * Find the pci device specified by pci address, then invoke probe function of
  * the driver of the devive.
  */
@@ -409,9 +378,13 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = rte_eal_pci_detach_dev(dev);
 		if (ret < 0)
+			/* negative value is an error */
 			goto err_return;
+		if (ret > 0)
+			/* positive value means driver doesn't support it */
+			continue;
 
 		TAILQ_REMOVE(&pci_device_list, dev, next);
 		free(dev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v12 3/5] pci: add bus driver
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 1/5] pci: split match and probe Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 2/5] pci: remove loop over drivers in device detach Gaetan Rivet
@ 2017-04-07 15:28             ` Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 4/5] pci: use bus driver for scan/probe Gaetan Rivet
                               ` (2 subsequent siblings)
  5 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-07 15:28 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain, Thomas Monjalon

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

EAL continues to have direct PCI init/scan calls as well. These would be
removed in subsequent patches to enable bus only PCI devices.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
Reviewed-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     | 11 ++++++
 lib/librte_eal/common/eal_common_pci.c  | 25 +++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 65 +++++++++++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 12 ++++++
 4 files changed, 113 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 16a1743..06b5a3a 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -675,3 +675,14 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 498a3bb..853a12c 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -72,6 +72,7 @@
 #include <rte_errno.h>
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -88,6 +89,8 @@ struct pci_driver_list pci_driver_list =
 struct pci_device_list pci_device_list =
 	TAILQ_HEAD_INITIALIZER(pci_device_list);
 
+extern struct rte_pci_bus rte_pci_bus;
+
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -489,3 +492,25 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a device to PCI bus */
+void
+rte_eal_pci_add_device(struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&rte_pci_bus.device_list, pci_dev, next);
+}
+
+/* Insert a device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+}
+
+/* Remove a device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	TAILQ_REMOVE(&rte_pci_bus.device_list, pci_dev, next);
+}
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..6984fd5 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *bus;                /**< PCI bus reference. */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
@@ -508,6 +538,41 @@ RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
 void rte_eal_pci_unregister(struct rte_pci_driver *driver);
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Read PCI config space.
  *
  * @param device
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 7d6f50a..979b6f3 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -728,3 +729,14 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v12 4/5] pci: use bus driver for scan/probe
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
                               ` (2 preceding siblings ...)
  2017-04-07 15:28             ` [PATCH v12 3/5] pci: add bus driver Gaetan Rivet
@ 2017-04-07 15:28             ` Gaetan Rivet
  2017-04-07 15:28             ` [PATCH v12 5/5] test: remove pci tests Gaetan Rivet
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
  5 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-07 15:28 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain, Thomas Monjalon

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
Reviewed-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 | 14 ---------
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 35 ++++++++---------------
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 26 +++++++----------
 lib/librte_eal/common/eal_private.h             | 10 -------
 lib/librte_eal/common/include/rte_pci.h         | 19 +++----------
 lib/librte_eal/linuxapp/eal/eal.c               | 14 ---------
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 38 +++++++++----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 41 insertions(+), 119 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index fae6c7e..7321ac6 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -602,13 +602,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	if (rte_eal_pci_init() < 0) {
-		rte_eal_init_alert("Cannot init PCI\n");
-		rte_errno = EPROTO;
-		rte_atomic32_clear(&run_once);
-		return -1;
-	}
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -667,13 +660,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe()) {
-		rte_eal_init_alert("Cannot probe PCI\n");
-		rte_errno = ENOTSUP;
-		return -1;
-	}
-
 	if (rte_eal_dev_init() < 0)
 		rte_eal_init_alert("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 06b5a3a..f796ef6 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -87,6 +87,9 @@
  * enabling bus master.
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 /* Map pci device */
 int
 rte_eal_pci_map_device(struct rte_pci_device *dev)
@@ -313,21 +316,19 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 	}
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+		rte_eal_pci_add_device(dev);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 			else if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -338,8 +339,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_pci_add_device(dev);
 	}
 
 	return 0;
@@ -367,6 +367,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -661,21 +665,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index e1fbebc..ca12d89 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 853a12c..02d92b9 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -84,11 +84,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 extern struct rte_pci_bus rte_pci_bus;
 
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -336,6 +331,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -347,7 +343,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -377,7 +373,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -389,7 +385,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 			/* positive value means driver doesn't support it */
 			continue;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -419,7 +415,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		probed++;
 
 		/* set devargs in PCI structure */
@@ -472,7 +468,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -481,16 +477,16 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	driver->bus = &rte_pci_bus;
 }
 
 /* unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	TAILQ_REMOVE(&rte_pci_bus.driver_list, driver, next);
+	driver->bus = NULL;
 }
 
 /* Add a device to PCI bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 8b2d323..260dcbb 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -109,16 +109,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 6984fd5..f8d6fcb 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -208,8 +202,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -401,17 +393,14 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index d98d56d..7cf33d6 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -830,13 +830,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	if (rte_eal_pci_init() < 0) {
-		rte_eal_init_alert("Cannot init PCI\n");
-		rte_errno = EPROTO;
-		rte_atomic32_clear(&run_once);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO\n");
@@ -946,13 +939,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe()) {
-		rte_eal_init_alert("Cannot probe PCI\n");
-		rte_errno = ENOTSUP;
-		return -1;
-	}
-
 	if (rte_eal_dev_init() < 0)
 		rte_eal_init_alert("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 979b6f3..858d36b 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -55,6 +55,9 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+/* Forward declaration of PCI bus */
+struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
@@ -352,21 +355,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+		rte_eal_pci_add_device(dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -376,8 +377,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(dev);
 	}
 
 	return 0;
@@ -453,6 +454,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -469,6 +474,7 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
+
 		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
@@ -714,22 +720,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index d5d05ee..94da1e7 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v12 5/5] test: remove pci tests
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
                               ` (3 preceding siblings ...)
  2017-04-07 15:28             ` [PATCH v12 4/5] pci: use bus driver for scan/probe Gaetan Rivet
@ 2017-04-07 15:28             ` Gaetan Rivet
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
  5 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-07 15:28 UTC (permalink / raw)
  To: dev

These tests are not suited for the rte_bus PCI implementation anymore.

Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 MAINTAINERS                                        |   2 -
 test/test/Makefile                                 |   2 -
 test/test/test.h                                   |   3 -
 test/test/test_mp_secondary.c                      |  17 --
 test/test/test_pci.c                               | 322 ---------------------
 .../bus/pci/devices/0000:01:00.0/class             |   1 -
 .../bus/pci/devices/0000:01:00.0/config            | Bin 64 -> 0 bytes
 .../devices/0000:01:00.0/consistent_dma_mask_bits  |   1 -
 .../bus/pci/devices/0000:01:00.0/device            |   1 -
 .../bus/pci/devices/0000:01:00.0/dma_mask_bits     |   1 -
 .../bus/pci/devices/0000:01:00.0/enable            |   1 -
 .../bus/pci/devices/0000:01:00.0/irq               |   1 -
 .../bus/pci/devices/0000:01:00.0/modalias          |   1 -
 .../bus/pci/devices/0000:01:00.0/msi_bus           |   1 -
 .../bus/pci/devices/0000:01:00.0/numa_node         |   1 -
 .../bus/pci/devices/0000:01:00.0/resource          |  13 -
 .../bus/pci/devices/0000:01:00.0/sriov_numvfs      |   1 -
 .../bus/pci/devices/0000:01:00.0/sriov_totalvfs    |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:00.0/uevent            |   6 -
 .../bus/pci/devices/0000:01:00.0/vendor            |   1 -
 .../bus/pci/devices/0000:01:02.0/class             |   1 -
 .../bus/pci/devices/0000:01:02.0/device            |   1 -
 .../bus/pci/devices/0000:01:02.0/resource          |  13 -
 .../bus/pci/devices/0000:01:02.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:02.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:02.0/vendor            |   1 -
 .../bus/pci/devices/0000:02:ab.0/class             |   1 -
 .../bus/pci/devices/0000:02:ab.0/device            |   1 -
 .../bus/pci/devices/0000:02:ab.0/resource          |  13 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:02:ab.0/vendor            |   1 -
 34 files changed, 415 deletions(-)
 delete mode 100644 test/test/test_pci.c
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor

diff --git a/MAINTAINERS b/MAINTAINERS
index 382f740..39bf1fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -98,8 +98,6 @@ F: test/test/test_errno.c
 F: test/test/test_interrupts.c
 F: test/test/test_logs.c
 F: test/test/test_memcpy*
-F: test/test/test_pci.c
-F: test/test/test_pci_sysfs/
 F: test/test/test_per_lcore.c
 F: test/test/test_prefetch.c
 F: test/test/test_rwlock.c
diff --git a/test/test/Makefile b/test/test/Makefile
index 278b508..ee240be 100644
--- a/test/test/Makefile
+++ b/test/test/Makefile
@@ -83,8 +83,6 @@ test_resource.res: test_resource.c
 	@ cp $< $@
 $(eval $(call linked_resource,test_resource_c,test_resource.res))
 $(eval $(call linked_tar_resource,test_resource_tar,test_resource.c))
-SRCS-$(CONFIG_RTE_APP_TEST_RESOURCE_TAR) += test_pci.c
-$(eval $(call linked_tar_resource,test_pci_sysfs,test_pci_sysfs))
 SRCS-$(CONFIG_RTE_APP_TEST_RESOURCE_TAR) += test_cfgfile.c
 $(eval $(call linked_tar_resource,test_cfgfiles,test_cfgfiles))
 SRCS-y += test_prefetch.c
diff --git a/test/test/test.h b/test/test/test.h
index 9a979d3..08ffe94 100644
--- a/test/test/test.h
+++ b/test/test/test.h
@@ -228,9 +228,6 @@ extern const char *prgname;
 
 int commands_init(void);
 
-int test_pci(void);
-int test_pci_run;
-
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/test/test/test_mp_secondary.c b/test/test/test_mp_secondary.c
index 26c4afd..94042e5 100644
--- a/test/test/test_mp_secondary.c
+++ b/test/test/test_mp_secondary.c
@@ -245,16 +245,6 @@ run_object_creation_tests(void)
 	printf("# Checked rte_lpm_create() OK\n");
 #endif
 
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	/* Run a test_pci call */
-	if (test_pci() != 0) {
-		printf("PCI scan failed in secondary\n");
-		if (getuid() == 0) /* pci scans can fail as non-root */
-			return -1;
-	} else
-		printf("PCI scan succeeded in secondary\n");
-#endif
-
 	return 0;
 }
 
@@ -267,13 +257,6 @@ int
 test_mp_secondary(void)
 {
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
-		if (!test_pci_run) {
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-			printf("=== Running pre-requisite test of test_pci\n");
-			test_pci();
-			printf("=== Requisite test done\n");
-#endif
-		}
 		return run_secondary_instances();
 	}
 
diff --git a/test/test/test_pci.c b/test/test/test_pci.c
deleted file mode 100644
index 7985376..0000000
--- a/test/test/test_pci.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   Copyright(c) 2014 6WIND S.A.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <sys/queue.h>
-
-#include <rte_interrupts.h>
-#include <rte_pci.h>
-#include <rte_ethdev.h>
-#include <rte_devargs.h>
-
-#include "test.h"
-#include "resource.h"
-
-/* Generic maximum number of drivers to have room to allocate all drivers */
-#define NUM_MAX_DRIVERS 256
-
-/*
- * PCI test
- * ========
- *
- * - Register a driver with a ``probe()`` function.
- *
- * - Dump all PCI devices.
- *
- * - Check that the ``probe()`` function is called at least once.
- */
-
-int test_pci_run = 0; /* value checked by the multiprocess test */
-static unsigned pci_dev_count;
-
-static int my_driver_init(struct rte_pci_driver *dr,
-			  struct rte_pci_device *dev);
-
-/* IXGBE NICS */
-const struct rte_pci_id my_driver_id[] = {
-	{RTE_PCI_DEVICE(0x0001, 0x1234)},
-	{ .vendor_id = 0, /* sentinel */ },
-};
-
-const struct rte_pci_id my_driver_id2[] = {
-	{RTE_PCI_DEVICE(0x0001, 0x4444)},
-	{RTE_PCI_DEVICE(0x0002, 0xabcd)},
-	{ .vendor_id = 0, /* sentinel */ },
-};
-
-struct rte_pci_driver my_driver = {
-	.driver = {
-		.name = "test_driver"
-	},
-	.probe = my_driver_init,
-	.id_table = my_driver_id,
-	.drv_flags = 0,
-};
-
-struct rte_pci_driver my_driver2 = {
-	.driver = {
-		.name = "test_driver2"
-	},
-	.probe = my_driver_init,
-	.id_table = my_driver_id2,
-	.drv_flags = 0,
-};
-
-static int
-my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
-	       struct rte_pci_device *dev)
-{
-	printf("My driver init called in %s\n", dr->driver.name);
-	printf("%x:%x:%x.%d", dev->addr.domain, dev->addr.bus,
-	       dev->addr.devid, dev->addr.function);
-	printf(" - vendor:%x device:%x\n", dev->id.vendor_id, dev->id.device_id);
-
-	pci_dev_count ++;
-	return 0;
-}
-
-static void
-blacklist_all_devices(void)
-{
-	struct rte_pci_device *dev = NULL;
-	unsigned i = 0;
-	char pci_addr_str[16];
-
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
-			dev->addr.domain, dev->addr.bus, dev->addr.devid,
-			dev->addr.function);
-		if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,
-				pci_addr_str) < 0) {
-			printf("Error: cannot blacklist <%s>", pci_addr_str);
-			break;
-		}
-		i++;
-	}
-	printf("%u devices blacklisted\n", i);
-}
-
-/* clear devargs list that was modified by the test */
-static void free_devargs_list(void)
-{
-	struct rte_devargs *devargs;
-
-	while (!TAILQ_EMPTY(&devargs_list)) {
-		devargs = TAILQ_FIRST(&devargs_list);
-		TAILQ_REMOVE(&devargs_list, devargs, next);
-		free(devargs->args);
-		free(devargs);
-	}
-}
-
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
-REGISTER_LINKED_RESOURCE(test_pci_sysfs);
-
-static int
-test_pci_setup(void)
-{
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
-	const struct resource *r;
-	int ret;
-
-	r = resource_find("test_pci_sysfs");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_pci_sysfs");
-
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
-
-	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
-	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
-
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
-
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
-
-	ret = rte_eal_pci_scan();
-	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
-
-	return 0;
-}
-
-static int
-test_pci_cleanup(void)
-{
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
-	const struct resource *r;
-	int ret;
-
-	unsetenv("SYSFS_PCI_DEVICES");
-
-	r = resource_find("test_pci_sysfs");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_pci_sysfs");
-
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
-
-	/*
-	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
-	 * cannot free the devices in the right way. Let's assume that we
-	 * don't care for tests.
-	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-	}
-
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
-	}
-
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
-
-	return 0;
-}
-
-static int
-test_pci_blacklist(void)
-{
-	struct rte_devargs_list save_devargs_list;
-
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
-
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
-
-	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
-
-	if (pci_dev_count == 0) {
-		printf("no device detected\n");
-		return -1;
-	}
-
-	/* save the real devargs_list */
-	save_devargs_list = devargs_list;
-	TAILQ_INIT(&devargs_list);
-
-	blacklist_all_devices();
-
-	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
-
-	free_devargs_list();
-	devargs_list = save_devargs_list;
-
-	if (pci_dev_count != 0) {
-		printf("not all devices are blacklisted\n");
-		return -1;
-	}
-
-	test_pci_run = 1;
-
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
-
-	return 0;
-}
-
-static int test_pci_sysfs(void)
-{
-	const char *orig;
-	const char *newpath;
-	int ret;
-
-	orig = pci_get_sysfs_path();
-	ret = setenv("SYSFS_PCI_DEVICES", "My Documents", 1);
-	TEST_ASSERT_SUCCESS(ret, "Failed setenv to My Documents");
-
-	newpath = pci_get_sysfs_path();
-	TEST_ASSERT(!strcmp(newpath, "My Documents"),
-			"pci_get_sysfs_path() should return 'My Documents' "
-			"but gives %s", newpath);
-
-	ret = setenv("SYSFS_PCI_DEVICES", orig, 1);
-	TEST_ASSERT_SUCCESS(ret, "Failed setenv back to '%s'", orig);
-
-	newpath = pci_get_sysfs_path();
-	TEST_ASSERT(!strcmp(orig, newpath),
-			"pci_get_sysfs_path returned unexpected path: "
-			"%s (expected: %s)", newpath, orig);
-	return 0;
-}
-
-int
-test_pci(void)
-{
-	if (test_pci_sysfs())
-		return -1;
-
-	if (test_pci_setup())
-		return -1;
-
-	if (test_pci_blacklist())
-		return -1;
-
-	if (test_pci_cleanup())
-		return -1;
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(pci_autotest, test_pci);
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
deleted file mode 100644
index 2f9c1da..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
+++ /dev/null
@@ -1 +0,0 @@
-0x020000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
deleted file mode 100644
index 7752421cf13a5aa00a28eaee02cac2add9ce5566..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 64
zcmZo`_$|QBBEZ1Nz`(@7(7?dMz;S^A2oxWHNCpNT2LUi2#BOU~22l(SV3L7>8>k5Y
DD^Ld(

diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
deleted file mode 100644
index 900731f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
+++ /dev/null
@@ -1 +0,0 @@
-64
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
deleted file mode 100644
index 48a6290..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
+++ /dev/null
@@ -1 +0,0 @@
-0x1234
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
deleted file mode 100644
index 900731f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
+++ /dev/null
@@ -1 +0,0 @@
-64
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
deleted file mode 100644
index d00491f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
deleted file mode 100644
index 573541a..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
deleted file mode 100644
index f4c76ed..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
+++ /dev/null
@@ -1 +0,0 @@
-pci:v00008086d000010FBsv00008086sd00000003bc02sc00i00
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
deleted file mode 100644
index d00491f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
deleted file mode 100644
index 3a2e3f4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
+++ /dev/null
@@ -1 +0,0 @@
--1
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
deleted file mode 100644
index f388929..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
+++ /dev/null
@@ -1,13 +0,0 @@
-0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x000000000000e020 0x000000000000e03f 0x0000000000040101
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
deleted file mode 100644
index 573541a..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
deleted file mode 100644
index 4b9026d..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
+++ /dev/null
@@ -1 +0,0 @@
-63
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
deleted file mode 100644
index 89a932c..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
+++ /dev/null
@@ -1 +0,0 @@
-0x0003
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
deleted file mode 100644
index 1dbe34d..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
+++ /dev/null
@@ -1,6 +0,0 @@
-DRIVER=ixgbe
-PCI_CLASS=20000
-PCI_ID=8086:10FB
-PCI_SUBSYS_ID=8086:0003
-PCI_SLOT_NAME=0000:01:00.0
-MODALIAS=pci:v00008086d000010FBsv00008086sd00000003bc02sc00i00
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
deleted file mode 100644
index 22dd936..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
+++ /dev/null
@@ -1 +0,0 @@
-0x100000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
deleted file mode 100644
index f61bbe6..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
+++ /dev/null
@@ -1 +0,0 @@
-0xabcd
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
deleted file mode 100644
index f388929..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
+++ /dev/null
@@ -1,13 +0,0 @@
-0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x000000000000e020 0x000000000000e03f 0x0000000000040101
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
deleted file mode 100644
index f61bbe6..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
+++ /dev/null
@@ -1 +0,0 @@
-0xabcd
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
deleted file mode 100644
index 4321b81..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0002
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
deleted file mode 100644
index 4321b81..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0002
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
deleted file mode 100644
index 22dd936..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
+++ /dev/null
@@ -1 +0,0 @@
-0x100000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
deleted file mode 100644
index ccaa498..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
+++ /dev/null
@@ -1 +0,0 @@
-0x4444
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
deleted file mode 100644
index f388929..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
+++ /dev/null
@@ -1,13 +0,0 @@
-0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x000000000000e020 0x000000000000e03f 0x0000000000040101
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
deleted file mode 100644
index ccaa498..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
+++ /dev/null
@@ -1 +0,0 @@
-0x4444
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 0/7] rte_bus_pci
  2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
                               ` (4 preceding siblings ...)
  2017-04-07 15:28             ` [PATCH v12 5/5] test: remove pci tests Gaetan Rivet
@ 2017-04-11 11:07             ` Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 1/7] test: remove pci tests Gaetan Rivet
                                 ` (7 more replies)
  5 siblings, 8 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev

I have rebased the work done by Shreyansh and Thomas to follow
the bus abstraction introduced in v17.02 for the PCI bus
implementation.
This series is only a partial version of the previous one, because
some of the patches have already been integrated, and others still
need rework.

Additionally, Jan Blunck sent this RFC:

[RFC] eal: use busname and devargs to attach devices

That has not been considered for this version as it had not yet spawned
a discussion.

changes in v13:
  - Removed the PCI tests. They cannot follow the bus implementation
    anymore, and it is an opportunity to update their original design.
  - Changed the rte_pci_match function semantic to match its name.
  - Made the rte_pci_match function private.
  - Made the rte_bus_list private
  - Made rte_eal_pci_add_device,
         rte_eal_pci_insert_device,
         rte_eal_pci_remove_device,
     functions private.

Additional work is needed:
  - The PCI bus should be moved to the relevant bus sub-directory.
  - The documentation must be updated.

But this version should allow for the PCI bus implementation to be
integrated in v17.05-rc2.

Gaetan Rivet (1):
  test: remove pci tests

Shreyansh Jain (6):
  pci: split match and probe
  pci: remove loop over drivers in device detach
  pci: add bus driver
  pci: use bus driver for scan/probe
  pci: use bus driver for attach/detach
  doc: remove deprecation notice for rte_bus

 MAINTAINERS                                        |   2 -
 doc/guides/rel_notes/release_17_02.rst             |   2 +-
 lib/librte_eal/bsdapp/eal/Makefile                 |   2 +-
 lib/librte_eal/bsdapp/eal/eal.c                    |  14 -
 lib/librte_eal/bsdapp/eal/eal_pci.c                |  34 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map      |   2 -
 lib/librte_eal/common/eal_bus.h                    |  45 +++
 lib/librte_eal/common/eal_common_dev.c             |  57 +++-
 lib/librte_eal/common/eal_common_pci.c             | 362 +++++++++++++--------
 lib/librte_eal/common/eal_private.h                |  41 ++-
 lib/librte_eal/common/include/rte_bus.h            |  29 ++
 lib/librte_eal/common/include/rte_pci.h            |  94 ++++--
 lib/librte_eal/linuxapp/eal/Makefile               |   2 +-
 lib/librte_eal/linuxapp/eal/eal.c                  |  14 -
 lib/librte_eal/linuxapp/eal/eal_pci.c              |  38 +--
 lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   2 -
 test/test/Makefile                                 |   2 -
 test/test/test.h                                   |   3 -
 test/test/test_mp_secondary.c                      |  17 -
 test/test/test_pci.c                               | 322 ------------------
 .../bus/pci/devices/0000:01:00.0/class             |   1 -
 .../bus/pci/devices/0000:01:00.0/config            | Bin 64 -> 0 bytes
 .../devices/0000:01:00.0/consistent_dma_mask_bits  |   1 -
 .../bus/pci/devices/0000:01:00.0/device            |   1 -
 .../bus/pci/devices/0000:01:00.0/dma_mask_bits     |   1 -
 .../bus/pci/devices/0000:01:00.0/enable            |   1 -
 .../bus/pci/devices/0000:01:00.0/irq               |   1 -
 .../bus/pci/devices/0000:01:00.0/modalias          |   1 -
 .../bus/pci/devices/0000:01:00.0/msi_bus           |   1 -
 .../bus/pci/devices/0000:01:00.0/numa_node         |   1 -
 .../bus/pci/devices/0000:01:00.0/resource          |  13 -
 .../bus/pci/devices/0000:01:00.0/sriov_numvfs      |   1 -
 .../bus/pci/devices/0000:01:00.0/sriov_totalvfs    |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:00.0/uevent            |   6 -
 .../bus/pci/devices/0000:01:00.0/vendor            |   1 -
 .../bus/pci/devices/0000:01:02.0/class             |   1 -
 .../bus/pci/devices/0000:01:02.0/device            |   1 -
 .../bus/pci/devices/0000:01:02.0/resource          |  13 -
 .../bus/pci/devices/0000:01:02.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:02.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:02.0/vendor            |   1 -
 .../bus/pci/devices/0000:02:ab.0/class             |   1 -
 .../bus/pci/devices/0000:02:ab.0/device            |   1 -
 .../bus/pci/devices/0000:02:ab.0/resource          |  13 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:02:ab.0/vendor            |   1 -
 49 files changed, 478 insertions(+), 675 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_bus.h
 delete mode 100644 test/test/test_pci.c
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor

-- 
2.1.4

^ permalink raw reply	[flat|nested] 146+ messages in thread

* [PATCH v13 1/7] test: remove pci tests
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 2/7] pci: split match and probe Gaetan Rivet
                                 ` (6 subsequent siblings)
  7 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev

These tests are not suited for the rte_bus PCI implementation anymore.

Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 MAINTAINERS                                        |   2 -
 test/test/Makefile                                 |   2 -
 test/test/test.h                                   |   3 -
 test/test/test_mp_secondary.c                      |  17 --
 test/test/test_pci.c                               | 322 ---------------------
 .../bus/pci/devices/0000:01:00.0/class             |   1 -
 .../bus/pci/devices/0000:01:00.0/config            | Bin 64 -> 0 bytes
 .../devices/0000:01:00.0/consistent_dma_mask_bits  |   1 -
 .../bus/pci/devices/0000:01:00.0/device            |   1 -
 .../bus/pci/devices/0000:01:00.0/dma_mask_bits     |   1 -
 .../bus/pci/devices/0000:01:00.0/enable            |   1 -
 .../bus/pci/devices/0000:01:00.0/irq               |   1 -
 .../bus/pci/devices/0000:01:00.0/modalias          |   1 -
 .../bus/pci/devices/0000:01:00.0/msi_bus           |   1 -
 .../bus/pci/devices/0000:01:00.0/numa_node         |   1 -
 .../bus/pci/devices/0000:01:00.0/resource          |  13 -
 .../bus/pci/devices/0000:01:00.0/sriov_numvfs      |   1 -
 .../bus/pci/devices/0000:01:00.0/sriov_totalvfs    |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:00.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:00.0/uevent            |   6 -
 .../bus/pci/devices/0000:01:00.0/vendor            |   1 -
 .../bus/pci/devices/0000:01:02.0/class             |   1 -
 .../bus/pci/devices/0000:01:02.0/device            |   1 -
 .../bus/pci/devices/0000:01:02.0/resource          |  13 -
 .../bus/pci/devices/0000:01:02.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:01:02.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:01:02.0/vendor            |   1 -
 .../bus/pci/devices/0000:02:ab.0/class             |   1 -
 .../bus/pci/devices/0000:02:ab.0/device            |   1 -
 .../bus/pci/devices/0000:02:ab.0/resource          |  13 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_device  |   1 -
 .../bus/pci/devices/0000:02:ab.0/subsystem_vendor  |   1 -
 .../bus/pci/devices/0000:02:ab.0/vendor            |   1 -
 34 files changed, 415 deletions(-)
 delete mode 100644 test/test/test_pci.c
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
 delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor

diff --git a/MAINTAINERS b/MAINTAINERS
index 382f740..39bf1fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -98,8 +98,6 @@ F: test/test/test_errno.c
 F: test/test/test_interrupts.c
 F: test/test/test_logs.c
 F: test/test/test_memcpy*
-F: test/test/test_pci.c
-F: test/test/test_pci_sysfs/
 F: test/test/test_per_lcore.c
 F: test/test/test_prefetch.c
 F: test/test/test_rwlock.c
diff --git a/test/test/Makefile b/test/test/Makefile
index 278b508..ee240be 100644
--- a/test/test/Makefile
+++ b/test/test/Makefile
@@ -83,8 +83,6 @@ test_resource.res: test_resource.c
 	@ cp $< $@
 $(eval $(call linked_resource,test_resource_c,test_resource.res))
 $(eval $(call linked_tar_resource,test_resource_tar,test_resource.c))
-SRCS-$(CONFIG_RTE_APP_TEST_RESOURCE_TAR) += test_pci.c
-$(eval $(call linked_tar_resource,test_pci_sysfs,test_pci_sysfs))
 SRCS-$(CONFIG_RTE_APP_TEST_RESOURCE_TAR) += test_cfgfile.c
 $(eval $(call linked_tar_resource,test_cfgfiles,test_cfgfiles))
 SRCS-y += test_prefetch.c
diff --git a/test/test/test.h b/test/test/test.h
index 9a979d3..08ffe94 100644
--- a/test/test/test.h
+++ b/test/test/test.h
@@ -228,9 +228,6 @@ extern const char *prgname;
 
 int commands_init(void);
 
-int test_pci(void);
-int test_pci_run;
-
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/test/test/test_mp_secondary.c b/test/test/test_mp_secondary.c
index 26c4afd..94042e5 100644
--- a/test/test/test_mp_secondary.c
+++ b/test/test/test_mp_secondary.c
@@ -245,16 +245,6 @@ run_object_creation_tests(void)
 	printf("# Checked rte_lpm_create() OK\n");
 #endif
 
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-	/* Run a test_pci call */
-	if (test_pci() != 0) {
-		printf("PCI scan failed in secondary\n");
-		if (getuid() == 0) /* pci scans can fail as non-root */
-			return -1;
-	} else
-		printf("PCI scan succeeded in secondary\n");
-#endif
-
 	return 0;
 }
 
@@ -267,13 +257,6 @@ int
 test_mp_secondary(void)
 {
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
-		if (!test_pci_run) {
-#ifdef RTE_APP_TEST_RESOURCE_TAR
-			printf("=== Running pre-requisite test of test_pci\n");
-			test_pci();
-			printf("=== Requisite test done\n");
-#endif
-		}
 		return run_secondary_instances();
 	}
 
diff --git a/test/test/test_pci.c b/test/test/test_pci.c
deleted file mode 100644
index 7985376..0000000
--- a/test/test/test_pci.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   Copyright(c) 2014 6WIND S.A.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <sys/queue.h>
-
-#include <rte_interrupts.h>
-#include <rte_pci.h>
-#include <rte_ethdev.h>
-#include <rte_devargs.h>
-
-#include "test.h"
-#include "resource.h"
-
-/* Generic maximum number of drivers to have room to allocate all drivers */
-#define NUM_MAX_DRIVERS 256
-
-/*
- * PCI test
- * ========
- *
- * - Register a driver with a ``probe()`` function.
- *
- * - Dump all PCI devices.
- *
- * - Check that the ``probe()`` function is called at least once.
- */
-
-int test_pci_run = 0; /* value checked by the multiprocess test */
-static unsigned pci_dev_count;
-
-static int my_driver_init(struct rte_pci_driver *dr,
-			  struct rte_pci_device *dev);
-
-/* IXGBE NICS */
-const struct rte_pci_id my_driver_id[] = {
-	{RTE_PCI_DEVICE(0x0001, 0x1234)},
-	{ .vendor_id = 0, /* sentinel */ },
-};
-
-const struct rte_pci_id my_driver_id2[] = {
-	{RTE_PCI_DEVICE(0x0001, 0x4444)},
-	{RTE_PCI_DEVICE(0x0002, 0xabcd)},
-	{ .vendor_id = 0, /* sentinel */ },
-};
-
-struct rte_pci_driver my_driver = {
-	.driver = {
-		.name = "test_driver"
-	},
-	.probe = my_driver_init,
-	.id_table = my_driver_id,
-	.drv_flags = 0,
-};
-
-struct rte_pci_driver my_driver2 = {
-	.driver = {
-		.name = "test_driver2"
-	},
-	.probe = my_driver_init,
-	.id_table = my_driver_id2,
-	.drv_flags = 0,
-};
-
-static int
-my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr,
-	       struct rte_pci_device *dev)
-{
-	printf("My driver init called in %s\n", dr->driver.name);
-	printf("%x:%x:%x.%d", dev->addr.domain, dev->addr.bus,
-	       dev->addr.devid, dev->addr.function);
-	printf(" - vendor:%x device:%x\n", dev->id.vendor_id, dev->id.device_id);
-
-	pci_dev_count ++;
-	return 0;
-}
-
-static void
-blacklist_all_devices(void)
-{
-	struct rte_pci_device *dev = NULL;
-	unsigned i = 0;
-	char pci_addr_str[16];
-
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
-			dev->addr.domain, dev->addr.bus, dev->addr.devid,
-			dev->addr.function);
-		if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,
-				pci_addr_str) < 0) {
-			printf("Error: cannot blacklist <%s>", pci_addr_str);
-			break;
-		}
-		i++;
-	}
-	printf("%u devices blacklisted\n", i);
-}
-
-/* clear devargs list that was modified by the test */
-static void free_devargs_list(void)
-{
-	struct rte_devargs *devargs;
-
-	while (!TAILQ_EMPTY(&devargs_list)) {
-		devargs = TAILQ_FIRST(&devargs_list);
-		TAILQ_REMOVE(&devargs_list, devargs, next);
-		free(devargs->args);
-		free(devargs);
-	}
-}
-
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-	TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
-REGISTER_LINKED_RESOURCE(test_pci_sysfs);
-
-static int
-test_pci_setup(void)
-{
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
-	const struct resource *r;
-	int ret;
-
-	r = resource_find("test_pci_sysfs");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_pci_sysfs");
-
-	ret = resource_untar(r);
-	TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
-
-	ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
-	TEST_ASSERT_SUCCESS(ret, "failed to setenv");
-
-	/* Unregister original devices & drivers lists */
-	while (!TAILQ_EMPTY(&pci_driver_list)) {
-		dr = TAILQ_FIRST(&pci_driver_list);
-		rte_eal_pci_unregister(dr);
-		TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
-	}
-
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
-	}
-
-	ret = rte_eal_pci_scan();
-	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
-	rte_eal_pci_dump(stdout);
-
-	return 0;
-}
-
-static int
-test_pci_cleanup(void)
-{
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
-	const struct resource *r;
-	int ret;
-
-	unsetenv("SYSFS_PCI_DEVICES");
-
-	r = resource_find("test_pci_sysfs");
-	TEST_ASSERT_NOT_NULL(r, "missing resource test_pci_sysfs");
-
-	ret = resource_rm_by_tar(r);
-	TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
-
-	/*
-	 * FIXME: there is no API in DPDK to free a rte_pci_device so we
-	 * cannot free the devices in the right way. Let's assume that we
-	 * don't care for tests.
-	 */
-	while (!TAILQ_EMPTY(&pci_device_list)) {
-		dev = TAILQ_FIRST(&pci_device_list);
-		TAILQ_REMOVE(&pci_device_list, dev, next);
-	}
-
-	/* Restore original devices & drivers lists */
-	while (!TAILQ_EMPTY(&real_pci_driver_list)) {
-		dr = TAILQ_FIRST(&real_pci_driver_list);
-		TAILQ_REMOVE(&real_pci_driver_list, dr, next);
-		rte_eal_pci_register(dr);
-	}
-
-	while (!TAILQ_EMPTY(&real_pci_device_list)) {
-		dev = TAILQ_FIRST(&real_pci_device_list);
-		TAILQ_REMOVE(&real_pci_device_list, dev, next);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
-	}
-
-	return 0;
-}
-
-static int
-test_pci_blacklist(void)
-{
-	struct rte_devargs_list save_devargs_list;
-
-	printf("Dump all devices\n");
-	TEST_ASSERT(TAILQ_EMPTY(&pci_driver_list),
-			"pci_driver_list not empty");
-
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
-
-	pci_dev_count = 0;
-	printf("Scan bus\n");
-	rte_eal_pci_probe();
-
-	if (pci_dev_count == 0) {
-		printf("no device detected\n");
-		return -1;
-	}
-
-	/* save the real devargs_list */
-	save_devargs_list = devargs_list;
-	TAILQ_INIT(&devargs_list);
-
-	blacklist_all_devices();
-
-	pci_dev_count = 0;
-	printf("Scan bus with all devices blacklisted\n");
-	rte_eal_pci_probe();
-
-	free_devargs_list();
-	devargs_list = save_devargs_list;
-
-	if (pci_dev_count != 0) {
-		printf("not all devices are blacklisted\n");
-		return -1;
-	}
-
-	test_pci_run = 1;
-
-	rte_eal_pci_unregister(&my_driver);
-	rte_eal_pci_unregister(&my_driver2);
-
-	return 0;
-}
-
-static int test_pci_sysfs(void)
-{
-	const char *orig;
-	const char *newpath;
-	int ret;
-
-	orig = pci_get_sysfs_path();
-	ret = setenv("SYSFS_PCI_DEVICES", "My Documents", 1);
-	TEST_ASSERT_SUCCESS(ret, "Failed setenv to My Documents");
-
-	newpath = pci_get_sysfs_path();
-	TEST_ASSERT(!strcmp(newpath, "My Documents"),
-			"pci_get_sysfs_path() should return 'My Documents' "
-			"but gives %s", newpath);
-
-	ret = setenv("SYSFS_PCI_DEVICES", orig, 1);
-	TEST_ASSERT_SUCCESS(ret, "Failed setenv back to '%s'", orig);
-
-	newpath = pci_get_sysfs_path();
-	TEST_ASSERT(!strcmp(orig, newpath),
-			"pci_get_sysfs_path returned unexpected path: "
-			"%s (expected: %s)", newpath, orig);
-	return 0;
-}
-
-int
-test_pci(void)
-{
-	if (test_pci_sysfs())
-		return -1;
-
-	if (test_pci_setup())
-		return -1;
-
-	if (test_pci_blacklist())
-		return -1;
-
-	if (test_pci_cleanup())
-		return -1;
-
-	return 0;
-}
-
-REGISTER_TEST_COMMAND(pci_autotest, test_pci);
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
deleted file mode 100644
index 2f9c1da..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
+++ /dev/null
@@ -1 +0,0 @@
-0x020000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
deleted file mode 100644
index 7752421cf13a5aa00a28eaee02cac2add9ce5566..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 64
zcmZo`_$|QBBEZ1Nz`(@7(7?dMz;S^A2oxWHNCpNT2LUi2#BOU~22l(SV3L7>8>k5Y
DD^Ld(

diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
deleted file mode 100644
index 900731f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
+++ /dev/null
@@ -1 +0,0 @@
-64
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
deleted file mode 100644
index 48a6290..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
+++ /dev/null
@@ -1 +0,0 @@
-0x1234
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
deleted file mode 100644
index 900731f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
+++ /dev/null
@@ -1 +0,0 @@
-64
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
deleted file mode 100644
index d00491f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
deleted file mode 100644
index 573541a..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
deleted file mode 100644
index f4c76ed..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
+++ /dev/null
@@ -1 +0,0 @@
-pci:v00008086d000010FBsv00008086sd00000003bc02sc00i00
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
deleted file mode 100644
index d00491f..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
deleted file mode 100644
index 3a2e3f4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
+++ /dev/null
@@ -1 +0,0 @@
--1
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
deleted file mode 100644
index f388929..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
+++ /dev/null
@@ -1,13 +0,0 @@
-0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x000000000000e020 0x000000000000e03f 0x0000000000040101
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
deleted file mode 100644
index 573541a..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
deleted file mode 100644
index 4b9026d..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
+++ /dev/null
@@ -1 +0,0 @@
-63
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
deleted file mode 100644
index 89a932c..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
+++ /dev/null
@@ -1 +0,0 @@
-0x0003
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
deleted file mode 100644
index 1dbe34d..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
+++ /dev/null
@@ -1,6 +0,0 @@
-DRIVER=ixgbe
-PCI_CLASS=20000
-PCI_ID=8086:10FB
-PCI_SUBSYS_ID=8086:0003
-PCI_SLOT_NAME=0000:01:00.0
-MODALIAS=pci:v00008086d000010FBsv00008086sd00000003bc02sc00i00
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
deleted file mode 100644
index 22dd936..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
+++ /dev/null
@@ -1 +0,0 @@
-0x100000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
deleted file mode 100644
index f61bbe6..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
+++ /dev/null
@@ -1 +0,0 @@
-0xabcd
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
deleted file mode 100644
index f388929..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
+++ /dev/null
@@ -1,13 +0,0 @@
-0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x000000000000e020 0x000000000000e03f 0x0000000000040101
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
deleted file mode 100644
index f61bbe6..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
+++ /dev/null
@@ -1 +0,0 @@
-0xabcd
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
deleted file mode 100644
index 4321b81..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0002
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
deleted file mode 100644
index 4321b81..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0002
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
deleted file mode 100644
index 22dd936..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
+++ /dev/null
@@ -1 +0,0 @@
-0x100000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
deleted file mode 100644
index ccaa498..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
+++ /dev/null
@@ -1 +0,0 @@
-0x4444
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
deleted file mode 100644
index f388929..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
+++ /dev/null
@@ -1,13 +0,0 @@
-0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x000000000000e020 0x000000000000e03f 0x0000000000040101
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
-0x0000000000000000 0x0000000000000000 0x0000000000000000
-0x0000000000000000 0x0000000000000000 0x0000000000000000
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
deleted file mode 100644
index ccaa498..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
+++ /dev/null
@@ -1 +0,0 @@
-0x4444
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
diff --git a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor b/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor
deleted file mode 100644
index 446afb4..0000000
--- a/test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor
+++ /dev/null
@@ -1 +0,0 @@
-0x0001
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 2/7] pci: split match and probe
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 1/7] test: remove pci tests Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 3/7] pci: remove loop over drivers in device detach Gaetan Rivet
                                 ` (5 subsequent siblings)
  7 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Refactor the match logic as a single function.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/common/eal_common_pci.c | 176 ++++++++++++++++++---------------
 1 file changed, 98 insertions(+), 78 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 1ab92c9..83a81c4 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -154,73 +154,108 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 /*
- * If vendor/device ID match, call the probe() function of the
- * driver.
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	1 for successful match
+ *	0 for unsuccessful match
  */
 static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+	      const struct rte_pci_device *pci_dev)
 {
-	int ret;
 	const struct rte_pci_id *id_table;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
+		return 1;
+	}
 
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
+	return 0;
+}
 
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
+/*
+ * If vendor/device ID match, call the probe() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_pci_addr *loc;
 
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio or VFIO */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
+	loc = &dev->addr;
 
-		/* reference driver structure */
-		dev->driver = dr;
+	/* The device is not blacklisted; Check if driver supports it */
+	if (!rte_pci_match(dr, dev)) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			dr->driver.name);
+		return 1;
+	}
 
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret) {
-			dev->driver = NULL;
-			if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-				rte_eal_pci_unmap_device(dev);
-		}
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
+	}
 
-		return ret;
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+		dev->id.device_id, dr->driver.name);
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	/* reference driver structure */
+	dev->driver = dr;
+
+	/* call the driver probe() function */
+	ret = dr->probe(dr, dev);
+	if (ret) {
+		dev->driver = NULL;
+		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+			rte_eal_pci_unmap_device(dev);
+	}
+
+	return ret;
 }
 
 /*
@@ -231,51 +266,36 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
-	const struct rte_pci_id *id_table;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
+	if (!rte_pci_match(dr, dev)) {
+		/* Device and driver don't match */
+		return 1;
+	}
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	loc = &dev->addr;
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
 
-		if (dr->remove && (dr->remove(dev) < 0))
-			return -1;	/* negative value is an error */
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
 
-		/* clear driver structure */
-		dev->driver = NULL;
+	if (dr->remove && (dr->remove(dev) < 0))
+		return -1;	/* negative value is an error */
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
-			rte_eal_pci_unmap_device(dev);
+	/* clear driver structure */
+	dev->driver = NULL;
 
-		return 0;
-	}
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
 
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	return 0;
 }
 
 /*
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 3/7] pci: remove loop over drivers in device detach
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 1/7] test: remove pci tests Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 2/7] pci: split match and probe Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 4/7] pci: add bus driver Gaetan Rivet
                                 ` (4 subsequent siblings)
  7 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain

From: Shreyansh Jain <shreyansh.jain@nxp.com>

rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

Removing pci_detach_all_drivers and restructuring rte_eal_pci_detach
and rte_eal_pci_detach_dev to work without looping over driver list.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/common/eal_common_pci.c | 45 +++++++---------------------------
 1 file changed, 9 insertions(+), 36 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 83a81c4..498a3bb 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -263,19 +263,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
+rte_eal_pci_detach_dev(struct rte_pci_device *dev)
 {
 	struct rte_pci_addr *loc;
+	struct rte_pci_driver *dr;
 
-	if ((dr == NULL) || (dev == NULL))
+	if (dev == NULL)
 		return -EINVAL;
 
-	if (!rte_pci_match(dr, dev)) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
+	dr = dev->driver;
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -330,33 +326,6 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 }
 
 /*
- * If vendor/device ID match, call the remove() function of all
- * registered driver for the given device. Return -1 if initialization
- * failed, return 1 if no driver is found for this device.
- */
-static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
-{
-	struct rte_pci_driver *dr = NULL;
-	int rc = 0;
-
-	if (dev == NULL)
-		return -1;
-
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_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;
-}
-
-/*
  * Find the pci device specified by pci address, then invoke probe function of
  * the driver of the devive.
  */
@@ -409,9 +378,13 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = rte_eal_pci_detach_dev(dev);
 		if (ret < 0)
+			/* negative value is an error */
 			goto err_return;
+		if (ret > 0)
+			/* positive value means driver doesn't support it */
+			continue;
 
 		TAILQ_REMOVE(&pci_device_list, dev, next);
 		free(dev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 4/7] pci: add bus driver
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
                                 ` (2 preceding siblings ...)
  2017-04-11 11:07               ` [PATCH v13 3/7] pci: remove loop over drivers in device detach Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 5/7] pci: use bus driver for scan/probe Gaetan Rivet
                                 ` (3 subsequent siblings)
  7 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain, Thomas Monjalon

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

EAL continues to have direct PCI init/scan calls as well. These would be
removed in subsequent patches to enable bus only PCI devices.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
Reviewed-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  2 ++
 lib/librte_eal/common/eal_common_pci.c  | 36 +++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_private.h     | 35 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_pci.h | 30 +++++++++++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  3 +++
 5 files changed, 106 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 16a1743..6ef8781 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -87,6 +87,8 @@
  * enabling bus master.
  */
 
+extern struct rte_pci_bus rte_pci_bus;
+
 /* Map pci device */
 int
 rte_eal_pci_map_device(struct rte_pci_device *dev)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 498a3bb..5ac050a 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -72,6 +72,7 @@
 #include <rte_errno.h>
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -88,6 +89,8 @@ struct pci_driver_list pci_driver_list =
 struct pci_device_list pci_device_list =
 	TAILQ_HEAD_INITIALIZER(pci_device_list);
 
+extern struct rte_pci_bus rte_pci_bus;
+
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -489,3 +492,36 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
 	rte_eal_driver_unregister(&driver->driver);
 	TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a device to PCI bus */
+void
+rte_eal_pci_add_device(struct rte_pci_device *pci_dev)
+{
+	TAILQ_INSERT_TAIL(&rte_pci_bus.device_list, pci_dev, next);
+}
+
+/* Insert a device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			  struct rte_pci_device *new_pci_dev)
+{
+	TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+}
+
+/* Remove a device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+	TAILQ_REMOVE(&rte_pci_bus.device_list, pci_dev, next);
+}
+
+struct rte_pci_bus rte_pci_bus = {
+	.bus = {
+		.scan = rte_eal_pci_scan,
+		.probe = rte_eal_pci_probe,
+	},
+	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 8b2d323..47c84df 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -123,6 +123,41 @@ struct rte_pci_driver;
 struct rte_pci_device;
 
 /**
+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function
+ * also updates the bus references of the PCI Device (and the generic device
+ * object embedded within.
+ *
+ * @param pci_dev
+ *	PCI device to add
+ * @return void
+ */
+void rte_eal_pci_add_device(struct rte_pci_device *pci_dev);
+
+/**
+ * Insert a PCI device in the PCI Bus at a particular location in the device
+ * list. It also updates the PCI Bus reference of the new devices to be
+ * inserted.
+ *
+ * @param exist_pci_dev
+ *	Existing PCI device in PCI Bus
+ * @param new_pci_dev
+ *	PCI device to be added before exist_pci_dev
+ * @return void
+ */
+void rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+			       struct rte_pci_device *new_pci_dev);
+
+/**
+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references
+ * in the PCI device object as well as the generic device object.
+ *
+ * @param pci_device
+ *	PCI device to be removed from PCI Bus
+ * @return void
+ */
+void rte_eal_pci_remove_device(struct rte_pci_device *pci_device);
+
+/**
  * Update a pci device object by asking the kernel for the latest information.
  *
  * This function is private to EAL.
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 8557e47..729429f 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include <rte_debug.h>
 #include <rte_interrupts.h>
 #include <rte_dev.h>
+#include <rte_bus.h>
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)	\
+		TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
 	TAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */
 	struct rte_driver driver;               /**< Inherit core driver. */
+	struct rte_pci_bus *bus;                /**< PCI bus reference. */
 	pci_probe_t *probe;                     /**< Device Probe function. */
 	pci_remove_t *remove;                   /**< Device Remove function. */
 	const struct rte_pci_id *id_table;	/**< ID table, NULL terminated. */
 	uint32_t drv_flags;                     /**< Flags contolling handling of device. */
 };
 
+/**
+ * Structure describing the PCI bus
+ */
+struct rte_pci_bus {
+	struct rte_bus bus;               /**< Inherit the generic class */
+	struct rte_pci_device_list device_list;  /**< List of PCI devices */
+	struct rte_pci_driver_list driver_list;  /**< List of PCI drivers */
+};
+
 /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
 #define RTE_PCI_DRV_NEED_MAPPING 0x0001
 /** Device driver supports link state interrupt */
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 7d6f50a..1bd3496 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -54,6 +55,8 @@
  * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
  */
 
+extern struct rte_pci_bus rte_pci_bus;
+
 static int
 pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
 {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 5/7] pci: use bus driver for scan/probe
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
                                 ` (3 preceding siblings ...)
  2017-04-11 11:07               ` [PATCH v13 4/7] pci: add bus driver Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-11 11:07               ` [PATCH v13 6/7] pci: use bus driver for attach/detach Gaetan Rivet
                                 ` (2 subsequent siblings)
  7 siblings, 0 replies; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain, Thomas Monjalon

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
Reviewed-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal.c                 | 14 ----------
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 32 +++++++---------------
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  2 --
 lib/librte_eal/common/eal_common_pci.c          | 26 ++++++++----------
 lib/librte_eal/common/eal_private.h             | 10 -------
 lib/librte_eal/common/include/rte_pci.h         | 19 +++-----------
 lib/librte_eal/linuxapp/eal/eal.c               | 14 ----------
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 35 ++++++++-----------------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  2 --
 9 files changed, 35 insertions(+), 119 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index fae6c7e..7321ac6 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -602,13 +602,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	if (rte_eal_pci_init() < 0) {
-		rte_eal_init_alert("Cannot init PCI\n");
-		rte_errno = EPROTO;
-		rte_atomic32_clear(&run_once);
-		return -1;
-	}
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -667,13 +660,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe()) {
-		rte_eal_init_alert("Cannot probe PCI\n");
-		rte_errno = ENOTSUP;
-		return -1;
-	}
-
 	if (rte_eal_dev_init() < 0)
 		rte_eal_init_alert("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 6ef8781..1e9031c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -315,21 +315,19 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 	}
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+		rte_eal_pci_add_device(dev);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 			else if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -340,8 +338,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_pci_add_device(dev);
 	}
 
 	return 0;
@@ -369,6 +366,10 @@ rte_eal_pci_scan(void)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -662,18 +663,3 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 
 	return ret;
 }
-
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index e1fbebc..ca12d89 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 5ac050a..6f0d4d8 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -84,11 +84,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 extern struct rte_pci_bus rte_pci_bus;
 
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	FOREACH_DRIVER_ON_PCIBUS(dr) {
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -336,6 +331,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+
 	int ret = 0;
 
 	if (addr == NULL)
@@ -347,7 +343,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -377,7 +373,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
@@ -389,7 +385,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 			/* positive value means driver doesn't support it */
 			continue;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_pci_remove_device(dev);
 		free(dev);
 		return 0;
 	}
@@ -419,7 +415,7 @@ rte_eal_pci_probe(void)
 	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
 		probe_all = 1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		probed++;
 
 		/* set devargs in PCI structure */
@@ -472,7 +468,7 @@ rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -481,16 +477,16 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
+	driver->bus = &rte_pci_bus;
 }
 
 /* unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	TAILQ_REMOVE(&rte_pci_bus.driver_list, driver, next);
+	driver->bus = NULL;
 }
 
 /* Add a device to PCI bus */
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 47c84df..280126d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -109,16 +109,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 729429f..5980dd1 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -87,12 +87,6 @@ extern "C" {
 #include <rte_dev.h>
 #include <rte_bus.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -208,8 +202,6 @@ struct rte_pci_device {
 	.subsystem_device_id = PCI_ANY_ID
 #endif
 
-struct rte_pci_driver;
-
 /**
  * Initialisation function for the driver called during PCI probing.
  */
@@ -401,17 +393,14 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
+ * Probe the PCI bus
  *
  * @return
  *   - 0 on success.
- *   - Negative on error.
+ *   - !0 on error.
  */
-int rte_eal_pci_probe(void);
+int
+rte_eal_pci_probe(void);
 
 /**
  * Map the PCI device resources in user space virtual memory address
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index d98d56d..7cf33d6 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -830,13 +830,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	if (rte_eal_pci_init() < 0) {
-		rte_eal_init_alert("Cannot init PCI\n");
-		rte_errno = EPROTO;
-		rte_atomic32_clear(&run_once);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO\n");
@@ -946,13 +939,6 @@ rte_eal_init(int argc, char **argv)
 		return -1;
 	}
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe()) {
-		rte_eal_init_alert("Cannot probe PCI\n");
-		rte_errno = ENOTSUP;
-		return -1;
-	}
-
 	if (rte_eal_dev_init() < 0)
 		rte_eal_init_alert("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 1bd3496..7897e15 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -354,21 +354,19 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+		rte_eal_pci_add_device(dev);
 	} else {
 		struct rte_pci_device *dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
-				rte_eal_device_insert(&dev->device);
+				rte_eal_pci_insert_device(dev2, dev);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -378,8 +376,8 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			}
 			return 0;
 		}
-		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+
+		rte_eal_pci_add_device(dev);
 	}
 
 	return 0;
@@ -455,6 +453,10 @@ rte_eal_pci_scan(void)
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -471,6 +473,7 @@ rte_eal_pci_scan(void)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
+
 		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
@@ -715,19 +718,3 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 
 	return ret;
 }
-
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan() < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	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 d5d05ee..94da1e7 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 6/7] pci: use bus driver for attach/detach
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
                                 ` (4 preceding siblings ...)
  2017-04-11 11:07               ` [PATCH v13 5/7] pci: use bus driver for scan/probe Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-14  8:43                 ` Thomas Monjalon
  2017-04-11 11:07               ` [PATCH v13 7/7] doc: remove deprecation notice for rte_bus Gaetan Rivet
  2017-04-12 16:09               ` [PATCH v13 0/7] rte_bus_pci Stephen Hemminger
  7 siblings, 1 reply; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Signed-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>
---
 lib/librte_eal/common/eal_bus.h         | 45 ++++++++++++++++
 lib/librte_eal/common/eal_common_dev.c  | 57 ++++++++++++++++-----
 lib/librte_eal/common/eal_common_pci.c  | 91 +++++++++++++++++++++++++++++++--
 lib/librte_eal/common/include/rte_bus.h | 29 +++++++++++
 lib/librte_eal/common/include/rte_pci.h | 45 ++++++++++------
 5 files changed, 235 insertions(+), 32 deletions(-)
 create mode 100644 lib/librte_eal/common/eal_bus.h

diff --git a/lib/librte_eal/common/eal_bus.h b/lib/librte_eal/common/eal_bus.h
new file mode 100644
index 0000000..4148f16
--- /dev/null
+++ b/lib/librte_eal/common/eal_bus.h
@@ -0,0 +1,45 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright 2017 6WIND S.A.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of 6WIND S.A. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _EAL_BUS_H_
+#define _EAL_BUS_H_
+
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+
+/* Private bus list */
+extern struct rte_bus_list rte_bus_list;
+
+#define FOREACH_BUS(bus_p)	TAILQ_FOREACH(bus_p, &rte_bus_list, next)
+
+#endif /* _EAL_BUS_H_ */
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 9889997..d7d1f3d 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,12 +38,14 @@
 #include <sys/queue.h>
 
 #include <rte_dev.h>
+#include <rte_bus.h>
 #include <rte_devargs.h>
 #include <rte_debug.h>
 #include <rte_devargs.h>
 #include <rte_log.h>
 
 #include "eal_private.h"
+#include "eal_bus.h"
 
 /** Global list of device drivers. */
 static struct rte_driver_list dev_driver_list =
@@ -107,23 +109,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL || devargs == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_probe_one(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->attach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" attach.\n", bus->name);
+			continue;
+		}
+		ret = bus->attach(name);
+		if (!ret) /* device successfully attached */
+			return ret;
+		if (ret > 0) /* device not found on bus */
+			continue;
+		else
 			goto err;
+	}
 
-	} else {
-		if (rte_eal_vdev_init(name, devargs))
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_init(name, devargs);
+		if (ret)
 			goto err;
 	}
 
-	return 0;
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -132,21 +148,38 @@ int rte_eal_dev_attach(const char *name, const char *devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-	struct rte_pci_addr addr;
+	int ret = 1;
+	struct rte_bus *bus;
 
 	if (name == NULL) {
 		RTE_LOG(ERR, EAL, "Invalid device provided.\n");
 		return -EINVAL;
 	}
 
-	if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-		if (rte_eal_pci_detach(&addr) < 0)
+	FOREACH_BUS(bus) {
+		if (!bus->detach) {
+			RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+				" detach.\n", bus->name);
+			continue;
+		}
+
+		ret = bus->detach(name);
+		if (!ret) /* device successfully detached */
+			return ret;
+		if (ret > 0) /* device not found on the bus */
+			continue;
+		else
 			goto err;
-	} else {
-		if (rte_eal_vdev_uninit(name))
+	}
+
+	if (ret > 0) {
+		/* In case the device was not found on any bus, search VDEV */
+		ret = rte_eal_vdev_uninit(name);
+		if (ret)
 			goto err;
 	}
-	return 0;
+
+	return ret;
 
 err:
 	RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 6f0d4d8..c5168d8 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -362,19 +362,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+	struct rte_pci_device *dev = NULL;
+	struct rte_pci_driver *drv = NULL;
+	struct rte_pci_addr addr;
+	int ret;
+
+	if (!device_name)
+		return -1;
+
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
+	if (pci_update_device(&addr) < 0)
+		goto err_return;
+
+	FOREACH_DEVICE_ON_PCIBUS(dev) {
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
+			continue;
+
+		FOREACH_DRIVER_ON_PCIBUS(drv) {
+			ret = rte_pci_match(drv, dev);
+			if (ret) {
+				/* Match of device and driver failed */
+				RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match"
+					" the device (%s)\n", drv->driver.name,
+					device_name);
+				continue;
+			}
+
+			RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n",
+				dev->id.vendor_id, dev->id.device_id,
+				drv->driver.name);
+
+			if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+				/* map resources for devices that use
+				 * igb_uio
+				 */
+				ret = rte_eal_pci_map_device(dev);
+				if (ret != 0)
+					goto err_return;
+			}
+
+			/* reference driver structure */
+			dev->driver = drv;
+
+			/* call the driver probe() function */
+			ret = drv->probe(drv, dev);
+			if (ret) {
+				dev->driver = NULL;
+				if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+					rte_eal_pci_unmap_device(dev);
+			}
+			return ret;
+		}
+	}
+
+	return 1;
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", dev->addr.domain, dev->addr.bus,
+			dev->addr.devid, dev->addr.function);
+	return -1;
+}
+
+/*
  * Detach device specified by its pci address.
  */
 int
-rte_eal_pci_detach(const struct rte_pci_addr *addr)
+rte_eal_pci_detach(const char *device_name)
 {
 	struct rte_pci_device *dev = NULL;
-	int ret = 0;
+	struct rte_pci_addr addr;
+	int ret = 1;
 
-	if (addr == NULL)
+	if (!device_name)
 		return -1;
 
+	memset(&addr, 0, sizeof(addr));
+	if (eal_parse_pci_DomBDF(device_name, &addr)) {
+		/* Device doesn't match PCI BDF naming format */
+		return 1;
+	}
+
 	FOREACH_DEVICE_ON_PCIBUS(dev) {
-		if (rte_eal_compare_pci_addr(&dev->addr, addr))
+		if (rte_eal_compare_pci_addr(&dev->addr, &addr))
 			continue;
 
 		ret = rte_eal_pci_detach_dev(dev);
@@ -389,8 +468,8 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		free(dev);
 		return 0;
 	}
-	return -1;
 
+	return ret;
 err_return:
 	RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
 			" cannot be used\n", dev->addr.domain, dev->addr.bus,
@@ -515,6 +594,8 @@ struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_eal_pci_scan,
 		.probe = rte_eal_pci_probe,
+		.attach = rte_eal_pci_attach,
+		.detach = rte_eal_pci_detach,
 	},
 	.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
 	.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 7c36969..e23b9e5 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -82,6 +82,33 @@ typedef int (*rte_bus_scan_t)(void);
 typedef int (*rte_bus_probe_t)(void);
 
 /**
+ * Attach a device to a bus, assuming it is 'connected' to the bus.
+ * A bus is responsible for scanning for devices. Attaching a new device is
+ * for reenabling the device after being detached/removed.
+ *
+ * @param device_name
+ *	Name of the device to attach.
+ *
+ * @return
+ *	0 for successful attach
+ *	!0 for unsuccessful attach (or incorrect device name)
+ */
+typedef int (*rte_bus_attach_t)(const char *device_name);
+
+/**
+ * Detach a named device from a bus. Implementation would check the existence
+ * of device on the bus and detach it.
+ *
+ * @param device_name
+ *	Name of the device to detach
+ *
+ * @return
+ *	0 for successful detaching
+ *	!0 if device not found or can't detach
+ */
+typedef int (*rte_bus_detach_t)(const char *device_name);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -89,6 +116,8 @@ struct rte_bus {
 	const char *name;            /**< Name of the bus */
 	rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 	rte_bus_probe_t probe;       /**< Probe devices on bus */
+	rte_bus_attach_t attach;     /**< Attach a named device */
+	rte_bus_detach_t detach;     /**< Detach a named device */
 };
 
 /**
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 5980dd1..de0641a 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -403,6 +403,36 @@ int
 rte_eal_pci_probe(void);
 
 /**
+ * Search and attach a PCI device to PCI Bus
+ * Implements rte_bus->attach
+ *
+ * @param device_name
+ *	Name of the device to search and attach
+ *
+ * @return
+ *	0 for successful removal of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_attach(const char *device_name);
+
+/**
+ * Search and detach a PCI device from PCI Bus
+ * Implements rte_bus->detach
+ *
+ * @param device_name
+ *	Name of the device to search and detach
+ *
+ * @return
+ *	0 for successful detaching of device
+ *	>0 if device not found on bus
+ *	<0 in case of error in removal.
+ */
+int
+rte_eal_pci_detach(const char *device_name);
+
+/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
@@ -476,21 +506,6 @@ void pci_unmap_resource(void *requested_addr, size_t size);
 int rte_eal_pci_probe_one(const struct rte_pci_addr *addr);
 
 /**
- * Close the single PCI device.
- *
- * Scan the content of the PCI bus, and find the pci device specified by pci
- * address, then call the remove() function for registered driver that has a
- * matching entry in its id_table for discovered device.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to close.
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_detach(const struct rte_pci_addr *addr);
-
-/**
  * Dump the content of the PCI bus.
  *
  * @param f
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* [PATCH v13 7/7] doc: remove deprecation notice for rte_bus
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
                                 ` (5 preceding siblings ...)
  2017-04-11 11:07               ` [PATCH v13 6/7] pci: use bus driver for attach/detach Gaetan Rivet
@ 2017-04-11 11:07               ` Gaetan Rivet
  2017-04-11 11:32                 ` Shreyansh Jain
  2017-04-12 16:09               ` [PATCH v13 0/7] rte_bus_pci Stephen Hemminger
  7 siblings, 1 reply; 146+ messages in thread
From: Gaetan Rivet @ 2017-04-11 11:07 UTC (permalink / raw)
  To: dev; +Cc: Shreyansh Jain

From: Shreyansh Jain <shreyansh.jain@nxp.com>

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 doc/guides/rel_notes/release_17_02.rst | 2 +-
 lib/librte_eal/bsdapp/eal/Makefile     | 2 +-
 lib/librte_eal/linuxapp/eal/Makefile   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 357965a..e9d2e00 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -357,7 +357,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_cmdline.so.2
      librte_cryptodev.so.2
      librte_distributor.so.1
-     librte_eal.so.3
+   + librte_eal.so.4
    + librte_ethdev.so.6
      librte_hash.so.2
      librte_ip_frag.so.1
diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 16791df..a0f9950 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -48,7 +48,7 @@ LDLIBS += -lgcc_s
 
 EXPORT_MAP := rte_eal_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 # specific to bsdapp exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 8624ad2..640afd0 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -37,7 +37,7 @@ ARCH_DIR ?= $(RTE_ARCH)
 EXPORT_MAP := rte_eal_version.map
 VPATH += $(RTE_SDK)/lib/librte_eal/common/arch/$(ARCH_DIR)
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 VPATH += $(RTE_SDK)/lib/librte_eal/common
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 146+ messages in thread

* Re: [PATCH v13 7/7] doc: remove deprecation notice for rte_bus
  2017-04-11 11:07               ` [PATCH v13 7/7] doc: remove deprecation notice for rte_bus Gaetan Rivet
@ 2017-04-11 11:32                 ` Shreyansh Jain
  2017-04-11 11:54                   ` Gaëtan Rivet
  0 siblings, 1 reply; 146+ messages in thread
From: Shreyansh Jain @ 2017-04-11 11:32 UTC (permalink / raw)
  To: Gaetan Rivet; +Cc: dev

Hello Gaetan,

On Tuesday 11 April 2017 04:37 PM, Gaetan Rivet wrote:
> From: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  doc/guides/rel_notes/release_17_02.rst | 2 +-
>  lib/librte_eal/bsdapp/eal/Makefile     | 2 +-
>  lib/librte_eal/linuxapp/eal/Makefile   | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)

[...]

I think you removed the deprecation.rst file from original patch. In 
which case, the headline of the patch is now not correct.

-
Shreyansh

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v13 7/7] doc: remove deprecation notice for rte_bus
  2017-04-11 11:32                 ` Shreyansh Jain
@ 2017-04-11 11:54                   ` Gaëtan Rivet
  0 siblings, 0 replies; 146+ messages in thread
From: Gaëtan Rivet @ 2017-04-11 11:54 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev

Hi Shreyansh,

On Tue, Apr 11, 2017 at 05:02:31PM +0530, Shreyansh Jain wrote:
>Hello Gaetan,
>
>On Tuesday 11 April 2017 04:37 PM, Gaetan Rivet wrote:
>>From: Shreyansh Jain <shreyansh.jain@nxp.com>
>>
>>Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>---
>> doc/guides/rel_notes/release_17_02.rst | 2 +-
>> lib/librte_eal/bsdapp/eal/Makefile     | 2 +-
>> lib/librte_eal/linuxapp/eal/Makefile   | 2 +-
>> 3 files changed, 3 insertions(+), 3 deletions(-)
>
>[...]
>
>I think you removed the deprecation.rst file from original patch. In 
>which case, the headline of the patch is now not correct.
>

Yes you're right, actually the deprecation notice had already been removed.
I wanted to keep the patches the way they were as much as possible
however in order for readers to be able to find the reference in the
original series.

Now that you highlighted this patch, I see that I made an error
by keeping the release note update in the 17.02 file instead of 17.05.

-- 
Gaëtan Rivet
6WIND

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v13 0/7] rte_bus_pci
  2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
                                 ` (6 preceding siblings ...)
  2017-04-11 11:07               ` [PATCH v13 7/7] doc: remove deprecation notice for rte_bus Gaetan Rivet
@ 2017-04-12 16:09               ` Stephen Hemminger
  2017-04-14 12:16                 ` Thomas Monjalon
  7 siblings, 1 reply; 146+ messages in thread
From: Stephen Hemminger @ 2017-04-12 16:09 UTC (permalink / raw)
  To: Gaetan Rivet; +Cc: dev

On Tue, 11 Apr 2017 13:07:27 +0200
Gaetan Rivet <gaetan.rivet@6wind.com> wrote:

> I have rebased the work done by Shreyansh and Thomas to follow
> the bus abstraction introduced in v17.02 for the PCI bus
> implementation.
> This series is only a partial version of the previous one, because
> some of the patches have already been integrated, and others still
> need rework.
> 
> Additionally, Jan Blunck sent this RFC:
> 
> [RFC] eal: use busname and devargs to attach devices
> 
> That has not been considered for this version as it had not yet spawned
> a discussion.
> 
> changes in v13:
>   - Removed the PCI tests. They cannot follow the bus implementation
>     anymore, and it is an opportunity to update their original design.
>   - Changed the rte_pci_match function semantic to match its name.
>   - Made the rte_pci_match function private.
>   - Made the rte_bus_list private
>   - Made rte_eal_pci_add_device,
>          rte_eal_pci_insert_device,
>          rte_eal_pci_remove_device,
>      functions private.
> 
> Additional work is needed:
>   - The PCI bus should be moved to the relevant bus sub-directory.
>   - The documentation must be updated.
> 
> But this version should allow for the PCI bus implementation to be
> integrated in v17.05-rc2.
> 
> Gaetan Rivet (1):
>   test: remove pci tests
> 
> Shreyansh Jain (6):
>   pci: split match and probe
>   pci: remove loop over drivers in device detach
>   pci: add bus driver
>   pci: use bus driver for scan/probe
>   pci: use bus driver for attach/detach
>   doc: remove deprecation notice for rte_bus
> 
>  MAINTAINERS                                        |   2 -
>  doc/guides/rel_notes/release_17_02.rst             |   2 +-
>  lib/librte_eal/bsdapp/eal/Makefile                 |   2 +-
>  lib/librte_eal/bsdapp/eal/eal.c                    |  14 -
>  lib/librte_eal/bsdapp/eal/eal_pci.c                |  34 +-
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map      |   2 -
>  lib/librte_eal/common/eal_bus.h                    |  45 +++
>  lib/librte_eal/common/eal_common_dev.c             |  57 +++-
>  lib/librte_eal/common/eal_common_pci.c             | 362 +++++++++++++--------
>  lib/librte_eal/common/eal_private.h                |  41 ++-
>  lib/librte_eal/common/include/rte_bus.h            |  29 ++
>  lib/librte_eal/common/include/rte_pci.h            |  94 ++++--
>  lib/librte_eal/linuxapp/eal/Makefile               |   2 +-
>  lib/librte_eal/linuxapp/eal/eal.c                  |  14 -
>  lib/librte_eal/linuxapp/eal/eal_pci.c              |  38 +--
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map    |   2 -
>  test/test/Makefile                                 |   2 -
>  test/test/test.h                                   |   3 -
>  test/test/test_mp_secondary.c                      |  17 -
>  test/test/test_pci.c                               | 322 ------------------
>  .../bus/pci/devices/0000:01:00.0/class             |   1 -
>  .../bus/pci/devices/0000:01:00.0/config            | Bin 64 -> 0 bytes
>  .../devices/0000:01:00.0/consistent_dma_mask_bits  |   1 -
>  .../bus/pci/devices/0000:01:00.0/device            |   1 -
>  .../bus/pci/devices/0000:01:00.0/dma_mask_bits     |   1 -
>  .../bus/pci/devices/0000:01:00.0/enable            |   1 -
>  .../bus/pci/devices/0000:01:00.0/irq               |   1 -
>  .../bus/pci/devices/0000:01:00.0/modalias          |   1 -
>  .../bus/pci/devices/0000:01:00.0/msi_bus           |   1 -
>  .../bus/pci/devices/0000:01:00.0/numa_node         |   1 -
>  .../bus/pci/devices/0000:01:00.0/resource          |  13 -
>  .../bus/pci/devices/0000:01:00.0/sriov_numvfs      |   1 -
>  .../bus/pci/devices/0000:01:00.0/sriov_totalvfs    |   1 -
>  .../bus/pci/devices/0000:01:00.0/subsystem_device  |   1 -
>  .../bus/pci/devices/0000:01:00.0/subsystem_vendor  |   1 -
>  .../bus/pci/devices/0000:01:00.0/uevent            |   6 -
>  .../bus/pci/devices/0000:01:00.0/vendor            |   1 -
>  .../bus/pci/devices/0000:01:02.0/class             |   1 -
>  .../bus/pci/devices/0000:01:02.0/device            |   1 -
>  .../bus/pci/devices/0000:01:02.0/resource          |  13 -
>  .../bus/pci/devices/0000:01:02.0/subsystem_device  |   1 -
>  .../bus/pci/devices/0000:01:02.0/subsystem_vendor  |   1 -
>  .../bus/pci/devices/0000:01:02.0/vendor            |   1 -
>  .../bus/pci/devices/0000:02:ab.0/class             |   1 -
>  .../bus/pci/devices/0000:02:ab.0/device            |   1 -
>  .../bus/pci/devices/0000:02:ab.0/resource          |  13 -
>  .../bus/pci/devices/0000:02:ab.0/subsystem_device  |   1 -
>  .../bus/pci/devices/0000:02:ab.0/subsystem_vendor  |   1 -
>  .../bus/pci/devices/0000:02:ab.0/vendor            |   1 -
>  49 files changed, 478 insertions(+), 675 deletions(-)
>  create mode 100644 lib/librte_eal/common/eal_bus.h
>  delete mode 100644 test/test/test_pci.c
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/class
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/config
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/consistent_dma_mask_bits
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/device
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/dma_mask_bits
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/enable
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/irq
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/modalias
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/msi_bus
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/numa_node
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/resource
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_numvfs
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/sriov_totalvfs
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_device
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/subsystem_vendor
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/uevent
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:00.0/vendor
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/class
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/device
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/resource
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_device
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/subsystem_vendor
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:01:02.0/vendor
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/class
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/device
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/resource
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_device
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/subsystem_vendor
>  delete mode 100644 test/test/test_pci_sysfs/bus/pci/devices/0000:02:ab.0/vendor
> 

Looks good. Removing dependencies on PCI is part of the roadblocks in supporting Hyper-V/VMBUS
and Xen netfront properly.

Acked-by: Stephen Hemminger <stephen@networkplumber.org>

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v13 6/7] pci: use bus driver for attach/detach
  2017-04-11 11:07               ` [PATCH v13 6/7] pci: use bus driver for attach/detach Gaetan Rivet
@ 2017-04-14  8:43                 ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-04-14  8:43 UTC (permalink / raw)
  To: Gaetan Rivet, Shreyansh Jain, Jan Blunck; +Cc: dev

2017-04-11 13:07, Gaetan Rivet:
> +       if (ret > 0) {
> +               /* In case the device was not found on any bus, search VDEV */
> +               ret = rte_eal_vdev_init(name, devargs);

I think we should avoid to directly call a vdev function.

Anyway, Jan is preparing a new series for attach/detach rework.
Let's discuss it for 17.08.

The series will be applied without this patch.

^ permalink raw reply	[flat|nested] 146+ messages in thread

* Re: [PATCH v13 0/7] rte_bus_pci
  2017-04-12 16:09               ` [PATCH v13 0/7] rte_bus_pci Stephen Hemminger
@ 2017-04-14 12:16                 ` Thomas Monjalon
  0 siblings, 0 replies; 146+ messages in thread
From: Thomas Monjalon @ 2017-04-14 12:16 UTC (permalink / raw)
  To: Gaetan Rivet, shreyansh.jain, Jan Blunck; +Cc: dev, Stephen Hemminger

2017-04-12 09:09, Stephen Hemminger:
> On Tue, 11 Apr 2017 13:07:27 +0200
> Gaetan Rivet <gaetan.rivet@6wind.com> wrote:
> 
> > I have rebased the work done by Shreyansh and Thomas to follow
> > the bus abstraction introduced in v17.02 for the PCI bus
> > implementation.
> > This series is only a partial version of the previous one, because
> > some of the patches have already been integrated, and others still
> > need rework.
> > 
> > Additionally, Jan Blunck sent this RFC:
> > 
> > [RFC] eal: use busname and devargs to attach devices
> > 
> > That has not been considered for this version as it had not yet spawned
> > a discussion.
> > 
> > changes in v13:
> >   - Removed the PCI tests. They cannot follow the bus implementation
> >     anymore, and it is an opportunity to update their original design.
> >   - Changed the rte_pci_match function semantic to match its name.
> >   - Made the rte_pci_match function private.
> >   - Made the rte_bus_list private
> >   - Made rte_eal_pci_add_device,
> >          rte_eal_pci_insert_device,
> >          rte_eal_pci_remove_device,
> >      functions private.
> > 
> > Additional work is needed:
> >   - The PCI bus should be moved to the relevant bus sub-directory.
> >   - The documentation must be updated.
> > 
> > But this version should allow for the PCI bus implementation to be
> > integrated in v17.05-rc2.
> > 
> > Gaetan Rivet (1):
> >   test: remove pci tests
> > 
> > Shreyansh Jain (6):
> >   pci: split match and probe
> >   pci: remove loop over drivers in device detach
> >   pci: add bus driver
> >   pci: use bus driver for scan/probe
> >   pci: use bus driver for attach/detach
> >   doc: remove deprecation notice for rte_bus
> 
> Looks good. Removing dependencies on PCI is part of the roadblocks in supporting Hyper-V/VMBUS
> and Xen netfront properly.
> 
> Acked-by: Stephen Hemminger <stephen@networkplumber.org>

Applied without the attach/detach patch because it requires more work.
Thanks everybody

^ permalink raw reply	[flat|nested] 146+ messages in thread

end of thread, other threads:[~2017-04-14 12:16 UTC | newest]

Thread overview: 146+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-16 15:38 [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 1/8] eal/bus: introduce bus abstraction Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 2/8] test: add basic bus infrastructure tests Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 3/8] pci: split match and probe function Shreyansh Jain
2017-01-16 18:24   ` Stephen Hemminger
2017-01-17 10:10     ` Shreyansh Jain
2017-01-16 19:53   ` Ferruh Yigit
2017-01-17  4:54     ` Shreyansh Jain
2017-01-17  9:58       ` Ferruh Yigit
2017-01-17 10:14         ` Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 4/8] eal/bus: support for scanning of bus Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 5/8] eal: introduce bus scan and probe in EAL Shreyansh Jain
2017-01-16 19:58   ` Ferruh Yigit
2017-01-17  5:03     ` Shreyansh Jain
2017-01-17 23:04       ` Thomas Monjalon
2017-01-17 10:13     ` Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 6/8] test: update bus and pci unit test cases Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 7/8] eal: enable PCI bus Shreyansh Jain
2017-01-16 19:58   ` Ferruh Yigit
2017-01-17  5:04     ` Shreyansh Jain
2017-01-17 10:11     ` Shreyansh Jain
2017-01-16 15:38 ` [PATCH v6 8/8] eal: enable hotplugging of devices on bus Shreyansh Jain
2017-01-17  7:24   ` Shreyansh Jain
2017-01-16 18:27 ` [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model Stephen Hemminger
2017-01-17  5:08   ` Shreyansh Jain
2017-01-17  5:09   ` Shreyansh Jain
2017-01-17 10:09 ` [PATCH v7 0/9] " Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 2/9] test: add basic bus infrastructure tests Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 3/9] pci: split match and probe function Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 4/9] eal/bus: support for scanning of bus Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 7/9] test: update bus and pci unit test cases Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 8/9] eal: enable PCI bus Shreyansh Jain
2017-01-17 10:09   ` [PATCH v7 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
2017-01-17 10:47     ` Ferruh Yigit
2017-01-17 11:04       ` Shreyansh Jain
2017-01-17 13:40         ` Shreyansh Jain
2017-01-17 10:50   ` [PATCH v7 0/9] Introducing EAL Bus-Device-Driver Model Ferruh Yigit
2017-01-17 13:37   ` [PATCH v8 " Shreyansh Jain
2017-01-17 13:37     ` [PATCH v8 1/9] eal/bus: introduce bus abstraction Shreyansh Jain
2017-01-17 23:19       ` Thomas Monjalon
2017-01-18  5:12         ` Shreyansh Jain
2017-01-17 13:37     ` [PATCH v8 2/9] test: add basic bus infrastructure tests Shreyansh Jain
2017-01-17 23:23       ` Thomas Monjalon
2017-01-18  5:13         ` Shreyansh Jain
2017-01-18  6:56           ` Shreyansh Jain
2017-01-18  7:28             ` Thomas Monjalon
2017-01-18  8:42               ` Shreyansh Jain
2017-01-17 13:37     ` [PATCH v8 3/9] pci: split match and probe function Shreyansh Jain
2017-01-17 23:31       ` Thomas Monjalon
2017-01-18  6:17         ` Shreyansh Jain
2017-01-18  7:31           ` Thomas Monjalon
2017-01-17 13:37     ` [PATCH v8 4/9] eal/bus: support for scanning of bus Shreyansh Jain
2017-01-17 23:37       ` Thomas Monjalon
2017-01-18  5:15         ` Shreyansh Jain
2017-01-18  7:32           ` Thomas Monjalon
2017-01-17 13:37     ` [PATCH v8 5/9] eal/bus: introduce support for bus probing Shreyansh Jain
2017-01-17 23:38       ` Thomas Monjalon
2017-01-17 13:37     ` [PATCH v8 6/9] eal: integrate bus scan and probe with EAL Shreyansh Jain
2017-01-17 23:44       ` Thomas Monjalon
2017-01-17 13:37     ` [PATCH v8 7/9] test: update bus and pci unit test cases Shreyansh Jain
2017-01-17 23:46       ` Thomas Monjalon
2017-01-17 13:37     ` [PATCH v8 8/9] eal: enable PCI bus Shreyansh Jain
2017-01-17 23:57       ` Thomas Monjalon
2017-01-17 13:37     ` [PATCH v8 9/9] eal: enable hotplugging of devices on bus Shreyansh Jain
2017-01-17 15:17       ` Ferruh Yigit
2017-01-18 10:37     ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
2017-01-18 10:46         ` Thomas Monjalon
2017-01-18 10:52           ` Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 02/12] test: add basic bus infrastructure tests Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 03/12] pci: split match and probe function Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 04/12] eal: remove loop over drivers in device detach Shreyansh Jain
2017-01-18 10:41         ` Shreyansh Jain
2017-01-18 11:12         ` Thomas Monjalon
2017-01-18 12:15           ` Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 05/12] eal/bus: support for scanning of bus Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 06/12] eal/bus: introduce support for bus probing Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 07/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 08/12] eal/pci: add support for PCI bus Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 09/12] test: add test cases for scan and probe on BUS Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 10/12] test: add Bus based scan and probe test cases for PCI Shreyansh Jain
2017-01-18 10:37       ` [PATCH v9 11/12] eal: enable PCI bus Shreyansh Jain
2017-01-18 10:38       ` [PATCH v9 12/12] eal: enable hotplugging of devices on bus Shreyansh Jain
2017-01-18 11:10       ` [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
2017-01-18 14:05       ` [PATCH v10 00/13] " Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 01/13] eal/bus: introduce bus abstraction Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 02/13] test: add basic bus infrastructure tests Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 03/13] pci: split match and probe function Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 04/13] eal: remove loop over drivers in device detach Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 05/13] eal/bus: support for scanning of bus Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 06/13] eal/bus: introduce support for bus probing Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 07/13] eal: integrate bus scan and probe with EAL Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 08/13] eal/pci: add support for PCI bus Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 09/13] test: add test cases for scan and probe on BUS Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 10/13] test: add Bus based scan and probe test cases for PCI Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 11/13] eal: enable PCI bus Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 12/13] eal: enable hotplugging of devices on bus Shreyansh Jain
2017-01-18 14:05         ` [PATCH v10 13/13] doc: remove deprecation notice for rte_bus Shreyansh Jain
2017-01-19  4:45         ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 01/13] bus: introduce bus abstraction Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 02/13] bus: add scanning Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 03/13] bus: add probing Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 04/13] app/test: check bus registration Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 05/13] app/test: check bus scan Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 06/13] app/test: check bus probe Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 07/13] pci: split match and probe Thomas Monjalon
2017-02-15 10:45             ` Jan Blunck
2017-02-15 11:22               ` Thomas Monjalon
2017-02-15 11:52                 ` Shreyansh Jain
2017-02-15 11:30               ` Shreyansh Jain
2017-01-19  4:45           ` [PATCH v11 08/13] pci: remove loop over drivers in device detach Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 09/13] pci: add bus driver Thomas Monjalon
2017-02-15 10:42             ` Jan Blunck
2017-02-15 11:20               ` Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 10/13] app/test: add PCI " Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 11/13] pci: use bus driver for scan/probe Thomas Monjalon
2017-01-19  4:45           ` [PATCH v11 12/13] pci: use bus driver for attach/detach Thomas Monjalon
2017-02-15 11:08             ` Jan Blunck
2017-02-15 11:26               ` Thomas Monjalon
2017-02-15 11:39                 ` Jan Blunck
2017-02-15 14:04                   ` [RFC] eal: use busname and devargs to attach devices Jan Blunck
2017-01-19  4:45           ` [PATCH v11 13/13] doc: remove deprecation notice for rte_bus Thomas Monjalon
2017-01-19 17:40             ` Mcnamara, John
2017-01-19  4:50           ` [PATCH v11 00/13] rte_bus + rte_pci_bus Thomas Monjalon
2017-04-07 15:28           ` [PATCH v12 0/5] rte_bus_pci Gaetan Rivet
2017-04-07 15:28             ` [PATCH v12 1/5] pci: split match and probe Gaetan Rivet
2017-04-07 15:28             ` [PATCH v12 2/5] pci: remove loop over drivers in device detach Gaetan Rivet
2017-04-07 15:28             ` [PATCH v12 3/5] pci: add bus driver Gaetan Rivet
2017-04-07 15:28             ` [PATCH v12 4/5] pci: use bus driver for scan/probe Gaetan Rivet
2017-04-07 15:28             ` [PATCH v12 5/5] test: remove pci tests Gaetan Rivet
2017-04-11 11:07             ` [PATCH v13 0/7] rte_bus_pci Gaetan Rivet
2017-04-11 11:07               ` [PATCH v13 1/7] test: remove pci tests Gaetan Rivet
2017-04-11 11:07               ` [PATCH v13 2/7] pci: split match and probe Gaetan Rivet
2017-04-11 11:07               ` [PATCH v13 3/7] pci: remove loop over drivers in device detach Gaetan Rivet
2017-04-11 11:07               ` [PATCH v13 4/7] pci: add bus driver Gaetan Rivet
2017-04-11 11:07               ` [PATCH v13 5/7] pci: use bus driver for scan/probe Gaetan Rivet
2017-04-11 11:07               ` [PATCH v13 6/7] pci: use bus driver for attach/detach Gaetan Rivet
2017-04-14  8:43                 ` Thomas Monjalon
2017-04-11 11:07               ` [PATCH v13 7/7] doc: remove deprecation notice for rte_bus Gaetan Rivet
2017-04-11 11:32                 ` Shreyansh Jain
2017-04-11 11:54                   ` Gaëtan Rivet
2017-04-12 16:09               ` [PATCH v13 0/7] rte_bus_pci Stephen Hemminger
2017-04-14 12:16                 ` Thomas Monjalon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.