All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
@ 2016-12-04 10:11 Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 01/13] eal: define container_of macro Shreyansh Jain
                   ` (14 more replies)
  0 siblings, 15 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

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.

:: 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 context of DPDK EAL:
 - rte_bus, represents a Bus. An implementation of a physical bus would
   instantiate this class.
 - Buses are registered just like a PMD - RTE_REGISTER_BUS()
   `- Thus, implementation for PCI would instantiate a rte_bus, give it a
      name and provide scan/match hooks.
    - Currently, priority of RTE_REGISTER_BUS constructor has been set to
      101 to make sure bus is registered *before* drivers are.
 - Each registered bus is part of a doubly list.
   -- Each device refers to rte_bus on which it belongs
   -- Each driver refers to rte_bus with which it is associated
   -- Device and Drivers lists are part of rte_bus
   -- NO global device/driver list would exist
 - When a PMD wants to register itself, it would 'add' itself to an
   existing bus. Which essentially converts to adding the driver to
   a bus specific driver_list.
 - Bus would perform a scan and 'add' devices scanned to its list.
 - Bus would perform a probe and link devices and drivers on each bus and
   invoking a series of probes
   `-- There are some parallel work for combining scan/probe in EAL [5]
       and also for doing away with a independent scan function all
       together [6].


The view would be almost like:

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> device_list for this bus
                     | device_list----    
                     | scan()       | `-> driver_list for this bus
                     | match()      |
                     | probe()      |
                     |              |
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | *rte_bus    |                     | *rte_bus        |
    | rte_driver  |                     | probe()         |
    |             |                     | remove()        |
    |  devargs    |                     |                 |
    +---||--------+                     +---------|||-----+
        ||                                        '''      
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | PCI specific   | | xxx device    |               |||
 | info (mem,)    | | specific fns  |              / | \
 +----------------+ +---------------+             /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | PCI id table,  |    | <probably,     |    | ....          |
            | other driver   |    |  nothing>      |    +---------------+
            | data           |    |  ...           |
            |  probe()       |    +----------------+
            |  remove()      |
            +----------------+

In continuation to the RFC posted on 17/Nov [9],
A series of patches is being posted which attempts to create:
 1. A basic bus model
    `- define rte_bus and associated methods/helpers
    `- test infrastructure to test the Bus infra
 2. Changes in EAL to support PCI as a bus
    `- a "pci" bus is registered
    `- existing scan/match/probe are modified to allow for bus integration
    `- PCI Device and Driver list, which were global entities, have been
       moved to rte_bus->[device/driver]_list

I have sanity tested this patch over a XeonD X552 available with me, as
well as part of PoC for verifying NXP's DPAA2 PMD (being pushed out in a
separate series). Exhaustive testing is still pending.

:: Brief about Patch Layout ::

0001:      Container_of patch from [3]
0002~0003: Introducing the basic Bus model and associated test case
0004:      Add scan and match callbacks for the Bus and updated test case
0005:      Support insertion of device rather than addition to tail
0006:      Integrate bus scan/match with EAL, without any effective driver
0007:      rte_pci_driver->probe replaced with rte_driver->probe
0008:      Integrate probe of drivers with EAL
0009:      Split the existing PCI probe into match and probe
0010:      Make PCI probe/match work on rte_driver/device rather than
           rte_pci_device/rte_pci_driver
0011:      Patch from Ben [8], part of series [2]
0012~0013: Enable Scan/Match/probe on Bus from EAL and remove unused
           functions and lists 

:: Pending Changes/Caveats ::

0. eth_dev still contains rte_pci_device. I am banking on Jan's patches [1]
   for conversion to a macro (ETH_DEV_PCI_DEV) and subsequent replacement
   of all pci_dev usage in eth_dev.

1. One of the major changes pending, as against proposed in RFC, is the
   removal of eth_driver.
   Being a large change, and independent one, this would be done in a
   separate series of patches. []

2. app/test/test_pci.c is still not modified. It is rendered uncompilable
   as most of the APIs it was calling don't exist anymore. I will push a
   v2 which would include a complete re-write of test_pci (or, if someone
   can help me that, it would be awesome).

3. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   - there was an open question in RFC about where to place the PCI bus
     instance - whether in drivers/bus/... or in lib/librte_bus/... or
     lib/librte_eal/...; This patch uses the last option. But, movement
     only impacts placement of Makefiles. Please convey your reservations
     for current placement.
   - It also impacts the point (8) about priority use in constructor

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

5. There was a suggestion from Jan Blunk about a helper iterator within the
   rte_bus. I will send this out in v2.

6. Cyptodev and VDEV changes are still pending. Jan has already conveyed
   that he would be working on the VDEV part. I will work on the Crypto
   part and target that for v2.

7. The overall layout for driver probing has changed a little.
   earlier, it was:
    rte_eal_init()
     `-> rte_eal_pci_probe() (and parallel for VDEV)
         `-> rte_pci_driver->probe()
             `-> eth_driver->eth_dev_init()

   now, it would be:
    rte_eal_bus_probe()
    `-> bus->prove() (*) <- Iterator for PCI device/driver;
        |                   old rte_eal_pci_probe()
        `-> rte_driver->probe() <- create eth_dev
            `-> rte_pci_driver->probe() <- PMD init; old eth_dev_init

   (*) Buses don't do probe. But in DPDK, EAL was doing this. This patch
       pushes that responsibility a layer down, towards rte_bus.
       See Patch 0008 for more explanantion

       Also, rte_driver->probe() creating eth_dev certainly sounds a little
       wrong - but, I would like to get your opinion on how to lay this
       order of which layer ethernet device corresponds to.
       1) Which layer should allocate eth_dev?
          `-> My take: rte_driver->probe()
       2) which layer should fill the eth_dev?
          `-> My take: rte_xxx_driver->probe()
       3) Is init/uninit better name for rte_xxx_driver()->probe() if all
          they do is initialize the ethernet device?

 8. 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?

:: Some known issues ::

 - Checkpatch is failing on patch 0001
 - app/test/test_pci.c compilation is failing, if enabled. By default it
   seems to be disabled (CONFIG_RTE_APP_TEST_RESOURCE_TAR)
 - Bump to librte_eal version

:: 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

Ben Walker (1):
  pci: Pass rte_pci_addr to functions instead of separate args

Jan Blunck (1):
  eal: define container_of macro

Shreyansh Jain (11):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  eal/bus: add scan and match support
  eal/bus: add support for inserting a device on a bus
  eal: integrate bus scan and probe with EAL
  pci: replace probe and remove handlers with rte_driver
  eal: enable probe and remove from bus infrastructure
  pci: split match and probe function
  eal/pci: generalize args of PCI scan/match towards RTE device/driver
  eal: enable PCI bus
  eal/pci: remove PCI probe and init calls

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 688 ++++++++++++++++++++++++
 app/test/test_pci.c                             |   2 +-
 drivers/net/bnx2x/bnx2x_ethdev.c                |  12 +-
 drivers/net/bnxt/bnxt_ethdev.c                  |   6 +-
 drivers/net/cxgbe/cxgbe_ethdev.c                |   6 +-
 drivers/net/e1000/em_ethdev.c                   |   6 +-
 drivers/net/e1000/igb_ethdev.c                  |  12 +-
 drivers/net/ena/ena_ethdev.c                    |   6 +-
 drivers/net/enic/enic_ethdev.c                  |   6 +-
 drivers/net/fm10k/fm10k_ethdev.c                |   6 +-
 drivers/net/i40e/i40e_ethdev.c                  |   6 +-
 drivers/net/i40e/i40e_ethdev_vf.c               |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                |  12 +-
 drivers/net/mlx4/mlx4.c                         |   6 +-
 drivers/net/mlx5/mlx5.c                         |   4 +-
 drivers/net/nfp/nfp_net.c                       |   6 +-
 drivers/net/qede/qede_ethdev.c                  |  16 +-
 drivers/net/szedata2/rte_eth_szedata2.c         |   6 +-
 drivers/net/virtio/virtio_ethdev.c              |   4 +-
 drivers/net/vmxnet3/vmxnet3_ethdev.c            |   6 +-
 lib/librte_eal/bsdapp/eal/eal.c                 |  12 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  53 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  18 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 285 ++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 335 +++++++-----
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_bus.h         | 262 +++++++++
 lib/librte_eal/common/include/rte_common.h      |  20 +
 lib/librte_eal/common/include/rte_dev.h         |  14 +
 lib/librte_eal/common/include/rte_pci.h         |  32 +-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  12 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  82 +--
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  18 +-
 lib/librte_ether/rte_ethdev.c                   |  16 +-
 lib/librte_ether/rte_ethdev.h                   |   6 +-
 39 files changed, 1717 insertions(+), 291 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] 132+ messages in thread

* [PATCH 01/13] eal: define container_of macro
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 02/13] eal/bus: introduce bus abstraction Shreyansh Jain
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, david.marchand, Jan Blunck, Jan Viktorin,
	Shreyansh Jain

From: Jan Blunck <jblunck@infradead.org>

This macro is based on Jan Viktorin's original patch but also checks the
type of the passed pointer against the type of the member.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
[jblunck@infradead.org: add type checking and __extension__]
Signed-off-by: Jan Blunck <jblunck@infradead.org>
---
 lib/librte_eal/common/include/rte_common.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index db5ac91..8dda3e2 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -331,6 +331,26 @@ rte_bsf32(uint32_t v)
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
 #endif
 
+/**
+ * Return pointer to the wrapping struct instance.
+ *
+ * Example:
+ *
+ *  struct wrapper {
+ *      ...
+ *      struct child c;
+ *      ...
+ *  };
+ *
+ *  struct child *x = obtain(...);
+ *  struct wrapper *w = container_of(x, struct wrapper, c);
+ */
+#ifndef container_of
+#define container_of(ptr, type, member)	__extension__ ({		\
+			typeof(((type *)0)->member) *_ptr = (ptr);	\
+			(type *)(((char *)_ptr) - offsetof(type, member)); })
+#endif
+
 #define _RTE_STR(x) #x
 /** Take a macro value and get a string version of it */
 #define RTE_STR(x) _RTE_STR(x)
-- 
2.7.4

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

* [PATCH 02/13] eal/bus: introduce bus abstraction
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 01/13] eal: define container_of macro Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 03/13] test: add basic bus infrastructure tests Shreyansh Jain
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

This patch introduces the rte_bus abstraction for devices and drivers in
EAL framework. 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' class which rte_driver and rte_device refer.
This way, each device (rte_xxx_device) would have reference to the bus
it is based on. As well as, each driver (rte_xxx_driver) would have link
to the bus and devices on it for servicing.

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> List of rte_bus specific
                     | device_list----    devices
                     |              | `-> List of rte_bus associated
                     |              |     drivers
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | rte_bus     |                     | rte_bus         |
    | rte_driver  |                     | ...             |
    | ...         |                     +---------...-----+
    |             |                               |||
    +---||--------+                               |||
        ||                                        |||
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | ....           | | ....          |               |||
 +----------------+ +---------------+              / | \
                                                  /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | ....           |    | ....           |    | ....          |
            +----------------+    +----------------+    +---------------+

This patch only enables the bus references on rte_driver and rte_driver.
EAL wide global device and driver list continue to exist until an instance
of bus is added in subsequent patches.

This patch also introduces RTE_REGISTER_BUS macro on the lines of
RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
been explicitly set to 101 so as to execute bus registration before PMD.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 192 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 174 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   2 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
 7 files changed, 400 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/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..23fc1c1 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index dfd64aa..79f958d 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..612f64e
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,192 @@
+/*-
+ *   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);
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+	dev->bus = bus;
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev);
+	RTE_VERIFY(dev->bus);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+	dev->bus = NULL;
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+	drv->bus = bus;
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(drv);
+	RTE_VERIFY(drv->bus);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, drv, next);
+	drv->bus = NULL;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_get_bus(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strcmp(bus_name, bus->name)) {
+			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
+			return bus;
+		}
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_INIT(&(bus->driver_list));
+	TAILQ_INIT(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	/* TODO: For each device, call its rte_device->driver->remove()
+	 * and rte_eal_bus_remove_driver()
+	 */
+
+	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_eal_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..f0297a9
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,174 @@
+/*-
+ *   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);
+
+/* Global Bus list */
+extern struct rte_bus_list rte_bus_list;
+
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	struct rte_driver_list driver_list;
+				     /**< List of all drivers on bus */
+	struct rte_device_list device_list;
+				     /**< List of all devices on bus */
+	const char *name;            /**< Name of the bus */
+};
+
+/** @internal
+ * Add a device to a bus.
+ *
+ * @param bus
+ *	Bus on which device is to be added
+ * @param dev
+ *	Device handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
+
+/** @internal
+ * Remove a device from its bus.
+ *
+ * @param dev
+ *	Device handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev);
+
+/** @internal
+ * Associate a driver with a bus.
+ *
+ * @param bus
+ *	Bus on which driver is to be added
+ * @param dev
+ *	Driver handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
+
+/** @internal
+ * Disassociate a driver from its bus.
+ *
+ * @param dev
+ *	Driver handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv);
+
+/**
+ * Register a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_eal_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_eal_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Obtain handle for bus given its name.
+ *
+ * @param bus_name
+ *	Name of the bus handle to search
+ * @return
+ *	Pointer to Bus object if name matches any registered bus object
+ *	NULL, if no matching bus found
+ */
+struct rte_bus *rte_eal_get_bus(const char *bus_name);
+
+/**
+ * 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_eal_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_eal_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 8840380..4004f9a 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 */
 	struct rte_driver *driver;    /**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
@@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
  */
 struct rte_driver {
 	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
+	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
 };
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..c873a7f 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

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

* [PATCH 03/13] test: add basic bus infrastructure tests
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 01/13] eal: define container_of macro Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 02/13] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 04/13] eal/bus: add scan and match support Shreyansh Jain
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

Verification of bus registration, driver registration on a bus.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile   |   2 +-
 app/test/test.h     |   2 +
 app/test/test_bus.c | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 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..760d40a
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,423 @@
+/*-
+ *   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_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
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	const char *name;
+	struct rte_device dev;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus {
+	const char *name;
+	struct rte_bus *bus;
+	struct rte_driver *drivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *devices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct rte_bus busA = {
+	.name = "busA", /* "busA" */
+};
+
+struct rte_bus busB = {
+	.name = "busB", /* "busB */
+};
+
+struct rte_driver driverA = {
+	.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 rte_driver driverB = {
+	.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 dummy_buses[] = {
+	{
+		.name = "busA",
+		.bus = &busA,
+		.drivers = {&driverA, NULL},
+		.devices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.bus = &busB,
+		.drivers = {&driverB, NULL},
+		.devices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus *db;
+	struct rte_bus *bus;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; dummy_buses[i].name; i++) {
+		db = &dummy_buses[i];
+
+		bus = rte_eal_get_bus(db->name);
+		if (!bus)
+			return;
+
+		printf(" Bus: %s\n", bus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			printf("    %s\n", drv->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			printf("    Addr: %p\n", dev);
+			if (dev->driver)
+				printf("    Driver = %s\n", 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);
+		rte_eal_bus_unregister(bus_p);
+		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_eal_bus_unregister(bus_p);
+	}
+
+	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);
+		rte_eal_bus_register(bus_p);
+	}
+
+	dump_device_tree();
+	return 0;
+}
+
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = dummy_buses[i].bus;
+		rte_eal_bus_register(bus);
+		printf("Registered Bus %s\n", dummy_buses[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 dummy_buses */
+		ret = strcmp(bus->name, dummy_buses[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of dummy_buses[i] should be the NULL entry */
+	if (dummy_buses[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       dummy_buses[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_eal_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_eal_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;
+}
+
+/* Positive case: For each driver in dummy_buses, perform
+ * registration
+ */
+static int
+test_driver_registration_on_bus(void)
+{
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv, *drv2;
+
+	/* For each bus on the dummy_buses list:
+	 * 1. get the bus reference
+	 * 2. register all drivers from dummy_buses
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', register all drivers */
+		for (j = 0; dummy_buses[i].drivers[j]; j++) {
+			drv = dummy_buses[i].drivers[j];
+			rte_eal_bus_add_driver(bus, drv);
+		}
+	}
+
+	/* Drivers have been registered. Verify by parsing the list */
+	drv = NULL;
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		j = 0;
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			drv2 = dummy_buses[i].drivers[j++];
+			if (strcmp(drv2->name, drv->name)) {
+				printf("Incorrectly registered drivers."
+				       " Expected: %s; Available: %s\n",
+				       drv2->name, drv->name);
+				return -1;
+			}
+		}
+	}
+
+	printf("Driver registration test successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+static int
+test_driver_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all drivers */
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			rte_eal_bus_remove_driver(drv);
+		}
+	}
+
+	/* Verifying that all drivers have been removed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->driver_list)) {
+			printf("Unable to remove all drivers on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	printf("Unregistration of drivers on all buses is successful.\n");
+	/* All devices from all buses have been removed */
+	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;
+
+	/* Assuming that buses are already registered, register drivers
+	 * with them.
+	 */
+	if (test_driver_registration_on_bus())
+		return -1;
+
+	if (test_driver_unregistration_on_bus())
+		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);
-- 
2.7.4

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

* [PATCH 04/13] eal/bus: add scan and match support
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (2 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 03/13] test: add basic bus infrastructure tests Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 05/13] eal/bus: add support for inserting a device on a bus Shreyansh Jain
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

When a PMD is registred, it will associate itself with a bus.

A bus is responsible for 'scan' of all the devices attached to it.
All the scanned devices are attached to bus specific device_list.

During the probe operation, 'match' of the drivers and devices would
be done.

This patch also adds necessary test framework to test the scan and
match callbacks.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 760d40a..ed95479 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -80,12 +80,32 @@ struct dummy_bus {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+int scan_fn_for_busA(struct rte_bus *bus);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+int scan_fn_for_busB(struct rte_bus *bus);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus busA = {
 	.name = "busA", /* "busA" */
+	.scan = scan_fn_for_busA,
+	.match = generic_match_fn,
 };
 
 struct rte_bus busB = {
 	.name = "busB", /* "busB */
+	.scan = scan_fn_for_busB,
+	.match = generic_match_fn,
 };
 
 struct rte_driver driverA = {
@@ -184,6 +204,92 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the dummy_buses and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that dummy_buses list, register.
+ *
+ * @param bus
+ *	bus to scan againt test entry
+ * @return
+ *	0 for successful scan, even if no devices are found
+ *	!0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+	int i = 0;
+	struct rte_device *dev = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		if (!strcmp(dummy_buses[i].name, bus->name)) {
+			db = &dummy_buses[i];
+			break;
+		}
+	}
+
+	if (!db)
+		return -1;
+
+	/* For all the devices in the device tree (dummy_buses), add device */
+	for (i = 0; db->devices[i]; i++) {
+		dev = &(db->devices[i]->dev);
+		rte_eal_bus_add_device(bus, dev);
+	}
+
+	return 0;
+}
+
+/* @internal
+ * Obtain bus from driver object. Match the address of rte_device object
+ * with all the devices associated with that bus.
+ *
+ * Being a test function, all this does is validate that device object
+ * provided is available on the same bus to which driver is registered.
+ *
+ * @param drv
+ *	driver to which matching is to be performed
+ * @param dev
+ *	device object to match with driver
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct rte_device *dev_p = NULL;
+
+	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
+	 * from bus->device_list.
+	 */
+
+	/* a driver is registered with the bus *before* the scan. */
+	bus = drv->bus;
+	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
+		if (dev == dev_p)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+scan_fn_for_busA(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
+int
+scan_fn_for_busB(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
 static int
 test_bus_setup(void)
 {
@@ -391,6 +497,155 @@ test_driver_unregistration_on_bus(void)
 
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			rte_eal_bus_remove_device(dev);
+		}
+	}
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->device_list)) {
+			printf("Unable to remove all devices on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	/* All devices from all buses have been removed */
+	printf("All devices on all buses unregistered.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful scan
+ *	!0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Call the scan function for each bus */
+		ret = bus->scan(bus);
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * Function to perform 'probe' and link devices and drivers on a bus.
+ * This would work over all the buses registered, and all devices and drivers
+ * registered with it - call match on each pair.
+ * Aim is to test the match_fn for each bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_driver *drv = NULL;
+
+	/* In case of this test:
+	* 1. for each bus in rte_bus_list
+	* 2.  for each device in bus->device_list
+	* 3.   for each driver in bus->driver_list
+	* 4.    call match
+	* 5.    link driver and device
+	* 6. Verify the linkage.
+	*/
+	for (i = 0; dummy_buses[i].name; i++) {
+		/* get bus pointer from dummy_buses itself rather than
+		 * rte_eal_get_bus
+		 */
+		bus = dummy_buses[i].bus;
+
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			TAILQ_FOREACH(drv, &bus->driver_list, next) {
+				if (!bus->match) {
+					printf("Incorrect bus without match "
+					       "fn: (%s).\n", bus->name);
+					return -1;
+				}
+
+				ret = bus->match(drv, dev);
+				if (ret) {
+					printf("Device and driver don't "
+					       "belong to same bus.\n");
+					return -1;
+				}
+				dev->driver = drv;
+
+				/* As match is generic, it always results in
+				 * dev->drv pointing to first driver entry in
+				 * dummy_buses[i]
+				 */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a dummy_buses[i]
+	 * should have same driver (first driver entry of dummy_buses[i])
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		drv = dummy_buses[i].drivers[0];
+
+		for (j = 0; dummy_buses[i].devices[j]; j++) {
+			dev = &(dummy_buses[i].devices[j]->dev);
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
 int
 test_bus(void)
 {
@@ -407,6 +662,16 @@ test_bus(void)
 	if (test_driver_registration_on_bus())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	/* Now that the devices and drivers are registered, perform probe */
+	if (test_probe_on_bus())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_driver_unregistration_on_bus())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 612f64e..2473fe4 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -132,6 +132,9 @@ rte_eal_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan and match implemented */
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->match);
 
 	/* Initialize the driver and device list associated with the bus */
 	TAILQ_INIT(&(bus->driver_list));
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index f0297a9..b41105c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,49 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Global Bus list */
 extern struct rte_bus_list rte_bus_list;
 
+/**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * Successful detection of a device results in rte_device object which is
+ * embedded within the respective device type (rte_pci_device, for example).
+ * Thereafter, PCI specific bus would need to perform
+ * container_of(rte_pci_device) to obtain PCI device object.
+ *
+ * Scan failure of a bus is not treated as exit criteria for application. Scan
+ * for all other buses would still continue.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param bus
+ *	Reference to the bus on which device is added
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*bus_scan_t)(struct rte_bus *bus);
+
+/**
+ * Bus specific match for devices and drivers which can service them.
+ * For each scanned device, rte_driver->probe would be called for driver
+ * specific initialization of the device.
+ *
+ * It is the work of each bus handler to obtain the specific device object
+ * using container_of (or typecasting, as a less preferred way).
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param drv
+ *	Driver object attached to the bus
+ * @param dev
+ *	Device object which is being probed.
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	struct rte_driver_list driver_list;
@@ -66,6 +109,9 @@ struct rte_bus {
 	struct rte_device_list device_list;
 				     /**< List of all devices on bus */
 	const char *name;            /**< Name of the bus */
+	bus_scan_t scan;            /**< Scan for devices attached to bus */
+	bus_match_t match;
+	/**< Match device with drivers associated with the bus */
 };
 
 /** @internal
-- 
2.7.4

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

* [PATCH 05/13] eal/bus: add support for inserting a device on a bus
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (3 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 04/13] eal/bus: add scan and match support Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 06/13] eal: integrate bus scan and probe with EAL Shreyansh Jain
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

Rather than adding a device to tail, a new device might be added to the
list (pivoted on bus) at a predefined position, for example, adding it
order of addressing.

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

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 2473fe4..3be9c77 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -58,6 +58,17 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
 	dev->bus = bus;
 }
 
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev,
+			  struct rte_device *new_dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(old_dev);
+	RTE_VERIFY(new_dev);
+
+	TAILQ_INSERT_BEFORE(old_dev, new_dev, next);
+}
+
 /** @internal
  * Remove a device from its bus.
  */
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index b41105c..d1bd2e8 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -128,6 +128,24 @@ void
 rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
 
 /** @internal
+ * Rather than adding a device to tail, insert at a predefined location.
+ * This is specifically useful for update device cases, or where addition
+ * of devices in the list needs to be ordered (addressing, for example).
+ *
+ * @param bus
+ *	Handle for bus on which device is to be added
+ * @param old_dev
+ *	Existing rte_device object before which new device needs to be added
+ * @param new_dev
+ *	Object for device to be added before old_dev
+ * @return
+ *	void
+ */
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device,
+			  struct rte_device *new_device);
+
+/** @internal
  * Remove a device from its bus.
  *
  * @param dev
-- 
2.7.4

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

* [PATCH 06/13] eal: integrate bus scan and probe with EAL
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (4 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 05/13] eal/bus: add support for inserting a device on a bus Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 07/13] pci: replace probe and remove handlers with rte_driver Shreyansh Jain
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

Still a dummy implementation as no real bus driver exists. This adds calls
from EAL to bus specific scan, match functions.
Once driver->probe is in place, and a bus handler has been installed,
the code would become effective.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  7 +++++++
 lib/librte_eal/common/eal_common_bus.c  | 30 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h | 19 +++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c       |  7 +++++++
 4 files changed, 63 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 35e3117..30afc6b 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>
@@ -580,6 +581,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -616,6 +620,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 3be9c77..67b808b 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -173,6 +173,36 @@ rte_eal_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_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Match driver<->device and call driver->probe() */
+int
+rte_eal_bus_probe(void)
+{
+	/* Until driver->probe is available, this is dummy implementation */
+	return 0;
+}
+
 /* dump one bus info */
 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 d1bd2e8..9bd8650 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -209,6 +209,25 @@ void rte_eal_bus_unregister(struct rte_bus *bus);
  */
 struct rte_bus *rte_eal_get_bus(const char *bus_name);
 
+/** @internal
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);
+
+/** @internal
+ * For each device on the bus, perform a driver 'match' and call the
+ * driver's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_eal_bus_probe(void);
+
 /**
  * Dump information of all the buses registered with EAL.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 2075282..01d0cee 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>
@@ -847,6 +848,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -887,6 +891,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
-- 
2.7.4

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

* [PATCH 07/13] pci: replace probe and remove handlers with rte_driver
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (5 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 06/13] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-08 17:50   ` Ferruh Yigit
  2016-12-04 10:11 ` [PATCH 08/13] eal: enable probe and remove from bus infrastructure Shreyansh Jain
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

rte_pci_driver probe/remove callback are replaced with the rte_driver
based probe/remove. This patch changes all the PCI drivers which reference
rte_pci_driver->probe/remove.

rte_pci_driver continues to have probe/remove callback which would be used
once eth_driver is removed in later patches.

Only changes to PCI are done. VDEV changes require a different
model because of arguments being passed to vdev->probe/remove.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 drivers/net/bnx2x/bnx2x_ethdev.c        | 12 ++++++++----
 drivers/net/bnxt/bnxt_ethdev.c          |  6 ++++--
 drivers/net/cxgbe/cxgbe_ethdev.c        |  6 ++++--
 drivers/net/e1000/em_ethdev.c           |  6 ++++--
 drivers/net/e1000/igb_ethdev.c          | 12 ++++++++----
 drivers/net/ena/ena_ethdev.c            |  6 ++++--
 drivers/net/enic/enic_ethdev.c          |  6 ++++--
 drivers/net/fm10k/fm10k_ethdev.c        |  6 ++++--
 drivers/net/i40e/i40e_ethdev.c          |  6 ++++--
 drivers/net/i40e/i40e_ethdev_vf.c       |  6 ++++--
 drivers/net/ixgbe/ixgbe_ethdev.c        | 12 ++++++++----
 drivers/net/mlx4/mlx4.c                 |  6 ++++--
 drivers/net/mlx5/mlx5.c                 |  4 +++-
 drivers/net/nfp/nfp_net.c               |  6 ++++--
 drivers/net/qede/qede_ethdev.c          | 16 ++++++++++------
 drivers/net/szedata2/rte_eth_szedata2.c |  6 ++++--
 drivers/net/virtio/virtio_ethdev.c      |  4 ++--
 drivers/net/vmxnet3/vmxnet3_ethdev.c    |  6 ++++--
 lib/librte_eal/common/eal_common_pci.c  | 10 ++++++++--
 lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
 lib/librte_ether/rte_ethdev.c           | 16 ++++++++++++----
 lib/librte_ether/rte_ethdev.h           |  6 +++---
 22 files changed, 122 insertions(+), 54 deletions(-)

diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 0eae433..6b5f906 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -620,8 +620,10 @@ static struct eth_driver rte_bnx2x_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_bnx2x_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_bnx2x_dev_init,
 	.dev_private_size = sizeof(struct bnx2x_softc),
@@ -634,8 +636,10 @@ static struct eth_driver rte_bnx2xvf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_bnx2xvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_bnx2xvf_dev_init,
 	.dev_private_size = sizeof(struct bnx2x_softc),
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 035fe07..70dccf6 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1163,8 +1163,10 @@ static struct eth_driver bnxt_rte_pmd = {
 		    .id_table = bnxt_pci_id_map,
 		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
 			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
-		    .probe = rte_eth_dev_pci_probe,
-		    .remove = rte_eth_dev_pci_remove
+			.driver = {
+			    .probe = rte_eth_dev_pci_probe,
+			    .remove = rte_eth_dev_pci_remove
+			},
 		    },
 	.eth_dev_init = bnxt_dev_init,
 	.eth_dev_uninit = bnxt_dev_uninit,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index b7f28eb..334e462 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1041,8 +1041,10 @@ static struct eth_driver rte_cxgbe_pmd = {
 	.pci_drv = {
 		.id_table = cxgb4_pci_tbl,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_cxgbe_dev_init,
 	.dev_private_size = sizeof(struct port_info),
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index aee3d34..34c4b31 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -394,8 +394,10 @@ static struct eth_driver rte_em_pmd = {
 		.id_table = pci_id_em_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_em_dev_init,
 	.eth_dev_uninit = eth_em_dev_uninit,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 2fddf0c..ae75b7e 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1081,8 +1081,10 @@ static struct eth_driver rte_igb_pmd = {
 		.id_table = pci_id_igb_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_igb_dev_init,
 	.eth_dev_uninit = eth_igb_dev_uninit,
@@ -1096,8 +1098,10 @@ static struct eth_driver rte_igbvf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_igbvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_igbvf_dev_init,
 	.eth_dev_uninit = eth_igbvf_dev_uninit,
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index ab9a178..8825585 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1707,8 +1707,10 @@ static struct eth_driver rte_ena_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_ena_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_ena_dev_init,
 	.dev_private_size = sizeof(struct ena_adapter),
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index 2b154ec..1ed951f 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -636,8 +636,10 @@ static struct eth_driver rte_enic_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_enic_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_enicpmd_dev_init,
 	.dev_private_size = sizeof(struct enic),
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 923690c..53a8e33 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3064,8 +3064,10 @@ static struct eth_driver rte_pmd_fm10k = {
 		.id_table = pci_id_fm10k_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_fm10k_dev_init,
 	.eth_dev_uninit = eth_fm10k_dev_uninit,
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..7c08095 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -673,8 +673,10 @@ static struct eth_driver rte_i40e_pmd = {
 		.id_table = pci_id_i40e_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_i40e_dev_init,
 	.eth_dev_uninit = eth_i40e_dev_uninit,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index aa306d6..cbff0da 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1529,8 +1529,10 @@ static struct eth_driver rte_i40evf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_i40evf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = i40evf_dev_init,
 	.eth_dev_uninit = i40evf_dev_uninit,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index edc9b22..4b99ca1 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1567,8 +1567,10 @@ static struct eth_driver rte_ixgbe_pmd = {
 		.id_table = pci_id_ixgbe_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_ixgbe_dev_init,
 	.eth_dev_uninit = eth_ixgbe_dev_uninit,
@@ -1582,8 +1584,10 @@ static struct eth_driver rte_ixgbevf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_ixgbevf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_ixgbevf_dev_init,
 	.eth_dev_uninit = eth_ixgbevf_dev_uninit,
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index da61a85..b3f72d9 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5910,8 +5910,10 @@ static struct eth_driver mlx4_driver = {
 			.name = MLX4_DRIVER_NAME
 		},
 		.id_table = mlx4_pci_id_map,
-		.probe = mlx4_pci_probe,
-		.drv_flags = RTE_PCI_DRV_INTR_LSC,
+		.driver = {
+			.probe = mlx4_pci_probe,
+			.drv_flags = RTE_PCI_DRV_INTR_LSC,
+		},
 	},
 	.dev_private_size = sizeof(struct priv)
 };
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 90cc35e..fa34724 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -733,7 +733,9 @@ static struct eth_driver mlx5_driver = {
 			.name = MLX5_DRIVER_NAME
 		},
 		.id_table = mlx5_pci_id_map,
-		.probe = mlx5_pci_probe,
+		.driver = {
+			.probe = mlx5_pci_probe,
+		},
 		.drv_flags = RTE_PCI_DRV_INTR_LSC,
 	},
 	.dev_private_size = sizeof(struct priv)
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index c6b1587..ffcc1b5 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2472,8 +2472,10 @@ static struct eth_driver rte_nfp_net_pmd = {
 		.id_table = pci_id_nfp_net_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			     RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = nfp_net_init,
 	.dev_private_size = sizeof(struct nfp_net_adapter),
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index d106dd0..b8ad392 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1645,9 +1645,11 @@ static struct eth_driver rte_qedevf_pmd = {
 		    .id_table = pci_id_qedevf_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		    .probe = rte_eth_dev_pci_probe,
-		    .remove = rte_eth_dev_pci_remove,
-		   },
+		    .driver = {
+				.probe = rte_eth_dev_pci_probe,
+				.remove = rte_eth_dev_pci_remove,
+			},
+		},
 	.eth_dev_init = qedevf_eth_dev_init,
 	.eth_dev_uninit = qedevf_eth_dev_uninit,
 	.dev_private_size = sizeof(struct qede_dev),
@@ -1658,9 +1660,11 @@ static struct eth_driver rte_qede_pmd = {
 		    .id_table = pci_id_qede_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		    .probe = rte_eth_dev_pci_probe,
-		    .remove = rte_eth_dev_pci_remove,
-		   },
+		    .driver = {
+			    .probe = rte_eth_dev_pci_probe,
+			    .remove = rte_eth_dev_pci_remove,
+			},
+		},
 	.eth_dev_init = qede_eth_dev_init,
 	.eth_dev_uninit = qede_eth_dev_uninit,
 	.dev_private_size = sizeof(struct qede_dev),
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index f3cd52d..d08da9d 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1573,8 +1573,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
 static struct eth_driver szedata2_eth_driver = {
 	.pci_drv = {
 		.id_table = rte_szedata2_pci_id_table,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init     = rte_szedata2_eth_dev_init,
 	.eth_dev_uninit   = rte_szedata2_eth_dev_uninit,
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 079fd6c..b7bec8f 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1377,11 +1377,11 @@ static struct eth_driver rte_virtio_pmd = {
 	.pci_drv = {
 		.driver = {
 			.name = "net_virtio",
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
 		},
 		.id_table = pci_id_virtio_map,
 		.drv_flags = RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
 	},
 	.eth_dev_init = eth_virtio_dev_init,
 	.eth_dev_uninit = eth_virtio_dev_uninit,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 8bb13e5..52993de 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -337,8 +337,10 @@ static struct eth_driver rte_vmxnet3_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_vmxnet3_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_vmxnet3_dev_init,
 	.eth_dev_uninit = eth_vmxnet3_dev_uninit,
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 6bff675..3082b1a 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -161,6 +161,8 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
 {
 	int ret;
 	const struct rte_pci_id *id_table;
+	struct rte_driver *driver;
+	struct rte_device *device;
 
 	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
 
@@ -212,9 +214,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
 
 		/* reference driver structure */
 		dev->driver = dr;
+		driver = &dr->driver;
+		device = &dev->device;
 
 		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
+		ret = driver->probe(driver, device);
 		if (ret)
 			dev->driver = NULL;
 
@@ -232,6 +236,7 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
+	struct rte_driver *driver = NULL;
 	const struct rte_pci_id *id_table;
 
 	if ((dr == NULL) || (dev == NULL))
@@ -262,7 +267,8 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		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))
+		driver = &(dr->driver);
+		if (driver->remove && (driver->remove(&(dev->device)) < 0))
 			return -1;	/* negative value is an error */
 
 		/* clear driver structure */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4004f9a..7d2ab16 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -145,6 +145,16 @@ void rte_eal_device_insert(struct rte_device *dev);
 void rte_eal_device_remove(struct rte_device *dev);
 
 /**
+ * Initialisation function for the driver called during probing.
+ */
+typedef int (driver_probe_t)(struct rte_driver *, struct rte_device *);
+
+/**
+ * Uninitialisation function for the driver called during hotplugging.
+ */
+typedef int (driver_remove_t)(struct rte_device *);
+
+/**
  * A structure describing a device driver.
  */
 struct rte_driver {
@@ -152,6 +162,8 @@ struct rte_driver {
 	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
+	driver_probe_t *probe;         /**< Probe the device */
+	driver_remove_t *remove;       /**< Remove/hotplugging the device */
 };
 
 /**
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index fde8112..164d348 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -232,15 +232,20 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 }
 
 int
-rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
-		      struct rte_pci_device *pci_dev)
+rte_eth_dev_pci_probe(struct rte_driver *drv,
+		      struct rte_device *dev)
 {
 	struct eth_driver    *eth_drv;
 	struct rte_eth_dev *eth_dev;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
 
 	int diag;
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	eth_drv = (struct eth_driver *)pci_drv;
 
 	rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
@@ -285,16 +290,19 @@ rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
 }
 
 int
-rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
+rte_eth_dev_pci_remove(struct rte_device *dev)
 {
 	const struct eth_driver *eth_drv;
 	struct rte_eth_dev *eth_dev;
+	struct rte_pci_device *pci_dev;
 	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 
-	if (pci_dev == NULL)
+	if (dev == NULL)
 		return -EINVAL;
 
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
 			sizeof(ethdev_name));
 
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..3c45a1f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -4369,15 +4369,15 @@ rte_eth_dev_get_name_by_port(uint8_t port_id, char *name);
  * Wrapper for use by pci drivers as a .probe function to attach to a ethdev
  * interface.
  */
-int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
-			  struct rte_pci_device *pci_dev);
+int rte_eth_dev_pci_probe(struct rte_driver *drv,
+			  struct rte_device *dev);
 
 /**
  * @internal
  * Wrapper for use by pci drivers as a .remove function to detach a ethdev
  * interface.
  */
-int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);
+int rte_eth_dev_pci_remove(struct rte_device *dev);
 
 #ifdef __cplusplus
 }
-- 
2.7.4

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

* [PATCH 08/13] eal: enable probe and remove from bus infrastructure
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (6 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 07/13] pci: replace probe and remove handlers with rte_driver Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-06 10:45   ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 09/13] pci: split match and probe function Shreyansh Jain
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

The model is:
 rte_eal_init
 `--> calls rte_eal_bus_probe()
      This iterates over all the drivers and devices and matches them. For
      matched bus specific device-driver:
      `--> bus->probe()
           This would be responsible for generic work, equivalent to
           rte_eal_pci_probe - specific to the bus. Handles over control
           to,
           `--> rte_driver->probe()
                which works equivalent to rte_eth_dev_pci_probe for alloc-
                -ating a ethernet device. This would hand over the control
                to,
                `--> rte_xxx_driver->probe()
                     Calls driver specific initialization of the eth_dev
                     Similar to what eth_dev_init of eth_driver does.
                     In further changes, eth_driver would be removed.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c | 50 +++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 67b808b..469abac 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -195,11 +195,59 @@ rte_eal_bus_scan(void)
 	return 0;
 }
 
+static int
+perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+	      struct rte_device *device)
+{
+	int ret;
+
+	if (!driver->probe) {
+		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
+			driver->name);
+		/* This is not an error - just a badly implemented PMD */
+		return 0;
+	}
+
+	ret = driver->probe(driver, device);
+	if (ret < 0)
+		/* One of the probes failed */
+		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
+
+	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
+	 * success, return ret
+	 */
+	return ret;
+}
+
 /* Match driver<->device and call driver->probe() */
 int
 rte_eal_bus_probe(void)
 {
-	/* Until driver->probe is available, this is dummy implementation */
+	int ret;
+	struct rte_bus *bus;
+	struct rte_device *device;
+	struct rte_driver *driver;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		TAILQ_FOREACH(device, &bus->device_list, next) {
+			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+				ret = bus->match(driver, device);
+				if (!ret) {
+					ret = perform_probe(bus, driver,
+							    device);
+					if (ret < 0)
+						return ret;
+
+					/* ret == 0 is success; ret >0 implies
+					 * driver doesn't support the device.
+					 * in either case, continue
+					 */
+				}
+			}
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4

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

* [PATCH 09/13] pci: split match and probe function
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (7 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 08/13] eal: enable probe and remove from bus infrastructure Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 10/13] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, 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 rte_eal_pci_match_default.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_pci.c  | 210 ++++++++++++++++++--------------
 lib/librte_eal/common/include/rte_pci.h |  15 +++
 2 files changed, 133 insertions(+), 92 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 3082b1a..793ac59 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,80 +152,115 @@ 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_eal_pci_match_default(struct rte_pci_driver *pci_drv,
+			  struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 0;
 	const struct rte_pci_id *id_table;
-	struct rte_driver *driver;
-	struct rte_device *device;
 
-	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;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-				rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-		driver = &dr->driver;
-		device = &dev->device;
-
-		/* call the driver probe() function */
-		ret = driver->probe(driver, device);
-		if (ret)
-			dev->driver = NULL;
+		match = 1;
+		break;
+	}
+
+	return !match;
+}
+
+/*
+ * 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_driver *driver;
+	struct rte_device *device;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
 
-		return ret;
+	driver = &dr->driver;
+	device = &dev->device;
+	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;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_eal_pci_match_default(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			driver->name);
+		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;
+	} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+			rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* unbind current driver */
+		if (pci_unbind_kernel_driver(dev) < 0)
+			return -1;
+	}
+
+	/* reference driver structure */
+	dev->driver = dr;
+
+	/* call the driver probe() function */
+	ret = driver->probe(driver, device);
+	if (ret) {
+		RTE_LOG(DEBUG, EAL, "Driver (%s) probe failed.\n",
+			driver->name);
+		dev->driver = NULL;
+	}
+
+	return ret;
 }
 
 /*
@@ -236,53 +271,44 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
+	int ret;
 	struct rte_driver *driver = NULL;
-	const struct rte_pci_id *id_table;
+	struct rte_device *device;
+	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++) {
+	driver = &(dr->driver);
+	device = &(dev->device);
 
-		/* 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;
+	ret = rte_eal_pci_match_default(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	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, "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);
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
 
-		driver = &(dr->driver);
-		if (driver->remove && (driver->remove(&(dev->device)) < 0))
-			return -1;	/* negative value is an error */
+	driver = &(dr->driver);
+	if (driver->remove && (driver->remove(device) < 0))
+		return -1;	/* negative value is an error */
 
-		/* clear driver structure */
-		dev->driver = NULL;
+	/* 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);
+	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 positive value if driver doesn't support this device */
-	return 1;
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 9ce8847..eb9ef7d 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -369,6 +369,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_eal_pci_match_default(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
-- 
2.7.4

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

* [PATCH 10/13] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (8 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 09/13] pci: split match and probe function Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 11/13] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

PCI scan and match now work on rte_device/rte_driver rather than PCI
specific objects. These functions can now be plugged to the generic
bus callbacks for scanning and matching devices/drivers.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     |  2 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  4 ++--
 lib/librte_eal/common/eal_common_pci.c  | 17 +++++++++++------
 lib/librte_eal/common/include/rte_pci.h | 17 ++++++++++-------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  4 ++--
 5 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..f9b84db 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -180,7 +180,7 @@ test_pci_setup(void)
 		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
 	}
 
-	ret = rte_eal_pci_scan();
+	ret = rte_eal_pci_scan(NULL);
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
 	rte_eal_pci_dump(stdout);
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 8b3ed88..10b234e 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -361,7 +361,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -676,7 +676,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 793ac59..ba84ccb 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -153,17 +153,22 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 int
-rte_eal_pci_match_default(struct rte_pci_driver *pci_drv,
-			  struct rte_pci_device *pci_dev)
+rte_eal_pci_match_default(struct rte_driver *drv,
+			  struct rte_device *dev)
 {
 	int match = 0;
 	const struct rte_pci_id *id_table;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 
-	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
-		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+	if (!drv || !dev) {
+		RTE_LOG(DEBUG, EAL, "Invalid Device/Driver\n");
 		return -1;
 	}
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
 	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
@@ -226,7 +231,7 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 	}
 
 	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match_default(dr, dev);
+	ret = rte_eal_pci_match_default(driver, device);
 	if (ret) {
 		/* Match of device and driver failed */
 		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
@@ -282,7 +287,7 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 	driver = &(dr->driver);
 	device = &(dev->device);
 
-	ret = rte_eal_pci_match_default(dr, dev);
+	ret = rte_eal_pci_match_default(driver, device);
 	if (ret) {
 		/* Device and driver don't match */
 		return 1;
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index eb9ef7d..2a5f766 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -363,25 +363,28 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  * Scan the content of the PCI bus, and the devices in the devices
  * list
  *
+ * @param bus
+ *	Reference to the PCI bus
+ *
  * @return
  *  0 on success, negative on error
  */
-int rte_eal_pci_scan(void);
+int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
  * 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
+ * @param drv
+ *	driver from which ID table would be extracted
+ * @param dev
+ *	device to match against the driver
  * @return
  *	0 for successful match
  *	!0 for unsuccessful match
  */
 int
-rte_eal_pci_match_default(struct rte_pci_driver *pci_drv,
-			  struct rte_pci_device *pci_dev);
+rte_eal_pci_match_default(struct rte_driver *drv,
+			  struct rte_device *dev);
 
 /**
  * Probe the PCI bus for registered drivers.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 876ba38..bafb7fb 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -485,7 +485,7 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  * list
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 {
 	struct dirent *e;
 	DIR *dir;
@@ -763,7 +763,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
-- 
2.7.4

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

* [PATCH 11/13] pci: Pass rte_pci_addr to functions instead of separate args
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (9 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 10/13] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 12/13] eal: enable PCI bus Shreyansh Jain
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Ben Walker, Shreyansh Jain

From: Ben Walker <benjamin.walker@intel.com>

Instead of passing domain, bus, devid, func, just pass
an rte_pci_addr.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
[Shreyansh: Checkpatch error fix]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index bafb7fb..cbd25df 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -267,8 +267,7 @@ 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, uint16_t domain, uint8_t bus,
-	     uint8_t devid, uint8_t function)
+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -281,10 +280,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 		return -1;
 
 	memset(dev, 0, sizeof(*dev));
-	dev->addr.domain = domain;
-	dev->addr.bus = bus;
-	dev->addr.devid = devid;
-	dev->addr.function = function;
+	dev->addr = *addr;
 
 	/* get vendor id */
 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
@@ -429,16 +425,14 @@ 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->domain, addr->bus, addr->devid,
-				addr->function);
+	return pci_scan_one(filename, addr);
 }
 
 /*
  * split up a pci address into its constituent parts.
  */
 static int
-parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
-		uint8_t *bus, uint8_t *devid, uint8_t *function)
+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
 {
 	/* first split on ':' */
 	union splitaddr {
@@ -466,10 +460,10 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
 
 	/* now convert to int values */
 	errno = 0;
-	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
-	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
-	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
-	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	addr->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	addr->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	addr->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	addr->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
 	if (errno != 0)
 		goto error;
 
@@ -490,8 +484,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
-	uint16_t domain;
-	uint8_t bus, devid, function;
+	struct rte_pci_addr addr;
 
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
@@ -500,20 +493,22 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 		return -1;
 	}
 
+
 	while ((e = readdir(dir)) != NULL) {
 		if (e->d_name[0] == '.')
 			continue;
 
-		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
-				&bus, &devid, &function) != 0)
+		if (parse_pci_addr_format(e->d_name,
+					  sizeof(e->d_name), &addr) != 0)
 			continue;
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
+		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
+
 	return 0;
 
 error:
-- 
2.7.4

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

* [PATCH 12/13] eal: enable PCI bus
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (10 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 11/13] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-04 10:11 ` [PATCH 13/13] eal/pci: remove PCI probe and init calls Shreyansh Jain
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Removing PCI init and probe from rte_eal_init now that bus performs these
functions.

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     |  42 +++++++---
 lib/librte_eal/common/eal_common_bus.c  |   5 +-
 lib/librte_eal/common/eal_common_pci.c  | 137 ++++++++++++++++++++++++++------
 lib/librte_eal/common/eal_private.h     |   4 +-
 lib/librte_eal/common/include/rte_bus.h |   5 ++
 lib/librte_eal/common/include/rte_pci.h |   3 +
 lib/librte_eal/linuxapp/eal/eal.c       |   7 --
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  43 +++++++---
 9 files changed, 189 insertions(+), 64 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 30afc6b..79d82d4 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)
@@ -616,10 +613,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");
-
 	if (rte_eal_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 10b234e..ab04408 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -249,7 +250,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
 	struct rte_pci_device *dev;
 	struct pci_bar_io bar;
@@ -322,19 +323,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -346,7 +351,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
@@ -361,7 +366,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -374,6 +379,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 			.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__);
@@ -389,7 +398,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 		}
 
 		for (i = 0; i < conf_io.num_matches; i++)
-			if (pci_scan_one(fd, &matches[i]) < 0)
+			if (pci_scan_one(bus, fd, &matches[i]) < 0)
 				goto error;
 
 		dev_count += conf_io.num_matches;
@@ -407,9 +416,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-	int fd;
+	int fd = -1;
 	struct pci_conf matches[2];
 	struct pci_match_conf match = {
 		.pc_sel = {
@@ -427,6 +436,9 @@ pci_update_device(const struct rte_pci_addr *addr)
 		.matches = &matches[0],
 	};
 
+	if (!bus)
+		goto error;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -442,7 +454,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 	if (conf_io.num_matches != 1)
 		goto error;
 
-	if (pci_scan_one(fd, &matches[0]) < 0)
+	if (pci_scan_one(bus, fd, &matches[0]) < 0)
 		goto error;
 
 	close(fd);
@@ -682,3 +694,11 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match_default,
+	.probe = rte_eal_pci_probe_default,
+};
+
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 469abac..52bf051 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -196,7 +196,7 @@ rte_eal_bus_scan(void)
 }
 
 static int
-perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+perform_probe(struct rte_bus *bus, struct rte_driver *driver,
 	      struct rte_device *device)
 {
 	int ret;
@@ -208,7 +208,7 @@ perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
 		return 0;
 	}
 
-	ret = driver->probe(driver, device);
+	ret = bus->probe(driver, device);
 	if (ret < 0)
 		/* One of the probes failed */
 		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
@@ -234,6 +234,7 @@ rte_eal_bus_probe(void)
 			TAILQ_FOREACH(driver, &bus->driver_list, next) {
 				ret = bus->match(driver, device);
 				if (!ret) {
+					device->driver = driver;
 					ret = perform_probe(bus, driver,
 							    device);
 					if (ret < 0)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index ba84ccb..4093746 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>
@@ -230,15 +231,6 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 		return 1;
 	}
 
-	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match_default(driver, device);
-	if (ret) {
-		/* Match of device and driver failed */
-		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			driver->name);
-		return 1;
-	}
-
 	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
 			dev->id.device_id, dr->driver.name);
 
@@ -322,19 +314,24 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
+	if (!bus)
+		return -1;
+
 	/* Check if a driver is already loaded */
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -353,15 +350,20 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	if (!bus)
+		return -1;
+
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -382,22 +384,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
-	if (pci_update_device(addr) < 0)
+	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_probe_all_drivers(dev);
+		ret = pci_probe_all_drivers(bus, dev);
 		if (ret)
 			goto err_return;
 		return 0;
@@ -418,20 +429,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(bus, dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_bus_remove_device(r_dev);
 		free(dev);
 		return 0;
 	}
@@ -469,10 +489,10 @@ rte_eal_pci_probe(void)
 
 		/* probe all or only whitelisted devices */
 		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(NULL, dev);
 		else if (devargs != NULL &&
 			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(NULL, dev);
 		if (ret < 0)
 			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
 				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
@@ -482,6 +502,44 @@ rte_eal_pci_probe(void)
 	return 0;
 }
 
+int
+rte_eal_pci_probe_default(struct rte_driver *driver, struct rte_device *device)
+{
+	int ret = 0;
+	struct rte_devargs *devargs;
+	struct rte_pci_device *pci_dev;
+	struct rte_pci_driver *pci_drv;
+
+	if (!driver || !device)
+		return -1;
+
+	pci_dev = container_of(device, struct rte_pci_device, device);
+	pci_drv = container_of(driver, struct rte_pci_driver, driver);
+
+	ret = rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI);
+	if (ret != 0) {
+		/* set devargs in PCI structure */
+		devargs = pci_devargs_lookup(pci_dev);
+		if (devargs != NULL &&
+		    devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) {
+			pci_dev->device.devargs = devargs;
+		} else {
+			/* Ignore the device */
+			return 0;
+		}
+	}
+
+	ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
+	return 0;
+}
+
 /* dump one device */
 static int
 pci_dump_one_device(FILE *f, struct rte_pci_device *dev)
@@ -507,8 +565,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -517,14 +584,32 @@ 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);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_add_driver(bus, &driver->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_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = driver->driver.bus;
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..e006d95 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -126,13 +126,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *	The PCI bus on which device is connected
  * @param addr
  *	The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 9bd8650..e8db5b4 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -102,6 +102,10 @@ typedef int (*bus_scan_t)(struct rte_bus *bus);
  */
 typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
 
+/** TODO
+ */
+typedef int (*bus_probe_t)(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	struct rte_driver_list driver_list;
@@ -112,6 +116,7 @@ struct rte_bus {
 	bus_scan_t scan;            /**< Scan for devices attached to bus */
 	bus_match_t match;
 	/**< Match device with drivers associated with the bus */
+	bus_probe_t probe;           /**< TODO */
 };
 
 /** @internal
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 2a5f766..c0a0c6a 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,9 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  */
 int rte_eal_pci_scan(struct rte_bus *bus);
 
+int
+rte_eal_pci_probe_default(struct rte_driver *driver, struct rte_device *device);
+
 /**
  * Match the PCI Driver and Device using the ID Table
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 01d0cee..ff92de2 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");
@@ -887,10 +884,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");
-
 	if (rte_eal_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 cbd25df..de4ed86 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>
@@ -267,7 +268,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_bus *bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -385,20 +387,24 @@ 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)) {
+	if (TAILQ_EMPTY(&bus->device_list)) {
 		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	} else {
 		struct rte_pci_device *dev2;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+						device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				rte_eal_device_insert(&dev->device);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -410,14 +416,14 @@ 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_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 
@@ -425,7 +431,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(bus, filename, addr);
 }
 
 /*
@@ -479,13 +485,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	if (!bus_p) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	/* 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",
@@ -504,7 +519,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+		if (pci_scan_one(bus_p, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -765,3 +780,11 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match_default,
+	.probe = rte_eal_pci_probe_default,
+};
+
+RTE_REGISTER_BUS(pci, pci_bus);
-- 
2.7.4

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

* [PATCH 13/13] eal/pci: remove PCI probe and init calls
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (11 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 12/13] eal: enable PCI bus Shreyansh Jain
@ 2016-12-04 10:11 ` Shreyansh Jain
  2016-12-06 20:52 ` [PATCH 00/13] Introducing EAL Bus-Device-Driver Model David Marchand
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
  14 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 15 ---------
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  3 --
 lib/librte_eal/common/eal_common_pci.c          | 43 -------------------------
 lib/librte_eal/common/eal_private.h             | 10 ------
 lib/librte_eal/common/include/rte_pci.h         | 19 -----------
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 16 ---------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  3 --
 7 files changed, 109 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index ab04408..5344f9a 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -680,21 +680,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(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
-
 struct rte_bus pci_bus = {
 	.scan = rte_eal_pci_scan,
 	.match = rte_eal_pci_match_default,
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 23fc1c1..0d2c8ec 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4093746..6d7b53e 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)
@@ -464,44 +459,6 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	return -1;
 }
 
-/*
- * 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.
- */
-int
-rte_eal_pci_probe(void)
-{
-	struct rte_pci_device *dev = NULL;
-	struct rte_devargs *devargs;
-	int probe_all = 0;
-	int ret = 0;
-
-	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-		probe_all = 1;
-
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-
-		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
-		if (devargs != NULL)
-			dev->device.devargs = devargs;
-
-		/* probe all or only whitelisted devices */
-		if (probe_all)
-			ret = pci_probe_all_drivers(NULL, dev);
-		else if (devargs != NULL &&
-			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(NULL, dev);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
-	}
-
-	return 0;
-}
-
 int
 rte_eal_pci_probe_default(struct rte_driver *driver, struct rte_device *device)
 {
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index e006d95..06ec172 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 c0a0c6a..95e6656 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.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);
 
@@ -390,19 +384,6 @@ rte_eal_pci_match_default(struct rte_driver *drv,
 			  struct rte_device *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.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index de4ed86..a79b47c 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -765,22 +765,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(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_bus pci_bus = {
 	.scan = rte_eal_pci_scan,
 	.match = rte_eal_pci_match_default,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index c873a7f..48e847c 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
-- 
2.7.4

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

* Re: [PATCH 08/13] eal: enable probe and remove from bus infrastructure
  2016-12-04 10:11 ` [PATCH 08/13] eal: enable probe and remove from bus infrastructure Shreyansh Jain
@ 2016-12-06 10:45   ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-06 10:45 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand

On Sunday 04 December 2016 03:41 PM, Shreyansh Jain wrote:
> The model is:
>  rte_eal_init
>  `--> calls rte_eal_bus_probe()
>       This iterates over all the drivers and devices and matches them. For
>       matched bus specific device-driver:
>       `--> bus->probe()
>            This would be responsible for generic work, equivalent to
>            rte_eal_pci_probe - specific to the bus. Handles over control
>            to,
>            `--> rte_driver->probe()
>                 which works equivalent to rte_eth_dev_pci_probe for alloc-
>                 -ating a ethernet device. This would hand over the control
>                 to,
>                 `--> rte_xxx_driver->probe()
>                      Calls driver specific initialization of the eth_dev
>                      Similar to what eth_dev_init of eth_driver does.
>                      In further changes, eth_driver would be removed.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  lib/librte_eal/common/eal_common_bus.c | 50 +++++++++++++++++++++++++++++++++-
>  1 file changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
> index 67b808b..469abac 100644
> --- a/lib/librte_eal/common/eal_common_bus.c
> +++ b/lib/librte_eal/common/eal_common_bus.c
> @@ -195,11 +195,59 @@ rte_eal_bus_scan(void)
>  	return 0;
>  }
>
> +static int
> +perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
> +	      struct rte_device *device)
> +{
> +	int ret;
> +
> +	if (!driver->probe) {
> +		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
> +			driver->name);
> +		/* This is not an error - just a badly implemented PMD */
> +		return 0;
> +	}
> +
> +	ret = driver->probe(driver, device);

Just noticed an issue here: It is unlike what I have stated in the patch 
headline. bus->probe() is not getting called.


Just to open a debate:
eal=> rte_bus->probe() => rte_driver->probe() => rte_pci_driver->probe()
is debatable. 1) bus never probes and 2) it just looks very odd.

But, if bus->probe() doesn't happen, which layer is responsible for 
things like devargs which currently rte_eal_pci_probe() does in EAL.
If rte_driver->probe() does the devargs layer, eth_dev allocation might 
be shifted to rte_pci_driver->probe() - and subsequently calling 
rte_eth_dev->eth_dev_init().

I do need to get my head around this. Suggestions would be really 
appreciated.

> +	if (ret < 0)
> +		/* One of the probes failed */
> +		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
> +
> +	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
> +	 * success, return ret
> +	 */
> +	return ret;
> +}
> +
>  /* Match driver<->device and call driver->probe() */
>  int
>  rte_eal_bus_probe(void)
>  {
> -	/* Until driver->probe is available, this is dummy implementation */
> +	int ret;
> +	struct rte_bus *bus;
> +	struct rte_device *device;
> +	struct rte_driver *driver;
> +
> +	/* For each bus registered with EAL */
> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +		TAILQ_FOREACH(device, &bus->device_list, next) {
> +			TAILQ_FOREACH(driver, &bus->driver_list, next) {
> +				ret = bus->match(driver, device);
> +				if (!ret) {
> +					ret = perform_probe(bus, driver,
> +							    device);
> +					if (ret < 0)
> +						return ret;
> +
> +					/* ret == 0 is success; ret >0 implies
> +					 * driver doesn't support the device.
> +					 * in either case, continue
> +					 */
> +				}
> +			}
> +		}
> +	}
> +
>  	return 0;
>  }
>
>

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (12 preceding siblings ...)
  2016-12-04 10:11 ` [PATCH 13/13] eal/pci: remove PCI probe and init calls Shreyansh Jain
@ 2016-12-06 20:52 ` David Marchand
  2016-12-07  9:55   ` Shreyansh Jain
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
  14 siblings, 1 reply; 132+ messages in thread
From: David Marchand @ 2016-12-06 20:52 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev, Thomas Monjalon

"Big patchset and a lot of things to look at.

Here is a first look at it.

On Sun, Dec 4, 2016 at 11:11 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> In continuation to the RFC posted on 17/Nov [9],
> A series of patches is being posted which attempts to create:
>  1. A basic bus model
>     `- define rte_bus and associated methods/helpers
>     `- test infrastructure to test the Bus infra
>  2. Changes in EAL to support PCI as a bus
>     `- a "pci" bus is registered
>     `- existing scan/match/probe are modified to allow for bus integration
>     `- PCI Device and Driver list, which were global entities, have been
>        moved to rte_bus->[device/driver]_list
>
> I have sanity tested this patch over a XeonD X552 available with me, as
> well as part of PoC for verifying NXP's DPAA2 PMD (being pushed out in a
> separate series). Exhaustive testing is still pending.

I saw some checkpatch issues for patch 1 (I would ignore this one) and
4 (please check).


> :: Brief about Patch Layout ::
>
> 0001:      Container_of patch from [3]

> 0002~0003: Introducing the basic Bus model and associated test case
> 0005:      Support insertion of device rather than addition to tail

Patch 2 and 5 could be squashed.
The constructor priority stuff seems unneeded as long as we use
explicit reference to a global (or local, did not check) bus symbol
rather than a runtime lookup.


> 0004:      Add scan and match callbacks for the Bus and updated test case

Why do you push back the bus object in the 'scan' method ?
This method is bus specific which means that the code "knows" the
object registered with the callback.
Is is that you want to have a single scan method used by multiple buses ?


> 0006:      Integrate bus scan/match with EAL, without any effective driver

Hard to find a right balance in patch splittng, but patch 4 and 6 are
linked, I would squash them into one.


> 0007:      rte_pci_driver->probe replaced with rte_driver->probe

This patch is too big, please separate in two patches: eal changes
then ethdev/driver changes.
I almost missed that mlx4 has been broken : you moved the drv_flags
from the mlx4 pci driver to rte_driver.

Why do you push back the driver object in the 'probe' method ? (idem
rte_bus->scan).


> 0008:      Integrate probe of drivers with EAL

This patch does nothing about "remove" while its title talks about it.

+ What about hotplug code ? I suppose this is for later.


> 0009:      Split the existing PCI probe into match and probe

You don't need to expose rte_eal_pci_match_default() (and I am not
sure what the "default" means here).
This method should be internal to the pci bus object ?


> 0010:      Make PCI probe/match work on rte_driver/device rather than
>            rte_pci_device/rte_pci_driver
> 0011:      Patch from Ben [8], part of series [2]


> 0012~0013: Enable Scan/Match/probe on Bus from EAL and remove unused
>            functions and lists

Same thing as earlier in the series, you don't need to check for the bus object.
The pci bus code can't be called if the bus was not registered and
consequently, you are sure that the pci bus object is the pci_bus
symbol.



Regards,
-- 
David Marchand

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-06 20:52 ` [PATCH 00/13] Introducing EAL Bus-Device-Driver Model David Marchand
@ 2016-12-07  9:55   ` Shreyansh Jain
  2016-12-07 12:17     ` David Marchand
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-07  9:55 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Thomas Monjalon

Hello David,

On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
> "Big patchset and a lot of things to look at.
>
> Here is a first look at it.

Thanks for comments.

>
> On Sun, Dec 4, 2016 at 11:11 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> In continuation to the RFC posted on 17/Nov [9],
>> A series of patches is being posted which attempts to create:
>>  1. A basic bus model
>>     `- define rte_bus and associated methods/helpers
>>     `- test infrastructure to test the Bus infra
>>  2. Changes in EAL to support PCI as a bus
>>     `- a "pci" bus is registered
>>     `- existing scan/match/probe are modified to allow for bus integration
>>     `- PCI Device and Driver list, which were global entities, have been
>>        moved to rte_bus->[device/driver]_list
>>
>> I have sanity tested this patch over a XeonD X552 available with me, as
>> well as part of PoC for verifying NXP's DPAA2 PMD (being pushed out in a
>> separate series). Exhaustive testing is still pending.
>
> I saw some checkpatch issues for patch 1 (I would ignore this one) and
> 4 (please check).

Yes, for Patch 1 I too ignored the warnings.
For Patch 4, there are 3 warnings, of which first 2 were reported by 
checkpatch tool before I sent out. Surprisingly, I didn't see the third 
one when I ran the tool in my environment.

I will fix them (those which I can) in v2.

>
>
>> :: Brief about Patch Layout ::
>>
>> 0001:      Container_of patch from [3]
>
>> 0002~0003: Introducing the basic Bus model and associated test case
>> 0005:      Support insertion of device rather than addition to tail
>
> Patch 2 and 5 could be squashed.

I deliberately kept them separate. I intent to extend the Patch 5 for 
hotplugging. But, if I don't end up adding support for that in this 
series, I will merge these two.

> The constructor priority stuff seems unneeded as long as we use
> explicit reference to a global (or local, did not check) bus symbol
> rather than a runtime lookup.

I didn't understand your point here.
IMO, constructor priority (or some other way to handle this) is 
important. I faced this issue while verifying it at my end when the 
drivers were getting registered before the bus.

Can you elaborate more on '..use explicit reference to a global...'?

>
>
>> 0004:      Add scan and match callbacks for the Bus and updated test case
>
> Why do you push back the bus object in the 'scan' method ?
> This method is bus specific which means that the code "knows" the
> object registered with the callback.

This 'knows' is the grey area for me.
The bus (for example, PCI) after scanning needs to call 
rte_eal_bus_add_device() to link the device in bus's device_list.

Two options:
1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
2. Call rte_eal_get_bus() every time someone needs the reference.
3. C++ style, 'this->'.

I have taken the 3rd path. It simplifies my code to not assume a handle 
as well as not allow for reference fetch calls every now and then.

As a disadvantage: it means passing this as argument - and some cases 
maintaining it as __rte_unused.

Taking (1) or (2) is not advantageous than this approach.

> Is is that you want to have a single scan method used by multiple buses ?

Yes, but only as a use case. For example, platform devices are of 
various types - what if we have a south-bound bus over a platform bus. 
In which case, a hierarchical bus layout is possible.
But, this is far-fetched idea for now.

>
>
>> 0006:      Integrate bus scan/match with EAL, without any effective driver
>
> Hard to find a right balance in patch splittng, but patch 4 and 6 are
> linked, I would squash them into one.

Yes, it is hard and sometimes there is simply no strong rationale for 
splitting or merging. This is one of those cases.
My idea was that one patch _only_ introduces Bus services (structures, 
functions etc) and another should enable the calls to it from EAL.
In that sense, I still think 4 and 6 should remain separate, may be 
consecutive, though.

>
>
>> 0007:      rte_pci_driver->probe replaced with rte_driver->probe
>
> This patch is too big, please separate in two patches: eal changes
> then ethdev/driver changes.

I don't think that can be done. One change is incomplete without the other.

Changes to all files are only for rte_pci_driver->probe to 
rte_driver->probe movement. EAL changes is to allow 
rte_eth_dev_pci_probe function after such a change as rte_driver->probe 
has different arguments as compared to rte_pci_driver->probe. The 
patches won't compile if I split.

Am I missing something?

> I almost missed that mlx4 has been broken : you moved the drv_flags
> from the mlx4 pci driver to rte_driver.

Oh! This is indeed my mistake. I will fix this right away.

>
> Why do you push back the driver object in the 'probe' method ? (idem
> rte_bus->scan).

I am assuming you are referring to rte_driver->probe().
This is being done so that implementations (specific to drivers on a 
particular bus) can start extracting the rte_xxx_driver, if need be.

For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to 
rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In 
absence of the rte_driver object, this function cannot call 
rte_pci_driver->probe (for example) for driver specific operations.

>
>
>> 0008:      Integrate probe of drivers with EAL
>
> This patch does nothing about "remove" while its title talks about it.

Yes, that is a mistake on my part. I will fix this.

>
> + What about hotplug code ? I suppose this is for later.

I am still working on it. Maybe, with the current set, if there is some 
agreement over the overall changes, I would be more confident on this 
next level of changes.

>
>
>> 0009:      Split the existing PCI probe into match and probe
>
> You don't need to expose rte_eal_pci_match_default() (and I am not
> sure what the "default" means here).
> This method should be internal to the pci bus object ?

1) Yes, rte_eal_pci_match_default isn't really a 'default' I will remove 
that.

2) Yes, there is no need to expose it.
One trivial reason I took this liberty was so that I can put my 
implementation for PCI bus in ${RTE_SDK}/drivers/bus/pci/* rather than 
current ${RTE_SDK}/lib/librte_eal/linuxapp/eal_pci.c
And similarly if there are other PCI-like implementations which would 
like to have their own bus rather than using PCI bus.

But, I can remove this (from Map as well)

>
>
>> 0010:      Make PCI probe/match work on rte_driver/device rather than
>>            rte_pci_device/rte_pci_driver
>> 0011:      Patch from Ben [8], part of series [2]
>
>
>> 0012~0013: Enable Scan/Match/probe on Bus from EAL and remove unused
>>            functions and lists
>
> Same thing as earlier in the series, you don't need to check for the bus object.
> The pci bus code can't be called if the bus was not registered and
> consequently, you are sure that the pci bus object is the pci_bus
> symbol.

Hm. Ok. I will remove this.
I was doing this for two reasons 1) somehow I found drivers getting 
registered *before* bus and for debugging that. and 2) it made me avoid 
segfaults because of my wrong code.

Anyways, it was only a debugging level change.

>
>
>
> Regards,
>


Thanks for your review. I still look forward to more discussion on 
overall approach and if there are holes which I can't see (for example, 
hotplugging).

Regards,
Shreyansh

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-07  9:55   ` Shreyansh Jain
@ 2016-12-07 12:17     ` David Marchand
  2016-12-07 13:10       ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: David Marchand @ 2016-12-07 12:17 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: dev, Thomas Monjalon

Hello Shreyansh,

On Wed, Dec 7, 2016 at 10:55 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
>>> 0002~0003: Introducing the basic Bus model and associated test case
>>> 0005:      Support insertion of device rather than addition to tail
>>
>>
>> Patch 2 and 5 could be squashed.
>
>
> I deliberately kept them separate. I intent to extend the Patch 5 for
> hotplugging. But, if I don't end up adding support for that in this series,
> I will merge these two.

Fine.


>> The constructor priority stuff seems unneeded as long as we use
>> explicit reference to a global (or local, did not check) bus symbol
>> rather than a runtime lookup.
>
>
> I didn't understand your point here.
> IMO, constructor priority (or some other way to handle this) is important. I
> faced this issue while verifying it at my end when the drivers were getting
> registered before the bus.
>
> Can you elaborate more on '..use explicit reference to a global...'?

The drivers register themselves to a bus using this bus specific api.

For pci, this is rte_eal_pci_register().
The pci_bus object must be moved to eal_common_pci.c (we can stil
internally expose for bsd / linux specific implementations).
Then, rte_eal_pci_register() can add the pci driver to the pci_bus
drivers list even if this pci_bus object is not registered yet to the
buses list.

And no constructor order issue ?


>>
>>
>>> 0004:      Add scan and match callbacks for the Bus and updated test case
>>
>>
>> Why do you push back the bus object in the 'scan' method ?
>> This method is bus specific which means that the code "knows" the
>> object registered with the callback.
>
>
> This 'knows' is the grey area for me.
> The bus (for example, PCI) after scanning needs to call
> rte_eal_bus_add_device() to link the device in bus's device_list.
>
> Two options:
> 1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
> 2. Call rte_eal_get_bus() every time someone needs the reference.
> 3. C++ style, 'this->'.
>
> I have taken the 3rd path. It simplifies my code to not assume a handle as
> well as not allow for reference fetch calls every now and then.
>
> As a disadvantage: it means passing this as argument - and some cases
> maintaining it as __rte_unused.
>
> Taking (1) or (2) is not advantageous than this approach.

1) is the simplest one.

When you write a pci_scan method and embed it in you pci_bus object,
but this pci_scan method still wonders which bus object it is supposed
to work on, this is a bit like Schizophrenia ;-).


>> Is is that you want to have a single scan method used by multiple buses ?
>
>
> Yes, but only as a use case. For example, platform devices are of various
> types - what if we have a south-bound bus over a platform bus. In which
> case, a hierarchical bus layout is possible.
> But, this is far-fetched idea for now.

Well, if you have no usecase at the moment, let's keep it simple, please.


>>
>>> 0006:      Integrate bus scan/match with EAL, without any effective
>>> driver
>>
>>
>> Hard to find a right balance in patch splittng, but patch 4 and 6 are
>> linked, I would squash them into one.
>
>
> Yes, it is hard and sometimes there is simply no strong rationale for
> splitting or merging. This is one of those cases.
> My idea was that one patch _only_ introduces Bus services (structures,
> functions etc) and another should enable the calls to it from EAL.
> In that sense, I still think 4 and 6 should remain separate, may be
> consecutive, though.

Ok, will see in next version of the patchset.


>>
>>> 0007:      rte_pci_driver->probe replaced with rte_driver->probe
>>
>>
>> This patch is too big, please separate in two patches: eal changes
>> then ethdev/driver changes.
>
>
> I don't think that can be done. One change is incomplete without the other.
>
> Changes to all files are only for rte_pci_driver->probe to rte_driver->probe
> movement. EAL changes is to allow rte_eth_dev_pci_probe function after such
> a change as rte_driver->probe has different arguments as compared to
> rte_pci_driver->probe. The patches won't compile if I split.
>
> Am I missing something?
>>
>> Why do you push back the driver object in the 'probe' method ? (idem
>> rte_bus->scan).
>
>
> I am assuming you are referring to rte_driver->probe().
> This is being done so that implementations (specific to drivers on a
> particular bus) can start extracting the rte_xxx_driver, if need be.
>
> For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to
> rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In
> absence of the rte_driver object, this function cannot call
> rte_pci_driver->probe (for example) for driver specific operations.

Sorry, I am thinking a step ahead with eth_driver out of the picture.
But once eth_driver disappears, I can see no reason to keep this
driver in the probe method (Schizophrenia again).



-- 
David Marchand

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-07 12:17     ` David Marchand
@ 2016-12-07 13:10       ` Shreyansh Jain
  2016-12-07 13:24         ` Thomas Monjalon
  2016-12-12 14:35         ` Jianbo Liu
  0 siblings, 2 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-07 13:10 UTC (permalink / raw)
  To: David Marchand; +Cc: dev, Thomas Monjalon

On Wednesday 07 December 2016 05:47 PM, David Marchand wrote:
> Hello Shreyansh,
>
> On Wed, Dec 7, 2016 at 10:55 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
>>>> 0002~0003: Introducing the basic Bus model and associated test case
>>>> 0005:      Support insertion of device rather than addition to tail
>>>
>>>
>>> Patch 2 and 5 could be squashed.
>>
>>
>> I deliberately kept them separate. I intent to extend the Patch 5 for
>> hotplugging. But, if I don't end up adding support for that in this series,
>> I will merge these two.
>
> Fine.
>
>
>>> The constructor priority stuff seems unneeded as long as we use
>>> explicit reference to a global (or local, did not check) bus symbol
>>> rather than a runtime lookup.
>>
>>
>> I didn't understand your point here.
>> IMO, constructor priority (or some other way to handle this) is important. I
>> faced this issue while verifying it at my end when the drivers were getting
>> registered before the bus.
>>
>> Can you elaborate more on '..use explicit reference to a global...'?
>
> The drivers register themselves to a bus using this bus specific api.
>
> For pci, this is rte_eal_pci_register().
> The pci_bus object must be moved to eal_common_pci.c (we can stil
> internally expose for bsd / linux specific implementations).
> Then, rte_eal_pci_register() can add the pci driver to the pci_bus
> drivers list even if this pci_bus object is not registered yet to the
> buses list.

So, in eal_common_bus.c

--->8---

struct rte_bus *global_ptr_to_pci_bus = NULL;

struct rte_bus pci_bus = { ... };

rte_eal_pci_register() {
     if (global_ptr_to_pci_bus == NULL)
         rte_eal_bus_register(&pci_bus)
     else
        // continue as if PCI bus is registered
}

--->8---

so, no RTE_REGISTER_BUS()?

If yes, then RTE_REGISTER_BUS() should also check for an existing 
registration for duplication.

I was banking on a model where bus handlers (or bus drivers) are 
independent entities, just like PMDs. So, we have a bus XYZ without any 
drivers necessarily based on it.

By making registration dependent on driver registration, it becomes 
implicit that buses don't exist without drivers.
I am not in favor of this - or maybe I lack enough reason for this 
(about how it will make framework/PMD life better).

>
> And no constructor order issue ?
>
>
>>>
>>>
>>>> 0004:      Add scan and match callbacks for the Bus and updated test case
>>>
>>>
>>> Why do you push back the bus object in the 'scan' method ?
>>> This method is bus specific which means that the code "knows" the
>>> object registered with the callback.
>>
>>
>> This 'knows' is the grey area for me.
>> The bus (for example, PCI) after scanning needs to call
>> rte_eal_bus_add_device() to link the device in bus's device_list.
>>
>> Two options:
>> 1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
>> 2. Call rte_eal_get_bus() every time someone needs the reference.
>> 3. C++ style, 'this->'.
>>
>> I have taken the 3rd path. It simplifies my code to not assume a handle as
>> well as not allow for reference fetch calls every now and then.
>>
>> As a disadvantage: it means passing this as argument - and some cases
>> maintaining it as __rte_unused.
>>
>> Taking (1) or (2) is not advantageous than this approach.
>
> 1) is the simplest one.
>
> When you write a pci_scan method and embed it in you pci_bus object,
> but this pci_scan method still wonders which bus object it is supposed
> to work on, this is a bit like Schizophrenia ;-).

:)
This now is linked to the above issue of constructor priority and having 
a global bus reference. I don't personally prefer it.
I will still give this a serious thought, though.

>
>
>>> Is is that you want to have a single scan method used by multiple buses ?
>>
>>
>> Yes, but only as a use case. For example, platform devices are of various
>> types - what if we have a south-bound bus over a platform bus. In which
>> case, a hierarchical bus layout is possible.
>> But, this is far-fetched idea for now.
>
> Well, if you have no usecase at the moment, let's keep it simple, please.
>

Ok.

>
>>>
>>>> 0006:      Integrate bus scan/match with EAL, without any effective
>>>> driver
>>>
>>>
>>> Hard to find a right balance in patch splittng, but patch 4 and 6 are
>>> linked, I would squash them into one.
>>
>>
>> Yes, it is hard and sometimes there is simply no strong rationale for
>> splitting or merging. This is one of those cases.
>> My idea was that one patch _only_ introduces Bus services (structures,
>> functions etc) and another should enable the calls to it from EAL.
>> In that sense, I still think 4 and 6 should remain separate, may be
>> consecutive, though.
>
> Ok, will see in next version of the patchset.

Is there anything specific that you are looking for in patchset v2?
I was thinking of:
0. fixing BSD compilation issue reported by CI
1. improving the test_pci.c
2. hotplugging
3. trying to move PCI to drives/bus/pci/linux/* and resolving how 
drivers link to it, and how EAL resources like devargs are consumed.

Anything else?

>
>
>>>
>>>> 0007:      rte_pci_driver->probe replaced with rte_driver->probe
>>>
>>>
>>> This patch is too big, please separate in two patches: eal changes
>>> then ethdev/driver changes.
>>
>>
>> I don't think that can be done. One change is incomplete without the other.
>>
>> Changes to all files are only for rte_pci_driver->probe to rte_driver->probe
>> movement. EAL changes is to allow rte_eth_dev_pci_probe function after such
>> a change as rte_driver->probe has different arguments as compared to
>> rte_pci_driver->probe. The patches won't compile if I split.
>>
>> Am I missing something?
>>>
>>> Why do you push back the driver object in the 'probe' method ? (idem
>>> rte_bus->scan).
>>
>>
>> I am assuming you are referring to rte_driver->probe().
>> This is being done so that implementations (specific to drivers on a
>> particular bus) can start extracting the rte_xxx_driver, if need be.
>>
>> For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to
>> rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In
>> absence of the rte_driver object, this function cannot call
>> rte_pci_driver->probe (for example) for driver specific operations.
>
> Sorry, I am thinking a step ahead with eth_driver out of the picture.
> But once eth_driver disappears, I can see no reason to keep this
> driver in the probe method (Schizophrenia again).

When eth_driver disappears, i was thinking of accomodating the 
eth_dev_init into the rte_pci_driver->probe/init.
But, this is still a nascent thought.
I am yet to start working on eth_driver.

>
>
>

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-07 13:10       ` Shreyansh Jain
@ 2016-12-07 13:24         ` Thomas Monjalon
  2016-12-08  5:04           ` Shreyansh Jain
  2016-12-12 14:35         ` Jianbo Liu
  1 sibling, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2016-12-07 13:24 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: David Marchand, dev

2016-12-07 18:40, Shreyansh Jain:
> Is there anything specific that you are looking for in patchset v2?
> I was thinking of:
> 0. fixing BSD compilation issue reported by CI
> 1. improving the test_pci.c
> 2. hotplugging
> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how 
> drivers link to it, and how EAL resources like devargs are consumed.

I am concerned about the time needed for all these changes.
Please let's make sure that the basic parts are well done and pushed, first.
That's why I suggest to postpone 1, 2 and 3 to next release if possible.
The priority is to have a clean bus model,
and if time permits, integrate the NXP driver.

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-07 13:24         ` Thomas Monjalon
@ 2016-12-08  5:04           ` Shreyansh Jain
  2016-12-08  7:21             ` Thomas Monjalon
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-08  5:04 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: David Marchand, dev

On Wednesday 07 December 2016 06:54 PM, Thomas Monjalon wrote:
> 2016-12-07 18:40, Shreyansh Jain:
>> Is there anything specific that you are looking for in patchset v2?
>> I was thinking of:
>> 0. fixing BSD compilation issue reported by CI
>> 1. improving the test_pci.c
>> 2. hotplugging
>> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how
>> drivers link to it, and how EAL resources like devargs are consumed.
>
> I am concerned about the time needed for all these changes.
> Please let's make sure that the basic parts are well done and pushed, first.
> That's why I suggest to postpone 1, 2 and 3 to next release if possible.
> The priority is to have a clean bus model,
> and if time permits, integrate the NXP driver.
>

I am absolutely OK with this.

Just a confirmation, though. Is it OK to have a broken test_pci.c (1) in 
a series? It is not getting compiled by default, but it would definitely 
not work if compiled (symbols are missing).

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-08  5:04           ` Shreyansh Jain
@ 2016-12-08  7:21             ` Thomas Monjalon
  2016-12-08  7:53               ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2016-12-08  7:21 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: David Marchand, dev

2016-12-08 10:34, Shreyansh Jain:
> On Wednesday 07 December 2016 06:54 PM, Thomas Monjalon wrote:
> > 2016-12-07 18:40, Shreyansh Jain:
> >> Is there anything specific that you are looking for in patchset v2?
> >> I was thinking of:
> >> 0. fixing BSD compilation issue reported by CI
> >> 1. improving the test_pci.c
> >> 2. hotplugging
> >> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how
> >> drivers link to it, and how EAL resources like devargs are consumed.
> >
> > I am concerned about the time needed for all these changes.
> > Please let's make sure that the basic parts are well done and pushed, first.
> > That's why I suggest to postpone 1, 2 and 3 to next release if possible.
> > The priority is to have a clean bus model,
> > and if time permits, integrate the NXP driver.
> >
> 
> I am absolutely OK with this.
> 
> Just a confirmation, though. Is it OK to have a broken test_pci.c (1) in 
> a series? It is not getting compiled by default, but it would definitely 
> not work if compiled (symbols are missing).

No, that's why I said "if possible" :).
I thought 1. was about improvements. But if it does not compile, it is
a must.

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-08  7:21             ` Thomas Monjalon
@ 2016-12-08  7:53               ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-08  7:53 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: David Marchand, dev

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Thursday, December 08, 2016 12:51 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: David Marchand <david.marchand@6wind.com>; dev@dpdk.org
> Subject: Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
> 
> 2016-12-08 10:34, Shreyansh Jain:
> > On Wednesday 07 December 2016 06:54 PM, Thomas Monjalon wrote:
> > > 2016-12-07 18:40, Shreyansh Jain:
> > >> Is there anything specific that you are looking for in patchset v2?
> > >> I was thinking of:
> > >> 0. fixing BSD compilation issue reported by CI
> > >> 1. improving the test_pci.c
> > >> 2. hotplugging
> > >> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how
> > >> drivers link to it, and how EAL resources like devargs are consumed.
> > >
> > > I am concerned about the time needed for all these changes.
> > > Please let's make sure that the basic parts are well done and pushed,
> first.
> > > That's why I suggest to postpone 1, 2 and 3 to next release if possible.
> > > The priority is to have a clean bus model,
> > > and if time permits, integrate the NXP driver.
> > >
> >
> > I am absolutely OK with this.
> >
> > Just a confirmation, though. Is it OK to have a broken test_pci.c (1) in
> > a series? It is not getting compiled by default, but it would definitely
> > not work if compiled (symbols are missing).
> 
> No, that's why I said "if possible" :).
> I thought 1. was about improvements. But if it does not compile, it is
> a must.

Agree.
I should have mentioned 'fixing the test_pci.c' rather than 'improvement'.

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

* Re: [PATCH 07/13] pci: replace probe and remove handlers with rte_driver
  2016-12-04 10:11 ` [PATCH 07/13] pci: replace probe and remove handlers with rte_driver Shreyansh Jain
@ 2016-12-08 17:50   ` Ferruh Yigit
  2016-12-09  4:59     ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Ferruh Yigit @ 2016-12-08 17:50 UTC (permalink / raw)
  To: Shreyansh Jain, dev; +Cc: thomas.monjalon, david.marchand, Adrien Mazarguil

Hi Shreyansh,

On 12/4/2016 10:11 AM, Shreyansh Jain wrote:
> rte_pci_driver probe/remove callback are replaced with the rte_driver
> based probe/remove. This patch changes all the PCI drivers which reference
> rte_pci_driver->probe/remove.
> 
> rte_pci_driver continues to have probe/remove callback which would be used
> once eth_driver is removed in later patches.
> 
> Only changes to PCI are done. VDEV changes require a different
> model because of arguments being passed to vdev->probe/remove.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  drivers/net/bnx2x/bnx2x_ethdev.c        | 12 ++++++++----
>  drivers/net/bnxt/bnxt_ethdev.c          |  6 ++++--
>  drivers/net/cxgbe/cxgbe_ethdev.c        |  6 ++++--
>  drivers/net/e1000/em_ethdev.c           |  6 ++++--
>  drivers/net/e1000/igb_ethdev.c          | 12 ++++++++----
>  drivers/net/ena/ena_ethdev.c            |  6 ++++--
>  drivers/net/enic/enic_ethdev.c          |  6 ++++--
>  drivers/net/fm10k/fm10k_ethdev.c        |  6 ++++--
>  drivers/net/i40e/i40e_ethdev.c          |  6 ++++--
>  drivers/net/i40e/i40e_ethdev_vf.c       |  6 ++++--
>  drivers/net/ixgbe/ixgbe_ethdev.c        | 12 ++++++++----
>  drivers/net/mlx4/mlx4.c                 |  6 ++++--

Generating compile error:
.../net/mlx4/mlx4.c:5913:13: error: subobject initialization overrides
initialization of other fields within its enclosing subobject
[-Werror,-Winitializer-overrides]
                .driver = {
                          ^
.../net/mlx4/mlx4.c:5909:13: note: previous initialization is here
                .driver = {
                          ^


>  drivers/net/mlx5/mlx5.c                 |  4 +++-

.../net/mlx5/mlx5.c:736:13: error: subobject initialization overrides
initialization of other fields within its enclosing subobject
[-Werror,-Winitializer-overrides]
                .driver = {
                          ^
.../net/mlx5/mlx5.c:732:13: note: previous initialization is here
                .driver = {
                          ^


>  drivers/net/nfp/nfp_net.c               |  6 ++++--
>  drivers/net/qede/qede_ethdev.c          | 16 ++++++++++------
>  drivers/net/szedata2/rte_eth_szedata2.c |  6 ++++--
>  drivers/net/virtio/virtio_ethdev.c      |  4 ++--
>  drivers/net/vmxnet3/vmxnet3_ethdev.c    |  6 ++++--

Following drivers seems missing:
drivers/net/thunderx/nicvf_ethdev.c

Also new added drivers/net/sfc/sfc_ethdev.c, but since sfc is not merged
to main branch yet, perhaps fix may wait your patches to be applied first.

>  lib/librte_eal/common/eal_common_pci.c  | 10 ++++++++--
>  lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
>  lib/librte_ether/rte_ethdev.c           | 16 ++++++++++++----
>  lib/librte_ether/rte_ethdev.h           |  6 +++---
>  22 files changed, 122 insertions(+), 54 deletions(-)
> 

Also getting following with mlx5:

In file included from
.../x86_64-native-linuxapp-gcc/include/rte_mbuf.h:57:0,
                 from .../x86_64-native-linuxapp-gcc/include/rte_ether.h:52,
                 from .../drivers/net/mlx5/mlx5_trigger.c:38:
/usr/include/infiniband/verbs.h: In function ‘verbs_get_device’:
.../x86_64-native-linuxapp-gcc/include/rte_common.h:350:40: error:
initialization discards ‘const’ qualifier from pointer target type
[-Werror=discarded-qualifiers]
    typeof(((type *)0)->member) *_ptr = (ptr); \


<...>

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

* Re: [PATCH 07/13] pci: replace probe and remove handlers with rte_driver
  2016-12-08 17:50   ` Ferruh Yigit
@ 2016-12-09  4:59     ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-09  4:59 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: thomas.monjalon, david.marchand, Adrien Mazarguil

Hello Ferruh,

As always, thanks for your checks.

> -----Original Message-----
> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Thursday, December 08, 2016 11:21 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>; dev@dpdk.org
> Cc: thomas.monjalon@6wind.com; david.marchand@6wind.com; Adrien Mazarguil
> <adrien.mazarguil@6wind.com>
> Subject: Re: [dpdk-dev] [PATCH 07/13] pci: replace probe and remove handlers
> with rte_driver
> 
> Hi Shreyansh,
> 
> On 12/4/2016 10:11 AM, Shreyansh Jain wrote:
> > rte_pci_driver probe/remove callback are replaced with the rte_driver
> > based probe/remove. This patch changes all the PCI drivers which reference
> > rte_pci_driver->probe/remove.
> >
> > rte_pci_driver continues to have probe/remove callback which would be used
> > once eth_driver is removed in later patches.
> >
> > Only changes to PCI are done. VDEV changes require a different
> > model because of arguments being passed to vdev->probe/remove.
> >
> > Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> > ---
> >  drivers/net/bnx2x/bnx2x_ethdev.c        | 12 ++++++++----
> >  drivers/net/bnxt/bnxt_ethdev.c          |  6 ++++--
> >  drivers/net/cxgbe/cxgbe_ethdev.c        |  6 ++++--
> >  drivers/net/e1000/em_ethdev.c           |  6 ++++--
> >  drivers/net/e1000/igb_ethdev.c          | 12 ++++++++----
> >  drivers/net/ena/ena_ethdev.c            |  6 ++++--
> >  drivers/net/enic/enic_ethdev.c          |  6 ++++--
> >  drivers/net/fm10k/fm10k_ethdev.c        |  6 ++++--
> >  drivers/net/i40e/i40e_ethdev.c          |  6 ++++--
> >  drivers/net/i40e/i40e_ethdev_vf.c       |  6 ++++--
> >  drivers/net/ixgbe/ixgbe_ethdev.c        | 12 ++++++++----
> >  drivers/net/mlx4/mlx4.c                 |  6 ++++--
> 
> Generating compile error:
> .../net/mlx4/mlx4.c:5913:13: error: subobject initialization overrides
> initialization of other fields within its enclosing subobject
> [-Werror,-Winitializer-overrides]
>                 .driver = {
>                           ^
> .../net/mlx4/mlx4.c:5909:13: note: previous initialization is here
>                 .driver = {
>                           ^
> 
> 
> >  drivers/net/mlx5/mlx5.c                 |  4 +++-
> 
> .../net/mlx5/mlx5.c:736:13: error: subobject initialization overrides
> initialization of other fields within its enclosing subobject
> [-Werror,-Winitializer-overrides]
>                 .driver = {
>                           ^
> .../net/mlx5/mlx5.c:732:13: note: previous initialization is here
>                 .driver = {
>                           ^
> 

Yes, David Marchand also highlighted this another comment. Somehow I messed up the MLX changes. And just like the last time, I forgot to change my environment configuration to enable it before sending the patches.
 

> 
> >  drivers/net/nfp/nfp_net.c               |  6 ++++--
> >  drivers/net/qede/qede_ethdev.c          | 16 ++++++++++------
> >  drivers/net/szedata2/rte_eth_szedata2.c |  6 ++++--
> >  drivers/net/virtio/virtio_ethdev.c      |  4 ++--
> >  drivers/net/vmxnet3/vmxnet3_ethdev.c    |  6 ++++--
> 
> Following drivers seems missing:
> drivers/net/thunderx/nicvf_ethdev.c

I will fix this as well in v2. 

> 
> Also new added drivers/net/sfc/sfc_ethdev.c, but since sfc is not merged
> to main branch yet, perhaps fix may wait your patches to be applied first.
> 
> >  lib/librte_eal/common/eal_common_pci.c  | 10 ++++++++--
> >  lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
> >  lib/librte_ether/rte_ethdev.c           | 16 ++++++++++++----
> >  lib/librte_ether/rte_ethdev.h           |  6 +++---
> >  22 files changed, 122 insertions(+), 54 deletions(-)
> >
> 
> Also getting following with mlx5:
> 
> In file included from
> .../x86_64-native-linuxapp-gcc/include/rte_mbuf.h:57:0,
>                  from .../x86_64-native-linuxapp-gcc/include/rte_ether.h:52,
>                  from .../drivers/net/mlx5/mlx5_trigger.c:38:
> /usr/include/infiniband/verbs.h: In function 'verbs_get_device':
> .../x86_64-native-linuxapp-gcc/include/rte_common.h:350:40: error:
> initialization discards 'const' qualifier from pointer target type
> [-Werror=discarded-qualifiers]
>     typeof(((type *)0)->member) *_ptr = (ptr); \
> 
> 
> <...>

I will check MLX* again.
Thanks for your inputs.

-
Shreyansh

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-07 13:10       ` Shreyansh Jain
  2016-12-07 13:24         ` Thomas Monjalon
@ 2016-12-12 14:35         ` Jianbo Liu
  2016-12-13  6:56           ` Shreyansh Jain
  1 sibling, 1 reply; 132+ messages in thread
From: Jianbo Liu @ 2016-12-12 14:35 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: David Marchand, dev, Thomas Monjalon

Hi Shreyansh,

On 7 December 2016 at 21:10, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> On Wednesday 07 December 2016 05:47 PM, David Marchand wrote:
>>
>> Hello Shreyansh,
>>
>> On Wed, Dec 7, 2016 at 10:55 AM, Shreyansh Jain <shreyansh.jain@nxp.com>
>> wrote:
>>>
>>> On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
>>>>>
>>>>> 0002~0003: Introducing the basic Bus model and associated test case
>>>>> 0005:      Support insertion of device rather than addition to tail
>>>>
>>>>
>>>>
>>>> Patch 2 and 5 could be squashed.
>>>
>>>
>>>
>>> I deliberately kept them separate. I intent to extend the Patch 5 for
>>> hotplugging. But, if I don't end up adding support for that in this
>>> series,
>>> I will merge these two.
>>
>>
>> Fine.
>>
>>
>>>> The constructor priority stuff seems unneeded as long as we use
>>>> explicit reference to a global (or local, did not check) bus symbol
>>>> rather than a runtime lookup.
>>>
>>>
>>>
>>> I didn't understand your point here.
>>> IMO, constructor priority (or some other way to handle this) is
>>> important. I
>>> faced this issue while verifying it at my end when the drivers were
>>> getting
>>> registered before the bus.
>>>
>>> Can you elaborate more on '..use explicit reference to a global...'?
>>
>>
>> The drivers register themselves to a bus using this bus specific api.
>>
>> For pci, this is rte_eal_pci_register().
>> The pci_bus object must be moved to eal_common_pci.c (we can stil
>> internally expose for bsd / linux specific implementations).
>> Then, rte_eal_pci_register() can add the pci driver to the pci_bus
>> drivers list even if this pci_bus object is not registered yet to the
>> buses list.
>
>
> So, in eal_common_bus.c
>
> --->8---
>
> struct rte_bus *global_ptr_to_pci_bus = NULL;
>
> struct rte_bus pci_bus = { ... };
>
> rte_eal_pci_register() {
>     if (global_ptr_to_pci_bus == NULL)
>         rte_eal_bus_register(&pci_bus)
>     else
>        // continue as if PCI bus is registered
> }
>
> --->8---
>
> so, no RTE_REGISTER_BUS()?
>
> If yes, then RTE_REGISTER_BUS() should also check for an existing
> registration for duplication.
>
> I was banking on a model where bus handlers (or bus drivers) are independent
> entities, just like PMDs. So, we have a bus XYZ without any drivers
> necessarily based on it.
>
> By making registration dependent on driver registration, it becomes implicit
> that buses don't exist without drivers.
> I am not in favor of this - or maybe I lack enough reason for this (about
> how it will make framework/PMD life better).
>
>>
>> And no constructor order issue ?
>>
>>
>>>>
>>>>
>>>>> 0004:      Add scan and match callbacks for the Bus and updated test
>>>>> case
>>>>
>>>>
>>>>
>>>> Why do you push back the bus object in the 'scan' method ?
>>>> This method is bus specific which means that the code "knows" the
>>>> object registered with the callback.
>>>
>>>
>>>
>>> This 'knows' is the grey area for me.
>>> The bus (for example, PCI) after scanning needs to call
>>> rte_eal_bus_add_device() to link the device in bus's device_list.
>>>
>>> Two options:
>>> 1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
>>> 2. Call rte_eal_get_bus() every time someone needs the reference.
>>> 3. C++ style, 'this->'.
>>>
>>> I have taken the 3rd path. It simplifies my code to not assume a handle
>>> as
>>> well as not allow for reference fetch calls every now and then.
>>>
>>> As a disadvantage: it means passing this as argument - and some cases
>>> maintaining it as __rte_unused.
>>>
>>> Taking (1) or (2) is not advantageous than this approach.
>>
>>
>> 1) is the simplest one.
>>
>> When you write a pci_scan method and embed it in you pci_bus object,
>> but this pci_scan method still wonders which bus object it is supposed
>> to work on, this is a bit like Schizophrenia ;-).
>
>
> :)
> This now is linked to the above issue of constructor priority and having a
> global bus reference. I don't personally prefer it.
> I will still give this a serious thought, though.
>

I'm also in favor of (3).

>>
>>
>>>> Is is that you want to have a single scan method used by multiple buses
>>>> ?
>>>
>>>
>>>
>>> Yes, but only as a use case. For example, platform devices are of various
>>> types - what if we have a south-bound bus over a platform bus. In which
>>> case, a hierarchical bus layout is possible.
>>> But, this is far-fetched idea for now.
>>

How to express the hierarchical bus layout as the bus in your design
is more like independent objects to hold drivers and their devices?

>>
>> Well, if you have no usecase at the moment, let's keep it simple, please.
>>
>
> Ok.
>
>>
>>>>
>>>>> 0006:      Integrate bus scan/match with EAL, without any effective
>>>>> driver
>>>>
>>>>
>>>>
>>>> Hard to find a right balance in patch splittng, but patch 4 and 6 are
>>>> linked, I would squash them into one.
>>>
>>>
>>>
>>> Yes, it is hard and sometimes there is simply no strong rationale for
>>> splitting or merging. This is one of those cases.
>>> My idea was that one patch _only_ introduces Bus services (structures,
>>> functions etc) and another should enable the calls to it from EAL.
>>> In that sense, I still think 4 and 6 should remain separate, may be
>>> consecutive, though.
>>
>>
>> Ok, will see in next version of the patchset.
>
>
> Is there anything specific that you are looking for in patchset v2?
> I was thinking of:
> 0. fixing BSD compilation issue reported by CI
> 1. improving the test_pci.c
> 2. hotplugging
> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how drivers
> link to it, and how EAL resources like devargs are consumed.
>
> Anything else?
>
>>
>>
>>>>
>>>>> 0007:      rte_pci_driver->probe replaced with rte_driver->probe
>>>>
>>>>
>>>>
>>>> This patch is too big, please separate in two patches: eal changes
>>>> then ethdev/driver changes.
>>>
>>>
>>>
>>> I don't think that can be done. One change is incomplete without the
>>> other.
>>>
>>> Changes to all files are only for rte_pci_driver->probe to
>>> rte_driver->probe
>>> movement. EAL changes is to allow rte_eth_dev_pci_probe function after
>>> such
>>> a change as rte_driver->probe has different arguments as compared to
>>> rte_pci_driver->probe. The patches won't compile if I split.
>>>
>>> Am I missing something?
>>>>
>>>>
>>>> Why do you push back the driver object in the 'probe' method ? (idem
>>>> rte_bus->scan).
>>>
>>>
>>>
>>> I am assuming you are referring to rte_driver->probe().
>>> This is being done so that implementations (specific to drivers on a
>>> particular bus) can start extracting the rte_xxx_driver, if need be.
>>>
>>> For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to
>>> rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In
>>> absence of the rte_driver object, this function cannot call
>>> rte_pci_driver->probe (for example) for driver specific operations.
>>
>>
>> Sorry, I am thinking a step ahead with eth_driver out of the picture.
>> But once eth_driver disappears, I can see no reason to keep this
>> driver in the probe method (Schizophrenia again).
>
>
> When eth_driver disappears, i was thinking of accomodating the eth_dev_init
> into the rte_pci_driver->probe/init.
> But, this is still a nascent thought.
> I am yet to start working on eth_driver.
>
>>
>>
>>
>

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

* Re: [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
  2016-12-12 14:35         ` Jianbo Liu
@ 2016-12-13  6:56           ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13  6:56 UTC (permalink / raw)
  To: Jianbo Liu; +Cc: David Marchand, dev, Thomas Monjalon, Ferruh Yigit

Hello Jianbo,

On Monday 12 December 2016 08:05 PM, Jianbo Liu wrote:
> Hi Shreyansh,
>
> On 7 December 2016 at 21:10, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> On Wednesday 07 December 2016 05:47 PM, David Marchand wrote:
>>>
>>> Hello Shreyansh,
>>>
>>> On Wed, Dec 7, 2016 at 10:55 AM, Shreyansh Jain <shreyansh.jain@nxp.com>
>>> wrote:
>>>>
>>>> On Wednesday 07 December 2016 02:22 AM, David Marchand wrote:
>>>>>>
>>>>>> 0002~0003: Introducing the basic Bus model and associated test case
>>>>>> 0005:      Support insertion of device rather than addition to tail
>>>>>
>>>>>
>>>>>
>>>>> Patch 2 and 5 could be squashed.
>>>>
>>>>
>>>>
>>>> I deliberately kept them separate. I intent to extend the Patch 5 for
>>>> hotplugging. But, if I don't end up adding support for that in this
>>>> series,
>>>> I will merge these two.
>>>
>>>
>>> Fine.
>>>
>>>
>>>>> The constructor priority stuff seems unneeded as long as we use
>>>>> explicit reference to a global (or local, did not check) bus symbol
>>>>> rather than a runtime lookup.
>>>>
>>>>
>>>>
>>>> I didn't understand your point here.
>>>> IMO, constructor priority (or some other way to handle this) is
>>>> important. I
>>>> faced this issue while verifying it at my end when the drivers were
>>>> getting
>>>> registered before the bus.
>>>>
>>>> Can you elaborate more on '..use explicit reference to a global...'?
>>>
>>>
>>> The drivers register themselves to a bus using this bus specific api.
>>>
>>> For pci, this is rte_eal_pci_register().
>>> The pci_bus object must be moved to eal_common_pci.c (we can stil
>>> internally expose for bsd / linux specific implementations).
>>> Then, rte_eal_pci_register() can add the pci driver to the pci_bus
>>> drivers list even if this pci_bus object is not registered yet to the
>>> buses list.
>>
>>
>> So, in eal_common_bus.c
>>
>> --->8---
>>
>> struct rte_bus *global_ptr_to_pci_bus = NULL;
>>
>> struct rte_bus pci_bus = { ... };
>>
>> rte_eal_pci_register() {
>>     if (global_ptr_to_pci_bus == NULL)
>>         rte_eal_bus_register(&pci_bus)
>>     else
>>        // continue as if PCI bus is registered
>> }
>>
>> --->8---
>>
>> so, no RTE_REGISTER_BUS()?
>>
>> If yes, then RTE_REGISTER_BUS() should also check for an existing
>> registration for duplication.
>>
>> I was banking on a model where bus handlers (or bus drivers) are independent
>> entities, just like PMDs. So, we have a bus XYZ without any drivers
>> necessarily based on it.
>>
>> By making registration dependent on driver registration, it becomes implicit
>> that buses don't exist without drivers.
>> I am not in favor of this - or maybe I lack enough reason for this (about
>> how it will make framework/PMD life better).
>>
>>>
>>> And no constructor order issue ?
>>>
>>>
>>>>>
>>>>>
>>>>>> 0004:      Add scan and match callbacks for the Bus and updated test
>>>>>> case
>>>>>
>>>>>
>>>>>
>>>>> Why do you push back the bus object in the 'scan' method ?
>>>>> This method is bus specific which means that the code "knows" the
>>>>> object registered with the callback.
>>>>
>>>>
>>>>
>>>> This 'knows' is the grey area for me.
>>>> The bus (for example, PCI) after scanning needs to call
>>>> rte_eal_bus_add_device() to link the device in bus's device_list.
>>>>
>>>> Two options:
>>>> 1. Have a global reference to "pci" bus (rte_bus) somewhere in eal_pci.c
>>>> 2. Call rte_eal_get_bus() every time someone needs the reference.
>>>> 3. C++ style, 'this->'.
>>>>
>>>> I have taken the 3rd path. It simplifies my code to not assume a handle
>>>> as
>>>> well as not allow for reference fetch calls every now and then.
>>>>
>>>> As a disadvantage: it means passing this as argument - and some cases
>>>> maintaining it as __rte_unused.
>>>>
>>>> Taking (1) or (2) is not advantageous than this approach.
>>>
>>>
>>> 1) is the simplest one.
>>>
>>> When you write a pci_scan method and embed it in you pci_bus object,
>>> but this pci_scan method still wonders which bus object it is supposed
>>> to work on, this is a bit like Schizophrenia ;-).
>>
>>
>> :)
>> This now is linked to the above issue of constructor priority and having a
>> global bus reference. I don't personally prefer it.
>> I will still give this a serious thought, though.
>>
>
> I'm also in favor of (3).

Thank you. I was almost done with v2 and in that I had changed to what 
David had suggested. My preference too is (3). Now, I will prefer 
sticking with it - until someone comes with technical issue (like 
compiler compatibility etc) which I am unaware of.

@David: Can you re-think if you still prefer (1)? If so, I will change 
it in v3 (I will send v2 in a day or two max).

>
>>>
>>>
>>>>> Is is that you want to have a single scan method used by multiple buses
>>>>> ?
>>>>
>>>>
>>>>
>>>> Yes, but only as a use case. For example, platform devices are of various
>>>> types - what if we have a south-bound bus over a platform bus. In which
>>>> case, a hierarchical bus layout is possible.
>>>> But, this is far-fetched idea for now.
>>>
>
> How to express the hierarchical bus layout as the bus in your design
> is more like independent objects to hold drivers and their devices?

What I had in mind was something on the lines of:
  1) Add a new linked list 'bus_list' in rte_bus
  2) OR, embed rte_device in rte_bus

(1) is for maintaining buses as independent entity; (2) is for treating 
buses like devices (very similar to what Ferruh once suggested [2]). I
prefer (1), but I think programmatically (2) is much more symmetrical. I 
am assuming (1) below.

If we have: (taking hint from [1])

                  CPU
                   |
  ====,============`============= PCI Bus 0
      |
    PCI-PCI
    Bridge
      |
   =,='=======,====== PCI Bus 1
    |         |
   SCSI     Ethernet


PCI Bus 0 (rte_bus)pci_bus_0
`.-> scan(): this calls knows it is a PCI-PCI bridge. It would allocate
  |           a new pci_bus_1 (rte_bus object) and attach to bus_list.
  |           Then, assign generic SCSI scan functions to pci_bus_1->scan
  |           and pci_bus_1->match.
  `-> eal/probe()
             - bus->match() is called with rte_device/driver. In this
               case, it would move over all the buses in bus_list pivoted
               on pci_bus_0 and call rte_bus->match.
             - (#) For each matched entry, subsequently call the
               rte_bus->probe()
             - (*) Cascading calls to rte_driver->probe() for pci_bus_1

(#) there is still an open discussion about whether bus->probe() should 
exist or not. (I am not convinced buses should probe, but DPDK model 
doesn't bode well without it)

(*) pci_bus_0->probe() would get rte_device/rte_driver as NULL and 
rotate over each device/driver scanned in pci_bus_1 calling bus->probe.

[1] http://www.tldp.org/LDP/tlk/dd/pci.html
[2] http://dpdk.org/ml/archives/dev/2016-August/045947.html

(Note: I agree that there are minor holes in above theory, specifically 
from implementation point. But, I am confident that with minor changes 
this is achievable).

>
>>>
>>> Well, if you have no usecase at the moment, let's keep it simple, please.
>>>
>>
>> Ok.
>>
>>>
>>>>>
>>>>>> 0006:      Integrate bus scan/match with EAL, without any effective
>>>>>> driver
>>>>>
>>>>>
>>>>>
>>>>> Hard to find a right balance in patch splittng, but patch 4 and 6 are
>>>>> linked, I would squash them into one.
>>>>
>>>>
>>>>
>>>> Yes, it is hard and sometimes there is simply no strong rationale for
>>>> splitting or merging. This is one of those cases.
>>>> My idea was that one patch _only_ introduces Bus services (structures,
>>>> functions etc) and another should enable the calls to it from EAL.
>>>> In that sense, I still think 4 and 6 should remain separate, may be
>>>> consecutive, though.
>>>
>>>
>>> Ok, will see in next version of the patchset.
>>
>>
>> Is there anything specific that you are looking for in patchset v2?
>> I was thinking of:
>> 0. fixing BSD compilation issue reported by CI
>> 1. improving the test_pci.c
>> 2. hotplugging
>> 3. trying to move PCI to drives/bus/pci/linux/* and resolving how drivers
>> link to it, and how EAL resources like devargs are consumed.
>>
>> Anything else?
>>
>>>
>>>
>>>>>
>>>>>> 0007:      rte_pci_driver->probe replaced with rte_driver->probe
>>>>>
>>>>>
>>>>>
>>>>> This patch is too big, please separate in two patches: eal changes
>>>>> then ethdev/driver changes.
>>>>
>>>>
>>>>
>>>> I don't think that can be done. One change is incomplete without the
>>>> other.
>>>>
>>>> Changes to all files are only for rte_pci_driver->probe to
>>>> rte_driver->probe
>>>> movement. EAL changes is to allow rte_eth_dev_pci_probe function after
>>>> such
>>>> a change as rte_driver->probe has different arguments as compared to
>>>> rte_pci_driver->probe. The patches won't compile if I split.
>>>>
>>>> Am I missing something?
>>>>>
>>>>>
>>>>> Why do you push back the driver object in the 'probe' method ? (idem
>>>>> rte_bus->scan).
>>>>
>>>>
>>>>
>>>> I am assuming you are referring to rte_driver->probe().
>>>> This is being done so that implementations (specific to drivers on a
>>>> particular bus) can start extracting the rte_xxx_driver, if need be.
>>>>
>>>> For example, for e1000/em_ethdev.c, rte_driver->probe() have been set to
>>>> rte_eth_dev_pci_probe() which requires rte_pci_driver to work with. In
>>>> absence of the rte_driver object, this function cannot call
>>>> rte_pci_driver->probe (for example) for driver specific operations.
>>>
>>>
>>> Sorry, I am thinking a step ahead with eth_driver out of the picture.
>>> But once eth_driver disappears, I can see no reason to keep this
>>> driver in the probe method (Schizophrenia again).
>>
>>
>> When eth_driver disappears, i was thinking of accomodating the eth_dev_init
>> into the rte_pci_driver->probe/init.
>> But, this is still a nascent thought.
>> I am yet to start working on eth_driver.
>>
>>>
>>>
>>>
>>
>

Thanks for your comments.

-
Shreyansh

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

* [PATCH v2 00/12] Introducing EAL Bus-Device-Driver Model
  2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                   ` (13 preceding siblings ...)
  2016-12-06 20:52 ` [PATCH 00/13] Introducing EAL Bus-Device-Driver Model David Marchand
@ 2016-12-13 13:37 ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 01/12] eal: define container_of macro Shreyansh Jain
                     ` (12 more replies)
  14 siblings, 13 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Link to v1: [10]

:: 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 context of DPDK EAL:
 - rte_bus, represents a Bus. An implementation of a physical bus would
   instantiate this class.
 - Buses are registered just like a PMD - RTE_REGISTER_BUS()
   `- Thus, implementation for PCI would instantiate a rte_bus, give it a
      name and provide scan/match hooks.
    - Currently, priority of RTE_REGISTER_BUS constructor has been set to
      101 to make sure bus is registered *before* drivers are.
 - Each registered bus is part of a doubly list.
   -- Each device refers to rte_bus on which it belongs
   -- Each driver refers to rte_bus with which it is associated
   -- Device and Drivers lists are part of rte_bus
   -- NO global device/driver list would exist
 - When a PMD wants to register itself, it would 'add' itself to an
   existing bus. Which essentially converts to adding the driver to
   a bus specific driver_list.
 - Bus would perform a scan and 'add' devices scanned to its list.
 - Bus would perform a probe and link devices and drivers on each bus and
   invoking a series of probes
   `-- There are some parallel work for combining scan/probe in EAL [5]
       and also for doing away with a independent scan function all
       together [6].


The view would be almost like:

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> device_list for this bus
                     | device_list----    
                     | scan()       | `-> driver_list for this bus
                     | match()      |
                     | probe()      |
                     |              |
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | *rte_bus    |                     | *rte_bus        |
    | rte_driver  |                     | probe()         |
    |             |                     | remove()        |
    |  devargs    |                     |                 |
    +---||--------+                     +---------|||-----+
        ||                                        '''      
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | PCI specific   | | xxx device    |               |||
 | info (mem,)    | | specific fns  |              / | \
 +----------------+ +---------------+             /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | PCI id table,  |    | <probably,     |    | ....          |
            | other driver   |    |  nothing>      |    +---------------+
            | data           |    |  ...           |
            |  probe()       |    +----------------+
            |  remove()      |
            +----------------+

In continuation to the RFC posted on 17/Nov [9],
A series of patches is being posted which attempts to create:
 1. A basic bus model
    `- define rte_bus and associated methods/helpers
    `- test infrastructure to test the Bus infra
 2. Changes in EAL to support PCI as a bus
    `- a "pci" bus is registered
    `- existing scan/match/probe are modified to allow for bus integration
    `- PCI Device and Driver list, which were global entities, have been
       moved to rte_bus->[device/driver]_list

For v2 as well, I have sanity tested this patch over a XeonD X552 available
with me, as well as part of PoC for verifying NXP's DPAA2 PMD (being pushed
out in a separate series). Exhaustive testing is still pending.
 -> Please help in MLX & BSD related changes.

:: Brief about Patch Layout ::

0001:      Container_of patch from [3]
0002~0003: Introducing the basic Bus model and associated test case
0004~0005: Add scan, match and insert support for devices on bus
0006:      Add probe and remove for rte_driver
0007:      Enable probing of PCI Bus (devices) from EAL
0008:      Split the existing PCI probe into match and probe
0009:      Make PCI probe/match work on rte_driver/device rather than
           rte_pci_device/rte_pci_driver
0010:      Patch from Ben [8], part of series [2]
0011:      Enable Scan/Match/probe on Bus from EAL and remove unused
           functions and lists. PMDs still don't work (in fact, PCI PMD
           don't work after this patch - but without any compilation
           issues).
0012:      Change PMDs to integrate with PCI bus

:: Pending Changes/Caveats ::

0. eth_dev still contains rte_pci_device. I am banking on Jan's patches [1]
   for conversion to a macro (ETH_DEV_PCI_DEV) and subsequent replacement
   of all pci_dev usage in eth_dev.

1. One of the major changes pending, as against proposed in RFC, is the
   removal of eth_driver.
   Being a large change, and independent one, this would be done in a
   separate series of patches. []

2. app/test/test_pci.c is still not modified. It is rendered uncompilable
   as most of the APIs it was calling don't exist anymore. I will push a
   v2 which would include a complete re-write of test_pci (or, if someone
   can help me that, it would be awesome).

3. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   - there was an open question in RFC about where to place the PCI bus
     instance - whether in drivers/bus/... or in lib/librte_bus/... or
     lib/librte_eal/...; This patch uses the last option. But, movement
     only impacts placement of Makefiles. Please convey your reservations
     for current placement.
   - It also impacts the point (8) about priority use in constructor

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

5. There was a suggestion from Jan Blunk about a helper iterator within the
   rte_bus. I will send this out in v3.

6. Cyptodev and VDEV changes are still pending. Jan has already conveyed
   that he would be working on the VDEV part. I will work on the Crypto
   part and target that for v3.

7. The overall layout for driver probing has changed a little.
   earlier, it was:
    rte_eal_init()
     `-> rte_eal_pci_probe() (and parallel for VDEV)
         `-> rte_pci_driver->probe()
             `-> eth_driver->eth_dev_init()

   now, it would be:
   rte_eal_init()
     `-> rte_eal_bus_probe() <- Iterator for PCI device/driver
         `-> rte_driver->probe() <- devargs handling
             |                      old rte_eal_pci_probe()
             `-> rte_xxx_driver->probe() <- eth_dev allocation
                 `-> eth_driver->eth_dev_init <- eth_dev init

   Open Questions:
       Also, rte_driver->probe() creating eth_dev certainly sounds a little
       wrong - but, I would like to get your opinion on how to lay this
       order of which layer ethernet device corresponds to.
       1) Which layer should allocate eth_dev?
          `-> My take: rte_driver->probe()
       2) which layer should fill the eth_dev?
          `-> My take: rte_xxx_driver->probe()
       3) Is init/uninit better name for rte_xxx_driver()->probe() if all
          they do is initialize the ethernet device?

 8. 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 ::

 - app/test/test_pci.c compilation is failing, if enabled.
 - Bump to librte_eal version
 - Documentation continues to have references to some _old_ PCI symbols
 - vdev changes
 - eth_device, eth_driver changes

:: 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

:: Version Changes ::
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)

Ben Walker (1):
  pci: Pass rte_pci_addr to functions instead of separate args

Jan Blunck (1):
  eal: define container_of macro

Shreyansh Jain (10):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  eal/bus: add scan, match and insert support
  eal: integrate bus scan and probe with EAL
  eal: add probe and remove support for rte_driver
  eal: enable probe from bus infrastructure
  pci: split match and probe function
  eal/pci: generalize args of PCI scan/match towards RTE device/driver
  eal: enable PCI bus
  drivers: update PMDs to use rte_driver probe and remove

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 688 ++++++++++++++++++++++++
 app/test/test_pci.c                             |   2 +-
 drivers/net/bnx2x/bnx2x_ethdev.c                |   8 +
 drivers/net/bnxt/bnxt_ethdev.c                  |   4 +
 drivers/net/cxgbe/cxgbe_ethdev.c                |   4 +
 drivers/net/e1000/em_ethdev.c                   |   4 +
 drivers/net/e1000/igb_ethdev.c                  |   8 +
 drivers/net/ena/ena_ethdev.c                    |   4 +
 drivers/net/enic/enic_ethdev.c                  |   4 +
 drivers/net/fm10k/fm10k_ethdev.c                |   4 +
 drivers/net/i40e/i40e_ethdev.c                  |   4 +
 drivers/net/i40e/i40e_ethdev_vf.c               |   4 +
 drivers/net/ixgbe/ixgbe_ethdev.c                |   8 +
 drivers/net/mlx4/mlx4.c                         |   4 +-
 drivers/net/mlx5/mlx5.c                         |   1 +
 drivers/net/nfp/nfp_net.c                       |   4 +
 drivers/net/qede/qede_ethdev.c                  |   8 +
 drivers/net/szedata2/rte_eth_szedata2.c         |   4 +
 drivers/net/thunderx/nicvf_ethdev.c             |   4 +
 drivers/net/virtio/virtio_ethdev.c              |   2 +
 drivers/net/vmxnet3/vmxnet3_ethdev.c            |   4 +
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  12 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  22 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 285 ++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 341 +++++++-----
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_bus.h         | 257 +++++++++
 lib/librte_eal/common/include/rte_common.h      |  21 +
 lib/librte_eal/common/include/rte_dev.h         |  14 +
 lib/librte_eal/common/include/rte_pci.h         |  59 +-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  12 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  81 +--
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  22 +-
 39 files changed, 1737 insertions(+), 240 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] 132+ messages in thread

* [PATCH v2 01/12] eal: define container_of macro
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 22:24     ` Jan Blunck
  2016-12-13 13:37   ` [PATCH v2 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
                     ` (11 subsequent siblings)
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Jan Blunck,
	Jan Viktorin, Shreyansh Jain

From: Jan Blunck <jblunck@infradead.org>

This macro is based on Jan Viktorin's original patch but also checks the
type of the passed pointer against the type of the member.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
[shreyansh.jain@nxp.com: Fix checkpatch error]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
[jblunck@infradead.org: add type checking and __extension__]
Signed-off-by: Jan Blunck <jblunck@infradead.org>

--
v2:
 - fix checkpatch error
---
 lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index db5ac91..3eb8d11 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
 #endif
 
+/**
+ * Return pointer to the wrapping struct instance.
+ *
+ * Example:
+ *
+ *  struct wrapper {
+ *      ...
+ *      struct child c;
+ *      ...
+ *  };
+ *
+ *  struct child *x = obtain(...);
+ *  struct wrapper *w = container_of(x, struct wrapper, c);
+ */
+#ifndef container_of
+#define container_of(ptr, type, member)	(__extension__	({		\
+			typeof(((type *)0)->member) * _ptr = (ptr);	\
+			(type *)(((char *)_ptr) - offsetof(type, member));\
+			}))
+#endif
+
 #define _RTE_STR(x) #x
 /** Take a macro value and get a string version of it */
 #define RTE_STR(x) _RTE_STR(x)
-- 
2.7.4

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

* [PATCH v2 02/12] eal/bus: introduce bus abstraction
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 01/12] eal: define container_of macro Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 03/12] test: add basic bus infrastructure tests Shreyansh Jain
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

This patch introduces the rte_bus abstraction for devices and drivers in
EAL framework. 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' class which rte_driver and rte_device refer.
This way, each device (rte_xxx_device) would have reference to the bus
it is based on. As well as, each driver (rte_xxx_driver) would have link
to the bus and devices on it for servicing.

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> List of rte_bus specific
                     | device_list----    devices
                     |              | `-> List of rte_bus associated
                     |              |     drivers
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | rte_bus     |                     | rte_bus         |
    | rte_driver  |                     | ...             |
    | ...         |                     +---------...-----+
    |             |                               |||
    +---||--------+                               |||
        ||                                        |||
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | ....           | | ....          |               |||
 +----------------+ +---------------+              / | \
                                                  /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | ....           |    | ....           |    | ....          |
            +----------------+    +----------------+    +---------------+

This patch only enables the bus references on rte_driver and rte_driver.
EAL wide global device and driver list continue to exist until an instance
of bus is added in subsequent patches.

This patch also introduces RTE_REGISTER_BUS macro on the lines of
RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
been explicitly set to 101 so as to execute bus registration before PMD.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

--
v2:
 - fix bsdapp compilation issue because of missing export symbols in map
   file
---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 192 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 174 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   2 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
 8 files changed, 401 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..23fc1c1 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index a92c984..0c39414 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..612f64e
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,192 @@
+/*-
+ *   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);
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+	dev->bus = bus;
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev);
+	RTE_VERIFY(dev->bus);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+	dev->bus = NULL;
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+	drv->bus = bus;
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(drv);
+	RTE_VERIFY(drv->bus);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, drv, next);
+	drv->bus = NULL;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_get_bus(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strcmp(bus_name, bus->name)) {
+			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
+			return bus;
+		}
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_INIT(&(bus->driver_list));
+	TAILQ_INIT(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	/* TODO: For each device, call its rte_device->driver->remove()
+	 * and rte_eal_bus_remove_driver()
+	 */
+
+	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_eal_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..f0297a9
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,174 @@
+/*-
+ *   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);
+
+/* Global Bus list */
+extern struct rte_bus_list rte_bus_list;
+
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	struct rte_driver_list driver_list;
+				     /**< List of all drivers on bus */
+	struct rte_device_list device_list;
+				     /**< List of all devices on bus */
+	const char *name;            /**< Name of the bus */
+};
+
+/** @internal
+ * Add a device to a bus.
+ *
+ * @param bus
+ *	Bus on which device is to be added
+ * @param dev
+ *	Device handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
+
+/** @internal
+ * Remove a device from its bus.
+ *
+ * @param dev
+ *	Device handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev);
+
+/** @internal
+ * Associate a driver with a bus.
+ *
+ * @param bus
+ *	Bus on which driver is to be added
+ * @param dev
+ *	Driver handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
+
+/** @internal
+ * Disassociate a driver from its bus.
+ *
+ * @param dev
+ *	Driver handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv);
+
+/**
+ * Register a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_eal_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_eal_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Obtain handle for bus given its name.
+ *
+ * @param bus_name
+ *	Name of the bus handle to search
+ * @return
+ *	Pointer to Bus object if name matches any registered bus object
+ *	NULL, if no matching bus found
+ */
+struct rte_bus *rte_eal_get_bus(const char *bus_name);
+
+/**
+ * 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_eal_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_eal_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 8840380..4004f9a 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 */
 	struct rte_driver *driver;    /**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
@@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
  */
 struct rte_driver {
 	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
+	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
 };
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..c873a7f 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

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

* [PATCH v2 03/12] test: add basic bus infrastructure tests
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 01/12] eal: define container_of macro Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Verification of bus registration, driver registration on a bus.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile   |   2 +-
 app/test/test.h     |   2 +
 app/test/test_bus.c | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 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..760d40a
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,423 @@
+/*-
+ *   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_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
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	const char *name;
+	struct rte_device dev;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus {
+	const char *name;
+	struct rte_bus *bus;
+	struct rte_driver *drivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *devices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct rte_bus busA = {
+	.name = "busA", /* "busA" */
+};
+
+struct rte_bus busB = {
+	.name = "busB", /* "busB */
+};
+
+struct rte_driver driverA = {
+	.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 rte_driver driverB = {
+	.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 dummy_buses[] = {
+	{
+		.name = "busA",
+		.bus = &busA,
+		.drivers = {&driverA, NULL},
+		.devices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.bus = &busB,
+		.drivers = {&driverB, NULL},
+		.devices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus *db;
+	struct rte_bus *bus;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; dummy_buses[i].name; i++) {
+		db = &dummy_buses[i];
+
+		bus = rte_eal_get_bus(db->name);
+		if (!bus)
+			return;
+
+		printf(" Bus: %s\n", bus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			printf("    %s\n", drv->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			printf("    Addr: %p\n", dev);
+			if (dev->driver)
+				printf("    Driver = %s\n", 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);
+		rte_eal_bus_unregister(bus_p);
+		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_eal_bus_unregister(bus_p);
+	}
+
+	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);
+		rte_eal_bus_register(bus_p);
+	}
+
+	dump_device_tree();
+	return 0;
+}
+
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = dummy_buses[i].bus;
+		rte_eal_bus_register(bus);
+		printf("Registered Bus %s\n", dummy_buses[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 dummy_buses */
+		ret = strcmp(bus->name, dummy_buses[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of dummy_buses[i] should be the NULL entry */
+	if (dummy_buses[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       dummy_buses[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_eal_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_eal_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;
+}
+
+/* Positive case: For each driver in dummy_buses, perform
+ * registration
+ */
+static int
+test_driver_registration_on_bus(void)
+{
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv, *drv2;
+
+	/* For each bus on the dummy_buses list:
+	 * 1. get the bus reference
+	 * 2. register all drivers from dummy_buses
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', register all drivers */
+		for (j = 0; dummy_buses[i].drivers[j]; j++) {
+			drv = dummy_buses[i].drivers[j];
+			rte_eal_bus_add_driver(bus, drv);
+		}
+	}
+
+	/* Drivers have been registered. Verify by parsing the list */
+	drv = NULL;
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		j = 0;
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			drv2 = dummy_buses[i].drivers[j++];
+			if (strcmp(drv2->name, drv->name)) {
+				printf("Incorrectly registered drivers."
+				       " Expected: %s; Available: %s\n",
+				       drv2->name, drv->name);
+				return -1;
+			}
+		}
+	}
+
+	printf("Driver registration test successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+static int
+test_driver_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all drivers */
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			rte_eal_bus_remove_driver(drv);
+		}
+	}
+
+	/* Verifying that all drivers have been removed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->driver_list)) {
+			printf("Unable to remove all drivers on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	printf("Unregistration of drivers on all buses is successful.\n");
+	/* All devices from all buses have been removed */
+	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;
+
+	/* Assuming that buses are already registered, register drivers
+	 * with them.
+	 */
+	if (test_driver_registration_on_bus())
+		return -1;
+
+	if (test_driver_unregistration_on_bus())
+		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);
-- 
2.7.4

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

* [PATCH v2 04/12] eal/bus: add scan, match and insert support
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (2 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 03/12] test: add basic bus infrastructure tests Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 05/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

When a PMD is registred, it will associate itself with a bus.

A bus is responsible for 'scan' of all the devices attached to it.
All the scanned devices are attached to bus specific device_list.
During the probe operation, 'match' of the drivers and devices would
be done.

Also, rather than adding a device to tail, a new device might be added to
the list (pivoted on bus) at a predefined position, for example, adding it
in order of addressing. Support for this is added as '*bus_insert'.

This patch also adds necessary test framework to test the scan and
match callbacks.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 760d40a..ed95479 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -80,12 +80,32 @@ struct dummy_bus {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+int scan_fn_for_busA(struct rte_bus *bus);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+int scan_fn_for_busB(struct rte_bus *bus);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus busA = {
 	.name = "busA", /* "busA" */
+	.scan = scan_fn_for_busA,
+	.match = generic_match_fn,
 };
 
 struct rte_bus busB = {
 	.name = "busB", /* "busB */
+	.scan = scan_fn_for_busB,
+	.match = generic_match_fn,
 };
 
 struct rte_driver driverA = {
@@ -184,6 +204,92 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the dummy_buses and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that dummy_buses list, register.
+ *
+ * @param bus
+ *	bus to scan againt test entry
+ * @return
+ *	0 for successful scan, even if no devices are found
+ *	!0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+	int i = 0;
+	struct rte_device *dev = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		if (!strcmp(dummy_buses[i].name, bus->name)) {
+			db = &dummy_buses[i];
+			break;
+		}
+	}
+
+	if (!db)
+		return -1;
+
+	/* For all the devices in the device tree (dummy_buses), add device */
+	for (i = 0; db->devices[i]; i++) {
+		dev = &(db->devices[i]->dev);
+		rte_eal_bus_add_device(bus, dev);
+	}
+
+	return 0;
+}
+
+/* @internal
+ * Obtain bus from driver object. Match the address of rte_device object
+ * with all the devices associated with that bus.
+ *
+ * Being a test function, all this does is validate that device object
+ * provided is available on the same bus to which driver is registered.
+ *
+ * @param drv
+ *	driver to which matching is to be performed
+ * @param dev
+ *	device object to match with driver
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct rte_device *dev_p = NULL;
+
+	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
+	 * from bus->device_list.
+	 */
+
+	/* a driver is registered with the bus *before* the scan. */
+	bus = drv->bus;
+	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
+		if (dev == dev_p)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+scan_fn_for_busA(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
+int
+scan_fn_for_busB(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
 static int
 test_bus_setup(void)
 {
@@ -391,6 +497,155 @@ test_driver_unregistration_on_bus(void)
 
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			rte_eal_bus_remove_device(dev);
+		}
+	}
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->device_list)) {
+			printf("Unable to remove all devices on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	/* All devices from all buses have been removed */
+	printf("All devices on all buses unregistered.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful scan
+ *	!0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Call the scan function for each bus */
+		ret = bus->scan(bus);
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * Function to perform 'probe' and link devices and drivers on a bus.
+ * This would work over all the buses registered, and all devices and drivers
+ * registered with it - call match on each pair.
+ * Aim is to test the match_fn for each bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_driver *drv = NULL;
+
+	/* In case of this test:
+	* 1. for each bus in rte_bus_list
+	* 2.  for each device in bus->device_list
+	* 3.   for each driver in bus->driver_list
+	* 4.    call match
+	* 5.    link driver and device
+	* 6. Verify the linkage.
+	*/
+	for (i = 0; dummy_buses[i].name; i++) {
+		/* get bus pointer from dummy_buses itself rather than
+		 * rte_eal_get_bus
+		 */
+		bus = dummy_buses[i].bus;
+
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			TAILQ_FOREACH(drv, &bus->driver_list, next) {
+				if (!bus->match) {
+					printf("Incorrect bus without match "
+					       "fn: (%s).\n", bus->name);
+					return -1;
+				}
+
+				ret = bus->match(drv, dev);
+				if (ret) {
+					printf("Device and driver don't "
+					       "belong to same bus.\n");
+					return -1;
+				}
+				dev->driver = drv;
+
+				/* As match is generic, it always results in
+				 * dev->drv pointing to first driver entry in
+				 * dummy_buses[i]
+				 */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a dummy_buses[i]
+	 * should have same driver (first driver entry of dummy_buses[i])
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		drv = dummy_buses[i].drivers[0];
+
+		for (j = 0; dummy_buses[i].devices[j]; j++) {
+			dev = &(dummy_buses[i].devices[j]->dev);
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
 int
 test_bus(void)
 {
@@ -407,6 +662,16 @@ test_bus(void)
 	if (test_driver_registration_on_bus())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	/* Now that the devices and drivers are registered, perform probe */
+	if (test_probe_on_bus())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_driver_unregistration_on_bus())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 612f64e..3be9c77 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -58,6 +58,17 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
 	dev->bus = bus;
 }
 
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev,
+			  struct rte_device *new_dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(old_dev);
+	RTE_VERIFY(new_dev);
+
+	TAILQ_INSERT_BEFORE(old_dev, new_dev, next);
+}
+
 /** @internal
  * Remove a device from its bus.
  */
@@ -132,6 +143,9 @@ rte_eal_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan and match implemented */
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->match);
 
 	/* Initialize the driver and device list associated with the bus */
 	TAILQ_INIT(&(bus->driver_list));
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index f0297a9..d1bd2e8 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,49 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Global Bus list */
 extern struct rte_bus_list rte_bus_list;
 
+/**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * Successful detection of a device results in rte_device object which is
+ * embedded within the respective device type (rte_pci_device, for example).
+ * Thereafter, PCI specific bus would need to perform
+ * container_of(rte_pci_device) to obtain PCI device object.
+ *
+ * Scan failure of a bus is not treated as exit criteria for application. Scan
+ * for all other buses would still continue.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param bus
+ *	Reference to the bus on which device is added
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*bus_scan_t)(struct rte_bus *bus);
+
+/**
+ * Bus specific match for devices and drivers which can service them.
+ * For each scanned device, rte_driver->probe would be called for driver
+ * specific initialization of the device.
+ *
+ * It is the work of each bus handler to obtain the specific device object
+ * using container_of (or typecasting, as a less preferred way).
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param drv
+ *	Driver object attached to the bus
+ * @param dev
+ *	Device object which is being probed.
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	struct rte_driver_list driver_list;
@@ -66,6 +109,9 @@ struct rte_bus {
 	struct rte_device_list device_list;
 				     /**< List of all devices on bus */
 	const char *name;            /**< Name of the bus */
+	bus_scan_t scan;            /**< Scan for devices attached to bus */
+	bus_match_t match;
+	/**< Match device with drivers associated with the bus */
 };
 
 /** @internal
@@ -82,6 +128,24 @@ void
 rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
 
 /** @internal
+ * Rather than adding a device to tail, insert at a predefined location.
+ * This is specifically useful for update device cases, or where addition
+ * of devices in the list needs to be ordered (addressing, for example).
+ *
+ * @param bus
+ *	Handle for bus on which device is to be added
+ * @param old_dev
+ *	Existing rte_device object before which new device needs to be added
+ * @param new_dev
+ *	Object for device to be added before old_dev
+ * @return
+ *	void
+ */
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device,
+			  struct rte_device *new_device);
+
+/** @internal
  * Remove a device from its bus.
  *
  * @param dev
-- 
2.7.4

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

* [PATCH v2 05/12] eal: integrate bus scan and probe with EAL
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (3 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 06/12] eal: add probe and remove support for rte_driver Shreyansh Jain
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Still a dummy implementation as no real bus driver exists. This adds calls
from EAL to bus specific scan, match functions.
Once driver->probe is in place, and a bus handler has been installed,
the code would become effective.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  7 +++++++
 lib/librte_eal/common/eal_common_bus.c  | 30 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h | 19 +++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c       |  7 +++++++
 4 files changed, 63 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 35e3117..30afc6b 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>
@@ -580,6 +581,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -616,6 +620,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 3be9c77..67b808b 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -173,6 +173,36 @@ rte_eal_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_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Match driver<->device and call driver->probe() */
+int
+rte_eal_bus_probe(void)
+{
+	/* Until driver->probe is available, this is dummy implementation */
+	return 0;
+}
+
 /* dump one bus info */
 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 d1bd2e8..9bd8650 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -209,6 +209,25 @@ void rte_eal_bus_unregister(struct rte_bus *bus);
  */
 struct rte_bus *rte_eal_get_bus(const char *bus_name);
 
+/** @internal
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);
+
+/** @internal
+ * For each device on the bus, perform a driver 'match' and call the
+ * driver's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_eal_bus_probe(void);
+
 /**
  * Dump information of all the buses registered with EAL.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 2075282..01d0cee 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>
@@ -847,6 +848,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -887,6 +891,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
-- 
2.7.4

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

* [PATCH v2 06/12] eal: add probe and remove support for rte_driver
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (4 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 05/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 07/12] eal: enable probe from bus infrastructure Shreyansh Jain
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

rte_driver now supports probe and remove. These would be used for generic
device type (PCI, etc) probe and remove.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4004f9a..7d2ab16 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -145,6 +145,16 @@ void rte_eal_device_insert(struct rte_device *dev);
 void rte_eal_device_remove(struct rte_device *dev);
 
 /**
+ * Initialisation function for the driver called during probing.
+ */
+typedef int (driver_probe_t)(struct rte_driver *, struct rte_device *);
+
+/**
+ * Uninitialisation function for the driver called during hotplugging.
+ */
+typedef int (driver_remove_t)(struct rte_device *);
+
+/**
  * A structure describing a device driver.
  */
 struct rte_driver {
@@ -152,6 +162,8 @@ struct rte_driver {
 	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
+	driver_probe_t *probe;         /**< Probe the device */
+	driver_remove_t *remove;       /**< Remove/hotplugging the device */
 };
 
 /**
-- 
2.7.4

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

* [PATCH v2 07/12] eal: enable probe from bus infrastructure
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (5 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 06/12] eal: add probe and remove support for rte_driver Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 08/12] pci: split match and probe function Shreyansh Jain
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

The model is:
 rte_eal_init
 `--> calls rte_eal_bus_probe()
      This iterates over all the drivers and devices and matches them. For
      matched bus specific device-driver and calls:
      `-> rte_driver->probe()
          for all matched device/drivers (rte_bus->match() successful)
          This would be responsible for devargs related checks, eventually
          calling:
          `-> rte_xxx_driver->probe()
              which does all the work from eth_dev allocation to init.
              (Currently, eth_dev init is done by eth_driver->eth_dev_init,
                which would be removed soon)

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

--
v2:
 - No more bus->probe call

---
 lib/librte_eal/common/eal_common_bus.c | 50 +++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 67b808b..469abac 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -195,11 +195,59 @@ rte_eal_bus_scan(void)
 	return 0;
 }
 
+static int
+perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+	      struct rte_device *device)
+{
+	int ret;
+
+	if (!driver->probe) {
+		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
+			driver->name);
+		/* This is not an error - just a badly implemented PMD */
+		return 0;
+	}
+
+	ret = driver->probe(driver, device);
+	if (ret < 0)
+		/* One of the probes failed */
+		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
+
+	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
+	 * success, return ret
+	 */
+	return ret;
+}
+
 /* Match driver<->device and call driver->probe() */
 int
 rte_eal_bus_probe(void)
 {
-	/* Until driver->probe is available, this is dummy implementation */
+	int ret;
+	struct rte_bus *bus;
+	struct rte_device *device;
+	struct rte_driver *driver;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		TAILQ_FOREACH(device, &bus->device_list, next) {
+			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+				ret = bus->match(driver, device);
+				if (!ret) {
+					ret = perform_probe(bus, driver,
+							    device);
+					if (ret < 0)
+						return ret;
+
+					/* ret == 0 is success; ret >0 implies
+					 * driver doesn't support the device.
+					 * in either case, continue
+					 */
+				}
+			}
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4

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

* [PATCH v2 08/12] pci: split match and probe function
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (6 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 07/12] eal: enable probe from bus infrastructure Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, 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 rte_eal_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

--
v2:
 - Change default return in match function
---
 lib/librte_eal/common/eal_common_pci.c  | 198 ++++++++++++++++++--------------
 lib/librte_eal/common/include/rte_pci.h |  15 +++
 2 files changed, 125 insertions(+), 88 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 6bff675..706f91c 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,131 +152,153 @@ 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_eal_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;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-				rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret)
-			dev->driver = NULL;
-
-		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;
+	/* 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);
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_eal_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;
+	}
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	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;
+	} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+			rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* unbind current driver */
+		if (pci_unbind_kernel_driver(dev) < 0)
+			return -1;
+	}
 
-		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) {
+		RTE_LOG(DEBUG, EAL, "Driver (%s) probe failed.\n",
+			dr->driver.name);
 		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 ret;
+}
 
-		return 0;
+/*
+ * 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_eal_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 9ce8847..c9b113d 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -369,6 +369,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_eal_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
-- 
2.7.4

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

* [PATCH v2 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (7 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 08/12] pci: split match and probe function Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 10/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

PCI scan and match now work on rte_device/rte_driver rather than PCI
specific objects. These functions can now be plugged to the generic
bus callbacks for scanning and matching devices/drivers.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     |  2 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  4 ++--
 lib/librte_eal/common/eal_common_pci.c  | 28 +++++++++++++++++++++-------
 lib/librte_eal/common/include/rte_pci.h | 17 ++++++++++-------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  4 ++--
 5 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..f9b84db 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -180,7 +180,7 @@ test_pci_setup(void)
 		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
 	}
 
-	ret = rte_eal_pci_scan();
+	ret = rte_eal_pci_scan(NULL);
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
 	rte_eal_pci_dump(stdout);
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 8b3ed88..10b234e 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -361,7 +361,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -676,7 +676,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 706f91c..562c0fd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -153,17 +153,22 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev)
+rte_eal_pci_match(struct rte_driver *drv,
+		  struct rte_device *dev)
 {
 	int match = 1;
 	const struct rte_pci_id *id_table;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 
-	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
-		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+	if (!drv || !dev) {
+		RTE_LOG(DEBUG, EAL, "Invalid Device/Driver\n");
 		return -1;
 	}
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
 	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
@@ -201,11 +206,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
+	driver = &dr->driver;
+	device = &dev->device;
 	loc = &dev->addr;
 
 	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -222,11 +231,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 	}
 
 	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(dr, dev);
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Match of device and driver failed */
 		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			dr->driver.name);
+			driver->name);
 		return 1;
 	}
 
@@ -268,12 +277,17 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver = NULL;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	ret = rte_eal_pci_match(dr, dev);
+	driver = &(dr->driver);
+	device = &(dev->device);
+
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Device and driver don't match */
 		return 1;
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index c9b113d..10108a4 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -363,25 +363,28 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  * Scan the content of the PCI bus, and the devices in the devices
  * list
  *
+ * @param bus
+ *	Reference to the PCI bus
+ *
  * @return
  *  0 on success, negative on error
  */
-int rte_eal_pci_scan(void);
+int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
  * 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
+ * @param drv
+ *	driver from which ID table would be extracted
+ * @param dev
+ *	device to match against the driver
  * @return
  *	0 for successful match
  *	!0 for unsuccessful match
  */
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev);
+rte_eal_pci_match(struct rte_driver *drv,
+		  struct rte_device *dev);
 
 /**
  * Probe the PCI bus for registered drivers.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 876ba38..bafb7fb 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -485,7 +485,7 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  * list
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 {
 	struct dirent *e;
 	DIR *dir;
@@ -763,7 +763,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
-- 
2.7.4

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

* [PATCH v2 10/12] pci: Pass rte_pci_addr to functions instead of separate args
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (8 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 11/12] eal: enable PCI bus Shreyansh Jain
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Ben Walker, Shreyansh Jain

From: Ben Walker <benjamin.walker@intel.com>

Instead of passing domain, bus, devid, func, just pass
an rte_pci_addr.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
[Shreyansh: Checkpatch error fix]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index bafb7fb..cbd25df 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -267,8 +267,7 @@ 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, uint16_t domain, uint8_t bus,
-	     uint8_t devid, uint8_t function)
+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -281,10 +280,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 		return -1;
 
 	memset(dev, 0, sizeof(*dev));
-	dev->addr.domain = domain;
-	dev->addr.bus = bus;
-	dev->addr.devid = devid;
-	dev->addr.function = function;
+	dev->addr = *addr;
 
 	/* get vendor id */
 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
@@ -429,16 +425,14 @@ 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->domain, addr->bus, addr->devid,
-				addr->function);
+	return pci_scan_one(filename, addr);
 }
 
 /*
  * split up a pci address into its constituent parts.
  */
 static int
-parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
-		uint8_t *bus, uint8_t *devid, uint8_t *function)
+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
 {
 	/* first split on ':' */
 	union splitaddr {
@@ -466,10 +460,10 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
 
 	/* now convert to int values */
 	errno = 0;
-	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
-	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
-	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
-	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	addr->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	addr->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	addr->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	addr->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
 	if (errno != 0)
 		goto error;
 
@@ -490,8 +484,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
-	uint16_t domain;
-	uint8_t bus, devid, function;
+	struct rte_pci_addr addr;
 
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
@@ -500,20 +493,22 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 		return -1;
 	}
 
+
 	while ((e = readdir(dir)) != NULL) {
 		if (e->d_name[0] == '.')
 			continue;
 
-		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
-				&bus, &devid, &function) != 0)
+		if (parse_pci_addr_format(e->d_name,
+					  sizeof(e->d_name), &addr) != 0)
 			continue;
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
+		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
+
 	return 0;
 
 error:
-- 
2.7.4

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

* [PATCH v2 11/12] eal: enable PCI bus
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (9 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 10/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:37   ` [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Note: With this patch, all PCI PMDs would cease to work because of lack
      rte_driver->probe/remove implementations. Next patch would do that.

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             |  52 ++++---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-
 lib/librte_eal/common/eal_common_bus.c          |   1 +
 lib/librte_eal/common/eal_common_pci.c          | 187 +++++++++++++++---------
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_pci.h         |  53 ++++---
 lib/librte_eal/linuxapp/eal/eal.c               |   7 -
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  54 ++++---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-
 10 files changed, 220 insertions(+), 169 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 30afc6b..79d82d4 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)
@@ -616,10 +613,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");
-
 	if (rte_eal_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 10b234e..ab9f9d2 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -249,7 +250,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
 	struct rte_pci_device *dev;
 	struct pci_bar_io bar;
@@ -322,19 +323,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -346,7 +351,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
@@ -361,7 +366,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -374,6 +379,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 			.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__);
@@ -389,7 +398,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 		}
 
 		for (i = 0; i < conf_io.num_matches; i++)
-			if (pci_scan_one(fd, &matches[i]) < 0)
+			if (pci_scan_one(bus, fd, &matches[i]) < 0)
 				goto error;
 
 		dev_count += conf_io.num_matches;
@@ -407,9 +416,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-	int fd;
+	int fd = -1;
 	struct pci_conf matches[2];
 	struct pci_match_conf match = {
 		.pc_sel = {
@@ -427,6 +436,9 @@ pci_update_device(const struct rte_pci_addr *addr)
 		.matches = &matches[0],
 	};
 
+	if (!bus)
+		goto error;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -442,7 +454,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 	if (conf_io.num_matches != 1)
 		goto error;
 
-	if (pci_scan_one(fd, &matches[0]) < 0)
+	if (pci_scan_one(bus, fd, &matches[0]) < 0)
 		goto error;
 
 	close(fd);
@@ -668,17 +680,9 @@ 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;
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	if (rte_eal_pci_scan(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 23fc1c1..3dcf439 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -187,5 +184,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 469abac..d9ee347 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -234,6 +234,7 @@ rte_eal_bus_probe(void)
 			TAILQ_FOREACH(driver, &bus->driver_list, next) {
 				ret = bus->match(driver, device);
 				if (!ret) {
+					device->driver = driver;
 					ret = perform_probe(bus, driver,
 							    device);
 					if (ret < 0)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 562c0fd..fb4e39f 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>
@@ -82,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)
@@ -206,15 +202,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
-	struct rte_driver *driver;
-	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &dr->driver;
-	device = &dev->device;
 	loc = &dev->addr;
 
 	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -230,15 +222,6 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 		return 1;
 	}
 
-	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Match of device and driver failed */
-		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			driver->name);
-		return 1;
-	}
-
 	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
 			dev->id.device_id, dr->driver.name);
 
@@ -276,23 +259,11 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
-	int ret;
-	struct rte_driver *driver = NULL;
-	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &(dr->driver);
-	device = &(dev->device);
-
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -321,9 +292,10 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
@@ -333,7 +305,8 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -352,15 +325,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -381,22 +356,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
-	if (pci_update_device(addr) < 0)
+	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_probe_all_drivers(dev);
+		ret = pci_probe_all_drivers(bus, dev);
 		if (ret)
 			goto err_return;
 		return 0;
@@ -417,20 +401,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(bus, dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_bus_remove_device(r_dev);
 		free(dev);
 		return 0;
 	}
@@ -443,41 +436,66 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	return -1;
 }
 
-/*
- * 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.
- */
 int
-rte_eal_pci_probe(void)
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device)
 {
-	struct rte_pci_device *dev = NULL;
-	struct rte_devargs *devargs;
-	int probe_all = 0;
 	int ret = 0;
+	struct rte_devargs *devargs;
+	struct rte_pci_device *pci_dev;
+	struct rte_pci_driver *pci_drv;
 
-	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-		probe_all = 1;
+	if (!driver || !device)
+		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	pci_dev = container_of(device, struct rte_pci_device, device);
+	pci_drv = container_of(driver, struct rte_pci_driver, driver);
 
+	ret = rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI);
+	if (ret != 0) {
 		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
-		if (devargs != NULL)
-			dev->device.devargs = devargs;
-
-		/* probe all or only whitelisted devices */
-		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
-		else if (devargs != NULL &&
-			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
+		devargs = pci_devargs_lookup(pci_dev);
+		if (devargs != NULL &&
+		    devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) {
+			pci_dev->device.devargs = devargs;
+		} else {
+			/* Ignore the device */
+			return 0;
+		}
+	}
+
+	ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
 	}
+	return 0;
+}
+
+int
+rte_eal_pci_remove(struct rte_device *device)
+{
+	int ret = 0;
+	struct rte_pci_device *pci_dev;
+
+	if (!device)
+		return -1;
+
+	pci_dev = container_of(device, struct rte_pci_device, device);
 
+	if (!pci_dev->driver)
+		return -1;
+
+	ret = rte_eal_pci_detach_dev(pci_dev->driver, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
 	return 0;
 }
 
@@ -506,8 +524,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -516,14 +543,32 @@ 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);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_add_driver(bus, &driver->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_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = driver->driver.bus;
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..06ec172 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;
 
@@ -126,13 +116,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *	The PCI bus on which device is connected
  * @param addr
  *	The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 10108a4..ec8f672 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.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);
 
@@ -372,6 +366,40 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
+ * Probe callback for the PCI bus
+ *
+ * For each matched pair of PCI device and driver on PCI bus, perform devargs
+ * check, and call a series of callbacks to allocate ethdev/cryptodev instances
+ * and intializing them.
+ *
+ * @param driver
+ *	Generic driver object matched with the device
+ * @param device
+ *	Generic device object to initialize
+ * @return
+ *   - 0 on success.
+ *   - !0 on error.
+ */
+int
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device);
+
+/**
+ * Remove callback for the PCI bus
+ *
+ * Called when a device needs to be removed from a bus; wraps around the
+ * PCI specific implementation layered over rte_pci_driver->remove. Default
+ * handler used by PCI PMDs
+ *
+ * @param device
+ *	rte_device object referring to device to be removed
+ * @return
+ *	- 0 for successful removal
+ *	- !0 for failure in removal of device
+ */
+int
+rte_eal_pci_remove(struct rte_device *device);
+
+/**
  * Match the PCI Driver and Device using the ID Table
  *
  * @param drv
@@ -387,19 +415,6 @@ rte_eal_pci_match(struct rte_driver *drv,
 		  struct rte_device *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.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 01d0cee..ff92de2 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");
@@ -887,10 +884,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");
-
 	if (rte_eal_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 cbd25df..5cc89c5 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>
@@ -267,7 +268,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_bus *bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -385,20 +387,24 @@ 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)) {
+	if (TAILQ_EMPTY(&bus->device_list)) {
 		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	} else {
 		struct rte_pci_device *dev2;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				rte_eal_device_insert(&dev->device);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -410,14 +416,14 @@ 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_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 
@@ -425,7 +431,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(bus, filename, addr);
 }
 
 /*
@@ -479,13 +485,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	if (!bus_p) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	/* 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",
@@ -504,7 +519,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+		if (pci_scan_one(bus_p, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -750,18 +765,9 @@ 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(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index c873a7f..6e0ec51 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -191,5 +188,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
-- 
2.7.4

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

* [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (10 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 11/12] eal: enable PCI bus Shreyansh Jain
@ 2016-12-13 13:37   ` Shreyansh Jain
  2016-12-13 13:52     ` Andrew Rybchenko
  2016-12-14  9:49     ` Shreyansh Jain
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  12 siblings, 2 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-13 13:37 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

These callbacks now act as first layer of PCI interfaces from the Bus.
Bus probe would enter the PMDs through the rte_driver->probe/remove
callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
drivers are rte_pci_driver).

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
 drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
 drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
 drivers/net/e1000/em_ethdev.c           | 4 ++++
 drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
 drivers/net/ena/ena_ethdev.c            | 4 ++++
 drivers/net/enic/enic_ethdev.c          | 4 ++++
 drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
 drivers/net/i40e/i40e_ethdev.c          | 4 ++++
 drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
 drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
 drivers/net/mlx4/mlx4.c                 | 4 +++-
 drivers/net/mlx5/mlx5.c                 | 1 +
 drivers/net/nfp/nfp_net.c               | 4 ++++
 drivers/net/qede/qede_ethdev.c          | 8 ++++++++
 drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
 drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
 drivers/net/virtio/virtio_ethdev.c      | 2 ++
 drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
 19 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 0eae433..9f3b3f2 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -618,6 +618,10 @@ eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_bnx2x_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2x_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
@@ -632,6 +636,10 @@ static struct eth_driver rte_bnx2x_pmd = {
  */
 static struct eth_driver rte_bnx2xvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2xvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 035fe07..c8671c8 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1160,6 +1160,10 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev) {
 
 static struct eth_driver bnxt_rte_pmd = {
 	.pci_drv = {
+		    .driver = {
+			    .probe = rte_eal_pci_probe,
+			    .remove = rte_eal_pci_remove,
+		    },
 		    .id_table = bnxt_pci_id_map,
 		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
 			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index b7f28eb..67714fa 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1039,6 +1039,10 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_cxgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = cxgb4_pci_tbl,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index aee3d34..7be5da3 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -391,6 +391,10 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_em_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_em_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 2fddf0c..70dd24c 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1078,6 +1078,10 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_igb_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igb_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1094,6 +1098,10 @@ static struct eth_driver rte_igb_pmd = {
  */
 static struct eth_driver rte_igbvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igbvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index ab9a178..54fc8de 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1705,6 +1705,10 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 static struct eth_driver rte_ena_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ena_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index 2b154ec..c2783db 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -634,6 +634,10 @@ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_enic_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_enic_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 923690c..d1a2efa 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3061,6 +3061,10 @@ static const struct rte_pci_id pci_id_fm10k_map[] = {
 
 static struct eth_driver rte_pmd_fm10k = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_fm10k_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..9c5d50f 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -670,6 +670,10 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = {
 
 static struct eth_driver rte_i40e_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40e_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index aa306d6..10bf6ab 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1527,6 +1527,10 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
  */
 static struct eth_driver rte_i40evf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40evf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index edc9b22..80ee232 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1564,6 +1564,10 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_ixgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbe_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1580,6 +1584,10 @@ static struct eth_driver rte_ixgbe_pmd = {
  */
 static struct eth_driver rte_ixgbevf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbevf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index da61a85..e3dcd41 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5907,7 +5907,9 @@ static const struct rte_pci_id mlx4_pci_id_map[] = {
 static struct eth_driver mlx4_driver = {
 	.pci_drv = {
 		.driver = {
-			.name = MLX4_DRIVER_NAME
+			.name = MLX4_DRIVER_NAME,
+			.probe = rte_eal_pci_probe,
+		},
 		},
 		.id_table = mlx4_pci_id_map,
 		.probe = mlx4_pci_probe,
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 90cc35e..76dda13 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -731,6 +731,7 @@ static struct eth_driver mlx5_driver = {
 	.pci_drv = {
 		.driver = {
 			.name = MLX5_DRIVER_NAME
+			.probe = rte_eal_pci_probe,
 		},
 		.id_table = mlx5_pci_id_map,
 		.probe = mlx5_pci_probe,
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index de80b46..125ba86 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2469,6 +2469,10 @@ static struct rte_pci_id pci_id_nfp_net_map[] = {
 
 static struct eth_driver rte_nfp_net_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nfp_net_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			     RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index d106dd0..31f6733 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1642,6 +1642,10 @@ static struct rte_pci_id pci_id_qede_map[] = {
 
 static struct eth_driver rte_qedevf_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qedevf_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
@@ -1655,6 +1659,10 @@ static struct eth_driver rte_qedevf_pmd = {
 
 static struct eth_driver rte_qede_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qede_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index f3cd52d..a649e60 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1572,6 +1572,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
 
 static struct eth_driver szedata2_eth_driver = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = rte_szedata2_pci_id_table,
 		.probe = rte_eth_dev_pci_probe,
 		.remove = rte_eth_dev_pci_remove,
diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
index 466e49c..72ac748 100644
--- a/drivers/net/thunderx/nicvf_ethdev.c
+++ b/drivers/net/thunderx/nicvf_ethdev.c
@@ -2110,6 +2110,10 @@ static const struct rte_pci_id pci_id_nicvf_map[] = {
 
 static struct eth_driver rte_nicvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nicvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 079fd6c..4d5d1bb 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1377,6 +1377,8 @@ static struct eth_driver rte_virtio_pmd = {
 	.pci_drv = {
 		.driver = {
 			.name = "net_virtio",
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
 		},
 		.id_table = pci_id_virtio_map,
 		.drv_flags = RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 8bb13e5..57f66cb 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -335,6 +335,10 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_vmxnet3_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_vmxnet3_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
-- 
2.7.4

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-13 13:37   ` [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
@ 2016-12-13 13:52     ` Andrew Rybchenko
  2016-12-13 15:07       ` Ferruh Yigit
  2016-12-14  5:11       ` Shreyansh Jain
  2016-12-14  9:49     ` Shreyansh Jain
  1 sibling, 2 replies; 132+ messages in thread
From: Andrew Rybchenko @ 2016-12-13 13:52 UTC (permalink / raw)
  To: Shreyansh Jain, dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu

On 12/13/2016 04:37 PM, Shreyansh Jain wrote:
> These callbacks now act as first layer of PCI interfaces from the Bus.
> Bus probe would enter the PMDs through the rte_driver->probe/remove
> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
> drivers are rte_pci_driver).

I think similar changes in drivers/net/sfc/sfc_ethdev.c (already in 
dpdk-next-net) are required as well.

> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>   drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>   drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>   drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>   drivers/net/e1000/em_ethdev.c           | 4 ++++
>   drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>   drivers/net/ena/ena_ethdev.c            | 4 ++++
>   drivers/net/enic/enic_ethdev.c          | 4 ++++
>   drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>   drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>   drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>   drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>   drivers/net/mlx4/mlx4.c                 | 4 +++-
>   drivers/net/mlx5/mlx5.c                 | 1 +
>   drivers/net/nfp/nfp_net.c               | 4 ++++
>   drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>   drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>   drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>   drivers/net/virtio/virtio_ethdev.c      | 2 ++
>   drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>   19 files changed, 86 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
> index 0eae433..9f3b3f2 100644
> --- a/drivers/net/bnx2x/bnx2x_ethdev.c
> +++ b/drivers/net/bnx2x/bnx2x_ethdev.c
> @@ -618,6 +618,10 @@ eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_bnx2x_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_bnx2x_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>   		.probe = rte_eth_dev_pci_probe,
> @@ -632,6 +636,10 @@ static struct eth_driver rte_bnx2x_pmd = {
>    */
>   static struct eth_driver rte_bnx2xvf_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_bnx2xvf_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> index 035fe07..c8671c8 100644
> --- a/drivers/net/bnxt/bnxt_ethdev.c
> +++ b/drivers/net/bnxt/bnxt_ethdev.c
> @@ -1160,6 +1160,10 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev) {
>   
>   static struct eth_driver bnxt_rte_pmd = {
>   	.pci_drv = {
> +		    .driver = {
> +			    .probe = rte_eal_pci_probe,
> +			    .remove = rte_eal_pci_remove,
> +		    },
>   		    .id_table = bnxt_pci_id_map,
>   		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
>   			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
> diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
> index b7f28eb..67714fa 100644
> --- a/drivers/net/cxgbe/cxgbe_ethdev.c
> +++ b/drivers/net/cxgbe/cxgbe_ethdev.c
> @@ -1039,6 +1039,10 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_cxgbe_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = cxgb4_pci_tbl,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
> index aee3d34..7be5da3 100644
> --- a/drivers/net/e1000/em_ethdev.c
> +++ b/drivers/net/e1000/em_ethdev.c
> @@ -391,6 +391,10 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_em_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_em_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>   			RTE_PCI_DRV_DETACHABLE,
> diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
> index 2fddf0c..70dd24c 100644
> --- a/drivers/net/e1000/igb_ethdev.c
> +++ b/drivers/net/e1000/igb_ethdev.c
> @@ -1078,6 +1078,10 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_igb_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_igb_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>   			RTE_PCI_DRV_DETACHABLE,
> @@ -1094,6 +1098,10 @@ static struct eth_driver rte_igb_pmd = {
>    */
>   static struct eth_driver rte_igbvf_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_igbvf_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
> index ab9a178..54fc8de 100644
> --- a/drivers/net/ena/ena_ethdev.c
> +++ b/drivers/net/ena/ena_ethdev.c
> @@ -1705,6 +1705,10 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
>   
>   static struct eth_driver rte_ena_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_ena_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
> index 2b154ec..c2783db 100644
> --- a/drivers/net/enic/enic_ethdev.c
> +++ b/drivers/net/enic/enic_ethdev.c
> @@ -634,6 +634,10 @@ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_enic_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_enic_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
> index 923690c..d1a2efa 100644
> --- a/drivers/net/fm10k/fm10k_ethdev.c
> +++ b/drivers/net/fm10k/fm10k_ethdev.c
> @@ -3061,6 +3061,10 @@ static const struct rte_pci_id pci_id_fm10k_map[] = {
>   
>   static struct eth_driver rte_pmd_fm10k = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_fm10k_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>   			RTE_PCI_DRV_DETACHABLE,
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 67778ba..9c5d50f 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -670,6 +670,10 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = {
>   
>   static struct eth_driver rte_i40e_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_i40e_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>   			RTE_PCI_DRV_DETACHABLE,
> diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
> index aa306d6..10bf6ab 100644
> --- a/drivers/net/i40e/i40e_ethdev_vf.c
> +++ b/drivers/net/i40e/i40e_ethdev_vf.c
> @@ -1527,6 +1527,10 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
>    */
>   static struct eth_driver rte_i40evf_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_i40evf_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
> index edc9b22..80ee232 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -1564,6 +1564,10 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_ixgbe_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_ixgbe_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>   			RTE_PCI_DRV_DETACHABLE,
> @@ -1580,6 +1584,10 @@ static struct eth_driver rte_ixgbe_pmd = {
>    */
>   static struct eth_driver rte_ixgbevf_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_ixgbevf_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
> index da61a85..e3dcd41 100644
> --- a/drivers/net/mlx4/mlx4.c
> +++ b/drivers/net/mlx4/mlx4.c
> @@ -5907,7 +5907,9 @@ static const struct rte_pci_id mlx4_pci_id_map[] = {
>   static struct eth_driver mlx4_driver = {
>   	.pci_drv = {
>   		.driver = {
> -			.name = MLX4_DRIVER_NAME
> +			.name = MLX4_DRIVER_NAME,
> +			.probe = rte_eal_pci_probe,
> +		},
>   		},
>   		.id_table = mlx4_pci_id_map,
>   		.probe = mlx4_pci_probe,
> diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
> index 90cc35e..76dda13 100644
> --- a/drivers/net/mlx5/mlx5.c
> +++ b/drivers/net/mlx5/mlx5.c
> @@ -731,6 +731,7 @@ static struct eth_driver mlx5_driver = {
>   	.pci_drv = {
>   		.driver = {
>   			.name = MLX5_DRIVER_NAME
> +			.probe = rte_eal_pci_probe,
>   		},
>   		.id_table = mlx5_pci_id_map,
>   		.probe = mlx5_pci_probe,
> diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
> index de80b46..125ba86 100644
> --- a/drivers/net/nfp/nfp_net.c
> +++ b/drivers/net/nfp/nfp_net.c
> @@ -2469,6 +2469,10 @@ static struct rte_pci_id pci_id_nfp_net_map[] = {
>   
>   static struct eth_driver rte_nfp_net_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_nfp_net_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>   			     RTE_PCI_DRV_DETACHABLE,
> diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
> index d106dd0..31f6733 100644
> --- a/drivers/net/qede/qede_ethdev.c
> +++ b/drivers/net/qede/qede_ethdev.c
> @@ -1642,6 +1642,10 @@ static struct rte_pci_id pci_id_qede_map[] = {
>   
>   static struct eth_driver rte_qedevf_pmd = {
>   	.pci_drv = {
> +		    .driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		    },
>   		    .id_table = pci_id_qedevf_map,
>   		    .drv_flags =
>   		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
> @@ -1655,6 +1659,10 @@ static struct eth_driver rte_qedevf_pmd = {
>   
>   static struct eth_driver rte_qede_pmd = {
>   	.pci_drv = {
> +		    .driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		    },
>   		    .id_table = pci_id_qede_map,
>   		    .drv_flags =
>   		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
> diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
> index f3cd52d..a649e60 100644
> --- a/drivers/net/szedata2/rte_eth_szedata2.c
> +++ b/drivers/net/szedata2/rte_eth_szedata2.c
> @@ -1572,6 +1572,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
>   
>   static struct eth_driver szedata2_eth_driver = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = rte_szedata2_pci_id_table,
>   		.probe = rte_eth_dev_pci_probe,
>   		.remove = rte_eth_dev_pci_remove,
> diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
> index 466e49c..72ac748 100644
> --- a/drivers/net/thunderx/nicvf_ethdev.c
> +++ b/drivers/net/thunderx/nicvf_ethdev.c
> @@ -2110,6 +2110,10 @@ static const struct rte_pci_id pci_id_nicvf_map[] = {
>   
>   static struct eth_driver rte_nicvf_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_nicvf_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>   		.probe = rte_eth_dev_pci_probe,
> diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
> index 079fd6c..4d5d1bb 100644
> --- a/drivers/net/virtio/virtio_ethdev.c
> +++ b/drivers/net/virtio/virtio_ethdev.c
> @@ -1377,6 +1377,8 @@ static struct eth_driver rte_virtio_pmd = {
>   	.pci_drv = {
>   		.driver = {
>   			.name = "net_virtio",
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
>   		},
>   		.id_table = pci_id_virtio_map,
>   		.drv_flags = RTE_PCI_DRV_DETACHABLE,
> diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
> index 8bb13e5..57f66cb 100644
> --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
> +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
> @@ -335,6 +335,10 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
>   
>   static struct eth_driver rte_vmxnet3_pmd = {
>   	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},
>   		.id_table = pci_id_vmxnet3_map,
>   		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>   		.probe = rte_eth_dev_pci_probe,

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-13 13:52     ` Andrew Rybchenko
@ 2016-12-13 15:07       ` Ferruh Yigit
  2016-12-14  5:14         ` Shreyansh Jain
  2016-12-14  5:11       ` Shreyansh Jain
  1 sibling, 1 reply; 132+ messages in thread
From: Ferruh Yigit @ 2016-12-13 15:07 UTC (permalink / raw)
  To: Andrew Rybchenko, Shreyansh Jain, dev, david.marchand
  Cc: thomas.monjalon, jianbo.liu

On 12/13/2016 1:52 PM, Andrew Rybchenko wrote:
> On 12/13/2016 04:37 PM, Shreyansh Jain wrote:
>> These callbacks now act as first layer of PCI interfaces from the Bus.
>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>> drivers are rte_pci_driver).
> 
> I think similar changes in drivers/net/sfc/sfc_ethdev.c (already in
> dpdk-next-net) are required as well.

Yes, that change is required, but it is a little tricky because this
patchset targets main tree where sfc is not merged yet, so this patch
can't include required patches.

I think it is possible to wait for this patch to be merged into main
tree, and when next-net rebased on top of it, sfc can be patched
individually.

So, yes there is a work to do there, but I think it can be postponed a
little.

> 
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> ---
>>  drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>>  drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>>  drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>>  drivers/net/e1000/em_ethdev.c           | 4 ++++
>>  drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>>  drivers/net/ena/ena_ethdev.c            | 4 ++++
>>  drivers/net/enic/enic_ethdev.c          | 4 ++++
>>  drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>>  drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>>  drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>>  drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>>  drivers/net/mlx4/mlx4.c                 | 4 +++-
>>  drivers/net/mlx5/mlx5.c                 | 1 +
>>  drivers/net/nfp/nfp_net.c               | 4 ++++
>>  drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>>  drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>>  drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>>  drivers/net/virtio/virtio_ethdev.c      | 2 ++
>>  drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>>  19 files changed, 86 insertions(+), 1 deletion(-)
<...>

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-13 13:37   ` [PATCH v2 01/12] eal: define container_of macro Shreyansh Jain
@ 2016-12-13 22:24     ` Jan Blunck
  2016-12-14  5:12       ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Jan Blunck @ 2016-12-13 22:24 UTC (permalink / raw)
  To: Shreyansh Jain
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu,
	Jan Viktorin

On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> From: Jan Blunck <jblunck@infradead.org>
>
> This macro is based on Jan Viktorin's original patch but also checks the
> type of the passed pointer against the type of the member.
>
> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> [shreyansh.jain@nxp.com: Fix checkpatch error]
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> [jblunck@infradead.org: add type checking and __extension__]
> Signed-off-by: Jan Blunck <jblunck@infradead.org>
>
> --
> v2:
>  - fix checkpatch error
> ---
>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
>
> diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
> index db5ac91..3eb8d11 100644
> --- a/lib/librte_eal/common/include/rte_common.h
> +++ b/lib/librte_eal/common/include/rte_common.h
> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
>  #endif
>
> +/**
> + * Return pointer to the wrapping struct instance.
> + *
> + * Example:
> + *
> + *  struct wrapper {
> + *      ...
> + *      struct child c;
> + *      ...
> + *  };
> + *
> + *  struct child *x = obtain(...);
> + *  struct wrapper *w = container_of(x, struct wrapper, c);
> + */
> +#ifndef container_of
> +#define container_of(ptr, type, member)        (__extension__  ({              \
> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
> +                       (type *)(((char *)_ptr) - offsetof(type, member));\
> +                       }))

This is a checkpatch false positive. It should be fine to ignore this.
IIRC we already discussed this before.


> +#endif
> +
>  #define _RTE_STR(x) #x
>  /** Take a macro value and get a string version of it */
>  #define RTE_STR(x) _RTE_STR(x)
> --
> 2.7.4
>

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-13 13:52     ` Andrew Rybchenko
  2016-12-13 15:07       ` Ferruh Yigit
@ 2016-12-14  5:11       ` Shreyansh Jain
  1 sibling, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-14  5:11 UTC (permalink / raw)
  To: Andrew Rybchenko, dev
  Cc: david.marchand, thomas.monjalon, ferruh.yigit, jianbo.liu

On Tuesday 13 December 2016 07:22 PM, Andrew Rybchenko wrote:
> On 12/13/2016 04:37 PM, Shreyansh Jain wrote:
>> These callbacks now act as first layer of PCI interfaces from the Bus.
>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>> drivers are rte_pci_driver).
>
> I think similar changes in drivers/net/sfc/sfc_ethdev.c (already in
> dpdk-next-net) are required as well.

Thanks for highlighting.
IIRC, similar point was highlighted by Ferruh as well.
Indeed a related change is required for all PMDs (PCI, for now) - if 
this change set (or a variation) is accepted.

So, just to clarify: This patch series is based on master (dpdk). How 
should such changes (for drivers in dpdk-next-net) be highlighted? Or, 
how do we track such merges?

One obvious thing I can see is that those PMDs, which are in 
dpdk-next-net, are changed by their respective authors if this series 
(or similar changes by other series) are absorbed in master and when 
their series is merged upstream.

Any other expected/assumed way?

>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> ---
>>   drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>>   drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>>   drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>>   drivers/net/e1000/em_ethdev.c           | 4 ++++
>>   drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>>   drivers/net/ena/ena_ethdev.c            | 4 ++++
>>   drivers/net/enic/enic_ethdev.c          | 4 ++++
>>   drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>>   drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>>   drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>>   drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>>   drivers/net/mlx4/mlx4.c                 | 4 +++-
>>   drivers/net/mlx5/mlx5.c                 | 1 +
>>   drivers/net/nfp/nfp_net.c               | 4 ++++
>>   drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>>   drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>>   drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>>   drivers/net/virtio/virtio_ethdev.c      | 2 ++
>>   drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>>   19 files changed, 86 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c
>> b/drivers/net/bnx2x/bnx2x_ethdev.c
>> index 0eae433..9f3b3f2 100644
>> --- a/drivers/net/bnx2x/bnx2x_ethdev.c
>> +++ b/drivers/net/bnx2x/bnx2x_ethdev.c
>> @@ -618,6 +618,10 @@ eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev)
>>     static struct eth_driver rte_bnx2x_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_bnx2x_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>>           .probe = rte_eth_dev_pci_probe,
>> @@ -632,6 +636,10 @@ static struct eth_driver rte_bnx2x_pmd = {
>>    */
>>   static struct eth_driver rte_bnx2xvf_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_bnx2xvf_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/bnxt/bnxt_ethdev.c
>> b/drivers/net/bnxt/bnxt_ethdev.c
>> index 035fe07..c8671c8 100644
>> --- a/drivers/net/bnxt/bnxt_ethdev.c
>> +++ b/drivers/net/bnxt/bnxt_ethdev.c
>> @@ -1160,6 +1160,10 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev) {
>>     static struct eth_driver bnxt_rte_pmd = {
>>       .pci_drv = {
>> +            .driver = {
>> +                .probe = rte_eal_pci_probe,
>> +                .remove = rte_eal_pci_remove,
>> +            },
>>               .id_table = bnxt_pci_id_map,
>>               .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
>>                   RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
>> diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c
>> b/drivers/net/cxgbe/cxgbe_ethdev.c
>> index b7f28eb..67714fa 100644
>> --- a/drivers/net/cxgbe/cxgbe_ethdev.c
>> +++ b/drivers/net/cxgbe/cxgbe_ethdev.c
>> @@ -1039,6 +1039,10 @@ static int eth_cxgbe_dev_init(struct
>> rte_eth_dev *eth_dev)
>>     static struct eth_driver rte_cxgbe_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = cxgb4_pci_tbl,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/e1000/em_ethdev.c
>> b/drivers/net/e1000/em_ethdev.c
>> index aee3d34..7be5da3 100644
>> --- a/drivers/net/e1000/em_ethdev.c
>> +++ b/drivers/net/e1000/em_ethdev.c
>> @@ -391,6 +391,10 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
>>     static struct eth_driver rte_em_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_em_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>>               RTE_PCI_DRV_DETACHABLE,
>> diff --git a/drivers/net/e1000/igb_ethdev.c
>> b/drivers/net/e1000/igb_ethdev.c
>> index 2fddf0c..70dd24c 100644
>> --- a/drivers/net/e1000/igb_ethdev.c
>> +++ b/drivers/net/e1000/igb_ethdev.c
>> @@ -1078,6 +1078,10 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
>>     static struct eth_driver rte_igb_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_igb_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>>               RTE_PCI_DRV_DETACHABLE,
>> @@ -1094,6 +1098,10 @@ static struct eth_driver rte_igb_pmd = {
>>    */
>>   static struct eth_driver rte_igbvf_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_igbvf_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
>> index ab9a178..54fc8de 100644
>> --- a/drivers/net/ena/ena_ethdev.c
>> +++ b/drivers/net/ena/ena_ethdev.c
>> @@ -1705,6 +1705,10 @@ static uint16_t eth_ena_xmit_pkts(void
>> *tx_queue, struct rte_mbuf **tx_pkts,
>>     static struct eth_driver rte_ena_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_ena_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/enic/enic_ethdev.c
>> b/drivers/net/enic/enic_ethdev.c
>> index 2b154ec..c2783db 100644
>> --- a/drivers/net/enic/enic_ethdev.c
>> +++ b/drivers/net/enic/enic_ethdev.c
>> @@ -634,6 +634,10 @@ static int eth_enicpmd_dev_init(struct
>> rte_eth_dev *eth_dev)
>>     static struct eth_driver rte_enic_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_enic_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/fm10k/fm10k_ethdev.c
>> b/drivers/net/fm10k/fm10k_ethdev.c
>> index 923690c..d1a2efa 100644
>> --- a/drivers/net/fm10k/fm10k_ethdev.c
>> +++ b/drivers/net/fm10k/fm10k_ethdev.c
>> @@ -3061,6 +3061,10 @@ static const struct rte_pci_id
>> pci_id_fm10k_map[] = {
>>     static struct eth_driver rte_pmd_fm10k = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_fm10k_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>>               RTE_PCI_DRV_DETACHABLE,
>> diff --git a/drivers/net/i40e/i40e_ethdev.c
>> b/drivers/net/i40e/i40e_ethdev.c
>> index 67778ba..9c5d50f 100644
>> --- a/drivers/net/i40e/i40e_ethdev.c
>> +++ b/drivers/net/i40e/i40e_ethdev.c
>> @@ -670,6 +670,10 @@ static const struct rte_i40e_xstats_name_off
>> rte_i40e_txq_prio_strings[] = {
>>     static struct eth_driver rte_i40e_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_i40e_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>>               RTE_PCI_DRV_DETACHABLE,
>> diff --git a/drivers/net/i40e/i40e_ethdev_vf.c
>> b/drivers/net/i40e/i40e_ethdev_vf.c
>> index aa306d6..10bf6ab 100644
>> --- a/drivers/net/i40e/i40e_ethdev_vf.c
>> +++ b/drivers/net/i40e/i40e_ethdev_vf.c
>> @@ -1527,6 +1527,10 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
>>    */
>>   static struct eth_driver rte_i40evf_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_i40evf_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
>> b/drivers/net/ixgbe/ixgbe_ethdev.c
>> index edc9b22..80ee232 100644
>> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
>> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
>> @@ -1564,6 +1564,10 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev
>> *eth_dev)
>>     static struct eth_driver rte_ixgbe_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_ixgbe_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>>               RTE_PCI_DRV_DETACHABLE,
>> @@ -1580,6 +1584,10 @@ static struct eth_driver rte_ixgbe_pmd = {
>>    */
>>   static struct eth_driver rte_ixgbevf_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_ixgbevf_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
>> index da61a85..e3dcd41 100644
>> --- a/drivers/net/mlx4/mlx4.c
>> +++ b/drivers/net/mlx4/mlx4.c
>> @@ -5907,7 +5907,9 @@ static const struct rte_pci_id mlx4_pci_id_map[]
>> = {
>>   static struct eth_driver mlx4_driver = {
>>       .pci_drv = {
>>           .driver = {
>> -            .name = MLX4_DRIVER_NAME
>> +            .name = MLX4_DRIVER_NAME,
>> +            .probe = rte_eal_pci_probe,
>> +        },
>>           },
>>           .id_table = mlx4_pci_id_map,
>>           .probe = mlx4_pci_probe,
>> diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
>> index 90cc35e..76dda13 100644
>> --- a/drivers/net/mlx5/mlx5.c
>> +++ b/drivers/net/mlx5/mlx5.c
>> @@ -731,6 +731,7 @@ static struct eth_driver mlx5_driver = {
>>       .pci_drv = {
>>           .driver = {
>>               .name = MLX5_DRIVER_NAME
>> +            .probe = rte_eal_pci_probe,
>>           },
>>           .id_table = mlx5_pci_id_map,
>>           .probe = mlx5_pci_probe,
>> diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
>> index de80b46..125ba86 100644
>> --- a/drivers/net/nfp/nfp_net.c
>> +++ b/drivers/net/nfp/nfp_net.c
>> @@ -2469,6 +2469,10 @@ static struct rte_pci_id pci_id_nfp_net_map[] = {
>>     static struct eth_driver rte_nfp_net_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_nfp_net_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
>>                    RTE_PCI_DRV_DETACHABLE,
>> diff --git a/drivers/net/qede/qede_ethdev.c
>> b/drivers/net/qede/qede_ethdev.c
>> index d106dd0..31f6733 100644
>> --- a/drivers/net/qede/qede_ethdev.c
>> +++ b/drivers/net/qede/qede_ethdev.c
>> @@ -1642,6 +1642,10 @@ static struct rte_pci_id pci_id_qede_map[] = {
>>     static struct eth_driver rte_qedevf_pmd = {
>>       .pci_drv = {
>> +            .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +            },
>>               .id_table = pci_id_qedevf_map,
>>               .drv_flags =
>>               RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>> @@ -1655,6 +1659,10 @@ static struct eth_driver rte_qedevf_pmd = {
>>     static struct eth_driver rte_qede_pmd = {
>>       .pci_drv = {
>> +            .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +            },
>>               .id_table = pci_id_qede_map,
>>               .drv_flags =
>>               RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>> diff --git a/drivers/net/szedata2/rte_eth_szedata2.c
>> b/drivers/net/szedata2/rte_eth_szedata2.c
>> index f3cd52d..a649e60 100644
>> --- a/drivers/net/szedata2/rte_eth_szedata2.c
>> +++ b/drivers/net/szedata2/rte_eth_szedata2.c
>> @@ -1572,6 +1572,10 @@ static const struct rte_pci_id
>> rte_szedata2_pci_id_table[] = {
>>     static struct eth_driver szedata2_eth_driver = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = rte_szedata2_pci_id_table,
>>           .probe = rte_eth_dev_pci_probe,
>>           .remove = rte_eth_dev_pci_remove,
>> diff --git a/drivers/net/thunderx/nicvf_ethdev.c
>> b/drivers/net/thunderx/nicvf_ethdev.c
>> index 466e49c..72ac748 100644
>> --- a/drivers/net/thunderx/nicvf_ethdev.c
>> +++ b/drivers/net/thunderx/nicvf_ethdev.c
>> @@ -2110,6 +2110,10 @@ static const struct rte_pci_id
>> pci_id_nicvf_map[] = {
>>     static struct eth_driver rte_nicvf_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_nicvf_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
>>           .probe = rte_eth_dev_pci_probe,
>> diff --git a/drivers/net/virtio/virtio_ethdev.c
>> b/drivers/net/virtio/virtio_ethdev.c
>> index 079fd6c..4d5d1bb 100644
>> --- a/drivers/net/virtio/virtio_ethdev.c
>> +++ b/drivers/net/virtio/virtio_ethdev.c
>> @@ -1377,6 +1377,8 @@ static struct eth_driver rte_virtio_pmd = {
>>       .pci_drv = {
>>           .driver = {
>>               .name = "net_virtio",
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>>           },
>>           .id_table = pci_id_virtio_map,
>>           .drv_flags = RTE_PCI_DRV_DETACHABLE,
>> diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c
>> b/drivers/net/vmxnet3/vmxnet3_ethdev.c
>> index 8bb13e5..57f66cb 100644
>> --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
>> +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
>> @@ -335,6 +335,10 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
>>     static struct eth_driver rte_vmxnet3_pmd = {
>>       .pci_drv = {
>> +        .driver = {
>> +            .probe = rte_eal_pci_probe,
>> +            .remove = rte_eal_pci_remove,
>> +        },
>>           .id_table = pci_id_vmxnet3_map,
>>           .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
>>           .probe = rte_eth_dev_pci_probe,
>
>
>

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-13 22:24     ` Jan Blunck
@ 2016-12-14  5:12       ` Shreyansh Jain
  2016-12-16  8:14         ` Jan Blunck
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-14  5:12 UTC (permalink / raw)
  To: Jan Blunck
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu,
	Jan Viktorin

On Wednesday 14 December 2016 03:54 AM, Jan Blunck wrote:
> On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> From: Jan Blunck <jblunck@infradead.org>
>>
>> This macro is based on Jan Viktorin's original patch but also checks the
>> type of the passed pointer against the type of the member.
>>
>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
>> [shreyansh.jain@nxp.com: Fix checkpatch error]
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> [jblunck@infradead.org: add type checking and __extension__]
>> Signed-off-by: Jan Blunck <jblunck@infradead.org>
>>
>> --
>> v2:
>>  - fix checkpatch error
>> ---
>>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
>>  1 file changed, 21 insertions(+)
>>
>> diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
>> index db5ac91..3eb8d11 100644
>> --- a/lib/librte_eal/common/include/rte_common.h
>> +++ b/lib/librte_eal/common/include/rte_common.h
>> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
>>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
>>  #endif
>>
>> +/**
>> + * Return pointer to the wrapping struct instance.
>> + *
>> + * Example:
>> + *
>> + *  struct wrapper {
>> + *      ...
>> + *      struct child c;
>> + *      ...
>> + *  };
>> + *
>> + *  struct child *x = obtain(...);
>> + *  struct wrapper *w = container_of(x, struct wrapper, c);
>> + */
>> +#ifndef container_of
>> +#define container_of(ptr, type, member)        (__extension__  ({              \
>> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
>> +                       (type *)(((char *)_ptr) - offsetof(type, member));\
>> +                       }))
>
> This is a checkpatch false positive. It should be fine to ignore this.
> IIRC we already discussed this before.

I too thought something similar was discussed. I tried searching the 
archives but couldn't find anything - thus, I thought probably I was 
hallucinating :P

So, you want me to revert back the '()' change? Does it impact the 
expansion of this macro?

>
>
>> +#endif
>> +
>>  #define _RTE_STR(x) #x
>>  /** Take a macro value and get a string version of it */
>>  #define RTE_STR(x) _RTE_STR(x)
>> --
>> 2.7.4
>>
>

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-13 15:07       ` Ferruh Yigit
@ 2016-12-14  5:14         ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-14  5:14 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: Andrew Rybchenko, dev

Hello Ferruh,

On Tuesday 13 December 2016 08:37 PM, Ferruh Yigit wrote:
> On 12/13/2016 1:52 PM, Andrew Rybchenko wrote:
>> On 12/13/2016 04:37 PM, Shreyansh Jain wrote:
>>> These callbacks now act as first layer of PCI interfaces from the Bus.
>>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>>> drivers are rte_pci_driver).
>>
>> I think similar changes in drivers/net/sfc/sfc_ethdev.c (already in
>> dpdk-next-net) are required as well.
>
> Yes, that change is required, but it is a little tricky because this
> patchset targets main tree where sfc is not merged yet, so this patch
> can't include required patches.
>
> I think it is possible to wait for this patch to be merged into main
> tree, and when next-net rebased on top of it, sfc can be patched
> individually.
>
> So, yes there is a work to do there, but I think it can be postponed a
> little.
>
<snip>

I noticed this email after replying something similar (and a question) 
to Andrew. Sorry for double posting same thing.

-
Shreyansh

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-13 13:37   ` [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
  2016-12-13 13:52     ` Andrew Rybchenko
@ 2016-12-14  9:49     ` Shreyansh Jain
  2016-12-15 21:36       ` Jan Blunck
  1 sibling, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-14  9:49 UTC (permalink / raw)
  To: dev, Jan Blunck; +Cc: david.marchand, thomas.monjalon, ferruh.yigit, jianbo.liu

On Tuesday 13 December 2016 07:07 PM, Shreyansh Jain wrote:
> These callbacks now act as first layer of PCI interfaces from the Bus.
> Bus probe would enter the PMDs through the rte_driver->probe/remove
> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
> drivers are rte_pci_driver).
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>  drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>  drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>  drivers/net/e1000/em_ethdev.c           | 4 ++++
>  drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>  drivers/net/ena/ena_ethdev.c            | 4 ++++
>  drivers/net/enic/enic_ethdev.c          | 4 ++++
>  drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>  drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>  drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>  drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>  drivers/net/mlx4/mlx4.c                 | 4 +++-
>  drivers/net/mlx5/mlx5.c                 | 1 +
>  drivers/net/nfp/nfp_net.c               | 4 ++++
>  drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>  drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>  drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>  drivers/net/virtio/virtio_ethdev.c      | 2 ++
>  drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>  19 files changed, 86 insertions(+), 1 deletion(-)
>
<snip>

drivers/crypto/qat/rte_qat_cryptodev.c should also be changed for this. 
It seems to be only PCI registered PMD. All others are VDEV.

I will send a v3 soon to fix this.

@Jan, would you be looking in the VDEV part or should I start with that? [1]

[1] http://dpdk.org/ml/archives/dev/2016-November/050443.html

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-14  9:49     ` Shreyansh Jain
@ 2016-12-15 21:36       ` Jan Blunck
  2016-12-26  9:14         ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Jan Blunck @ 2016-12-15 21:36 UTC (permalink / raw)
  To: Shreyansh Jain
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu

On Wed, Dec 14, 2016 at 10:49 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> On Tuesday 13 December 2016 07:07 PM, Shreyansh Jain wrote:
>>
>> These callbacks now act as first layer of PCI interfaces from the Bus.
>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>> drivers are rte_pci_driver).
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> ---
>>  drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>>  drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>>  drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>>  drivers/net/e1000/em_ethdev.c           | 4 ++++
>>  drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>>  drivers/net/ena/ena_ethdev.c            | 4 ++++
>>  drivers/net/enic/enic_ethdev.c          | 4 ++++
>>  drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>>  drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>>  drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>>  drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>>  drivers/net/mlx4/mlx4.c                 | 4 +++-
>>  drivers/net/mlx5/mlx5.c                 | 1 +
>>  drivers/net/nfp/nfp_net.c               | 4 ++++
>>  drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>>  drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>>  drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>>  drivers/net/virtio/virtio_ethdev.c      | 2 ++
>>  drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>>  19 files changed, 86 insertions(+), 1 deletion(-)
>>
> <snip>
>
> drivers/crypto/qat/rte_qat_cryptodev.c should also be changed for this. It
> seems to be only PCI registered PMD. All others are VDEV.
>
> I will send a v3 soon to fix this.
>
> @Jan, would you be looking in the VDEV part or should I start with that? [1]
>

Yes, I am doing that. Will send out early next week.

Thx,
Jan

> [1] http://dpdk.org/ml/archives/dev/2016-November/050443.html
>

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-14  5:12       ` Shreyansh Jain
@ 2016-12-16  8:14         ` Jan Blunck
  2016-12-16  9:23           ` Adrien Mazarguil
  0 siblings, 1 reply; 132+ messages in thread
From: Jan Blunck @ 2016-12-16  8:14 UTC (permalink / raw)
  To: Shreyansh Jain
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu,
	Jan Viktorin

On Wed, Dec 14, 2016 at 6:12 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> On Wednesday 14 December 2016 03:54 AM, Jan Blunck wrote:
>>
>> On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com>
>> wrote:
>>>
>>> From: Jan Blunck <jblunck@infradead.org>
>>>
>>> This macro is based on Jan Viktorin's original patch but also checks the
>>> type of the passed pointer against the type of the member.
>>>
>>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
>>> [shreyansh.jain@nxp.com: Fix checkpatch error]
>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>> [jblunck@infradead.org: add type checking and __extension__]
>>> Signed-off-by: Jan Blunck <jblunck@infradead.org>
>>>
>>> --
>>> v2:
>>>  - fix checkpatch error
>>> ---
>>>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
>>>  1 file changed, 21 insertions(+)
>>>
>>> diff --git a/lib/librte_eal/common/include/rte_common.h
>>> b/lib/librte_eal/common/include/rte_common.h
>>> index db5ac91..3eb8d11 100644
>>> --- a/lib/librte_eal/common/include/rte_common.h
>>> +++ b/lib/librte_eal/common/include/rte_common.h
>>> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
>>>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
>>>  #endif
>>>
>>> +/**
>>> + * Return pointer to the wrapping struct instance.
>>> + *
>>> + * Example:
>>> + *
>>> + *  struct wrapper {
>>> + *      ...
>>> + *      struct child c;
>>> + *      ...
>>> + *  };
>>> + *
>>> + *  struct child *x = obtain(...);
>>> + *  struct wrapper *w = container_of(x, struct wrapper, c);
>>> + */
>>> +#ifndef container_of
>>> +#define container_of(ptr, type, member)        (__extension__  ({
>>> \
>>> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
>>> +                       (type *)(((char *)_ptr) - offsetof(type,
>>> member));\
>>> +                       }))
>>
>>
>> This is a checkpatch false positive. It should be fine to ignore this.
>> IIRC we already discussed this before.
>
>
> I too thought something similar was discussed. I tried searching the
> archives but couldn't find anything - thus, I thought probably I was
> hallucinating :P
>
> So, you want me to revert back the '()' change? Does it impact the expansion
> of this macro?

We haven't added this on any other usage of the __extension__ keyword
in the existing code. From my perspective it is more consistent to
revert it.

Anyone else with an opinion here? David? Thomas?


>
>>
>>
>>> +#endif
>>> +
>>>  #define _RTE_STR(x) #x
>>>  /** Take a macro value and get a string version of it */
>>>  #define RTE_STR(x) _RTE_STR(x)
>>> --
>>> 2.7.4
>>>
>>
>

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-16  8:14         ` Jan Blunck
@ 2016-12-16  9:23           ` Adrien Mazarguil
  2016-12-16 10:47             ` Jan Blunck
  0 siblings, 1 reply; 132+ messages in thread
From: Adrien Mazarguil @ 2016-12-16  9:23 UTC (permalink / raw)
  To: Jan Blunck
  Cc: Shreyansh Jain, dev, David Marchand, Thomas Monjalon,
	Ferruh Yigit, jianbo.liu, Jan Viktorin

On Fri, Dec 16, 2016 at 09:14:29AM +0100, Jan Blunck wrote:
> On Wed, Dec 14, 2016 at 6:12 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> > On Wednesday 14 December 2016 03:54 AM, Jan Blunck wrote:
> >>
> >> On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com>
> >> wrote:
> >>>
> >>> From: Jan Blunck <jblunck@infradead.org>
> >>>
> >>> This macro is based on Jan Viktorin's original patch but also checks the
> >>> type of the passed pointer against the type of the member.
> >>>
> >>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> >>> [shreyansh.jain@nxp.com: Fix checkpatch error]
> >>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> >>> [jblunck@infradead.org: add type checking and __extension__]
> >>> Signed-off-by: Jan Blunck <jblunck@infradead.org>
> >>>
> >>> --
> >>> v2:
> >>>  - fix checkpatch error
> >>> ---
> >>>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
> >>>  1 file changed, 21 insertions(+)
> >>>
> >>> diff --git a/lib/librte_eal/common/include/rte_common.h
> >>> b/lib/librte_eal/common/include/rte_common.h
> >>> index db5ac91..3eb8d11 100644
> >>> --- a/lib/librte_eal/common/include/rte_common.h
> >>> +++ b/lib/librte_eal/common/include/rte_common.h
> >>> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
> >>>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
> >>>  #endif
> >>>
> >>> +/**
> >>> + * Return pointer to the wrapping struct instance.
> >>> + *
> >>> + * Example:
> >>> + *
> >>> + *  struct wrapper {
> >>> + *      ...
> >>> + *      struct child c;
> >>> + *      ...
> >>> + *  };
> >>> + *
> >>> + *  struct child *x = obtain(...);
> >>> + *  struct wrapper *w = container_of(x, struct wrapper, c);
> >>> + */
> >>> +#ifndef container_of
> >>> +#define container_of(ptr, type, member)        (__extension__  ({
> >>> \
> >>> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
> >>> +                       (type *)(((char *)_ptr) - offsetof(type,
> >>> member));\
> >>> +                       }))
> >>
> >>
> >> This is a checkpatch false positive. It should be fine to ignore this.
> >> IIRC we already discussed this before.
> >
> >
> > I too thought something similar was discussed. I tried searching the
> > archives but couldn't find anything - thus, I thought probably I was
> > hallucinating :P
> >
> > So, you want me to revert back the '()' change? Does it impact the expansion
> > of this macro?
> 
> We haven't added this on any other usage of the __extension__ keyword
> in the existing code. From my perspective it is more consistent to
> revert it.
> 
> Anyone else with an opinion here? David? Thomas?

As an exported header, rte_common.h must pass check-includes.sh. Both
typeof() and the ({ ... }) construct are non-standard GCC extensions and
would fail to compile with pedantic options.

-- 
Adrien Mazarguil
6WIND

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-16  9:23           ` Adrien Mazarguil
@ 2016-12-16 10:47             ` Jan Blunck
  2016-12-16 11:21               ` Adrien Mazarguil
  0 siblings, 1 reply; 132+ messages in thread
From: Jan Blunck @ 2016-12-16 10:47 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: Shreyansh Jain, dev, David Marchand, Thomas Monjalon,
	Ferruh Yigit, jianbo.liu, Jan Viktorin

On Fri, Dec 16, 2016 at 10:23 AM, Adrien Mazarguil
<adrien.mazarguil@6wind.com> wrote:
> On Fri, Dec 16, 2016 at 09:14:29AM +0100, Jan Blunck wrote:
>> On Wed, Dec 14, 2016 at 6:12 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> > On Wednesday 14 December 2016 03:54 AM, Jan Blunck wrote:
>> >>
>> >> On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com>
>> >> wrote:
>> >>>
>> >>> From: Jan Blunck <jblunck@infradead.org>
>> >>>
>> >>> This macro is based on Jan Viktorin's original patch but also checks the
>> >>> type of the passed pointer against the type of the member.
>> >>>
>> >>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
>> >>> [shreyansh.jain@nxp.com: Fix checkpatch error]
>> >>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> >>> [jblunck@infradead.org: add type checking and __extension__]
>> >>> Signed-off-by: Jan Blunck <jblunck@infradead.org>
>> >>>
>> >>> --
>> >>> v2:
>> >>>  - fix checkpatch error
>> >>> ---
>> >>>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
>> >>>  1 file changed, 21 insertions(+)
>> >>>
>> >>> diff --git a/lib/librte_eal/common/include/rte_common.h
>> >>> b/lib/librte_eal/common/include/rte_common.h
>> >>> index db5ac91..3eb8d11 100644
>> >>> --- a/lib/librte_eal/common/include/rte_common.h
>> >>> +++ b/lib/librte_eal/common/include/rte_common.h
>> >>> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
>> >>>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
>> >>>  #endif
>> >>>
>> >>> +/**
>> >>> + * Return pointer to the wrapping struct instance.
>> >>> + *
>> >>> + * Example:
>> >>> + *
>> >>> + *  struct wrapper {
>> >>> + *      ...
>> >>> + *      struct child c;
>> >>> + *      ...
>> >>> + *  };
>> >>> + *
>> >>> + *  struct child *x = obtain(...);
>> >>> + *  struct wrapper *w = container_of(x, struct wrapper, c);
>> >>> + */
>> >>> +#ifndef container_of
>> >>> +#define container_of(ptr, type, member)        (__extension__  ({
>> >>> \
>> >>> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
>> >>> +                       (type *)(((char *)_ptr) - offsetof(type,
>> >>> member));\
>> >>> +                       }))
>> >>
>> >>
>> >> This is a checkpatch false positive. It should be fine to ignore this.
>> >> IIRC we already discussed this before.
>> >
>> >
>> > I too thought something similar was discussed. I tried searching the
>> > archives but couldn't find anything - thus, I thought probably I was
>> > hallucinating :P
>> >
>> > So, you want me to revert back the '()' change? Does it impact the expansion
>> > of this macro?
>>
>> We haven't added this on any other usage of the __extension__ keyword
>> in the existing code. From my perspective it is more consistent to
>> revert it.
>>
>> Anyone else with an opinion here? David? Thomas?
>
> As an exported header, rte_common.h must pass check-includes.sh. Both
> typeof() and the ({ ... }) construct are non-standard GCC extensions and
> would fail to compile with pedantic options.
>

Thanks Adrien. These extensions are already in use by rte_common.h and
other headers. I don't believe we can remove the usage of typeof()
that easily without making the code really ugly.

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-16 10:47             ` Jan Blunck
@ 2016-12-16 11:21               ` Adrien Mazarguil
  2016-12-16 11:54                 ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Adrien Mazarguil @ 2016-12-16 11:21 UTC (permalink / raw)
  To: Jan Blunck
  Cc: Shreyansh Jain, dev, David Marchand, Thomas Monjalon,
	Ferruh Yigit, jianbo.liu, Jan Viktorin

On Fri, Dec 16, 2016 at 11:47:14AM +0100, Jan Blunck wrote:
> On Fri, Dec 16, 2016 at 10:23 AM, Adrien Mazarguil
> <adrien.mazarguil@6wind.com> wrote:
> > On Fri, Dec 16, 2016 at 09:14:29AM +0100, Jan Blunck wrote:
> >> On Wed, Dec 14, 2016 at 6:12 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> >> > On Wednesday 14 December 2016 03:54 AM, Jan Blunck wrote:
> >> >>
> >> >> On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com>
> >> >> wrote:
> >> >>>
> >> >>> From: Jan Blunck <jblunck@infradead.org>
> >> >>>
> >> >>> This macro is based on Jan Viktorin's original patch but also checks the
> >> >>> type of the passed pointer against the type of the member.
> >> >>>
> >> >>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
> >> >>> [shreyansh.jain@nxp.com: Fix checkpatch error]
> >> >>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> >> >>> [jblunck@infradead.org: add type checking and __extension__]
> >> >>> Signed-off-by: Jan Blunck <jblunck@infradead.org>
> >> >>>
> >> >>> --
> >> >>> v2:
> >> >>>  - fix checkpatch error
> >> >>> ---
> >> >>>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
> >> >>>  1 file changed, 21 insertions(+)
> >> >>>
> >> >>> diff --git a/lib/librte_eal/common/include/rte_common.h
> >> >>> b/lib/librte_eal/common/include/rte_common.h
> >> >>> index db5ac91..3eb8d11 100644
> >> >>> --- a/lib/librte_eal/common/include/rte_common.h
> >> >>> +++ b/lib/librte_eal/common/include/rte_common.h
> >> >>> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
> >> >>>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
> >> >>>  #endif
> >> >>>
> >> >>> +/**
> >> >>> + * Return pointer to the wrapping struct instance.
> >> >>> + *
> >> >>> + * Example:
> >> >>> + *
> >> >>> + *  struct wrapper {
> >> >>> + *      ...
> >> >>> + *      struct child c;
> >> >>> + *      ...
> >> >>> + *  };
> >> >>> + *
> >> >>> + *  struct child *x = obtain(...);
> >> >>> + *  struct wrapper *w = container_of(x, struct wrapper, c);
> >> >>> + */
> >> >>> +#ifndef container_of
> >> >>> +#define container_of(ptr, type, member)        (__extension__  ({
> >> >>> \
> >> >>> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
> >> >>> +                       (type *)(((char *)_ptr) - offsetof(type,
> >> >>> member));\
> >> >>> +                       }))
> >> >>
> >> >>
> >> >> This is a checkpatch false positive. It should be fine to ignore this.
> >> >> IIRC we already discussed this before.
> >> >
> >> >
> >> > I too thought something similar was discussed. I tried searching the
> >> > archives but couldn't find anything - thus, I thought probably I was
> >> > hallucinating :P
> >> >
> >> > So, you want me to revert back the '()' change? Does it impact the expansion
> >> > of this macro?
> >>
> >> We haven't added this on any other usage of the __extension__ keyword
> >> in the existing code. From my perspective it is more consistent to
> >> revert it.
> >>
> >> Anyone else with an opinion here? David? Thomas?
> >
> > As an exported header, rte_common.h must pass check-includes.sh. Both
> > typeof() and the ({ ... }) construct are non-standard GCC extensions and
> > would fail to compile with pedantic options.
> >
> 
> Thanks Adrien. These extensions are already in use by rte_common.h and
> other headers. I don't believe we can remove the usage of typeof()
> that easily without making the code really ugly.

Sure, no problem with that, I misread and thought you wanted to drop
__extension__ as well.

Parentheses may perhaps cause more accurate warnings in case of syntax
errors. That is not significant so either way is fine by me.

-- 
Adrien Mazarguil
6WIND

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

* Re: [PATCH v2 01/12] eal: define container_of macro
  2016-12-16 11:21               ` Adrien Mazarguil
@ 2016-12-16 11:54                 ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 11:54 UTC (permalink / raw)
  To: Adrien Mazarguil, Jan Blunck
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu,
	Jan Viktorin

On Friday 16 December 2016 04:51 PM, Adrien Mazarguil wrote:
> On Fri, Dec 16, 2016 at 11:47:14AM +0100, Jan Blunck wrote:
>> On Fri, Dec 16, 2016 at 10:23 AM, Adrien Mazarguil
>> <adrien.mazarguil@6wind.com> wrote:
>>> On Fri, Dec 16, 2016 at 09:14:29AM +0100, Jan Blunck wrote:
>>>> On Wed, Dec 14, 2016 at 6:12 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>>>>> On Wednesday 14 December 2016 03:54 AM, Jan Blunck wrote:
>>>>>>
>>>>>> On Tue, Dec 13, 2016 at 2:37 PM, Shreyansh Jain <shreyansh.jain@nxp.com>
>>>>>> wrote:
>>>>>>>
>>>>>>> From: Jan Blunck <jblunck@infradead.org>
>>>>>>>
>>>>>>> This macro is based on Jan Viktorin's original patch but also checks the
>>>>>>> type of the passed pointer against the type of the member.
>>>>>>>
>>>>>>> Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
>>>>>>> [shreyansh.jain@nxp.com: Fix checkpatch error]
>>>>>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>>>>>> [jblunck@infradead.org: add type checking and __extension__]
>>>>>>> Signed-off-by: Jan Blunck <jblunck@infradead.org>
>>>>>>>
>>>>>>> --
>>>>>>> v2:
>>>>>>>  - fix checkpatch error
>>>>>>> ---
>>>>>>>  lib/librte_eal/common/include/rte_common.h | 21 +++++++++++++++++++++
>>>>>>>  1 file changed, 21 insertions(+)
>>>>>>>
>>>>>>> diff --git a/lib/librte_eal/common/include/rte_common.h
>>>>>>> b/lib/librte_eal/common/include/rte_common.h
>>>>>>> index db5ac91..3eb8d11 100644
>>>>>>> --- a/lib/librte_eal/common/include/rte_common.h
>>>>>>> +++ b/lib/librte_eal/common/include/rte_common.h
>>>>>>> @@ -331,6 +331,27 @@ rte_bsf32(uint32_t v)
>>>>>>>  #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
>>>>>>>  #endif
>>>>>>>
>>>>>>> +/**
>>>>>>> + * Return pointer to the wrapping struct instance.
>>>>>>> + *
>>>>>>> + * Example:
>>>>>>> + *
>>>>>>> + *  struct wrapper {
>>>>>>> + *      ...
>>>>>>> + *      struct child c;
>>>>>>> + *      ...
>>>>>>> + *  };
>>>>>>> + *
>>>>>>> + *  struct child *x = obtain(...);
>>>>>>> + *  struct wrapper *w = container_of(x, struct wrapper, c);
>>>>>>> + */
>>>>>>> +#ifndef container_of
>>>>>>> +#define container_of(ptr, type, member)        (__extension__  ({
>>>>>>> \
>>>>>>> +                       typeof(((type *)0)->member) * _ptr = (ptr);     \
>>>>>>> +                       (type *)(((char *)_ptr) - offsetof(type,
>>>>>>> member));\
>>>>>>> +                       }))
>>>>>>
>>>>>>
>>>>>> This is a checkpatch false positive. It should be fine to ignore this.
>>>>>> IIRC we already discussed this before.
>>>>>
>>>>>
>>>>> I too thought something similar was discussed. I tried searching the
>>>>> archives but couldn't find anything - thus, I thought probably I was
>>>>> hallucinating :P
>>>>>
>>>>> So, you want me to revert back the '()' change? Does it impact the expansion
>>>>> of this macro?
>>>>
>>>> We haven't added this on any other usage of the __extension__ keyword
>>>> in the existing code. From my perspective it is more consistent to
>>>> revert it.
>>>>
>>>> Anyone else with an opinion here? David? Thomas?
>>>
>>> As an exported header, rte_common.h must pass check-includes.sh. Both
>>> typeof() and the ({ ... }) construct are non-standard GCC extensions and
>>> would fail to compile with pedantic options.
>>>
>>
>> Thanks Adrien. These extensions are already in use by rte_common.h and
>> other headers. I don't believe we can remove the usage of typeof()
>> that easily without making the code really ugly.
>
> Sure, no problem with that, I misread and thought you wanted to drop
> __extension__ as well.
>
> Parentheses may perhaps cause more accurate warnings in case of syntax
> errors. That is not significant so either way is fine by me.
>

If that is the case, and it is OK to ignore the checkpatche warnings 
because of missing '(' and ')' (or, something else), I too prefer not to 
touch the patch unnecessarily.

I will remove my changes and revert back to original patch as created by 
Jan Blunck.

Thanks for clarifications.

-
Shreyansh

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

* [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model
  2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
                     ` (11 preceding siblings ...)
  2016-12-13 13:37   ` [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
@ 2016-12-16 13:10   ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 01/12] eal: define container_of macro Shreyansh Jain
                       ` (12 more replies)
  12 siblings, 13 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Link to v1: [10]
Link to v2: [11]

:: 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 context of DPDK EAL:
 - rte_bus, represents a Bus. An implementation of a physical bus would
   instantiate this class.
 - Buses are registered just like a PMD - RTE_REGISTER_BUS()
   `- Thus, implementation for PCI would instantiate a rte_bus, give it a
      name and provide scan/match hooks.
    - Currently, priority of RTE_REGISTER_BUS constructor has been set to
      101 to make sure bus is registered *before* drivers are.
 - Each registered bus is part of a doubly list.
   -- Each device refers to rte_bus on which it belongs
   -- Each driver refers to rte_bus with which it is associated
   -- Device and Drivers lists are part of rte_bus
   -- NO global device/driver list would exist
 - When a PMD wants to register itself, it would 'add' itself to an
   existing bus. Which essentially converts to adding the driver to
   a bus specific driver_list.
 - Bus would perform a scan and 'add' devices scanned to its list.
 - Bus would perform a probe and link devices and drivers on each bus and
   invoking a series of probes
   `-- There are some parallel work for combining scan/probe in EAL [5]
       and also for doing away with a independent scan function all
       together [6].


The view would be almost like:

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> device_list for this bus
                     | device_list----    
                     | scan()       | `-> driver_list for this bus
                     | match()      |
                     | probe()      |
                     |              |
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | *rte_bus    |                     | *rte_bus        |
    | rte_driver  |                     | probe()         |
    |             |                     | remove()        |
    |  devargs    |                     |                 |
    +---||--------+                     +---------|||-----+
        ||                                        '''      
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | PCI specific   | | xxx device    |               |||
 | info (mem,)    | | specific fns  |              / | \
 +----------------+ +---------------+             /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | PCI id table,  |    | <probably,     |    | ....          |
            | other driver   |    |  nothing>      |    +---------------+
            | data           |    |  ...           |
            |  probe()       |    +----------------+
            |  remove()      |
            +----------------+

In continuation to the RFC posted on 17/Nov [9],
A series of patches is being posted which attempts to create:
 1. A basic bus model
    `- define rte_bus and associated methods/helpers
    `- test infrastructure to test the Bus infra
 2. Changes in EAL to support PCI as a bus
    `- a "pci" bus is registered
    `- existing scan/match/probe are modified to allow for bus integration
    `- PCI Device and Driver list, which were global entities, have been
       moved to rte_bus->[device/driver]_list

For v2 as well, I have sanity tested this patch over a XeonD X552 available
with me, as well as part of PoC for verifying NXP's DPAA2 PMD (being pushed
out in a separate series). Exhaustive testing is still pending.
 -> Please help in MLX & BSD related changes.

:: Brief about Patch Layout ::

0001:      Container_of patch from [3]
0002~0003: Introducing the basic Bus model and associated test case
0004~0005: Add scan, match and insert support for devices on bus
0006:      Add probe and remove for rte_driver
0007:      Enable probing of PCI Bus (devices) from EAL
0008:      Split the existing PCI probe into match and probe
0009:      Make PCI probe/match work on rte_driver/device rather than
           rte_pci_device/rte_pci_driver
0010:      Patch from Ben [8], part of series [2]
0011:      Enable Scan/Match/probe on Bus from EAL and remove unused
           functions and lists. PMDs still don't work (in fact, PCI PMD
           don't work after this patch - but without any compilation
           issues). Also, fix PCI test framework to reflect the bus
           integration.
0012:      Change PMDs to integrate with PCI bus

:: Pending Changes/Caveats ::

0. eth_dev still contains rte_pci_device. I am banking on Jan's patches [1]
   for conversion to a macro (ETH_DEV_PCI_DEV) and subsequent replacement
   of all pci_dev usage in eth_dev.

1. One of the major changes pending, as against proposed in RFC, is the
   removal of eth_driver.
   Being a large change, and independent one, this would be done in a
   separate series of patches.

2. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   - there was an open question in RFC about where to place the PCI bus
     instance - whether in drivers/bus/... or in lib/librte_bus/... or
     lib/librte_eal/...; This patch uses the last option. But, movement
     only impacts placement of Makefiles. Please convey your reservations
     for current placement.
   - It also impacts the point (8) about priority use in constructor

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

4. There was a suggestion from Jan Blunk about a helper iterator within the
   rte_bus. That is still pending.

5. The overall layout for driver probing has changed a little.
   earlier, it was:
    rte_eal_init()
     `-> rte_eal_pci_probe() (and parallel for VDEV)
         `-> rte_pci_driver->probe()
             `-> eth_driver->eth_dev_init()

   now, it would be:
   rte_eal_init()
     `-> rte_eal_bus_probe() <- Iterator for PCI device/driver
         `-> rte_driver->probe() <- devargs handling
             |                      old rte_eal_pci_probe()
             `-> rte_xxx_driver->probe() <- eth_dev allocation
                 `-> eth_driver->eth_dev_init <- eth_dev init

   Open Questions:
       Also, rte_driver->probe() creating eth_dev certainly sounds a little
       wrong - but, I would like to get your opinion on how to lay this
       order of which layer ethernet device corresponds to.
       1) Which layer should allocate eth_dev?
          `-> My take: rte_driver->probe()
       2) which layer should fill the eth_dev?
          `-> My take: rte_xxx_driver->probe()
       3) Is init/uninit better name for rte_xxx_driver()->probe() if all
          they do is initialize the ethernet device?

 8. 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
 - vdev changes
 - eth_device, eth_driver changes

:: 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

:: Version Changes ::
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)

Ben Walker (1):
  pci: Pass rte_pci_addr to functions instead of separate args

Jan Blunck (1):
  eal: define container_of macro

Shreyansh Jain (10):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  eal/bus: add scan, match and insert support
  eal: integrate bus scan and probe with EAL
  eal: add probe and remove support for rte_driver
  eal: enable probe from bus infrastructure
  pci: split match and probe function
  eal/pci: generalize args of PCI scan/match towards RTE device/driver
  eal: enable PCI bus and PCI test framework
  drivers: update PMDs to use rte_driver probe and remove

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 688 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 154 ++++--
 drivers/crypto/qat/rte_qat_cryptodev.c          |   4 +
 drivers/net/bnx2x/bnx2x_ethdev.c                |   8 +
 drivers/net/bnxt/bnxt_ethdev.c                  |   4 +
 drivers/net/cxgbe/cxgbe_ethdev.c                |   4 +
 drivers/net/e1000/em_ethdev.c                   |   4 +
 drivers/net/e1000/igb_ethdev.c                  |   8 +
 drivers/net/ena/ena_ethdev.c                    |   4 +
 drivers/net/enic/enic_ethdev.c                  |   4 +
 drivers/net/fm10k/fm10k_ethdev.c                |   4 +
 drivers/net/i40e/i40e_ethdev.c                  |   4 +
 drivers/net/i40e/i40e_ethdev_vf.c               |   4 +
 drivers/net/ixgbe/ixgbe_ethdev.c                |   8 +
 drivers/net/mlx4/mlx4.c                         |   4 +-
 drivers/net/mlx5/mlx5.c                         |   1 +
 drivers/net/nfp/nfp_net.c                       |   4 +
 drivers/net/qede/qede_ethdev.c                  |   8 +
 drivers/net/szedata2/rte_eth_szedata2.c         |   4 +
 drivers/net/thunderx/nicvf_ethdev.c             |   4 +
 drivers/net/virtio/virtio_ethdev.c              |   2 +
 drivers/net/vmxnet3/vmxnet3_ethdev.c            |   4 +
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  12 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  22 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 286 ++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 344 +++++++-----
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_bus.h         | 257 +++++++++
 lib/librte_eal/common/include/rte_common.h      |  20 +
 lib/librte_eal/common/include/rte_dev.h         |  14 +
 lib/librte_eal/common/include/rte_pci.h         |  59 +-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  12 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  84 ++-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  22 +-
 40 files changed, 1840 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.4

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

* [PATCH v3 01/12] eal: define container_of macro
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
                       ` (11 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Jan Blunck,
	Jan Viktorin, Shreyansh Jain

From: Jan Blunck <jblunck@infradead.org>

This macro is based on Jan Viktorin's original patch but also checks the
type of the passed pointer against the type of the member.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
[jblunck@infradead.org: add type checking and __extension__]
Signed-off-by: Jan Blunck <jblunck@infradead.org>
---
 lib/librte_eal/common/include/rte_common.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index db5ac91..8dda3e2 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -331,6 +331,26 @@ rte_bsf32(uint32_t v)
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
 #endif
 
+/**
+ * Return pointer to the wrapping struct instance.
+ *
+ * Example:
+ *
+ *  struct wrapper {
+ *      ...
+ *      struct child c;
+ *      ...
+ *  };
+ *
+ *  struct child *x = obtain(...);
+ *  struct wrapper *w = container_of(x, struct wrapper, c);
+ */
+#ifndef container_of
+#define container_of(ptr, type, member)	__extension__ ({		\
+			typeof(((type *)0)->member) *_ptr = (ptr);	\
+			(type *)(((char *)_ptr) - offsetof(type, member)); })
+#endif
+
 #define _RTE_STR(x) #x
 /** Take a macro value and get a string version of it */
 #define RTE_STR(x) _RTE_STR(x)
-- 
2.7.4

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

* [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 01/12] eal: define container_of macro Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-20 12:37       ` Hemant Agrawal
  2016-12-20 13:17       ` Jan Blunck
  2016-12-16 13:10     ` [PATCH v3 03/12] test: add basic bus infrastructure tests Shreyansh Jain
                       ` (10 subsequent siblings)
  12 siblings, 2 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

This patch introduces the rte_bus abstraction for devices and drivers in
EAL framework. 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' class which rte_driver and rte_device refer.
This way, each device (rte_xxx_device) would have reference to the bus
it is based on. As well as, each driver (rte_xxx_driver) would have link
to the bus and devices on it for servicing.

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> List of rte_bus specific
                     | device_list----    devices
                     |              | `-> List of rte_bus associated
                     |              |     drivers
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | rte_bus     |                     | rte_bus         |
    | rte_driver  |                     | ...             |
    | ...         |                     +---------...-----+
    |             |                               |||
    +---||--------+                               |||
        ||                                        |||
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | ....           | | ....          |               |||
 +----------------+ +---------------+              / | \
                                                  /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | ....           |    | ....           |    | ....          |
            +----------------+    +----------------+    +---------------+

This patch only enables the bus references on rte_driver and rte_driver.
EAL wide global device and driver list continue to exist until an instance
of bus is added in subsequent patches.

This patch also introduces RTE_REGISTER_BUS macro on the lines of
RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
been explicitly set to 101 so as to execute bus registration before PMD.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

--
v2:
 - fix bsdapp compilation issue because of missing export symbols in map
   file
---
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 192 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 174 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   2 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
 8 files changed, 401 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..23fc1c1 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index a92c984..0c39414 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..612f64e
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,192 @@
+/*-
+ *   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);
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+	dev->bus = bus;
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev);
+	RTE_VERIFY(dev->bus);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+	dev->bus = NULL;
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+	drv->bus = bus;
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(drv);
+	RTE_VERIFY(drv->bus);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, drv, next);
+	drv->bus = NULL;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_get_bus(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strcmp(bus_name, bus->name)) {
+			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
+			return bus;
+		}
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_INIT(&(bus->driver_list));
+	TAILQ_INIT(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	/* TODO: For each device, call its rte_device->driver->remove()
+	 * and rte_eal_bus_remove_driver()
+	 */
+
+	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_eal_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..f0297a9
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,174 @@
+/*-
+ *   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);
+
+/* Global Bus list */
+extern struct rte_bus_list rte_bus_list;
+
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	struct rte_driver_list driver_list;
+				     /**< List of all drivers on bus */
+	struct rte_device_list device_list;
+				     /**< List of all devices on bus */
+	const char *name;            /**< Name of the bus */
+};
+
+/** @internal
+ * Add a device to a bus.
+ *
+ * @param bus
+ *	Bus on which device is to be added
+ * @param dev
+ *	Device handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
+
+/** @internal
+ * Remove a device from its bus.
+ *
+ * @param dev
+ *	Device handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev);
+
+/** @internal
+ * Associate a driver with a bus.
+ *
+ * @param bus
+ *	Bus on which driver is to be added
+ * @param dev
+ *	Driver handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
+
+/** @internal
+ * Disassociate a driver from its bus.
+ *
+ * @param dev
+ *	Driver handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv);
+
+/**
+ * Register a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_eal_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_eal_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Obtain handle for bus given its name.
+ *
+ * @param bus_name
+ *	Name of the bus handle to search
+ * @return
+ *	Pointer to Bus object if name matches any registered bus object
+ *	NULL, if no matching bus found
+ */
+struct rte_bus *rte_eal_get_bus(const char *bus_name);
+
+/**
+ * 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_eal_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_eal_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 8840380..4004f9a 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 */
 	struct rte_driver *driver;    /**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
@@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
  */
 struct rte_driver {
 	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
+	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
 };
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..c873a7f 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

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

* [PATCH v3 03/12] test: add basic bus infrastructure tests
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 01/12] eal: define container_of macro Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
                       ` (9 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Verification of bus registration, driver registration on a bus.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile   |   2 +-
 app/test/test.h     |   2 +
 app/test/test_bus.c | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 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..760d40a
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,423 @@
+/*-
+ *   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_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
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	const char *name;
+	struct rte_device dev;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus {
+	const char *name;
+	struct rte_bus *bus;
+	struct rte_driver *drivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *devices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct rte_bus busA = {
+	.name = "busA", /* "busA" */
+};
+
+struct rte_bus busB = {
+	.name = "busB", /* "busB */
+};
+
+struct rte_driver driverA = {
+	.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 rte_driver driverB = {
+	.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 dummy_buses[] = {
+	{
+		.name = "busA",
+		.bus = &busA,
+		.drivers = {&driverA, NULL},
+		.devices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.bus = &busB,
+		.drivers = {&driverB, NULL},
+		.devices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus *db;
+	struct rte_bus *bus;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; dummy_buses[i].name; i++) {
+		db = &dummy_buses[i];
+
+		bus = rte_eal_get_bus(db->name);
+		if (!bus)
+			return;
+
+		printf(" Bus: %s\n", bus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			printf("    %s\n", drv->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			printf("    Addr: %p\n", dev);
+			if (dev->driver)
+				printf("    Driver = %s\n", 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);
+		rte_eal_bus_unregister(bus_p);
+		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_eal_bus_unregister(bus_p);
+	}
+
+	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);
+		rte_eal_bus_register(bus_p);
+	}
+
+	dump_device_tree();
+	return 0;
+}
+
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = dummy_buses[i].bus;
+		rte_eal_bus_register(bus);
+		printf("Registered Bus %s\n", dummy_buses[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 dummy_buses */
+		ret = strcmp(bus->name, dummy_buses[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of dummy_buses[i] should be the NULL entry */
+	if (dummy_buses[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       dummy_buses[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_eal_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_eal_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;
+}
+
+/* Positive case: For each driver in dummy_buses, perform
+ * registration
+ */
+static int
+test_driver_registration_on_bus(void)
+{
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv, *drv2;
+
+	/* For each bus on the dummy_buses list:
+	 * 1. get the bus reference
+	 * 2. register all drivers from dummy_buses
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', register all drivers */
+		for (j = 0; dummy_buses[i].drivers[j]; j++) {
+			drv = dummy_buses[i].drivers[j];
+			rte_eal_bus_add_driver(bus, drv);
+		}
+	}
+
+	/* Drivers have been registered. Verify by parsing the list */
+	drv = NULL;
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		j = 0;
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			drv2 = dummy_buses[i].drivers[j++];
+			if (strcmp(drv2->name, drv->name)) {
+				printf("Incorrectly registered drivers."
+				       " Expected: %s; Available: %s\n",
+				       drv2->name, drv->name);
+				return -1;
+			}
+		}
+	}
+
+	printf("Driver registration test successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+static int
+test_driver_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all drivers */
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			rte_eal_bus_remove_driver(drv);
+		}
+	}
+
+	/* Verifying that all drivers have been removed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->driver_list)) {
+			printf("Unable to remove all drivers on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	printf("Unregistration of drivers on all buses is successful.\n");
+	/* All devices from all buses have been removed */
+	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;
+
+	/* Assuming that buses are already registered, register drivers
+	 * with them.
+	 */
+	if (test_driver_registration_on_bus())
+		return -1;
+
+	if (test_driver_unregistration_on_bus())
+		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);
-- 
2.7.4

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

* [PATCH v3 04/12] eal/bus: add scan, match and insert support
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (2 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 03/12] test: add basic bus infrastructure tests Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:25       ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 05/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
                       ` (8 subsequent siblings)
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

When a PMD is registred, it will associate itself with a bus.

A bus is responsible for 'scan' of all the devices attached to it.
All the scanned devices are attached to bus specific device_list.
During the probe operation, 'match' of the drivers and devices would
be done.

Also, rather than adding a device to tail, a new device might be added to
the list (pivoted on bus) at a predefined position, for example, adding it
in order of addressing. Support for this is added as '*bus_insert'.

This patch also adds necessary test framework to test the scan and
match callbacks.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 760d40a..ed95479 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -80,12 +80,32 @@ struct dummy_bus {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+int scan_fn_for_busA(struct rte_bus *bus);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+int scan_fn_for_busB(struct rte_bus *bus);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus busA = {
 	.name = "busA", /* "busA" */
+	.scan = scan_fn_for_busA,
+	.match = generic_match_fn,
 };
 
 struct rte_bus busB = {
 	.name = "busB", /* "busB */
+	.scan = scan_fn_for_busB,
+	.match = generic_match_fn,
 };
 
 struct rte_driver driverA = {
@@ -184,6 +204,92 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the dummy_buses and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that dummy_buses list, register.
+ *
+ * @param bus
+ *	bus to scan againt test entry
+ * @return
+ *	0 for successful scan, even if no devices are found
+ *	!0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+	int i = 0;
+	struct rte_device *dev = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		if (!strcmp(dummy_buses[i].name, bus->name)) {
+			db = &dummy_buses[i];
+			break;
+		}
+	}
+
+	if (!db)
+		return -1;
+
+	/* For all the devices in the device tree (dummy_buses), add device */
+	for (i = 0; db->devices[i]; i++) {
+		dev = &(db->devices[i]->dev);
+		rte_eal_bus_add_device(bus, dev);
+	}
+
+	return 0;
+}
+
+/* @internal
+ * Obtain bus from driver object. Match the address of rte_device object
+ * with all the devices associated with that bus.
+ *
+ * Being a test function, all this does is validate that device object
+ * provided is available on the same bus to which driver is registered.
+ *
+ * @param drv
+ *	driver to which matching is to be performed
+ * @param dev
+ *	device object to match with driver
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct rte_device *dev_p = NULL;
+
+	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
+	 * from bus->device_list.
+	 */
+
+	/* a driver is registered with the bus *before* the scan. */
+	bus = drv->bus;
+	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
+		if (dev == dev_p)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+scan_fn_for_busA(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
+int
+scan_fn_for_busB(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
 static int
 test_bus_setup(void)
 {
@@ -391,6 +497,155 @@ test_driver_unregistration_on_bus(void)
 
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			rte_eal_bus_remove_device(dev);
+		}
+	}
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->device_list)) {
+			printf("Unable to remove all devices on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	/* All devices from all buses have been removed */
+	printf("All devices on all buses unregistered.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful scan
+ *	!0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Call the scan function for each bus */
+		ret = bus->scan(bus);
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * Function to perform 'probe' and link devices and drivers on a bus.
+ * This would work over all the buses registered, and all devices and drivers
+ * registered with it - call match on each pair.
+ * Aim is to test the match_fn for each bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_driver *drv = NULL;
+
+	/* In case of this test:
+	* 1. for each bus in rte_bus_list
+	* 2.  for each device in bus->device_list
+	* 3.   for each driver in bus->driver_list
+	* 4.    call match
+	* 5.    link driver and device
+	* 6. Verify the linkage.
+	*/
+	for (i = 0; dummy_buses[i].name; i++) {
+		/* get bus pointer from dummy_buses itself rather than
+		 * rte_eal_get_bus
+		 */
+		bus = dummy_buses[i].bus;
+
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			TAILQ_FOREACH(drv, &bus->driver_list, next) {
+				if (!bus->match) {
+					printf("Incorrect bus without match "
+					       "fn: (%s).\n", bus->name);
+					return -1;
+				}
+
+				ret = bus->match(drv, dev);
+				if (ret) {
+					printf("Device and driver don't "
+					       "belong to same bus.\n");
+					return -1;
+				}
+				dev->driver = drv;
+
+				/* As match is generic, it always results in
+				 * dev->drv pointing to first driver entry in
+				 * dummy_buses[i]
+				 */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a dummy_buses[i]
+	 * should have same driver (first driver entry of dummy_buses[i])
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		drv = dummy_buses[i].drivers[0];
+
+		for (j = 0; dummy_buses[i].devices[j]; j++) {
+			dev = &(dummy_buses[i].devices[j]->dev);
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
 int
 test_bus(void)
 {
@@ -407,6 +662,16 @@ test_bus(void)
 	if (test_driver_registration_on_bus())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	/* Now that the devices and drivers are registered, perform probe */
+	if (test_probe_on_bus())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_driver_unregistration_on_bus())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 612f64e..162a16f 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -58,6 +58,18 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
 	dev->bus = bus;
 }
 
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev,
+			  struct rte_device *new_dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(old_dev);
+	RTE_VERIFY(new_dev);
+
+	TAILQ_INSERT_BEFORE(old_dev, new_dev, next);
+	new_dev->bus = bus;
+}
+
 /** @internal
  * Remove a device from its bus.
  */
@@ -132,6 +144,9 @@ rte_eal_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan and match implemented */
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->match);
 
 	/* Initialize the driver and device list associated with the bus */
 	TAILQ_INIT(&(bus->driver_list));
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index f0297a9..d1bd2e8 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,49 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Global Bus list */
 extern struct rte_bus_list rte_bus_list;
 
+/**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * Successful detection of a device results in rte_device object which is
+ * embedded within the respective device type (rte_pci_device, for example).
+ * Thereafter, PCI specific bus would need to perform
+ * container_of(rte_pci_device) to obtain PCI device object.
+ *
+ * Scan failure of a bus is not treated as exit criteria for application. Scan
+ * for all other buses would still continue.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param bus
+ *	Reference to the bus on which device is added
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*bus_scan_t)(struct rte_bus *bus);
+
+/**
+ * Bus specific match for devices and drivers which can service them.
+ * For each scanned device, rte_driver->probe would be called for driver
+ * specific initialization of the device.
+ *
+ * It is the work of each bus handler to obtain the specific device object
+ * using container_of (or typecasting, as a less preferred way).
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param drv
+ *	Driver object attached to the bus
+ * @param dev
+ *	Device object which is being probed.
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	struct rte_driver_list driver_list;
@@ -66,6 +109,9 @@ struct rte_bus {
 	struct rte_device_list device_list;
 				     /**< List of all devices on bus */
 	const char *name;            /**< Name of the bus */
+	bus_scan_t scan;            /**< Scan for devices attached to bus */
+	bus_match_t match;
+	/**< Match device with drivers associated with the bus */
 };
 
 /** @internal
@@ -82,6 +128,24 @@ void
 rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
 
 /** @internal
+ * Rather than adding a device to tail, insert at a predefined location.
+ * This is specifically useful for update device cases, or where addition
+ * of devices in the list needs to be ordered (addressing, for example).
+ *
+ * @param bus
+ *	Handle for bus on which device is to be added
+ * @param old_dev
+ *	Existing rte_device object before which new device needs to be added
+ * @param new_dev
+ *	Object for device to be added before old_dev
+ * @return
+ *	void
+ */
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device,
+			  struct rte_device *new_device);
+
+/** @internal
  * Remove a device from its bus.
  *
  * @param dev
-- 
2.7.4

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

* [PATCH v3 05/12] eal: integrate bus scan and probe with EAL
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (3 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 06/12] eal: add probe and remove support for rte_driver Shreyansh Jain
                       ` (7 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Still a dummy implementation as no real bus driver exists. This adds calls
from EAL to bus specific scan, match functions.
Once driver->probe is in place, and a bus handler has been installed,
the code would become effective.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  7 +++++++
 lib/librte_eal/common/eal_common_bus.c  | 30 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h | 19 +++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c       |  7 +++++++
 4 files changed, 63 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 35e3117..30afc6b 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>
@@ -580,6 +581,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -616,6 +620,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 162a16f..5fbfdcc 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -174,6 +174,36 @@ rte_eal_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_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Match driver<->device and call driver->probe() */
+int
+rte_eal_bus_probe(void)
+{
+	/* Until driver->probe is available, this is dummy implementation */
+	return 0;
+}
+
 /* dump one bus info */
 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 d1bd2e8..9bd8650 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -209,6 +209,25 @@ void rte_eal_bus_unregister(struct rte_bus *bus);
  */
 struct rte_bus *rte_eal_get_bus(const char *bus_name);
 
+/** @internal
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);
+
+/** @internal
+ * For each device on the bus, perform a driver 'match' and call the
+ * driver's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_eal_bus_probe(void);
+
 /**
  * Dump information of all the buses registered with EAL.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 2075282..01d0cee 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>
@@ -847,6 +848,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -887,6 +891,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
-- 
2.7.4

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

* [PATCH v3 06/12] eal: add probe and remove support for rte_driver
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (4 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 05/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 07/12] eal: enable probe from bus infrastructure Shreyansh Jain
                       ` (6 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

rte_driver now supports probe and remove. These would be used for generic
device type (PCI, etc) probe and remove.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4004f9a..7d2ab16 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -145,6 +145,16 @@ void rte_eal_device_insert(struct rte_device *dev);
 void rte_eal_device_remove(struct rte_device *dev);
 
 /**
+ * Initialisation function for the driver called during probing.
+ */
+typedef int (driver_probe_t)(struct rte_driver *, struct rte_device *);
+
+/**
+ * Uninitialisation function for the driver called during hotplugging.
+ */
+typedef int (driver_remove_t)(struct rte_device *);
+
+/**
  * A structure describing a device driver.
  */
 struct rte_driver {
@@ -152,6 +162,8 @@ struct rte_driver {
 	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
+	driver_probe_t *probe;         /**< Probe the device */
+	driver_remove_t *remove;       /**< Remove/hotplugging the device */
 };
 
 /**
-- 
2.7.4

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

* [PATCH v3 07/12] eal: enable probe from bus infrastructure
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (5 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 06/12] eal: add probe and remove support for rte_driver Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 08/12] pci: split match and probe function Shreyansh Jain
                       ` (5 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

The model is:
 rte_eal_init
 `--> calls rte_eal_bus_probe()
      This iterates over all the drivers and devices and matches them. For
      matched bus specific device-driver and calls:
      `-> rte_driver->probe()
          for all matched device/drivers (rte_bus->match() successful)
          This would be responsible for devargs related checks, eventually
          calling:
          `-> rte_xxx_driver->probe()
              which does all the work from eth_dev allocation to init.
              (Currently, eth_dev init is done by eth_driver->eth_dev_init,
                which would be removed soon)

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c | 51 +++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 5fbfdcc..0dfa800 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -196,11 +196,60 @@ rte_eal_bus_scan(void)
 	return 0;
 }
 
+static int
+perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+	      struct rte_device *device)
+{
+	int ret;
+
+	if (!driver->probe) {
+		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
+			driver->name);
+		/* This is not an error - just a badly implemented PMD */
+		return 0;
+	}
+
+	ret = driver->probe(driver, device);
+	if (ret < 0)
+		/* One of the probes failed */
+		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
+
+	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
+	 * success, return ret
+	 */
+	return ret;
+}
+
 /* Match driver<->device and call driver->probe() */
 int
 rte_eal_bus_probe(void)
 {
-	/* Until driver->probe is available, this is dummy implementation */
+	int ret;
+	struct rte_bus *bus;
+	struct rte_device *device;
+	struct rte_driver *driver;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		TAILQ_FOREACH(device, &bus->device_list, next) {
+			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+				ret = bus->match(driver, device);
+				if (!ret) {
+					ret = perform_probe(bus, driver,
+							    device);
+					if (ret < 0)
+						return ret;
+
+					device->driver = driver;
+					/* ret == 0 is success; ret >0 implies
+					 * driver doesn't support the device.
+					 * in either case, continue
+					 */
+				}
+			}
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4

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

* [PATCH v3 08/12] pci: split match and probe function
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (6 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 07/12] eal: enable probe from bus infrastructure Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
                       ` (4 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, 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 rte_eal_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_pci.c  | 198 ++++++++++++++++++--------------
 lib/librte_eal/common/include/rte_pci.h |  15 +++
 2 files changed, 125 insertions(+), 88 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 6bff675..706f91c 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,131 +152,153 @@ 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_eal_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;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-				rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret)
-			dev->driver = NULL;
-
-		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;
+	/* 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);
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_eal_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;
+	}
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	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;
+	} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+			rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* unbind current driver */
+		if (pci_unbind_kernel_driver(dev) < 0)
+			return -1;
+	}
 
-		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) {
+		RTE_LOG(DEBUG, EAL, "Driver (%s) probe failed.\n",
+			dr->driver.name);
 		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 ret;
+}
 
-		return 0;
+/*
+ * 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_eal_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 9ce8847..c9b113d 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -369,6 +369,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_eal_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
-- 
2.7.4

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

* [PATCH v3 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (7 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 08/12] pci: split match and probe function Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 10/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
                       ` (3 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

PCI scan and match now work on rte_device/rte_driver rather than PCI
specific objects. These functions can now be plugged to the generic
bus callbacks for scanning and matching devices/drivers.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     |  2 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  4 ++--
 lib/librte_eal/common/eal_common_pci.c  | 28 +++++++++++++++++++++-------
 lib/librte_eal/common/include/rte_pci.h | 17 ++++++++++-------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  4 ++--
 5 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..f9b84db 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -180,7 +180,7 @@ test_pci_setup(void)
 		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
 	}
 
-	ret = rte_eal_pci_scan();
+	ret = rte_eal_pci_scan(NULL);
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
 	rte_eal_pci_dump(stdout);
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 8b3ed88..10b234e 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -361,7 +361,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -676,7 +676,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 706f91c..562c0fd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -153,17 +153,22 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev)
+rte_eal_pci_match(struct rte_driver *drv,
+		  struct rte_device *dev)
 {
 	int match = 1;
 	const struct rte_pci_id *id_table;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 
-	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
-		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+	if (!drv || !dev) {
+		RTE_LOG(DEBUG, EAL, "Invalid Device/Driver\n");
 		return -1;
 	}
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
 	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
@@ -201,11 +206,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
+	driver = &dr->driver;
+	device = &dev->device;
 	loc = &dev->addr;
 
 	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -222,11 +231,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 	}
 
 	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(dr, dev);
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Match of device and driver failed */
 		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			dr->driver.name);
+			driver->name);
 		return 1;
 	}
 
@@ -268,12 +277,17 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver = NULL;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	ret = rte_eal_pci_match(dr, dev);
+	driver = &(dr->driver);
+	device = &(dev->device);
+
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Device and driver don't match */
 		return 1;
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index c9b113d..10108a4 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -363,25 +363,28 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  * Scan the content of the PCI bus, and the devices in the devices
  * list
  *
+ * @param bus
+ *	Reference to the PCI bus
+ *
  * @return
  *  0 on success, negative on error
  */
-int rte_eal_pci_scan(void);
+int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
  * 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
+ * @param drv
+ *	driver from which ID table would be extracted
+ * @param dev
+ *	device to match against the driver
  * @return
  *	0 for successful match
  *	!0 for unsuccessful match
  */
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev);
+rte_eal_pci_match(struct rte_driver *drv,
+		  struct rte_device *dev);
 
 /**
  * Probe the PCI bus for registered drivers.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 876ba38..bafb7fb 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -485,7 +485,7 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  * list
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 {
 	struct dirent *e;
 	DIR *dir;
@@ -763,7 +763,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
-- 
2.7.4

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

* [PATCH v3 10/12] pci: Pass rte_pci_addr to functions instead of separate args
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (8 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 11/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
                       ` (2 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Ben Walker, Shreyansh Jain

From: Ben Walker <benjamin.walker@intel.com>

Instead of passing domain, bus, devid, func, just pass
an rte_pci_addr.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
[Shreyansh: Checkpatch error fix]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index bafb7fb..cbd25df 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -267,8 +267,7 @@ 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, uint16_t domain, uint8_t bus,
-	     uint8_t devid, uint8_t function)
+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -281,10 +280,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 		return -1;
 
 	memset(dev, 0, sizeof(*dev));
-	dev->addr.domain = domain;
-	dev->addr.bus = bus;
-	dev->addr.devid = devid;
-	dev->addr.function = function;
+	dev->addr = *addr;
 
 	/* get vendor id */
 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
@@ -429,16 +425,14 @@ 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->domain, addr->bus, addr->devid,
-				addr->function);
+	return pci_scan_one(filename, addr);
 }
 
 /*
  * split up a pci address into its constituent parts.
  */
 static int
-parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
-		uint8_t *bus, uint8_t *devid, uint8_t *function)
+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
 {
 	/* first split on ':' */
 	union splitaddr {
@@ -466,10 +460,10 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
 
 	/* now convert to int values */
 	errno = 0;
-	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
-	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
-	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
-	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	addr->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	addr->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	addr->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	addr->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
 	if (errno != 0)
 		goto error;
 
@@ -490,8 +484,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
-	uint16_t domain;
-	uint8_t bus, devid, function;
+	struct rte_pci_addr addr;
 
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
@@ -500,20 +493,22 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 		return -1;
 	}
 
+
 	while ((e = readdir(dir)) != NULL) {
 		if (e->d_name[0] == '.')
 			continue;
 
-		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
-				&bus, &devid, &function) != 0)
+		if (parse_pci_addr_format(e->d_name,
+					  sizeof(e->d_name), &addr) != 0)
 			continue;
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
+		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
+
 	return 0;
 
 error:
-- 
2.7.4

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

* [PATCH v3 11/12] eal: enable PCI bus and PCI test framework
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (9 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 10/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-16 13:20       ` Shreyansh Jain
  2016-12-16 13:10     ` [PATCH v3 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Changes to test_pci:
- use a dummy test_pci_bus for all PCI test driver registrations
- this reduces the need for cleaning global list
- add necessary callbacks for invoking scan and probing/matching
  using EAL PCI scan code

Note: With this patch, all PCI PMDs would cease to work because of lack
      rte_driver->probe/remove implementations. Next patch would do that.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                             | 154 +++++++++++------
 lib/librte_eal/bsdapp/eal/eal.c                 |   7 -
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +++---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-
 lib/librte_eal/common/eal_common_pci.c          | 212 ++++++++++++++----------
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_pci.h         |  53 +++---
 lib/librte_eal/linuxapp/eal/eal.c               |   7 -
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 ++++---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-
 10 files changed, 330 insertions(+), 240 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index f9b84db..e95b758 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
@@ -61,10 +62,18 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+static struct rte_bus *pci_bus; /* global reference to a Test PCI bus */
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+/* Test PCI bus. */
+struct rte_bus test_pci_bus = {
+	.name = "test_pci_bus",
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +88,9 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
+		.probe = rte_eal_pci_probe,
+		.remove = rte_eal_pci_remove,
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +99,9 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
+		.probe = rte_eal_pci_probe,
+		.remove = rte_eal_pci_remove,
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,14 +121,67 @@ 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;
+	struct rte_device *r_dev = NULL;
+
+	TAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
+
+		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_device *device;
+	struct rte_driver *driver;
+
+	TAILQ_FOREACH(device, &pci_bus->device_list, next) {
+		TAILQ_FOREACH(driver, &pci_bus->driver_list, next) {
+			ret = pci_bus->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)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *device = NULL;
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(device, &(pci_bus->device_list), next) {
+		dev = container_of(device, struct rte_pci_device, device);
 		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 +208,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 +225,19 @@ 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);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_eal_bus_register(&test_pci_bus);
+	pci_bus = &test_pci_bus;
 
-	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);
-	}
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->scan(pci_bus);
 
-	ret = rte_eal_pci_scan(NULL);
 	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,8 +245,8 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_device *dev = NULL;
+	struct rte_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
 
@@ -203,28 +258,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(dev, &(pci_bus->device_list), next) {
+		rte_eal_bus_remove_device(dev);
+		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(dr, &(pci_bus->driver_list), next) {
+		rte_eal_bus_remove_driver(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);
-	}
+	rte_eal_bus_unregister(pci_bus);
 
 	return 0;
 }
@@ -234,16 +284,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");
+
+	TEST_ASSERT(TAILQ_EMPTY(&pci_bus->driver_list),
+		    "PCI Driver list not empty");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	/* Add test drivers to Bus */
+	rte_eal_bus_add_driver(pci_bus, &(my_driver.driver));
+	rte_eal_bus_add_driver(pci_bus, &(my_driver2.driver));
 
 	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 +310,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 +323,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 */
+	rte_eal_bus_remove_driver(&(my_driver.driver));
+	rte_eal_bus_remove_driver(&(my_driver2.driver));
 
 	return 0;
 }
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 30afc6b..79d82d4 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)
@@ -616,10 +613,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");
-
 	if (rte_eal_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 10b234e..ab9f9d2 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -249,7 +250,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
 	struct rte_pci_device *dev;
 	struct pci_bar_io bar;
@@ -322,19 +323,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -346,7 +351,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
@@ -361,7 +366,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -374,6 +379,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 			.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__);
@@ -389,7 +398,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 		}
 
 		for (i = 0; i < conf_io.num_matches; i++)
-			if (pci_scan_one(fd, &matches[i]) < 0)
+			if (pci_scan_one(bus, fd, &matches[i]) < 0)
 				goto error;
 
 		dev_count += conf_io.num_matches;
@@ -407,9 +416,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-	int fd;
+	int fd = -1;
 	struct pci_conf matches[2];
 	struct pci_match_conf match = {
 		.pc_sel = {
@@ -427,6 +436,9 @@ pci_update_device(const struct rte_pci_addr *addr)
 		.matches = &matches[0],
 	};
 
+	if (!bus)
+		goto error;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -442,7 +454,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 	if (conf_io.num_matches != 1)
 		goto error;
 
-	if (pci_scan_one(fd, &matches[0]) < 0)
+	if (pci_scan_one(bus, fd, &matches[0]) < 0)
 		goto error;
 
 	close(fd);
@@ -668,17 +680,9 @@ 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;
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	if (rte_eal_pci_scan(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 23fc1c1..3dcf439 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -187,5 +184,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 562c0fd..e6d8d87 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>
@@ -82,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)
@@ -206,39 +202,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
-	struct rte_driver *driver;
-	struct rte_device *device;
-	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &dr->driver;
-	device = &dev->device;
-	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;
-	}
-
-	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Match of device and driver failed */
-		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			driver->name);
-		return 1;
-	}
-
 	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
 			dev->id.device_id, dr->driver.name);
 
@@ -276,23 +243,11 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
-	int ret;
-	struct rte_driver *driver = NULL;
-	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &(dr->driver);
-	device = &(dev->device);
-
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -321,9 +276,9 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
-	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
@@ -333,8 +288,8 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_probe_one_driver(dr, dev);
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		rc = rte_eal_pci_probe(r_dr, &dev->device);
 		if (rc < 0)
 			/* negative value is an error */
 			return -1;
@@ -352,15 +307,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -381,22 +338,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
-	if (pci_update_device(addr) < 0)
+	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_probe_all_drivers(dev);
+		ret = pci_probe_all_drivers(bus, dev);
 		if (ret)
 			goto err_return;
 		return 0;
@@ -417,20 +383,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(bus, dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_bus_remove_device(r_dev);
 		free(dev);
 		return 0;
 	}
@@ -443,41 +418,73 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	return -1;
 }
 
-/*
- * 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.
- */
 int
-rte_eal_pci_probe(void)
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device)
 {
-	struct rte_pci_device *dev = NULL;
-	struct rte_devargs *devargs;
-	int probe_all = 0;
 	int ret = 0;
+	struct rte_devargs *devargs;
+	struct rte_pci_device *pci_dev;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_addr *loc;
 
-	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-		probe_all = 1;
+	if (!driver || !device)
+		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	pci_dev = container_of(device, struct rte_pci_device, device);
+	pci_drv = container_of(driver, struct rte_pci_driver, driver);
 
-		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
-		if (devargs != NULL)
-			dev->device.devargs = devargs;
+	loc = &pci_dev->addr;
 
-		/* probe all or only whitelisted devices */
-		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
-		else if (devargs != NULL &&
-			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			pci_dev->device.numa_node);
+
+	/* Fetch the devargs associated with the device */
+	devargs = pci_devargs_lookup(pci_dev);
+	if (devargs != NULL)
+		pci_dev->device.devargs = devargs;
+
+	/* no initialization when blacklisted, return without error */
+	if (pci_dev->device.devargs != NULL &&
+	    pci_dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
 	}
 
+	ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_eal_pci_remove(struct rte_device *device)
+{
+	int ret = 0;
+	struct rte_pci_device *pci_dev;
+
+	if (!device)
+		return -1;
+
+	pci_dev = container_of(device, struct rte_pci_device, device);
+
+	if (!pci_dev->driver)
+		return -1;
+
+	ret = rte_eal_pci_detach_dev(pci_dev->driver, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
 	return 0;
 }
 
@@ -506,8 +513,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -516,14 +532,32 @@ 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);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_add_driver(bus, &driver->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_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = driver->driver.bus;
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..06ec172 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;
 
@@ -126,13 +116,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *	The PCI bus on which device is connected
  * @param addr
  *	The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 10108a4..ec8f672 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.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);
 
@@ -372,6 +366,40 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
+ * Probe callback for the PCI bus
+ *
+ * For each matched pair of PCI device and driver on PCI bus, perform devargs
+ * check, and call a series of callbacks to allocate ethdev/cryptodev instances
+ * and intializing them.
+ *
+ * @param driver
+ *	Generic driver object matched with the device
+ * @param device
+ *	Generic device object to initialize
+ * @return
+ *   - 0 on success.
+ *   - !0 on error.
+ */
+int
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device);
+
+/**
+ * Remove callback for the PCI bus
+ *
+ * Called when a device needs to be removed from a bus; wraps around the
+ * PCI specific implementation layered over rte_pci_driver->remove. Default
+ * handler used by PCI PMDs
+ *
+ * @param device
+ *	rte_device object referring to device to be removed
+ * @return
+ *	- 0 for successful removal
+ *	- !0 for failure in removal of device
+ */
+int
+rte_eal_pci_remove(struct rte_device *device);
+
+/**
  * Match the PCI Driver and Device using the ID Table
  *
  * @param drv
@@ -387,19 +415,6 @@ rte_eal_pci_match(struct rte_driver *drv,
 		  struct rte_device *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.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 01d0cee..ff92de2 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");
@@ -887,10 +884,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");
-
 	if (rte_eal_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 cbd25df..5c66aa7 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>
@@ -267,7 +268,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_bus *bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -385,21 +387,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	} else {
 		struct rte_pci_device *dev2;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -409,15 +413,14 @@ 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_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 
@@ -425,7 +428,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(bus, filename, addr);
 }
 
 /*
@@ -479,13 +482,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	if (!bus_p) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	/* 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",
@@ -504,7 +516,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+		if (pci_scan_one(bus_p, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -750,18 +762,9 @@ 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(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index c873a7f..6e0ec51 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -191,5 +188,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
-- 
2.7.4

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

* [PATCH v3 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (10 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 11/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
@ 2016-12-16 13:10     ` Shreyansh Jain
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:10 UTC (permalink / raw)
  To: dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu, Shreyansh Jain

These callbacks now act as first layer of PCI interfaces from the Bus.
Bus probe would enter the PMDs through the rte_driver->probe/remove
callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
drivers are rte_pci_driver).

This patch also changes QAT which is the only crypto PMD based on PCI.
All others would be changed in a separate patch focused on VDEV.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 drivers/crypto/qat/rte_qat_cryptodev.c  | 4 ++++
 drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
 drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
 drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
 drivers/net/e1000/em_ethdev.c           | 4 ++++
 drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
 drivers/net/ena/ena_ethdev.c            | 4 ++++
 drivers/net/enic/enic_ethdev.c          | 4 ++++
 drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
 drivers/net/i40e/i40e_ethdev.c          | 4 ++++
 drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
 drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
 drivers/net/mlx4/mlx4.c                 | 4 +++-
 drivers/net/mlx5/mlx5.c                 | 1 +
 drivers/net/nfp/nfp_net.c               | 4 ++++
 drivers/net/qede/qede_ethdev.c          | 8 ++++++++
 drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
 drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
 drivers/net/virtio/virtio_ethdev.c      | 2 ++
 drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
 20 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 1e7ee61..bc1a9c6 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -120,6 +120,10 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 
 static struct rte_cryptodev_driver rte_qat_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_qat_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_cryptodev_pci_probe,
diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 0eae433..9f3b3f2 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -618,6 +618,10 @@ eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_bnx2x_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2x_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
@@ -632,6 +636,10 @@ static struct eth_driver rte_bnx2x_pmd = {
  */
 static struct eth_driver rte_bnx2xvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2xvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 035fe07..c8671c8 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1160,6 +1160,10 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev) {
 
 static struct eth_driver bnxt_rte_pmd = {
 	.pci_drv = {
+		    .driver = {
+			    .probe = rte_eal_pci_probe,
+			    .remove = rte_eal_pci_remove,
+		    },
 		    .id_table = bnxt_pci_id_map,
 		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
 			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index b7f28eb..67714fa 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1039,6 +1039,10 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_cxgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = cxgb4_pci_tbl,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index aee3d34..7be5da3 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -391,6 +391,10 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_em_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_em_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 2fddf0c..70dd24c 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1078,6 +1078,10 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_igb_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igb_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1094,6 +1098,10 @@ static struct eth_driver rte_igb_pmd = {
  */
 static struct eth_driver rte_igbvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igbvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index ab9a178..54fc8de 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1705,6 +1705,10 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 static struct eth_driver rte_ena_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ena_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index 2b154ec..c2783db 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -634,6 +634,10 @@ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_enic_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_enic_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 923690c..d1a2efa 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3061,6 +3061,10 @@ static const struct rte_pci_id pci_id_fm10k_map[] = {
 
 static struct eth_driver rte_pmd_fm10k = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_fm10k_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..9c5d50f 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -670,6 +670,10 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = {
 
 static struct eth_driver rte_i40e_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40e_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index aa306d6..10bf6ab 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1527,6 +1527,10 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
  */
 static struct eth_driver rte_i40evf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40evf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index edc9b22..80ee232 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1564,6 +1564,10 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_ixgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbe_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1580,6 +1584,10 @@ static struct eth_driver rte_ixgbe_pmd = {
  */
 static struct eth_driver rte_ixgbevf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbevf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index da61a85..e3dcd41 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5907,7 +5907,9 @@ static const struct rte_pci_id mlx4_pci_id_map[] = {
 static struct eth_driver mlx4_driver = {
 	.pci_drv = {
 		.driver = {
-			.name = MLX4_DRIVER_NAME
+			.name = MLX4_DRIVER_NAME,
+			.probe = rte_eal_pci_probe,
+		},
 		},
 		.id_table = mlx4_pci_id_map,
 		.probe = mlx4_pci_probe,
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 90cc35e..76dda13 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -731,6 +731,7 @@ static struct eth_driver mlx5_driver = {
 	.pci_drv = {
 		.driver = {
 			.name = MLX5_DRIVER_NAME
+			.probe = rte_eal_pci_probe,
 		},
 		.id_table = mlx5_pci_id_map,
 		.probe = mlx5_pci_probe,
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index de80b46..125ba86 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2469,6 +2469,10 @@ static struct rte_pci_id pci_id_nfp_net_map[] = {
 
 static struct eth_driver rte_nfp_net_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nfp_net_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			     RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index d106dd0..31f6733 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1642,6 +1642,10 @@ static struct rte_pci_id pci_id_qede_map[] = {
 
 static struct eth_driver rte_qedevf_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qedevf_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
@@ -1655,6 +1659,10 @@ static struct eth_driver rte_qedevf_pmd = {
 
 static struct eth_driver rte_qede_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qede_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index f3cd52d..a649e60 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1572,6 +1572,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
 
 static struct eth_driver szedata2_eth_driver = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = rte_szedata2_pci_id_table,
 		.probe = rte_eth_dev_pci_probe,
 		.remove = rte_eth_dev_pci_remove,
diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
index 466e49c..72ac748 100644
--- a/drivers/net/thunderx/nicvf_ethdev.c
+++ b/drivers/net/thunderx/nicvf_ethdev.c
@@ -2110,6 +2110,10 @@ static const struct rte_pci_id pci_id_nicvf_map[] = {
 
 static struct eth_driver rte_nicvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nicvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 079fd6c..4d5d1bb 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1377,6 +1377,8 @@ static struct eth_driver rte_virtio_pmd = {
 	.pci_drv = {
 		.driver = {
 			.name = "net_virtio",
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
 		},
 		.id_table = pci_id_virtio_map,
 		.drv_flags = RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 8bb13e5..57f66cb 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -335,6 +335,10 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_vmxnet3_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_vmxnet3_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
-- 
2.7.4

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

* Re: [PATCH v3 11/12] eal: enable PCI bus and PCI test framework
  2016-12-16 13:10     ` [PATCH v3 11/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
@ 2016-12-16 13:20       ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:20 UTC (permalink / raw)
  To: dev; +Cc: david.marchand, thomas.monjalon, ferruh.yigit, jianbo.liu

On Friday 16 December 2016 06:40 PM, Shreyansh Jain wrote:
> Register a PCI bus with Scan/match and probe callbacks. Necessary changes
> in EAL layer for enabling bus interfaces. PCI devices and drivers now
> reside within the Bus object.
>
> Now that PCI bus handles the scan/probe methods, independent calls to
> PCI scan and probe can be removed from the code.
> PCI device and driver list are also removed.
>
> rte_device and rte_driver list continue to exist. As does the VDEV lists.
>
> Changes to test_pci:
> - use a dummy test_pci_bus for all PCI test driver registrations
> - this reduces the need for cleaning global list
> - add necessary callbacks for invoking scan and probing/matching
>   using EAL PCI scan code
>
> Note: With this patch, all PCI PMDs would cease to work because of lack
>       rte_driver->probe/remove implementations. Next patch would do that.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  app/test/test_pci.c                             | 154 +++++++++++------
>  lib/librte_eal/bsdapp/eal/eal.c                 |   7 -
>  lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +++---
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-
>  lib/librte_eal/common/eal_common_pci.c          | 212 ++++++++++++++----------
>  lib/librte_eal/common/eal_private.h             |  14 +-
>  lib/librte_eal/common/include/rte_pci.h         |  53 +++---
>  lib/librte_eal/linuxapp/eal/eal.c               |   7 -
>  lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 ++++---
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-
>  10 files changed, 330 insertions(+), 240 deletions(-)
>
<snip>

This is a relatively large patch. I would love to split it but
currently I am unable to find a nice/clean way. Any suggestions would
be really appreciated:

This currently does 3 broad things:
  - Move the PCI device/driver registration to PCI Bus
   -- So, introduce PCI bus
   -- change EAL to point to this new bus
  - remove/refactor existing EAL/*/*pci* code to accommodate this shift
  - Test PCI framework.

I could have split test_pci changes into a new patch, but that breaks
compilation after this patchset if test_pci compilation is enabled
(disabled by default). Is that acceptable? (if not, I am stuck with
keeping this set of changes into a single patch).

And, I would appreciate some help in confirming if the changes to
test_pci are OK or not from PCI testing perspective.

-
Shreyansh

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

* Re: [PATCH v3 04/12] eal/bus: add scan, match and insert support
  2016-12-16 13:10     ` [PATCH v3 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
@ 2016-12-16 13:25       ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-16 13:25 UTC (permalink / raw)
  To: dev; +Cc: david.marchand, thomas.monjalon, ferruh.yigit, jianbo.liu

On Friday 16 December 2016 06:40 PM, Shreyansh Jain wrote:
> When a PMD is registred, it will associate itself with a bus.
>
> A bus is responsible for 'scan' of all the devices attached to it.
> All the scanned devices are attached to bus specific device_list.
> During the probe operation, 'match' of the drivers and devices would
> be done.
>
> Also, rather than adding a device to tail, a new device might be added to
> the list (pivoted on bus) at a predefined position, for example, adding it
> in order of addressing. Support for this is added as '*bus_insert'.
>
> This patch also adds necessary test framework to test the scan and
> match callbacks.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  app/test/test_bus.c                     | 265 ++++++++++++++++++++++++++++++++
>  lib/librte_eal/common/eal_common_bus.c  |  15 ++
>  lib/librte_eal/common/include/rte_bus.h |  64 ++++++++
>  3 files changed, 344 insertions(+)
>
> diff --git a/app/test/test_bus.c b/app/test/test_bus.c
> index 760d40a..ed95479 100644
> --- a/app/test/test_bus.c
> +++ b/app/test/test_bus.c
> @@ -80,12 +80,32 @@ struct dummy_bus {
>  struct rte_bus_list orig_bus_list =
>  	TAILQ_HEAD_INITIALIZER(orig_bus_list);
>
> +/* Forward declarations for callbacks from bus */
> +
> +/* Bus A
> + * Scan would register devA1 and devA2 to bus
> + */
> +int scan_fn_for_busA(struct rte_bus *bus);
> +
> +/* Bus B
> + * Scan would register devB1 and devB2 to bus
> + */
> +int scan_fn_for_busB(struct rte_bus *bus);
> +
> +/* generic implementations wrapped around by above declarations */
> +static int generic_scan_fn(struct rte_bus *bus);
> +static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
> +
>  struct rte_bus busA = {
>  	.name = "busA", /* "busA" */
> +	.scan = scan_fn_for_busA,
> +	.match = generic_match_fn,
>  };
>
>  struct rte_bus busB = {
>  	.name = "busB", /* "busB */
> +	.scan = scan_fn_for_busB,
> +	.match = generic_match_fn,
>  };
>
>  struct rte_driver driverA = {
> @@ -184,6 +204,92 @@ dump_device_tree(void)
>  	printf("------>8-------\n");
>  }
>
> +/* @internal
> + * Move over the dummy_buses and find the entry matching the bus object
> + * passed as argument.
> + * For each device in that dummy_buses list, register.
> + *
> + * @param bus
> + *	bus to scan againt test entry
> + * @return
> + *	0 for successful scan, even if no devices are found
> + *	!0 for any error in scanning (like, invalid bus)
> + */
> +static int
> +generic_scan_fn(struct rte_bus *bus)
> +{
> +	int i = 0;
> +	struct rte_device *dev = NULL;
> +	struct dummy_bus *db = NULL;
> +
> +	if (!bus)
> +		return -1;
> +
> +	/* Extract the device tree node using the bus passed */
> +	for (i = 0; dummy_buses[i].name; i++) {
> +		if (!strcmp(dummy_buses[i].name, bus->name)) {
> +			db = &dummy_buses[i];
> +			break;
> +		}
> +	}
> +
> +	if (!db)
> +		return -1;
> +
> +	/* For all the devices in the device tree (dummy_buses), add device */
> +	for (i = 0; db->devices[i]; i++) {
> +		dev = &(db->devices[i]->dev);
> +		rte_eal_bus_add_device(bus, dev);
> +	}
> +
> +	return 0;
> +}
> +
> +/* @internal
> + * Obtain bus from driver object. Match the address of rte_device object
> + * with all the devices associated with that bus.
> + *
> + * Being a test function, all this does is validate that device object
> + * provided is available on the same bus to which driver is registered.
> + *
> + * @param drv
> + *	driver to which matching is to be performed
> + * @param dev
> + *	device object to match with driver
> + * @return
> + *	0 for successful match
> + *	!0 for failed match
> + */
> +static int
> +generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
> +{
> +	struct rte_bus *bus;
> +	struct rte_device *dev_p = NULL;
> +
> +	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
> +	 * from bus->device_list.
> +	 */
> +
> +	/* a driver is registered with the bus *before* the scan. */
> +	bus = drv->bus;
> +	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
> +		if (dev == dev_p)
> +			return 0;
> +	}
> +
> +	return 1;
> +}
> +
> +int
> +scan_fn_for_busA(struct rte_bus *bus) {
> +	return generic_scan_fn(bus);
> +}
> +
> +int
> +scan_fn_for_busB(struct rte_bus *bus) {
> +	return generic_scan_fn(bus);
> +}
> +
>  static int
>  test_bus_setup(void)
>  {
> @@ -391,6 +497,155 @@ test_driver_unregistration_on_bus(void)
>
>  }
>
> +static int
> +test_device_unregistration_on_bus(void)
> +{
> +	int i;
> +	struct rte_bus *bus = NULL;
> +	struct rte_device *dev;
> +
> +	for (i = 0; dummy_buses[i].name; i++) {
> +		bus = rte_eal_get_bus(dummy_buses[i].name);
> +		if (!bus) {
> +			printf("Unable to find bus (%s)\n",
> +			       dummy_buses[i].name);
> +			return -1;
> +		}
> +
> +		/* For bus 'bus', unregister all devices */
> +		TAILQ_FOREACH(dev, &bus->device_list, next) {
> +			rte_eal_bus_remove_device(dev);
> +		}
> +	}
> +
> +	for (i = 0; dummy_buses[i].name; i++) {
> +		bus = rte_eal_get_bus(dummy_buses[i].name);
> +
> +		if (!TAILQ_EMPTY(&bus->device_list)) {
> +			printf("Unable to remove all devices on bus (%s)\n",
> +			       bus->name);
> +			return -1;
> +		}
> +	}
> +
> +	/* All devices from all buses have been removed */
> +	printf("All devices on all buses unregistered.\n");
> +	dump_device_tree();
> +
> +	return 0;
> +}
> +
> +/* @internal
> + * For each bus registered, call the scan function to identify devices
> + * on the bus.
> + *
> + * @param void
> + * @return
> + *	0 for successful scan
> + *	!0 for unsuccessful scan
> + *
> + */
> +static int
> +test_bus_scan(void)
> +{
> +	int ret;
> +	struct rte_bus *bus;
> +
> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +		/* Call the scan function for each bus */
> +		ret = bus->scan(bus);
> +		if (ret) {
> +			printf("Scan of buses failed.\n");
> +			return -1;
> +		}
> +	}
> +
> +	printf("Scan of all buses completed.\n");
> +	dump_device_tree();
> +
> +	return 0;
> +}
> +
> +/* @internal
> + * Function to perform 'probe' and link devices and drivers on a bus.
> + * This would work over all the buses registered, and all devices and drivers
> + * registered with it - call match on each pair.
> + * Aim is to test the match_fn for each bus.
> + *
> + * @param void
> + * @return
> + *	0 for successful probe
> + *	!0 for failure in probe
> + *
> + */
> +static int
> +test_probe_on_bus(void)
> +{
> +	int ret = 0;
> +	int i, j;
> +	struct rte_bus *bus = NULL;
> +	struct rte_device *dev = NULL;
> +	struct rte_driver *drv = NULL;
> +
> +	/* In case of this test:
> +	* 1. for each bus in rte_bus_list
> +	* 2.  for each device in bus->device_list
> +	* 3.   for each driver in bus->driver_list
> +	* 4.    call match
> +	* 5.    link driver and device
> +	* 6. Verify the linkage.
> +	*/

This comment style is indeed in a warning from checkpatch. My bad -
somehow I missed fixing this before sending out. v4, along with any
other major comments/reviews.

<snip>

-
Shreyansh

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-16 13:10     ` [PATCH v3 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2016-12-20 12:37       ` Hemant Agrawal
  2016-12-20 13:17       ` Jan Blunck
  1 sibling, 0 replies; 132+ messages in thread
From: Hemant Agrawal @ 2016-12-20 12:37 UTC (permalink / raw)
  To: Shreyansh Jain, dev, david.marchand
  Cc: thomas.monjalon, ferruh.yigit, jianbo.liu

On 12/16/2016 6:40 PM, Shreyansh Jain wrote:
> This patch introduces the rte_bus abstraction for devices and drivers in
> EAL framework. 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' class which rte_driver and rte_device refer.
> This way, each device (rte_xxx_device) would have reference to the bus
> it is based on. As well as, each driver (rte_xxx_driver) would have link
> to the bus and devices on it for servicing.
>
>                                   __ rte_bus_list
>                                  /
>                      +----------'---+
>                      |rte_bus       |
>                      | driver_list------> List of rte_bus specific
>                      | device_list----    devices
>                      |              | `-> List of rte_bus associated
>                      |              |     drivers
>                      +--|------|----+
>               _________/        \_________
>     +--------/----+                     +-\---------------+
>     |rte_device   |                     |rte_driver       |
>     | rte_bus     |                     | rte_bus         |
>     | rte_driver  |                     | ...             |
>     | ...         |                     +---------...-----+
>     |             |                               |||
>     +---||--------+                               |||
>         ||                                        |||
>         | \                                        \\\
>         |  \_____________                           \\\
>         |                \                          |||
>  +------|---------+ +----|----------+               |||
>  |rte_pci_device  | |rte_xxx_device |               |||
>  | ....           | | ....          |               |||
>  +----------------+ +---------------+              / | \
>                                                   /  |  \
>                             _____________________/  /    \
>                            /                    ___/      \
>             +-------------'--+    +------------'---+    +--'------------+
>             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
>             | ....           |    | ....           |    | ....          |
>             +----------------+    +----------------+    +---------------+
>
> This patch only enables the bus references on rte_driver and rte_driver.
> EAL wide global device and driver list continue to exist until an instance
> of bus is added in subsequent patches.
>
> This patch also introduces RTE_REGISTER_BUS macro on the lines of
> RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
> been explicitly set to 101 so as to execute bus registration before PMD.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> --
> v2:
>  - fix bsdapp compilation issue because of missing export symbols in map
>    file
> ---
>  lib/librte_eal/bsdapp/eal/Makefile              |   1 +
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
>  lib/librte_eal/common/Makefile                  |   2 +-
>  lib/librte_eal/common/eal_common_bus.c          | 192 ++++++++++++++++++++++++
>  lib/librte_eal/common/include/rte_bus.h         | 174 +++++++++++++++++++++
>  lib/librte_eal/common/include/rte_dev.h         |   2 +
>  lib/librte_eal/linuxapp/eal/Makefile            |   1 +
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
>  8 files changed, 401 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..23fc1c1 100644
> --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> @@ -174,3 +174,18 @@ DPDK_16.11 {
>  	rte_eal_vdrv_unregister;
>
>  } DPDK_16.07;
> +
> +DPDK_17.02 {
> +	global:
> +
> +	rte_bus_list;
> +	rte_eal_bus_add_device;
> +	rte_eal_bus_add_driver;
> +	rte_eal_get_bus;
> +	rte_eal_bus_dump;
> +	rte_eal_bus_register;
> +	rte_eal_bus_remove_device;
> +	rte_eal_bus_remove_driver;
> +	rte_eal_bus_unregister;
> +
> +} DPDK_16.11;
> diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
> index a92c984..0c39414 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..612f64e
> --- /dev/null
> +++ b/lib/librte_eal/common/eal_common_bus.c
> @@ -0,0 +1,192 @@
> +/*-
> + *   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);
> +
> +/** @internal
> + * Add a device to a bus.
> + */
> +void
> +rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
> +{
> +	RTE_VERIFY(bus);
> +	RTE_VERIFY(dev);
> +
> +	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
> +	dev->bus = bus;
> +}
> +
> +/** @internal
> + * Remove a device from its bus.
> + */
> +void
> +rte_eal_bus_remove_device(struct rte_device *dev)
> +{
> +	struct rte_bus *bus;
> +
> +	RTE_VERIFY(dev);
> +	RTE_VERIFY(dev->bus);
> +
> +	bus = dev->bus;
> +	TAILQ_REMOVE(&bus->device_list, dev, next);
> +	dev->bus = NULL;
> +}
> +
> +/** @internal
> + * Associate a driver with a bus.
> + */
> +void
> +rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
> +{
> +	RTE_VERIFY(bus);
> +	RTE_VERIFY(drv);
> +
> +	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
> +	drv->bus = bus;
> +}
> +
> +/** @internal
> + * Disassociate a driver from bus.
> + */
> +void
> +rte_eal_bus_remove_driver(struct rte_driver *drv)
> +{
> +	struct rte_bus *bus;
> +
> +	RTE_VERIFY(drv);
> +	RTE_VERIFY(drv->bus);
> +
> +	bus = drv->bus;
> +	TAILQ_REMOVE(&bus->driver_list, drv, next);
> +	drv->bus = NULL;
> +}
> +
> +/**
> + * Get the bus handle using its name
> + */
> +struct rte_bus *
> +rte_eal_get_bus(const char *bus_name)
> +{
> +	struct rte_bus *bus;
> +
> +	RTE_VERIFY(bus_name);
> +
> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +		RTE_VERIFY(bus->name);
> +
> +		if (!strcmp(bus_name, bus->name)) {
> +			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
> +			return bus;
> +		}
> +	}
> +
> +	/* Unable to find bus requested */
> +	return NULL;
> +}
> +
> +/* register a bus */
> +void
> +rte_eal_bus_register(struct rte_bus *bus)
> +{
> +	RTE_VERIFY(bus);
> +	RTE_VERIFY(bus->name && strlen(bus->name));
> +
> +	/* Initialize the driver and device list associated with the bus */
> +	TAILQ_INIT(&(bus->driver_list));
> +	TAILQ_INIT(&(bus->device_list));
> +
> +	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> +	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
> +}
> +
> +/* unregister a bus */
> +void
> +rte_eal_bus_unregister(struct rte_bus *bus)
> +{
> +	/* All devices and drivers associated with the bus should have been
> +	 * 'device->uninit' and 'driver->remove()' already.
> +	 */
> +	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
> +	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
> +
> +	/* TODO: For each device, call its rte_device->driver->remove()
> +	 * and rte_eal_bus_remove_driver()
> +	 */
> +
> +	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_eal_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..f0297a9
> --- /dev/null
> +++ b/lib/librte_eal/common/include/rte_bus.h
> @@ -0,0 +1,174 @@
> +/*-
> + *   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);
> +
> +/* Global Bus list */
> +extern struct rte_bus_list rte_bus_list;
> +
> +struct rte_bus {
> +	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
> +	struct rte_driver_list driver_list;
> +				     /**< List of all drivers on bus */
> +	struct rte_device_list device_list;
> +				     /**< List of all devices on bus */
> +	const char *name;            /**< Name of the bus */
> +};
> +
> +/** @internal
> + * Add a device to a bus.
> + *
> + * @param bus
> + *	Bus on which device is to be added
> + * @param dev
> + *	Device handle
> + * @return
> + *	None
> + */
> +void
> +rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
> +
> +/** @internal
> + * Remove a device from its bus.
> + *
> + * @param dev
> + *	Device handle to remove
> + * @return
> + *	None
> + */
> +void
> +rte_eal_bus_remove_device(struct rte_device *dev);
> +
> +/** @internal
> + * Associate a driver with a bus.
> + *
> + * @param bus
> + *	Bus on which driver is to be added
> + * @param dev
> + *	Driver handle
> + * @return
> + *	None
> + */
> +void
> +rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
> +
> +/** @internal
> + * Disassociate a driver from its bus.
> + *
> + * @param dev
> + *	Driver handle to remove
> + * @return
> + *	None
> + */
> +void
> +rte_eal_bus_remove_driver(struct rte_driver *drv);
> +
> +/**
> + * Register a Bus handler.
> + *
> + * @param driver
> + *   A pointer to a rte_bus structure describing the bus
> + *   to be registered.
> + */
> +void rte_eal_bus_register(struct rte_bus *bus);
> +
> +/**
> + * Unregister a Bus handler.
> + *
> + * @param driver
> + *   A pointer to a rte_bus structure describing the bus
> + *   to be unregistered.
> + */
> +void rte_eal_bus_unregister(struct rte_bus *bus);
> +
> +/**
> + * Obtain handle for bus given its name.
> + *
> + * @param bus_name
> + *	Name of the bus handle to search
> + * @return
> + *	Pointer to Bus object if name matches any registered bus object
> + *	NULL, if no matching bus found
> + */
> +struct rte_bus *rte_eal_get_bus(const char *bus_name);
> +
> +/**
> + * 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_eal_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_eal_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 8840380..4004f9a 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 */
>  	struct rte_driver *driver;    /**< Associated driver */
>  	int numa_node;                /**< NUMA node connection */
>  	struct rte_devargs *devargs;  /**< Device user arguments */
> @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
>   */
>  struct rte_driver {
>  	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
> +	struct rte_bus *bus;           /**< Bus serviced by this driver */
>  	const char *name;                   /**< Driver name. */
>  	const char *alias;              /**< Driver alias. */
>  };
> 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..c873a7f 100644
> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> @@ -178,3 +178,18 @@ DPDK_16.11 {
>  	rte_eal_vdrv_unregister;
>
>  } DPDK_16.07;
> +
> +DPDK_17.02 {
> +	global:
> +
> +	rte_bus_list;
> +	rte_eal_bus_add_device;
> +	rte_eal_bus_add_driver;
> +	rte_eal_get_bus;

This should be rte_eal_bus_get

Also you are missing rte_eal_bus_insert_device

> +	rte_eal_bus_dump;
> +	rte_eal_bus_register;
> +	rte_eal_bus_remove_device;
> +	rte_eal_bus_remove_driver;
> +	rte_eal_bus_unregister;
> +
> +} DPDK_16.11;
>

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-16 13:10     ` [PATCH v3 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
  2016-12-20 12:37       ` Hemant Agrawal
@ 2016-12-20 13:17       ` Jan Blunck
  2016-12-20 13:51         ` Shreyansh Jain
                           ` (2 more replies)
  1 sibling, 3 replies; 132+ messages in thread
From: Jan Blunck @ 2016-12-20 13:17 UTC (permalink / raw)
  To: Shreyansh Jain
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu

On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> This patch introduces the rte_bus abstraction for devices and drivers in
> EAL framework. 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' class which rte_driver and rte_device refer.
> This way, each device (rte_xxx_device) would have reference to the bus
> it is based on. As well as, each driver (rte_xxx_driver) would have link
> to the bus and devices on it for servicing.
>
>                                   __ rte_bus_list
>                                  /
>                      +----------'---+
>                      |rte_bus       |
>                      | driver_list------> List of rte_bus specific
>                      | device_list----    devices
>                      |              | `-> List of rte_bus associated
>                      |              |     drivers
>                      +--|------|----+
>               _________/        \_________
>     +--------/----+                     +-\---------------+
>     |rte_device   |                     |rte_driver       |
>     | rte_bus     |                     | rte_bus         |
>     | rte_driver  |                     | ...             |
>     | ...         |                     +---------...-----+
>     |             |                               |||
>     +---||--------+                               |||
>         ||                                        |||
>         | \                                        \\\
>         |  \_____________                           \\\
>         |                \                          |||
>  +------|---------+ +----|----------+               |||
>  |rte_pci_device  | |rte_xxx_device |               |||
>  | ....           | | ....          |               |||
>  +----------------+ +---------------+              / | \
>                                                   /  |  \
>                             _____________________/  /    \
>                            /                    ___/      \
>             +-------------'--+    +------------'---+    +--'------------+
>             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
>             | ....           |    | ....           |    | ....          |
>             +----------------+    +----------------+    +---------------+
>
> This patch only enables the bus references on rte_driver and rte_driver.
> EAL wide global device and driver list continue to exist until an instance
> of bus is added in subsequent patches.
>
> This patch also introduces RTE_REGISTER_BUS macro on the lines of
> RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
> been explicitly set to 101 so as to execute bus registration before PMD.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>
> --
> v2:
>  - fix bsdapp compilation issue because of missing export symbols in map
>    file
> ---
>  lib/librte_eal/bsdapp/eal/Makefile              |   1 +
>  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
>  lib/librte_eal/common/Makefile                  |   2 +-
>  lib/librte_eal/common/eal_common_bus.c          | 192 ++++++++++++++++++++++++
>  lib/librte_eal/common/include/rte_bus.h         | 174 +++++++++++++++++++++
>  lib/librte_eal/common/include/rte_dev.h         |   2 +
>  lib/librte_eal/linuxapp/eal/Makefile            |   1 +
>  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
>  8 files changed, 401 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..23fc1c1 100644
> --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> @@ -174,3 +174,18 @@ DPDK_16.11 {
>         rte_eal_vdrv_unregister;
>
>  } DPDK_16.07;
> +
> +DPDK_17.02 {
> +       global:
> +
> +       rte_bus_list;
> +       rte_eal_bus_add_device;
> +       rte_eal_bus_add_driver;
> +       rte_eal_get_bus;
> +       rte_eal_bus_dump;
> +       rte_eal_bus_register;
> +       rte_eal_bus_remove_device;
> +       rte_eal_bus_remove_driver;
> +       rte_eal_bus_unregister;
> +
> +} DPDK_16.11;
> diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
> index a92c984..0c39414 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..612f64e
> --- /dev/null
> +++ b/lib/librte_eal/common/eal_common_bus.c
> @@ -0,0 +1,192 @@
> +/*-
> + *   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);
> +
> +/** @internal
> + * Add a device to a bus.
> + */
> +void
> +rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
> +{
> +       RTE_VERIFY(bus);
> +       RTE_VERIFY(dev);
> +
> +       TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
> +       dev->bus = bus;
> +}
> +
> +/** @internal
> + * Remove a device from its bus.
> + */
> +void
> +rte_eal_bus_remove_device(struct rte_device *dev)
> +{
> +       struct rte_bus *bus;
> +
> +       RTE_VERIFY(dev);
> +       RTE_VERIFY(dev->bus);
> +
> +       bus = dev->bus;
> +       TAILQ_REMOVE(&bus->device_list, dev, next);
> +       dev->bus = NULL;
> +}
> +
> +/** @internal
> + * Associate a driver with a bus.
> + */
> +void
> +rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
> +{
> +       RTE_VERIFY(bus);
> +       RTE_VERIFY(drv);
> +
> +       TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
> +       drv->bus = bus;
> +}
> +
> +/** @internal
> + * Disassociate a driver from bus.
> + */
> +void
> +rte_eal_bus_remove_driver(struct rte_driver *drv)
> +{
> +       struct rte_bus *bus;
> +
> +       RTE_VERIFY(drv);
> +       RTE_VERIFY(drv->bus);
> +
> +       bus = drv->bus;
> +       TAILQ_REMOVE(&bus->driver_list, drv, next);
> +       drv->bus = NULL;
> +}
> +
> +/**
> + * Get the bus handle using its name
> + */
> +struct rte_bus *
> +rte_eal_get_bus(const char *bus_name)
> +{
> +       struct rte_bus *bus;
> +
> +       RTE_VERIFY(bus_name);
> +
> +       TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +               RTE_VERIFY(bus->name);
> +
> +               if (!strcmp(bus_name, bus->name)) {
> +                       RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
> +                       return bus;
> +               }
> +       }
> +
> +       /* Unable to find bus requested */
> +       return NULL;
> +}
> +
> +/* register a bus */
> +void
> +rte_eal_bus_register(struct rte_bus *bus)
> +{
> +       RTE_VERIFY(bus);
> +       RTE_VERIFY(bus->name && strlen(bus->name));
> +
> +       /* Initialize the driver and device list associated with the bus */
> +       TAILQ_INIT(&(bus->driver_list));
> +       TAILQ_INIT(&(bus->device_list));
> +
> +       TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> +       RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
> +}
> +
> +/* unregister a bus */
> +void
> +rte_eal_bus_unregister(struct rte_bus *bus)
> +{
> +       /* All devices and drivers associated with the bus should have been
> +        * 'device->uninit' and 'driver->remove()' already.
> +        */
> +       RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
> +       RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
> +
> +       /* TODO: For each device, call its rte_device->driver->remove()
> +        * and rte_eal_bus_remove_driver()
> +        */
> +
> +       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_eal_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..f0297a9
> --- /dev/null
> +++ b/lib/librte_eal/common/include/rte_bus.h
> @@ -0,0 +1,174 @@
> +/*-
> + *   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);
> +
> +/* Global Bus list */
> +extern struct rte_bus_list rte_bus_list;
> +
> +struct rte_bus {
> +       TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
> +       struct rte_driver_list driver_list;
> +                                    /**< List of all drivers on bus */
> +       struct rte_device_list device_list;
> +                                    /**< List of all devices on bus */
> +       const char *name;            /**< Name of the bus */
> +};
> +
> +/** @internal
> + * Add a device to a bus.
> + *
> + * @param bus
> + *     Bus on which device is to be added
> + * @param dev
> + *     Device handle
> + * @return
> + *     None
> + */
> +void
> +rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
> +
> +/** @internal
> + * Remove a device from its bus.
> + *
> + * @param dev
> + *     Device handle to remove
> + * @return
> + *     None
> + */
> +void
> +rte_eal_bus_remove_device(struct rte_device *dev);
> +
> +/** @internal
> + * Associate a driver with a bus.
> + *
> + * @param bus
> + *     Bus on which driver is to be added
> + * @param dev
> + *     Driver handle
> + * @return
> + *     None
> + */
> +void
> +rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
> +
> +/** @internal
> + * Disassociate a driver from its bus.
> + *
> + * @param dev
> + *     Driver handle to remove
> + * @return
> + *     None
> + */
> +void
> +rte_eal_bus_remove_driver(struct rte_driver *drv);
> +
> +/**
> + * Register a Bus handler.
> + *
> + * @param driver
> + *   A pointer to a rte_bus structure describing the bus
> + *   to be registered.
> + */
> +void rte_eal_bus_register(struct rte_bus *bus);
> +
> +/**
> + * Unregister a Bus handler.
> + *
> + * @param driver
> + *   A pointer to a rte_bus structure describing the bus
> + *   to be unregistered.
> + */
> +void rte_eal_bus_unregister(struct rte_bus *bus);
> +
> +/**
> + * Obtain handle for bus given its name.
> + *
> + * @param bus_name
> + *     Name of the bus handle to search
> + * @return
> + *     Pointer to Bus object if name matches any registered bus object
> + *     NULL, if no matching bus found
> + */
> +struct rte_bus *rte_eal_get_bus(const char *bus_name);
> +
> +/**
> + * 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_eal_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_eal_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 8840380..4004f9a 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 */

Is there a reason why this isn't const?


>         struct rte_driver *driver;    /**< Associated driver */
>         int numa_node;                /**< NUMA node connection */
>         struct rte_devargs *devargs;  /**< Device user arguments */
> @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
>   */
>  struct rte_driver {
>         TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
> +       struct rte_bus *bus;           /**< Bus serviced by this driver */

Same thing here.

>         const char *name;                   /**< Driver name. */
>         const char *alias;              /**< Driver alias. */
>  };
> 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..c873a7f 100644
> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> @@ -178,3 +178,18 @@ DPDK_16.11 {
>         rte_eal_vdrv_unregister;
>
>  } DPDK_16.07;
> +
> +DPDK_17.02 {
> +       global:
> +
> +       rte_bus_list;
> +       rte_eal_bus_add_device;
> +       rte_eal_bus_add_driver;
> +       rte_eal_get_bus;
> +       rte_eal_bus_dump;
> +       rte_eal_bus_register;
> +       rte_eal_bus_remove_device;
> +       rte_eal_bus_remove_driver;
> +       rte_eal_bus_unregister;
> +
> +} DPDK_16.11;
> --
> 2.7.4
>

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-20 13:17       ` Jan Blunck
@ 2016-12-20 13:51         ` Shreyansh Jain
  2016-12-20 17:11         ` Stephen Hemminger
  2016-12-25 17:39         ` Shreyansh Jain
  2 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-20 13:51 UTC (permalink / raw)
  To: Jan Blunck; +Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu

> -----Original Message-----
> From: jblunck@gmail.com [mailto:jblunck@gmail.com] On Behalf Of Jan Blunck
> Sent: Tuesday, December 20, 2016 6:47 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org; David Marchand <david.marchand@6wind.com>; Thomas Monjalon
> <thomas.monjalon@6wind.com>; Ferruh Yigit <ferruh.yigit@intel.com>;
> jianbo.liu@linaro.org
> Subject: Re: [dpdk-dev] [PATCH v3 02/12] eal/bus: introduce bus abstraction
> 
> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com>
> wrote:
> > This patch introduces the rte_bus abstraction for devices and drivers in
> > EAL framework. 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' class which rte_driver and rte_device refer.
> > This way, each device (rte_xxx_device) would have reference to the bus
> > it is based on. As well as, each driver (rte_xxx_driver) would have link
> > to the bus and devices on it for servicing.
> >
> >                                   __ rte_bus_list
> >                                  /
> >                      +----------'---+
> >                      |rte_bus       |
> >                      | driver_list------> List of rte_bus specific
> >                      | device_list----    devices
> >                      |              | `-> List of rte_bus associated
> >                      |              |     drivers
> >                      +--|------|----+
> >               _________/        \_________
> >     +--------/----+                     +-\---------------+
> >     |rte_device   |                     |rte_driver       |
> >     | rte_bus     |                     | rte_bus         |
> >     | rte_driver  |                     | ...             |
> >     | ...         |                     +---------...-----+
> >     |             |                               |||
> >     +---||--------+                               |||
> >         ||                                        |||
> >         | \                                        \\\
> >         |  \_____________                           \\\
> >         |                \                          |||
> >  +------|---------+ +----|----------+               |||
> >  |rte_pci_device  | |rte_xxx_device |               |||
> >  | ....           | | ....          |               |||
> >  +----------------+ +---------------+              / | \
> >                                                   /  |  \
> >                             _____________________/  /    \
> >                            /                    ___/      \
> >             +-------------'--+    +------------'---+    +--'------------+
> >             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
> >             | ....           |    | ....           |    | ....          |
> >             +----------------+    +----------------+    +---------------+
> >
> > This patch only enables the bus references on rte_driver and rte_driver.
> > EAL wide global device and driver list continue to exist until an instance
> > of bus is added in subsequent patches.
> >
> > This patch also introduces RTE_REGISTER_BUS macro on the lines of
> > RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
> > been explicitly set to 101 so as to execute bus registration before PMD.
> >
> > Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> >
> > --
> > v2:
> >  - fix bsdapp compilation issue because of missing export symbols in map
> >    file
> > ---
> >  lib/librte_eal/bsdapp/eal/Makefile              |   1 +
> >  lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
> >  lib/librte_eal/common/Makefile                  |   2 +-
> >  lib/librte_eal/common/eal_common_bus.c          | 192
> ++++++++++++++++++++++++
> >  lib/librte_eal/common/include/rte_bus.h         | 174
> +++++++++++++++++++++
> >  lib/librte_eal/common/include/rte_dev.h         |   2 +
> >  lib/librte_eal/linuxapp/eal/Makefile            |   1 +
> >  lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
> >  8 files changed, 401 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..23fc1c1 100644
> > --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> > +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> > @@ -174,3 +174,18 @@ DPDK_16.11 {
> >         rte_eal_vdrv_unregister;
> >
> >  } DPDK_16.07;
> > +
> > +DPDK_17.02 {
> > +       global:
> > +
> > +       rte_bus_list;
> > +       rte_eal_bus_add_device;
> > +       rte_eal_bus_add_driver;
> > +       rte_eal_get_bus;
> > +       rte_eal_bus_dump;
> > +       rte_eal_bus_register;
> > +       rte_eal_bus_remove_device;
> > +       rte_eal_bus_remove_driver;
> > +       rte_eal_bus_unregister;
> > +
> > +} DPDK_16.11;
> > diff --git a/lib/librte_eal/common/Makefile
> b/lib/librte_eal/common/Makefile
> > index a92c984..0c39414 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..612f64e
> > --- /dev/null
> > +++ b/lib/librte_eal/common/eal_common_bus.c
> > @@ -0,0 +1,192 @@
> > +/*-
> > + *   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);
> > +
> > +/** @internal
> > + * Add a device to a bus.
> > + */
> > +void
> > +rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
> > +{
> > +       RTE_VERIFY(bus);
> > +       RTE_VERIFY(dev);
> > +
> > +       TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
> > +       dev->bus = bus;
> > +}
> > +
> > +/** @internal
> > + * Remove a device from its bus.
> > + */
> > +void
> > +rte_eal_bus_remove_device(struct rte_device *dev)
> > +{
> > +       struct rte_bus *bus;
> > +
> > +       RTE_VERIFY(dev);
> > +       RTE_VERIFY(dev->bus);
> > +
> > +       bus = dev->bus;
> > +       TAILQ_REMOVE(&bus->device_list, dev, next);
> > +       dev->bus = NULL;
> > +}
> > +
> > +/** @internal
> > + * Associate a driver with a bus.
> > + */
> > +void
> > +rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
> > +{
> > +       RTE_VERIFY(bus);
> > +       RTE_VERIFY(drv);
> > +
> > +       TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
> > +       drv->bus = bus;
> > +}
> > +
> > +/** @internal
> > + * Disassociate a driver from bus.
> > + */
> > +void
> > +rte_eal_bus_remove_driver(struct rte_driver *drv)
> > +{
> > +       struct rte_bus *bus;
> > +
> > +       RTE_VERIFY(drv);
> > +       RTE_VERIFY(drv->bus);
> > +
> > +       bus = drv->bus;
> > +       TAILQ_REMOVE(&bus->driver_list, drv, next);
> > +       drv->bus = NULL;
> > +}
> > +
> > +/**
> > + * Get the bus handle using its name
> > + */
> > +struct rte_bus *
> > +rte_eal_get_bus(const char *bus_name)
> > +{
> > +       struct rte_bus *bus;
> > +
> > +       RTE_VERIFY(bus_name);
> > +
> > +       TAILQ_FOREACH(bus, &rte_bus_list, next) {
> > +               RTE_VERIFY(bus->name);
> > +
> > +               if (!strcmp(bus_name, bus->name)) {
> > +                       RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n",
> bus);
> > +                       return bus;
> > +               }
> > +       }
> > +
> > +       /* Unable to find bus requested */
> > +       return NULL;
> > +}
> > +
> > +/* register a bus */
> > +void
> > +rte_eal_bus_register(struct rte_bus *bus)
> > +{
> > +       RTE_VERIFY(bus);
> > +       RTE_VERIFY(bus->name && strlen(bus->name));
> > +
> > +       /* Initialize the driver and device list associated with the bus */
> > +       TAILQ_INIT(&(bus->driver_list));
> > +       TAILQ_INIT(&(bus->device_list));
> > +
> > +       TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
> > +       RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
> > +}
> > +
> > +/* unregister a bus */
> > +void
> > +rte_eal_bus_unregister(struct rte_bus *bus)
> > +{
> > +       /* All devices and drivers associated with the bus should have been
> > +        * 'device->uninit' and 'driver->remove()' already.
> > +        */
> > +       RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
> > +       RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
> > +
> > +       /* TODO: For each device, call its rte_device->driver->remove()
> > +        * and rte_eal_bus_remove_driver()
> > +        */
> > +
> > +       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_eal_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..f0297a9
> > --- /dev/null
> > +++ b/lib/librte_eal/common/include/rte_bus.h
> > @@ -0,0 +1,174 @@
> > +/*-
> > + *   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);
> > +
> > +/* Global Bus list */
> > +extern struct rte_bus_list rte_bus_list;
> > +
> > +struct rte_bus {
> > +       TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
> > +       struct rte_driver_list driver_list;
> > +                                    /**< List of all drivers on bus */
> > +       struct rte_device_list device_list;
> > +                                    /**< List of all devices on bus */
> > +       const char *name;            /**< Name of the bus */
> > +};
> > +
> > +/** @internal
> > + * Add a device to a bus.
> > + *
> > + * @param bus
> > + *     Bus on which device is to be added
> > + * @param dev
> > + *     Device handle
> > + * @return
> > + *     None
> > + */
> > +void
> > +rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
> > +
> > +/** @internal
> > + * Remove a device from its bus.
> > + *
> > + * @param dev
> > + *     Device handle to remove
> > + * @return
> > + *     None
> > + */
> > +void
> > +rte_eal_bus_remove_device(struct rte_device *dev);
> > +
> > +/** @internal
> > + * Associate a driver with a bus.
> > + *
> > + * @param bus
> > + *     Bus on which driver is to be added
> > + * @param dev
> > + *     Driver handle
> > + * @return
> > + *     None
> > + */
> > +void
> > +rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
> > +
> > +/** @internal
> > + * Disassociate a driver from its bus.
> > + *
> > + * @param dev
> > + *     Driver handle to remove
> > + * @return
> > + *     None
> > + */
> > +void
> > +rte_eal_bus_remove_driver(struct rte_driver *drv);
> > +
> > +/**
> > + * Register a Bus handler.
> > + *
> > + * @param driver
> > + *   A pointer to a rte_bus structure describing the bus
> > + *   to be registered.
> > + */
> > +void rte_eal_bus_register(struct rte_bus *bus);
> > +
> > +/**
> > + * Unregister a Bus handler.
> > + *
> > + * @param driver
> > + *   A pointer to a rte_bus structure describing the bus
> > + *   to be unregistered.
> > + */
> > +void rte_eal_bus_unregister(struct rte_bus *bus);
> > +
> > +/**
> > + * Obtain handle for bus given its name.
> > + *
> > + * @param bus_name
> > + *     Name of the bus handle to search
> > + * @return
> > + *     Pointer to Bus object if name matches any registered bus object
> > + *     NULL, if no matching bus found
> > + */
> > +struct rte_bus *rte_eal_get_bus(const char *bus_name);
> > +
> > +/**
> > + * 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_eal_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_eal_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 8840380..4004f9a 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 */
> 
> Is there a reason why this isn't const?

No reason. Miss from my end. I will fix this.
(I also took hint from Stephen's recent patches) 

> 
> 
> >         struct rte_driver *driver;    /**< Associated driver */
> >         int numa_node;                /**< NUMA node connection */
> >         struct rte_devargs *devargs;  /**< Device user arguments */
> > @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
> >   */
> >  struct rte_driver {
> >         TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
> > +       struct rte_bus *bus;           /**< Bus serviced by this driver */
> 
> Same thing here.

I will send out v4 with this. Thanks for comments.

> 
> >         const char *name;                   /**< Driver name. */
> >         const char *alias;              /**< Driver alias. */
> >  };
> > 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..c873a7f 100644
> > --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> > +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> > @@ -178,3 +178,18 @@ DPDK_16.11 {
> >         rte_eal_vdrv_unregister;
> >
> >  } DPDK_16.07;
> > +
> > +DPDK_17.02 {
> > +       global:
> > +
> > +       rte_bus_list;
> > +       rte_eal_bus_add_device;
> > +       rte_eal_bus_add_driver;
> > +       rte_eal_get_bus;
> > +       rte_eal_bus_dump;
> > +       rte_eal_bus_register;
> > +       rte_eal_bus_remove_device;
> > +       rte_eal_bus_remove_driver;
> > +       rte_eal_bus_unregister;
> > +
> > +} DPDK_16.11;
> > --
> > 2.7.4
> >

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-20 13:17       ` Jan Blunck
  2016-12-20 13:51         ` Shreyansh Jain
@ 2016-12-20 17:11         ` Stephen Hemminger
  2016-12-21  7:11           ` Shreyansh Jain
  2016-12-21 15:38           ` Jan Blunck
  2016-12-25 17:39         ` Shreyansh Jain
  2 siblings, 2 replies; 132+ messages in thread
From: Stephen Hemminger @ 2016-12-20 17:11 UTC (permalink / raw)
  To: Jan Blunck
  Cc: Shreyansh Jain, dev, David Marchand, Thomas Monjalon,
	Ferruh Yigit, jianbo.liu

On Tue, 20 Dec 2016 14:17:14 +0100
Jan Blunck <jblunck@infradead.org> wrote:

> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
> > This patch introduces the rte_bus abstraction for devices and drivers in
> > EAL framework. 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' class which rte_driver and rte_device refer.
> > This way, each device (rte_xxx_device) would have reference to the bus
> > it is based on. As well as, each driver (rte_xxx_driver) would have link
> > to the bus and devices on it for servicing.
> >
> >                                   __ rte_bus_list
> >                                  /
> >                      +----------'---+
> >                      |rte_bus       |
> >                      | driver_list------> List of rte_bus specific
> >                      | device_list----    devices
> >                      |              | `-> List of rte_bus associated
> >                      |              |     drivers
> >                      +--|------|----+
> >               _________/        \_________
> >     +--------/----+                     +-\---------------+
> >     |rte_device   |                     |rte_driver       |
> >     | rte_bus     |                     | rte_bus         |
> >     | rte_driver  |                     | ...             |
> >     | ...         |                     +---------...-----+
> >     |             |                               |||
> >     +---||--------+                               |||
> >         ||                                        |||
> >         | \                                        \\\
> >         |  \_____________                           \\\
> >         |                \                          |||
> >  +------|---------+ +----|----------+               |||
> >  |rte_pci_device  | |rte_xxx_device |               |||
> >  | ....           | | ....          |               |||
> >  +----------------+ +---------------+              / | \
> >                                                   /  |  \
> >                             _____________________/  /    \
> >                            /                    ___/      \
> >             +-------------'--+    +------------'---+    +--'------------+
> >             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
> >             | ....           |    | ....           |    | ....          |
> >             +----------------+    +----------------+    +---------------+
> >
> > This patch only enables the bus references on rte_driver and rte_driver.
> > EAL wide global device and driver list continue to exist until an instance
> > of bus is added in subsequent patches.
> >
> > This patch also introduces RTE_REGISTER_BUS macro on the lines of
> > RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
> > been explicitly set to 101 so as to execute bus registration before PMD.
> >
> > Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> >

Ok, but let's keep this as bus type not bus. It gets really hard and complex
to enumerate all layers of PCI bus and bridges. 

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-20 17:11         ` Stephen Hemminger
@ 2016-12-21  7:11           ` Shreyansh Jain
  2016-12-21 15:38           ` Jan Blunck
  1 sibling, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-21  7:11 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jan Blunck, dev, David Marchand, Thomas Monjalon, Ferruh Yigit,
	jianbo.liu

On Tuesday 20 December 2016 10:41 PM, Stephen Hemminger wrote:
> On Tue, 20 Dec 2016 14:17:14 +0100
> Jan Blunck <jblunck@infradead.org> wrote:
>
>> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>>> This patch introduces the rte_bus abstraction for devices and drivers in
>>> EAL framework. 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' class which rte_driver and rte_device refer.
>>> This way, each device (rte_xxx_device) would have reference to the bus
>>> it is based on. As well as, each driver (rte_xxx_driver) would have link
>>> to the bus and devices on it for servicing.
>>>
>>>                                   __ rte_bus_list
>>>                                  /
>>>                      +----------'---+
>>>                      |rte_bus       |
>>>                      | driver_list------> List of rte_bus specific
>>>                      | device_list----    devices
>>>                      |              | `-> List of rte_bus associated
>>>                      |              |     drivers
>>>                      +--|------|----+
>>>               _________/        \_________
>>>     +--------/----+                     +-\---------------+
>>>     |rte_device   |                     |rte_driver       |
>>>     | rte_bus     |                     | rte_bus         |
>>>     | rte_driver  |                     | ...             |
>>>     | ...         |                     +---------...-----+
>>>     |             |                               |||
>>>     +---||--------+                               |||
>>>         ||                                        |||
>>>         | \                                        \\\
>>>         |  \_____________                           \\\
>>>         |                \                          |||
>>>  +------|---------+ +----|----------+               |||
>>>  |rte_pci_device  | |rte_xxx_device |               |||
>>>  | ....           | | ....          |               |||
>>>  +----------------+ +---------------+              / | \
>>>                                                   /  |  \
>>>                             _____________________/  /    \
>>>                            /                    ___/      \
>>>             +-------------'--+    +------------'---+    +--'------------+
>>>             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
>>>             | ....           |    | ....           |    | ....          |
>>>             +----------------+    +----------------+    +---------------+
>>>
>>> This patch only enables the bus references on rte_driver and rte_driver.
>>> EAL wide global device and driver list continue to exist until an instance
>>> of bus is added in subsequent patches.
>>>
>>> This patch also introduces RTE_REGISTER_BUS macro on the lines of
>>> RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
>>> been explicitly set to 101 so as to execute bus registration before PMD.
>>>
>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>>
>
> Ok, but let's keep this as bus type not bus. It gets really hard and complex
> to enumerate all layers of PCI bus and bridges.
>

Sorry, I couldn't understand your comment. You mean it should be 
rte_bus_type rather than rte_bus? Or, you mean rather than creating a 
rte_bus, we should rather have a type embedded in rte_device/driver?

(Though this is 'to' Jan, the context is hinting at my mail)

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-20 17:11         ` Stephen Hemminger
  2016-12-21  7:11           ` Shreyansh Jain
@ 2016-12-21 15:38           ` Jan Blunck
  2016-12-21 23:33             ` Stephen Hemminger
  1 sibling, 1 reply; 132+ messages in thread
From: Jan Blunck @ 2016-12-21 15:38 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Shreyansh Jain, dev, David Marchand, Thomas Monjalon,
	Ferruh Yigit, jianbo.liu

On Tue, Dec 20, 2016 at 6:11 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Tue, 20 Dec 2016 14:17:14 +0100
> Jan Blunck <jblunck@infradead.org> wrote:
>
>> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> > This patch introduces the rte_bus abstraction for devices and drivers in
>> > EAL framework. 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' class which rte_driver and rte_device refer.
>> > This way, each device (rte_xxx_device) would have reference to the bus
>> > it is based on. As well as, each driver (rte_xxx_driver) would have link
>> > to the bus and devices on it for servicing.
>> >
>> >                                   __ rte_bus_list
>> >                                  /
>> >                      +----------'---+
>> >                      |rte_bus       |
>> >                      | driver_list------> List of rte_bus specific
>> >                      | device_list----    devices
>> >                      |              | `-> List of rte_bus associated
>> >                      |              |     drivers
>> >                      +--|------|----+
>> >               _________/        \_________
>> >     +--------/----+                     +-\---------------+
>> >     |rte_device   |                     |rte_driver       |
>> >     | rte_bus     |                     | rte_bus         |
>> >     | rte_driver  |                     | ...             |
>> >     | ...         |                     +---------...-----+
>> >     |             |                               |||
>> >     +---||--------+                               |||
>> >         ||                                        |||
>> >         | \                                        \\\
>> >         |  \_____________                           \\\
>> >         |                \                          |||
>> >  +------|---------+ +----|----------+               |||
>> >  |rte_pci_device  | |rte_xxx_device |               |||
>> >  | ....           | | ....          |               |||
>> >  +----------------+ +---------------+              / | \
>> >                                                   /  |  \
>> >                             _____________________/  /    \
>> >                            /                    ___/      \
>> >             +-------------'--+    +------------'---+    +--'------------+
>> >             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
>> >             | ....           |    | ....           |    | ....          |
>> >             +----------------+    +----------------+    +---------------+
>> >
>> > This patch only enables the bus references on rte_driver and rte_driver.
>> > EAL wide global device and driver list continue to exist until an instance
>> > of bus is added in subsequent patches.
>> >
>> > This patch also introduces RTE_REGISTER_BUS macro on the lines of
>> > RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
>> > been explicitly set to 101 so as to execute bus registration before PMD.
>> >
>> > Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> >
>
> Ok, but let's keep this as bus type not bus. It gets really hard and complex
> to enumerate all layers of PCI bus and bridges.

As far as I understand it this isn't the intention to replicate the
hierarchy of buses we have in the kernel. The PCI bus in this case
becomes a list of PCI devices.

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-21 15:38           ` Jan Blunck
@ 2016-12-21 23:33             ` Stephen Hemminger
  2016-12-22  5:12               ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Stephen Hemminger @ 2016-12-21 23:33 UTC (permalink / raw)
  To: Jan Blunck
  Cc: Shreyansh Jain, dev, David Marchand, Thomas Monjalon,
	Ferruh Yigit, jianbo.liu

On Wed, 21 Dec 2016 16:38:42 +0100
Jan Blunck <jblunck@infradead.org> wrote:

> On Tue, Dec 20, 2016 at 6:11 PM, Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> > On Tue, 20 Dec 2016 14:17:14 +0100
> > Jan Blunck <jblunck@infradead.org> wrote:
> >  
> >> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:  
> >> > This patch introduces the rte_bus abstraction for devices and drivers in
> >> > EAL framework. 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' class which rte_driver and rte_device refer.
> >> > This way, each device (rte_xxx_device) would have reference to the bus
> >> > it is based on. As well as, each driver (rte_xxx_driver) would have link
> >> > to the bus and devices on it for servicing.
> >> >
> >> >                                   __ rte_bus_list
> >> >                                  /
> >> >                      +----------'---+
> >> >                      |rte_bus       |
> >> >                      | driver_list------> List of rte_bus specific
> >> >                      | device_list----    devices
> >> >                      |              | `-> List of rte_bus associated
> >> >                      |              |     drivers
> >> >                      +--|------|----+
> >> >               _________/        \_________
> >> >     +--------/----+                     +-\---------------+
> >> >     |rte_device   |                     |rte_driver       |
> >> >     | rte_bus     |                     | rte_bus         |
> >> >     | rte_driver  |                     | ...             |
> >> >     | ...         |                     +---------...-----+
> >> >     |             |                               |||
> >> >     +---||--------+                               |||
> >> >         ||                                        |||
> >> >         | \                                        \\\
> >> >         |  \_____________                           \\\
> >> >         |                \                          |||
> >> >  +------|---------+ +----|----------+               |||
> >> >  |rte_pci_device  | |rte_xxx_device |               |||
> >> >  | ....           | | ....          |               |||
> >> >  +----------------+ +---------------+              / | \
> >> >                                                   /  |  \
> >> >                             _____________________/  /    \
> >> >                            /                    ___/      \
> >> >             +-------------'--+    +------------'---+    +--'------------+
> >> >             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
> >> >             | ....           |    | ....           |    | ....          |
> >> >             +----------------+    +----------------+    +---------------+
> >> >
> >> > This patch only enables the bus references on rte_driver and rte_driver.
> >> > EAL wide global device and driver list continue to exist until an instance
> >> > of bus is added in subsequent patches.
> >> >
> >> > This patch also introduces RTE_REGISTER_BUS macro on the lines of
> >> > RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
> >> > been explicitly set to 101 so as to execute bus registration before PMD.
> >> >
> >> > Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> >> >  
> >
> > Ok, but let's keep this as bus type not bus. It gets really hard and complex
> > to enumerate all layers of PCI bus and bridges.  
> 
> As far as I understand it this isn't the intention to replicate the
> hierarchy of buses we have in the kernel. The PCI bus in this case
> becomes a list of PCI devices.

One of the motivations seems to be "lets be able to handle lots of devices",
but the current model with an array of ports is not going to scale well for that.

It is time to make rte_eth_devices into rb-tree and get rid of MAX_PORTS config
option.

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-21 23:33             ` Stephen Hemminger
@ 2016-12-22  5:12               ` Shreyansh Jain
  2016-12-22  5:52                 ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-22  5:12 UTC (permalink / raw)
  To: Stephen Hemminger, Jan Blunck
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu

On Thursday 22 December 2016 05:03 AM, Stephen Hemminger wrote:
> On Wed, 21 Dec 2016 16:38:42 +0100
> Jan Blunck <jblunck@infradead.org> wrote:
>
>> On Tue, Dec 20, 2016 at 6:11 PM, Stephen Hemminger
>> <stephen@networkplumber.org> wrote:
>>> On Tue, 20 Dec 2016 14:17:14 +0100
>>> Jan Blunck <jblunck@infradead.org> wrote:
>>>
>>>> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>>>>> This patch introduces the rte_bus abstraction for devices and drivers in
>>>>> EAL framework. 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' class which rte_driver and rte_device refer.
>>>>> This way, each device (rte_xxx_device) would have reference to the bus
>>>>> it is based on. As well as, each driver (rte_xxx_driver) would have link
>>>>> to the bus and devices on it for servicing.
>>>>>
>>>>>                                   __ rte_bus_list
>>>>>                                  /
>>>>>                      +----------'---+
>>>>>                      |rte_bus       |
>>>>>                      | driver_list------> List of rte_bus specific
>>>>>                      | device_list----    devices
>>>>>                      |              | `-> List of rte_bus associated
>>>>>                      |              |     drivers
>>>>>                      +--|------|----+
>>>>>               _________/        \_________
>>>>>     +--------/----+                     +-\---------------+
>>>>>     |rte_device   |                     |rte_driver       |
>>>>>     | rte_bus     |                     | rte_bus         |
>>>>>     | rte_driver  |                     | ...             |
>>>>>     | ...         |                     +---------...-----+
>>>>>     |             |                               |||
>>>>>     +---||--------+                               |||
>>>>>         ||                                        |||
>>>>>         | \                                        \\\
>>>>>         |  \_____________                           \\\
>>>>>         |                \                          |||
>>>>>  +------|---------+ +----|----------+               |||
>>>>>  |rte_pci_device  | |rte_xxx_device |               |||
>>>>>  | ....           | | ....          |               |||
>>>>>  +----------------+ +---------------+              / | \
>>>>>                                                   /  |  \
>>>>>                             _____________________/  /    \
>>>>>                            /                    ___/      \
>>>>>             +-------------'--+    +------------'---+    +--'------------+
>>>>>             |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
>>>>>             | ....           |    | ....           |    | ....          |
>>>>>             +----------------+    +----------------+    +---------------+
>>>>>
>>>>> This patch only enables the bus references on rte_driver and rte_driver.
>>>>> EAL wide global device and driver list continue to exist until an instance
>>>>> of bus is added in subsequent patches.
>>>>>
>>>>> This patch also introduces RTE_REGISTER_BUS macro on the lines of
>>>>> RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
>>>>> been explicitly set to 101 so as to execute bus registration before PMD.
>>>>>
>>>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>>>>
>>>
>>> Ok, but let's keep this as bus type not bus. It gets really hard and complex
>>> to enumerate all layers of PCI bus and bridges.
>>
>> As far as I understand it this isn't the intention to replicate the
>> hierarchy of buses we have in the kernel. The PCI bus in this case
>> becomes a list of PCI devices.
>
> One of the motivations seems to be "lets be able to handle lots of devices",
> but the current model with an array of ports is not going to scale well for that.
>
> It is time to make rte_eth_devices into rb-tree and get rid of MAX_PORTS config
> option.
>

That is a nice idea. Probably once we get the EAL compatible for 'lots 
of devices', this would be next good change.

-
Shreyansh

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-22  5:12               ` Shreyansh Jain
@ 2016-12-22  5:52                 ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-22  5:52 UTC (permalink / raw)
  To: Stephen Hemminger, Jan Blunck
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu

On Thursday 22 December 2016 10:42 AM, Shreyansh Jain wrote:
> On Thursday 22 December 2016 05:03 AM, Stephen Hemminger wrote:
>> On Wed, 21 Dec 2016 16:38:42 +0100
>> Jan Blunck <jblunck@infradead.org> wrote:
>>
>>> On Tue, Dec 20, 2016 at 6:11 PM, Stephen Hemminger
>>> <stephen@networkplumber.org> wrote:
>>>> On Tue, 20 Dec 2016 14:17:14 +0100
>>>> Jan Blunck <jblunck@infradead.org> wrote:
>>>>
>>>>> On Fri, Dec 16, 2016 at 2:10 PM, Shreyansh Jain
>>>>> <shreyansh.jain@nxp.com> wrote:
>>>>>> This patch introduces the rte_bus abstraction for devices and
>>>>>> drivers in
>>>>>> EAL framework. 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' class which rte_driver and rte_device
>>>>>> refer.
>>>>>> This way, each device (rte_xxx_device) would have reference to the
>>>>>> bus
>>>>>> it is based on. As well as, each driver (rte_xxx_driver) would
>>>>>> have link
>>>>>> to the bus and devices on it for servicing.
>>>>>>
>>>>>>                                   __ rte_bus_list
>>>>>>                                  /
>>>>>>                      +----------'---+
>>>>>>                      |rte_bus       |
>>>>>>                      | driver_list------> List of rte_bus specific
>>>>>>                      | device_list----    devices
>>>>>>                      |              | `-> List of rte_bus associated
>>>>>>                      |              |     drivers
>>>>>>                      +--|------|----+
>>>>>>               _________/        \_________
>>>>>>     +--------/----+                     +-\---------------+
>>>>>>     |rte_device   |                     |rte_driver       |
>>>>>>     | rte_bus     |                     | rte_bus         |
>>>>>>     | rte_driver  |                     | ...             |
>>>>>>     | ...         |                     +---------...-----+
>>>>>>     |             |                               |||
>>>>>>     +---||--------+                               |||
>>>>>>         ||                                        |||
>>>>>>         | \                                        \\\
>>>>>>         |  \_____________                           \\\
>>>>>>         |                \                          |||
>>>>>>  +------|---------+ +----|----------+               |||
>>>>>>  |rte_pci_device  | |rte_xxx_device |               |||
>>>>>>  | ....           | | ....          |               |||
>>>>>>  +----------------+ +---------------+              / | \
>>>>>>                                                   /  |  \
>>>>>>                             _____________________/  /    \
>>>>>>                            /                    ___/      \
>>>>>>             +-------------'--+    +------------'---+
>>>>>> +--'------------+
>>>>>>             |rte_pci_driver  |    |rte_vdev_driver |
>>>>>> |rte_xxx_driver |
>>>>>>             | ....           |    | ....           |    |
>>>>>> ....          |
>>>>>>             +----------------+    +----------------+
>>>>>> +---------------+
>>>>>>
>>>>>> This patch only enables the bus references on rte_driver and
>>>>>> rte_driver.
>>>>>> EAL wide global device and driver list continue to exist until an
>>>>>> instance
>>>>>> of bus is added in subsequent patches.
>>>>>>
>>>>>> This patch also introduces RTE_REGISTER_BUS macro on the lines of
>>>>>> RTE_PMD_REGISTER_XXX. Key difference is that the constructor
>>>>>> priority has
>>>>>> been explicitly set to 101 so as to execute bus registration
>>>>>> before PMD.
>>>>>>
>>>>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>>>>>
>>>>
>>>> Ok, but let's keep this as bus type not bus. It gets really hard and
>>>> complex
>>>> to enumerate all layers of PCI bus and bridges.
>>>
>>> As far as I understand it this isn't the intention to replicate the
>>> hierarchy of buses we have in the kernel. The PCI bus in this case
>>> becomes a list of PCI devices.
>>
>> One of the motivations seems to be "lets be able to handle lots of
>> devices",
>> but the current model with an array of ports is not going to scale
>> well for that.
>>
>> It is time to make rte_eth_devices into rb-tree and get rid of
>> MAX_PORTS config
>> option.
>>
>
> That is a nice idea. Probably once we get the EAL compatible for 'lots
> of devices', this would be next good change.

Just out of curiosity - I think only need here is to do away with 
'MAX_PORTS'. There is no need for a 'fast' lookup of ports as this part 
wouldn't be part of datapath. Am I wrong in assuming this?

>
> -
> Shreyansh
>
>

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

* Re: [PATCH v3 02/12] eal/bus: introduce bus abstraction
  2016-12-20 13:17       ` Jan Blunck
  2016-12-20 13:51         ` Shreyansh Jain
  2016-12-20 17:11         ` Stephen Hemminger
@ 2016-12-25 17:39         ` Shreyansh Jain
  2 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-25 17:39 UTC (permalink / raw)
  To: Jan Blunck; +Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu

Hi Jan,

> -----Original Message-----
> From: jblunck@gmail.com [mailto:jblunck@gmail.com] On Behalf Of Jan Blunck
> Sent: Tuesday, December 20, 2016 6:47 PM
> To: Shreyansh Jain <shreyansh.jain@nxp.com>
> Cc: dev@dpdk.org; David Marchand <david.marchand@6wind.com>; Thomas Monjalon
> <thomas.monjalon@6wind.com>; Ferruh Yigit <ferruh.yigit@intel.com>;
> jianbo.liu@linaro.org
> Subject: Re: [dpdk-dev] [PATCH v3 02/12] eal/bus: introduce bus abstraction
> 

[...]

> > +#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 8840380..4004f9a 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 */
> 
> Is there a reason why this isn't const?

Though initially I thought it should be fine, while creating v4 of Bus patches, I didn't change it.

There are cases where the rte_device is used to access the bus and modify the device list within (attaching/detaching the device). Same is the case for rte_driver. Making bus object read-only, prevents that change.

So, I will skip this in v4. If need be, I will revisit in v5 (if any).

> 
> 
> >         struct rte_driver *driver;    /**< Associated driver */
> >         int numa_node;                /**< NUMA node connection */
> >         struct rte_devargs *devargs;  /**< Device user arguments */
> > @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
> >   */
> >  struct rte_driver {
> >         TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
> > +       struct rte_bus *bus;           /**< Bus serviced by this driver */
> 
> Same thing here.
> 
> >         const char *name;                   /**< Driver name. */
> >         const char *alias;              /**< Driver alias. */
> >  };
> > 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..c873a7f 100644
> > --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> > +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> > @@ -178,3 +178,18 @@ DPDK_16.11 {
> >         rte_eal_vdrv_unregister;
> >
> >  } DPDK_16.07;
> > +
> > +DPDK_17.02 {
> > +       global:
> > +
> > +       rte_bus_list;
> > +       rte_eal_bus_add_device;
> > +       rte_eal_bus_add_driver;
> > +       rte_eal_get_bus;
> > +       rte_eal_bus_dump;
> > +       rte_eal_bus_register;
> > +       rte_eal_bus_remove_device;
> > +       rte_eal_bus_remove_driver;
> > +       rte_eal_bus_unregister;
> > +
> > +} DPDK_16.11;
> > --
> > 2.7.4
> >

-
Shreyansh

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

* Re: [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-15 21:36       ` Jan Blunck
@ 2016-12-26  9:14         ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26  9:14 UTC (permalink / raw)
  To: Jan Blunck
  Cc: dev, David Marchand, Thomas Monjalon, Ferruh Yigit, jianbo.liu,
	Thomas Monjalon

On Friday 16 December 2016 03:06 AM, Jan Blunck wrote:
> On Wed, Dec 14, 2016 at 10:49 AM, Shreyansh Jain <shreyansh.jain@nxp.com> wrote:
>> On Tuesday 13 December 2016 07:07 PM, Shreyansh Jain wrote:
>>>
>>> These callbacks now act as first layer of PCI interfaces from the Bus.
>>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>>> drivers are rte_pci_driver).
>>>
>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>> ---
>>>  drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>>>  drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>>>  drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>>>  drivers/net/e1000/em_ethdev.c           | 4 ++++
>>>  drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>>>  drivers/net/ena/ena_ethdev.c            | 4 ++++
>>>  drivers/net/enic/enic_ethdev.c          | 4 ++++
>>>  drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>>>  drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>>>  drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>>>  drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>>>  drivers/net/mlx4/mlx4.c                 | 4 +++-
>>>  drivers/net/mlx5/mlx5.c                 | 1 +
>>>  drivers/net/nfp/nfp_net.c               | 4 ++++
>>>  drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>>>  drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>>>  drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>>>  drivers/net/virtio/virtio_ethdev.c      | 2 ++
>>>  drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>>>  19 files changed, 86 insertions(+), 1 deletion(-)
>>>
>> <snip>
>>
>> drivers/crypto/qat/rte_qat_cryptodev.c should also be changed for this. It
>> seems to be only PCI registered PMD. All others are VDEV.
>>
>> I will send a v3 soon to fix this.
>>
>> @Jan, would you be looking in the VDEV part or should I start with that? [1]
>>
>
> Yes, I am doing that. Will send out early next week.

Do you think following model will help you for VDEV devices?

--->8--
Each bus has following methods:
  .probe(...)
  .remove(...)
  .attach(const char *name)
  .detach(const char *name)
--->8---

Each bus, in this case VDEV bus, would implement these (attach/detach
being optional).
  - For rte_eal_dev_attach, 'attach()' of each bus would be called and
    name of the devices passed to it.
  - Bus->attach() would search for the device name (in case of PCI, BDF)
    and call appropriate initialization routine.
  - Search over bus stops as soon as any bus confirms a successful attach

This is what I was thinking for VDEV:
1. Expose the attach/detach functions in eal_common_bus
2. Define VDEV bus
3. Rather than probe/remove, VDEV implements attach/detach.
    Rationale for this is that VDEV don't really have a bus and neither
    is a probe/remove natural for them. They are 'attached'/'detached'.

Let me know if this helps.
I can provide you base patches over bus series to enable this (I have it 
ready without much testing).

>
> Thx,
> Jan
>
>> [1] http://dpdk.org/ml/archives/dev/2016-November/050443.html
>>
>

-
Shreyansh

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

* [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model
  2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                       ` (11 preceding siblings ...)
  2016-12-16 13:10     ` [PATCH v3 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
@ 2016-12-26 12:50     ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
                         ` (12 more replies)
  12 siblings, 13 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v1: [10]
Link to v2: [11]
Link to v3: [13]

:: 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 context of DPDK EAL:
 - rte_bus, represents a Bus. An implementation of a physical bus would
   instantiate this class.
 - Buses are registered just like a PMD - RTE_REGISTER_BUS()
   `- Thus, implementation for PCI would instantiate a rte_bus, give it a
      name and provide scan/match hooks.
    - Currently, priority of RTE_REGISTER_BUS constructor has been set to
      101 to make sure bus is registered *before* drivers are.
 - Each registered bus is part of a doubly list.
   -- Each device refers to rte_bus on which it belongs
   -- Each driver refers to rte_bus with which it is associated
   -- Device and Drivers lists are part of rte_bus
   -- NO global device/driver list would exist
 - When a PMD wants to register itself, it would 'add' itself to an
   existing bus. Which essentially converts to adding the driver to
   a bus specific driver_list.
 - Bus would perform a scan and 'add' devices scanned to its list.
 - Bus would perform a probe and link devices and drivers on each bus and
   invoking a series of probes
   `-- There are some parallel work for combining scan/probe in EAL [5]
       and also for doing away with a independent scan function all
       together [6].


The view would be almost like:

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> device_list for this bus
                     | device_list----    
                     | scan()       | `-> driver_list for this bus
                     | match()      |
                     | probe()      |
                     |              |
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | *rte_bus    |                     | *rte_bus        |
    | rte_driver  |                     | probe()         |
    |             |                     | remove()        |
    |  devargs    |                     |                 |
    +---||--------+                     +---------|||-----+
        ||                                        '''      
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | PCI specific   | | xxx device    |               |||
 | info (mem,)    | | specific fns  |              / | \
 +----------------+ +---------------+             /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | PCI id table,  |    | <probably,     |    | ....          |
            | other driver   |    |  nothing>      |    +---------------+
            | data           |    |  ...           |
            |  probe()       |    +----------------+
            |  remove()      |
            +----------------+

In continuation to the RFC posted on 17/Nov [9],
A series of patches is being posted which attempts to create:
 1. A basic bus model
    `- define rte_bus and associated methods/helpers
    `- test infrastructure to test the Bus infra
 2. Changes in EAL to support PCI as a bus
    `- a "pci" bus is registered
    `- existing scan/match/probe are modified to allow for bus integration
    `- PCI Device and Driver list, which were global entities, have been
       moved to rte_bus->[device/driver]_list

:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003~0004: Add scan, match and insert support for devices on bus
0005:      Add probe and remove for rte_driver
0006:      Enable probing of PCI Bus (devices) from EAL
0007:      Split the existing PCI probe into match and probe
0008:      Make PCI probe/match work on rte_driver/device rather than
           rte_pci_device/rte_pci_driver
0009:      Patch from Ben [8], part of series [2]
0010:      Enable Scan/Match/probe on Bus from EAL and remove unused
           functions and lists. PMDs still don't work (in fact, PCI PMD
           don't work after this patch - but without any compilation
           issues). Also, fix PCI test framework to reflect the bus
           integration.
0011:      Change PMDs to integrate with PCI bus
0012:      Introduce helper macros for iteration over bus resources

:: Pending Changes/Caveats ::

1. One of the major changes pending, as against proposed in RFC, is the
   removal of eth_driver.
   Being a large change, and independent one, this would be done in a
   separate series of patches.
   - some patches to support this have already been merged into master

2. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   - there was an open question in RFC about where to place the PCI bus
     instance - whether in drivers/bus/... or in lib/librte_bus/... or
     lib/librte_eal/...; This patch uses the last option. But, movement
     only impacts placement of Makefiles.
   - It also impacts the point (5) about priority use in constructor

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

4. The overall layout for driver probing has changed a little.
   earlier, it was:
    rte_eal_init()
     `-> rte_eal_pci_probe() (and parallel for VDEV)
         `-> rte_pci_driver->probe()
             `-> eth_driver->eth_dev_init()

   now, it would be:
   rte_eal_init()
     `-> rte_eal_bus_probe() <- Iterator for PCI device/driver
         `-> rte_driver->probe() <- devargs handling
             |                      old rte_eal_pci_probe()
             `-> rte_xxx_driver->probe() <- eth_dev allocation
                 `-> eth_driver->eth_dev_init <- eth_dev init

   Open Questions:
       Also, rte_driver->probe() creating eth_dev certainly sounds a little
       wrong - but, I would like to get your opinion on how to lay this
       order of which layer ethernet device corresponds to.
       1) Which layer should allocate eth_dev?
          `-> My take: rte_driver->probe()
       2) which layer should fill the eth_dev?
          `-> My take: rte_xxx_driver->probe()
       3) Is init/uninit better name for rte_xxx_driver()->probe() if all
          they do is initialize the ethernet device?

 5. 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
 - vdev changes
 - eth_device, eth_driver changes

:: 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

:: Version Changes ::
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)

Ben Walker (1):
  pci: Pass rte_pci_addr to functions instead of separate args

Shreyansh Jain (11):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  eal/bus: add scan, match and insert support
  eal: integrate bus scan and probe with EAL
  eal: add probe and remove support for rte_driver
  eal: enable probe from bus infrastructure
  pci: split match and probe function
  eal/pci: generalize args of PCI scan/match towards RTE device/driver
  eal: enable PCI bus and PCI test framework
  drivers: update PMDs to use rte_driver probe and remove
  eal/bus: add bus iteration macros

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 689 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 154 ++++--
 drivers/crypto/qat/rte_qat_cryptodev.c          |   4 +
 drivers/net/bnx2x/bnx2x_ethdev.c                |   8 +
 drivers/net/bnxt/bnxt_ethdev.c                  |   4 +
 drivers/net/cxgbe/cxgbe_ethdev.c                |   4 +
 drivers/net/e1000/em_ethdev.c                   |   4 +
 drivers/net/e1000/igb_ethdev.c                  |   8 +
 drivers/net/ena/ena_ethdev.c                    |   4 +
 drivers/net/enic/enic_ethdev.c                  |   4 +
 drivers/net/fm10k/fm10k_ethdev.c                |   4 +
 drivers/net/i40e/i40e_ethdev.c                  |   4 +
 drivers/net/i40e/i40e_ethdev_vf.c               |   4 +
 drivers/net/ixgbe/ixgbe_ethdev.c                |   8 +
 drivers/net/mlx4/mlx4.c                         |   3 +-
 drivers/net/mlx5/mlx5.c                         |   3 +-
 drivers/net/nfp/nfp_net.c                       |   4 +
 drivers/net/qede/qede_ethdev.c                  |   8 +
 drivers/net/szedata2/rte_eth_szedata2.c         |   4 +
 drivers/net/thunderx/nicvf_ethdev.c             |   4 +
 drivers/net/virtio/virtio_ethdev.c              |   2 +
 drivers/net/vmxnet3/vmxnet3_ethdev.c            |   4 +
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  23 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 284 ++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 322 ++++++-----
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_bus.h         | 293 ++++++++++
 lib/librte_eal/common/include/rte_dev.h         |  14 +
 lib/librte_eal/common/include/rte_pci.h         |  58 +-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  84 ++-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  23 +-
 39 files changed, 1847 insertions(+), 289 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] 132+ messages in thread

* [PATCH v4 01/12] eal/bus: introduce bus abstraction
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 02/12] test: add basic bus infrastructure tests Shreyansh Jain
                         ` (11 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for devices and drivers in
EAL framework. 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' class which rte_driver and rte_device refer.
This way, each device (rte_xxx_device) would have reference to the bus
it is based on. As well as, each driver (rte_xxx_driver) would have link
to the bus and devices on it for servicing.

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> List of rte_bus specific
                     | device_list----    devices
                     |              | `-> List of rte_bus associated
                     |              |     drivers
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | rte_bus     |                     | rte_bus         |
    | rte_driver  |                     | ...             |
    | ...         |                     +---------...-----+
    |             |                               |||
    +---||--------+                               |||
        ||                                        |||
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | ....           | | ....          |               |||
 +----------------+ +---------------+              / | \
                                                  /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | ....           |    | ....           |    | ....          |
            +----------------+    +----------------+    +---------------+

This patch only enables the bus references on rte_driver and rte_driver.
EAL wide global device and driver list continue to exist until an instance
of bus is added in subsequent patches.

This patch also introduces RTE_REGISTER_BUS macro on the lines of
RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
been explicitly set to 101 so as to execute bus registration before PMD.

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   |  16 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 190 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 177 ++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   2 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  16 ++
 8 files changed, 404 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..51115f4 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,19 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_bus_get;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_insert_device;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index a92c984..0c39414 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..01730f8
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,190 @@
+/*-
+ *   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);
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+	dev->bus = bus;
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev);
+	RTE_VERIFY(dev->bus);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+	dev->bus = NULL;
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+	drv->bus = bus;
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(drv);
+	RTE_VERIFY(drv->bus);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, drv, next);
+	drv->bus = NULL;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_bus_get(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strcmp(bus_name, bus->name))
+			return bus;
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_INIT(&(bus->driver_list));
+	TAILQ_INIT(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	/* TODO: For each device, call its rte_device->driver->remove()
+	 * and rte_eal_bus_remove_driver()
+	 */
+
+	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_eal_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..ad2873c
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,177 @@
+/*-
+ *   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);
+
+/* Global Bus list */
+extern struct rte_bus_list rte_bus_list;
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	struct rte_driver_list driver_list;
+				     /**< List of all drivers on bus */
+	struct rte_device_list device_list;
+				     /**< List of all devices on bus */
+	const char *name;            /**< Name of the bus */
+};
+
+/** @internal
+ * Add a device to a bus.
+ *
+ * @param bus
+ *	Bus on which device is to be added
+ * @param dev
+ *	Device handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
+
+/** @internal
+ * Remove a device from its bus.
+ *
+ * @param dev
+ *	Device handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev);
+
+/** @internal
+ * Associate a driver with a bus.
+ *
+ * @param bus
+ *	Bus on which driver is to be added
+ * @param dev
+ *	Driver handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
+
+/** @internal
+ * Disassociate a driver from its bus.
+ *
+ * @param dev
+ *	Driver handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv);
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_eal_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_eal_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Obtain handle for bus given its name.
+ *
+ * @param bus_name
+ *	Name of the bus handle to search
+ * @return
+ *	Pointer to Bus object if name matches any registered bus object
+ *	NULL, if no matching bus found
+ */
+struct rte_bus *rte_eal_bus_get(const char *bus_name);
+
+/**
+ * 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_eal_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_eal_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..8ac09e0 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 */
@@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
  */
 struct rte_driver {
 	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
+	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
 };
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..abfe93e 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,19 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_bus_get;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_insert_device;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

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

* [PATCH v4 02/12] test: add basic bus infrastructure tests
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
                         ` (10 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, driver registration on a bus.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile   |   2 +-
 app/test/test.h     |   2 +
 app/test/test_bus.c | 424 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 427 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..60950d3
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,424 @@
+/*-
+ *   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_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
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	const char *name;
+	struct rte_device dev;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus {
+	const char *name;
+	struct rte_bus *bus;
+	struct rte_driver *drivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *devices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct rte_bus busA = {
+	.name = "busA", /* "busA" */
+};
+
+struct rte_bus busB = {
+	.name = "busB", /* "busB */
+};
+
+struct rte_driver driverA = {
+	.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 rte_driver driverB = {
+	.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 dummy_buses[] = {
+	{
+		.name = "busA",
+		.bus = &busA,
+		.drivers = {&driverA, NULL},
+		.devices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.bus = &busB,
+		.drivers = {&driverB, NULL},
+		.devices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus *db;
+	struct rte_bus *bus;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; dummy_buses[i].name; i++) {
+		db = &dummy_buses[i];
+
+		bus = rte_eal_bus_get(db->name);
+		if (!bus)
+			return;
+
+		printf(" Bus: %s\n", bus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			printf("    %s\n", drv->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			printf("    Addr: %p\n", dev);
+			if (dev->driver)
+				printf("    Driver = %s\n", 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_eal_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);
+	}
+
+	dump_device_tree();
+	return 0;
+}
+
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = dummy_buses[i].bus;
+		rte_eal_bus_register(bus);
+		printf("Registered Bus %s\n", dummy_buses[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 dummy_buses */
+		ret = strcmp(bus->name, dummy_buses[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of dummy_buses[i] should be the NULL entry */
+	if (dummy_buses[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       dummy_buses[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_eal_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_eal_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;
+}
+
+/* Positive case: For each driver in dummy_buses, perform
+ * registration
+ */
+static int
+test_driver_registration_on_bus(void)
+{
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv, *drv2;
+
+	/* For each bus on the dummy_buses list:
+	 * 1. get the bus reference
+	 * 2. register all drivers from dummy_buses
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', register all drivers */
+		for (j = 0; dummy_buses[i].drivers[j]; j++) {
+			drv = dummy_buses[i].drivers[j];
+			rte_eal_bus_add_driver(bus, drv);
+		}
+	}
+
+	/* Drivers have been registered. Verify by parsing the list */
+	drv = NULL;
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		j = 0;
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			drv2 = dummy_buses[i].drivers[j++];
+			if (strcmp(drv2->name, drv->name)) {
+				printf("Incorrectly registered drivers."
+				       " Expected: %s; Available: %s\n",
+				       drv2->name, drv->name);
+				return -1;
+			}
+		}
+	}
+
+	printf("Driver registration test successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+static int
+test_driver_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all drivers */
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			rte_eal_bus_remove_driver(drv);
+		}
+	}
+
+	/* Verifying that all drivers have been removed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->driver_list)) {
+			printf("Unable to remove all drivers on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	printf("Unregistration of drivers on all buses is successful.\n");
+	/* All devices from all buses have been removed */
+	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;
+
+	/* Assuming that buses are already registered, register drivers
+	 * with them.
+	 */
+	if (test_driver_registration_on_bus())
+		return -1;
+
+	if (test_driver_unregistration_on_bus())
+		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);
-- 
2.7.4

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

* [PATCH v4 03/12] eal/bus: add scan, match and insert support
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 02/12] test: add basic bus infrastructure tests Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 13:27         ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
                         ` (9 subsequent siblings)
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

When a PMD is registred, it will associate itself with a bus.

A bus is responsible for 'scan' of all the devices attached to it.
All the scanned devices are attached to bus specific device_list.
During the probe operation, 'match' of the drivers and devices would
be done.

Also, rather than adding a device to tail, a new device might be added to
the list (pivoted on bus) at a predefined position, for example, adding it
in order of addressing. Support for this is added as '*bus_insert'.

This patch also adds necessary test framework to test the scan and
match callbacks.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 60950d3..98250c8 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -80,12 +80,32 @@ struct dummy_bus {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+int scan_fn_for_busA(struct rte_bus *bus);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+int scan_fn_for_busB(struct rte_bus *bus);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus busA = {
 	.name = "busA", /* "busA" */
+	.scan = scan_fn_for_busA,
+	.match = generic_match_fn,
 };
 
 struct rte_bus busB = {
 	.name = "busB", /* "busB */
+	.scan = scan_fn_for_busB,
+	.match = generic_match_fn,
 };
 
 struct rte_driver driverA = {
@@ -184,6 +204,92 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the dummy_buses and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that dummy_buses list, register.
+ *
+ * @param bus
+ *	bus to scan againt test entry
+ * @return
+ *	0 for successful scan, even if no devices are found
+ *	!0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+	int i = 0;
+	struct rte_device *dev = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		if (!strcmp(dummy_buses[i].name, bus->name)) {
+			db = &dummy_buses[i];
+			break;
+		}
+	}
+
+	if (!db)
+		return -1;
+
+	/* For all the devices in the device tree (dummy_buses), add device */
+	for (i = 0; db->devices[i]; i++) {
+		dev = &(db->devices[i]->dev);
+		rte_eal_bus_add_device(bus, dev);
+	}
+
+	return 0;
+}
+
+/* @internal
+ * Obtain bus from driver object. Match the address of rte_device object
+ * with all the devices associated with that bus.
+ *
+ * Being a test function, all this does is validate that device object
+ * provided is available on the same bus to which driver is registered.
+ *
+ * @param drv
+ *	driver to which matching is to be performed
+ * @param dev
+ *	device object to match with driver
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct rte_device *dev_p = NULL;
+
+	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
+	 * from bus->device_list.
+	 */
+
+	/* a driver is registered with the bus *before* the scan. */
+	bus = drv->bus;
+	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
+		if (dev == dev_p)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+scan_fn_for_busA(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
+int
+scan_fn_for_busB(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
 static int
 test_bus_setup(void)
 {
@@ -392,6 +498,155 @@ test_driver_unregistration_on_bus(void)
 
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			rte_eal_bus_remove_device(dev);
+		}
+	}
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->device_list)) {
+			printf("Unable to remove all devices on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	/* All devices from all buses have been removed */
+	printf("All devices on all buses unregistered.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful scan
+ *	!0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Call the scan function for each bus */
+		ret = bus->scan(bus);
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * Function to perform 'probe' and link devices and drivers on a bus.
+ * This would work over all the buses registered, and all devices and drivers
+ * registered with it - call match on each pair.
+ * Aim is to test the match_fn for each bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_driver *drv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device in bus->device_list
+	 * 3.   for each driver in bus->driver_list
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		/* get bus pointer from dummy_buses itself rather than
+		 * rte_eal_bus_get
+		 */
+		bus = dummy_buses[i].bus;
+
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			TAILQ_FOREACH(drv, &bus->driver_list, next) {
+				if (!bus->match) {
+					printf("Incorrect bus without match "
+					       "fn: (%s).\n", bus->name);
+					return -1;
+				}
+
+				ret = bus->match(drv, dev);
+				if (ret) {
+					printf("Device and driver don't "
+					       "belong to same bus.\n");
+					return -1;
+				}
+				dev->driver = drv;
+
+				/* As match is generic, it always results in
+				 * dev->drv pointing to first driver entry in
+				 * dummy_buses[i]
+				 */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a dummy_buses[i]
+	 * should have same driver (first driver entry of dummy_buses[i])
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		drv = dummy_buses[i].drivers[0];
+
+		for (j = 0; dummy_buses[i].devices[j]; j++) {
+			dev = &(dummy_buses[i].devices[j]->dev);
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
 int
 test_bus(void)
 {
@@ -408,6 +663,16 @@ test_bus(void)
 	if (test_driver_registration_on_bus())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	/* Now that the devices and drivers are registered, perform probe */
+	if (test_probe_on_bus())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_driver_unregistration_on_bus())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 01730f8..5a5ae75 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -58,6 +58,18 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
 	dev->bus = bus;
 }
 
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev,
+			  struct rte_device *new_dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(old_dev);
+	RTE_VERIFY(new_dev);
+
+	TAILQ_INSERT_BEFORE(old_dev, new_dev, next);
+	new_dev->bus = bus;
+}
+
 /** @internal
  * Remove a device from its bus.
  */
@@ -130,6 +142,9 @@ rte_eal_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan and match implemented */
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->match);
 
 	/* Initialize the driver and device list associated with the bus */
 	TAILQ_INIT(&(bus->driver_list));
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index ad2873c..da76db3 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,6 +60,49 @@ 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.
+ *
+ * Successful detection of a device results in rte_device object which is
+ * embedded within the respective device type (rte_pci_device, for example).
+ * Thereafter, PCI specific bus would need to perform
+ * container_of(rte_pci_device) to obtain PCI device object.
+ *
+ * Scan failure of a bus is not treated as exit criteria for application. Scan
+ * for all other buses would still continue.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param bus
+ *	Reference to the bus on which device is added
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*bus_scan_t)(struct rte_bus *bus);
+
+/**
+ * Bus specific match for devices and drivers which can service them.
+ * For each scanned device, rte_driver->probe would be called for driver
+ * specific initialization of the device.
+ *
+ * It is the work of each bus handler to obtain the specific device object
+ * using container_of (or typecasting, as a less preferred way).
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param drv
+ *	Driver object attached to the bus
+ * @param dev
+ *	Device object which is being probed.
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -69,6 +112,9 @@ struct rte_bus {
 	struct rte_device_list device_list;
 				     /**< List of all devices on bus */
 	const char *name;            /**< Name of the bus */
+	bus_scan_t scan;            /**< Scan for devices attached to bus */
+	bus_match_t match;
+	/**< Match device with drivers associated with the bus */
 };
 
 /** @internal
@@ -85,6 +131,24 @@ void
 rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
 
 /** @internal
+ * Rather than adding a device to tail, insert at a predefined location.
+ * This is specifically useful for update device cases, or where addition
+ * of devices in the list needs to be ordered (addressing, for example).
+ *
+ * @param bus
+ *	Handle for bus on which device is to be added
+ * @param old_dev
+ *	Existing rte_device object before which new device needs to be added
+ * @param new_dev
+ *	Object for device to be added before old_dev
+ * @return
+ *	void
+ */
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device,
+			  struct rte_device *new_device);
+
+/** @internal
  * Remove a device from its bus.
  *
  * @param dev
-- 
2.7.4

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

* [PATCH v4 04/12] eal: integrate bus scan and probe with EAL
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (2 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
                         ` (8 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Still a dummy implementation as no real bus driver exists. This adds calls
from EAL to bus specific scan, match functions.
Once driver->probe is in place, and a bus handler has been installed,
the code would become effective.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  7 +++++++
 lib/librte_eal/common/eal_common_bus.c  | 30 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h | 19 +++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c       |  7 +++++++
 4 files changed, 63 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..2c223de 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_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +617,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_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/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 5a5ae75..b7ccbd8 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -172,6 +172,36 @@ rte_eal_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_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Match driver<->device and call driver->probe() */
+int
+rte_eal_bus_probe(void)
+{
+	/* Until driver->probe is available, this is dummy implementation */
+	return 0;
+}
+
 /* dump one bus info */
 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 da76db3..3bd3ab5 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -212,6 +212,25 @@ void rte_eal_bus_unregister(struct rte_bus *bus);
  */
 struct rte_bus *rte_eal_bus_get(const char *bus_name);
 
+/** @internal
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);
+
+/** @internal
+ * For each device on the bus, perform a driver 'match' and call the
+ * driver's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_eal_bus_probe(void);
+
 /**
  * Dump information of all the buses registered with EAL.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..1a17891 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_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
-- 
2.7.4

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

* [PATCH v4 05/12] eal: add probe and remove support for rte_driver
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (3 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 06/12] eal: enable probe from bus infrastructure Shreyansh Jain
                         ` (7 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

rte_driver now supports probe and remove. These would be used for generic
device type (PCI, etc) probe and remove.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 8ac09e0..3a3dc9b 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -145,6 +145,16 @@ void rte_eal_device_insert(struct rte_device *dev);
 void rte_eal_device_remove(struct rte_device *dev);
 
 /**
+ * Initialisation function for the driver called during probing.
+ */
+typedef int (driver_probe_t)(struct rte_driver *, struct rte_device *);
+
+/**
+ * Uninitialisation function for the driver called during hotplugging.
+ */
+typedef int (driver_remove_t)(struct rte_device *);
+
+/**
  * A structure describing a device driver.
  */
 struct rte_driver {
@@ -152,6 +162,8 @@ struct rte_driver {
 	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
+	driver_probe_t *probe;         /**< Probe the device */
+	driver_remove_t *remove;       /**< Remove/hotplugging the device */
 };
 
 /**
-- 
2.7.4

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

* [PATCH v4 06/12] eal: enable probe from bus infrastructure
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (4 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 07/12] pci: split match and probe function Shreyansh Jain
                         ` (6 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

The model is:
 rte_eal_init
 `--> calls rte_eal_bus_probe()
      This iterates over all the drivers and devices and matches them. For
      matched bus specific device-driver and calls:
      `-> rte_driver->probe()
          for all matched device/drivers (rte_bus->match() successful)
          This would be responsible for devargs related checks, eventually
          calling:
          `-> rte_xxx_driver->probe()
              which does all the work from eth_dev allocation to init.
              (Currently, eth_dev init is done by eth_driver->eth_dev_init,
                which would be removed soon)

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c | 51 +++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index b7ccbd8..6dc7b73 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -194,11 +194,60 @@ rte_eal_bus_scan(void)
 	return 0;
 }
 
+static int
+perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+	      struct rte_device *device)
+{
+	int ret;
+
+	if (!driver->probe) {
+		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
+			driver->name);
+		/* This is not an error - just a badly implemented PMD */
+		return 0;
+	}
+
+	ret = driver->probe(driver, device);
+	if (ret < 0)
+		/* One of the probes failed */
+		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
+
+	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
+	 * success, return ret
+	 */
+	return ret;
+}
+
 /* Match driver<->device and call driver->probe() */
 int
 rte_eal_bus_probe(void)
 {
-	/* Until driver->probe is available, this is dummy implementation */
+	int ret;
+	struct rte_bus *bus;
+	struct rte_device *device;
+	struct rte_driver *driver;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		TAILQ_FOREACH(device, &bus->device_list, next) {
+			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+				ret = bus->match(driver, device);
+				if (!ret) {
+					ret = perform_probe(bus, driver,
+							    device);
+					if (ret < 0)
+						return ret;
+
+					device->driver = driver;
+					/* ret == 0 is success; ret >0 implies
+					 * driver doesn't support the device.
+					 * in either case, continue
+					 */
+				}
+			}
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4

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

* [PATCH v4 07/12] pci: split match and probe function
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (5 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 06/12] eal: enable probe from bus infrastructure Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
                         ` (5 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 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 rte_eal_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

--
v2:
 - Change default return in match function
---
 lib/librte_eal/common/eal_common_pci.c  | 176 ++++++++++++++++++--------------
 lib/librte_eal/common/include/rte_pci.h |  15 +++
 2 files changed, 114 insertions(+), 77 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 33485bc..f466448 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,71 +152,106 @@ 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_eal_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;
+		match = 0;
+		break;
+	}
 
-		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 match;
+}
 
-		/* 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 */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
+	loc = &dev->addr;
 
-		/* reference driver structure */
-		dev->driver = dr;
+	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);
 
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret)
-			dev->driver = NULL;
+	/* 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;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_eal_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;
 	}
-	/* return positive value if driver doesn't support this device */
-	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) {
+		RTE_LOG(DEBUG, EAL, "Driver (%s) probe failed.\n",
+			dr->driver.name);
+		dev->driver = NULL;
+	}
+
+	return ret;
 }
 
 /*
@@ -227,51 +262,38 @@ static int
 rte_eal_pci_detach_dev(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++) {
-
-		/* 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;
+	ret = rte_eal_pci_match(dr, dev);
+	if (ret) {
+		/* 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;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 87cad59..34ff3d1 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -373,6 +373,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_eal_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
-- 
2.7.4

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

* [PATCH v4 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (6 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 07/12] pci: split match and probe function Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 09/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
                         ` (4 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

PCI scan and match now work on rte_device/rte_driver rather than PCI
specific objects. These functions can now be plugged to the generic
bus callbacks for scanning and matching devices/drivers.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     |  2 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  4 ++--
 lib/librte_eal/common/eal_common_pci.c  | 28 +++++++++++++++++++++-------
 lib/librte_eal/common/include/rte_pci.h | 16 +++++++++-------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  4 ++--
 5 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..f9b84db 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -180,7 +180,7 @@ test_pci_setup(void)
 		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
 	}
 
-	ret = rte_eal_pci_scan();
+	ret = rte_eal_pci_scan(NULL);
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
 	rte_eal_pci_dump(stdout);
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..56b506e 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -352,7 +352,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -667,7 +667,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index f466448..b7be6aa 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -153,17 +153,22 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev)
+rte_eal_pci_match(struct rte_driver *drv,
+		  struct rte_device *dev)
 {
 	int match = 1;
 	const struct rte_pci_id *id_table;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 
-	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
-		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+	if (!drv || !dev) {
+		RTE_LOG(DEBUG, EAL, "Invalid Device/Driver\n");
 		return -1;
 	}
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
 	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
@@ -201,11 +206,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
+	driver = &dr->driver;
+	device = &dev->device;
 	loc = &dev->addr;
 
 	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -222,11 +231,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 	}
 
 	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(dr, dev);
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Match of device and driver failed */
 		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			dr->driver.name);
+			driver->name);
 		return 1;
 	}
 
@@ -263,12 +272,17 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver = NULL;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	ret = rte_eal_pci_match(dr, dev);
+	driver = &(dr->driver);
+	device = &(dev->device);
+
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Device and driver don't match */
 		return 1;
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 34ff3d1..e5e58dd 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -367,25 +367,27 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  * Scan the content of the PCI bus, and the devices in the devices
  * list
  *
+ * @param bus
+ *	Reference to the PCI bus
+ *
  * @return
  *  0 on success, negative on error
  */
-int rte_eal_pci_scan(void);
+int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
  * 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
+ * @param drv
+ *	driver from which ID table would be extracted
+ * @param dev
+ *	device to match against the driver
  * @return
  *	0 for successful match
  *	!0 for unsuccessful match
  */
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev);
+rte_eal_pci_match(struct rte_driver *drv, struct rte_device *dev);
 
 /**
  * Probe the PCI bus for registered drivers.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 4350134..7e092d2 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -446,7 +446,7 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  * list
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 {
 	struct dirent *e;
 	DIR *dir;
@@ -724,7 +724,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
-- 
2.7.4

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

* [PATCH v4 09/12] pci: Pass rte_pci_addr to functions instead of separate args
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (7 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 10/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
                         ` (3 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Ben Walker, Shreyansh Jain

From: Ben Walker <benjamin.walker@intel.com>

Instead of passing domain, bus, devid, func, just pass
an rte_pci_addr.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
[Shreyansh: Checkpatch error fix]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 7e092d2..4a0207d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -228,8 +228,7 @@ 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, uint16_t domain, uint8_t bus,
-	     uint8_t devid, uint8_t function)
+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -242,10 +241,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 		return -1;
 
 	memset(dev, 0, sizeof(*dev));
-	dev->addr.domain = domain;
-	dev->addr.bus = bus;
-	dev->addr.devid = devid;
-	dev->addr.function = function;
+	dev->addr = *addr;
 
 	/* get vendor id */
 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
@@ -390,16 +386,14 @@ 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->domain, addr->bus, addr->devid,
-				addr->function);
+	return pci_scan_one(filename, addr);
 }
 
 /*
  * split up a pci address into its constituent parts.
  */
 static int
-parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
-		uint8_t *bus, uint8_t *devid, uint8_t *function)
+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
 {
 	/* first split on ':' */
 	union splitaddr {
@@ -427,10 +421,10 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
 
 	/* now convert to int values */
 	errno = 0;
-	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
-	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
-	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
-	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	addr->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	addr->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	addr->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	addr->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
 	if (errno != 0)
 		goto error;
 
@@ -451,8 +445,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
-	uint16_t domain;
-	uint8_t bus, devid, function;
+	struct rte_pci_addr addr;
 
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
@@ -461,20 +454,22 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 		return -1;
 	}
 
+
 	while ((e = readdir(dir)) != NULL) {
 		if (e->d_name[0] == '.')
 			continue;
 
-		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
-				&bus, &devid, &function) != 0)
+		if (parse_pci_addr_format(e->d_name,
+					  sizeof(e->d_name), &addr) != 0)
 			continue;
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
+		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
+
 	return 0;
 
 error:
-- 
2.7.4

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

* [PATCH v4 10/12] eal: enable PCI bus and PCI test framework
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (8 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 09/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
                         ` (2 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Changes to test_pci:
- use a dummy test_pci_bus for all PCI test driver registrations
- this reduces the need for cleaning global list
- add necessary callbacks for invoking scan and probing/matching
  using EAL PCI scan code

Note: With this patch, all PCI PMDs would cease to work because of lack
      rte_driver->probe/remove implementations. Next patch would do that.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                             | 154 +++++++++++------
 lib/librte_eal/bsdapp/eal/eal.c                 |   8 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +++---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-
 lib/librte_eal/common/eal_common_pci.c          | 212 ++++++++++++++----------
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_pci.h         |  53 +++---
 lib/librte_eal/linuxapp/eal/eal.c               |   8 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 ++++---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-
 10 files changed, 332 insertions(+), 240 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index f9b84db..e95b758 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
@@ -61,10 +62,18 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+static struct rte_bus *pci_bus; /* global reference to a Test PCI bus */
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+/* Test PCI bus. */
+struct rte_bus test_pci_bus = {
+	.name = "test_pci_bus",
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +88,9 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
+		.probe = rte_eal_pci_probe,
+		.remove = rte_eal_pci_remove,
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +99,9 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
+		.probe = rte_eal_pci_probe,
+		.remove = rte_eal_pci_remove,
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,14 +121,67 @@ 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;
+	struct rte_device *r_dev = NULL;
+
+	TAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
+
+		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_device *device;
+	struct rte_driver *driver;
+
+	TAILQ_FOREACH(device, &pci_bus->device_list, next) {
+		TAILQ_FOREACH(driver, &pci_bus->driver_list, next) {
+			ret = pci_bus->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)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *device = NULL;
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(device, &(pci_bus->device_list), next) {
+		dev = container_of(device, struct rte_pci_device, device);
 		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 +208,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 +225,19 @@ 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);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_eal_bus_register(&test_pci_bus);
+	pci_bus = &test_pci_bus;
 
-	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);
-	}
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->scan(pci_bus);
 
-	ret = rte_eal_pci_scan(NULL);
 	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,8 +245,8 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_device *dev = NULL;
+	struct rte_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
 
@@ -203,28 +258,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(dev, &(pci_bus->device_list), next) {
+		rte_eal_bus_remove_device(dev);
+		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(dr, &(pci_bus->driver_list), next) {
+		rte_eal_bus_remove_driver(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);
-	}
+	rte_eal_bus_unregister(pci_bus);
 
 	return 0;
 }
@@ -234,16 +284,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");
+
+	TEST_ASSERT(TAILQ_EMPTY(&pci_bus->driver_list),
+		    "PCI Driver list not empty");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	/* Add test drivers to Bus */
+	rte_eal_bus_add_driver(pci_bus, &(my_driver.driver));
+	rte_eal_bus_add_driver(pci_bus, &(my_driver2.driver));
 
 	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 +310,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 +323,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 */
+	rte_eal_bus_remove_driver(&(my_driver.driver));
+	rte_eal_bus_remove_driver(&(my_driver2.driver));
 
 	return 0;
 }
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2c223de..f801076 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,7 @@ 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_eal_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 56b506e..2190d0d 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -240,7 +241,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
 	struct rte_pci_device *dev;
 	struct pci_bar_io bar;
@@ -313,19 +314,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -337,7 +342,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
@@ -352,7 +357,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -365,6 +370,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 			.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__);
@@ -380,7 +389,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 		}
 
 		for (i = 0; i < conf_io.num_matches; i++)
-			if (pci_scan_one(fd, &matches[i]) < 0)
+			if (pci_scan_one(bus, fd, &matches[i]) < 0)
 				goto error;
 
 		dev_count += conf_io.num_matches;
@@ -398,9 +407,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-	int fd;
+	int fd = -1;
 	struct pci_conf matches[2];
 	struct pci_match_conf match = {
 		.pc_sel = {
@@ -418,6 +427,9 @@ pci_update_device(const struct rte_pci_addr *addr)
 		.matches = &matches[0],
 	};
 
+	if (!bus)
+		goto error;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -433,7 +445,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 	if (conf_io.num_matches != 1)
 		goto error;
 
-	if (pci_scan_one(fd, &matches[0]) < 0)
+	if (pci_scan_one(bus, fd, &matches[0]) < 0)
 		goto error;
 
 	close(fd);
@@ -659,17 +671,9 @@ 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;
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	if (rte_eal_pci_scan(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 51115f4..4874902 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -188,5 +185,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index b7be6aa..ce19b9a 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>
@@ -82,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)
@@ -206,39 +202,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
-	struct rte_driver *driver;
-	struct rte_device *device;
-	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &dr->driver;
-	device = &dev->device;
-	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;
-	}
-
-	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Match of device and driver failed */
-		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			driver->name);
-		return 1;
-	}
-
 	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
 			dev->id.device_id, dr->driver.name);
 
@@ -271,23 +238,11 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
-	int ret;
-	struct rte_driver *driver = NULL;
-	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &(dr->driver);
-	device = &(dev->device);
-
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -316,9 +271,9 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
-	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
@@ -328,8 +283,8 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_probe_one_driver(dr, dev);
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		rc = rte_eal_pci_probe(r_dr, &dev->device);
 		if (rc < 0)
 			/* negative value is an error */
 			return -1;
@@ -347,15 +302,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -376,22 +333,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
-	if (pci_update_device(addr) < 0)
+	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_probe_all_drivers(dev);
+		ret = pci_probe_all_drivers(bus, dev);
 		if (ret)
 			goto err_return;
 		return 0;
@@ -412,20 +378,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(bus, dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_bus_remove_device(r_dev);
 		free(dev);
 		return 0;
 	}
@@ -438,41 +413,73 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	return -1;
 }
 
-/*
- * 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.
- */
 int
-rte_eal_pci_probe(void)
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device)
 {
-	struct rte_pci_device *dev = NULL;
-	struct rte_devargs *devargs;
-	int probe_all = 0;
 	int ret = 0;
+	struct rte_devargs *devargs;
+	struct rte_pci_device *pci_dev;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_addr *loc;
 
-	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-		probe_all = 1;
+	if (!driver || !device)
+		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	pci_dev = container_of(device, struct rte_pci_device, device);
+	pci_drv = container_of(driver, struct rte_pci_driver, driver);
 
-		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
-		if (devargs != NULL)
-			dev->device.devargs = devargs;
+	loc = &pci_dev->addr;
 
-		/* probe all or only whitelisted devices */
-		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
-		else if (devargs != NULL &&
-			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			pci_dev->device.numa_node);
+
+	/* Fetch the devargs associated with the device */
+	devargs = pci_devargs_lookup(pci_dev);
+	if (devargs != NULL)
+		pci_dev->device.devargs = devargs;
+
+	/* no initialization when blacklisted, return without error */
+	if (pci_dev->device.devargs != NULL &&
+	    pci_dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
 	}
 
+	ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_eal_pci_remove(struct rte_device *device)
+{
+	int ret = 0;
+	struct rte_pci_device *pci_dev;
+
+	if (!device)
+		return -1;
+
+	pci_dev = container_of(device, struct rte_pci_device, device);
+
+	if (!pci_dev->driver)
+		return -1;
+
+	ret = rte_eal_pci_detach_dev(pci_dev->driver, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
 	return 0;
 }
 
@@ -501,8 +508,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -511,14 +527,32 @@ 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);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_add_driver(bus, &driver->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_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = driver->driver.bus;
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..06ec172 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;
 
@@ -126,13 +116,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *	The PCI bus on which device is connected
  * @param addr
  *	The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index e5e58dd..1647672 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.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);
 
@@ -376,6 +370,40 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
+ * Probe callback for the PCI bus
+ *
+ * For each matched pair of PCI device and driver on PCI bus, perform devargs
+ * check, and call a series of callbacks to allocate ethdev/cryptodev instances
+ * and intializing them.
+ *
+ * @param driver
+ *	Generic driver object matched with the device
+ * @param device
+ *	Generic device object to initialize
+ * @return
+ *   - 0 on success.
+ *   - !0 on error.
+ */
+int
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device);
+
+/**
+ * Remove callback for the PCI bus
+ *
+ * Called when a device needs to be removed from a bus; wraps around the
+ * PCI specific implementation layered over rte_pci_driver->remove. Default
+ * handler used by PCI PMDs
+ *
+ * @param device
+ *	rte_device object referring to device to be removed
+ * @return
+ *	- 0 for successful removal
+ *	- !0 for failure in removal of device
+ */
+int
+rte_eal_pci_remove(struct rte_device *device);
+
+/**
  * Match the PCI Driver and Device using the ID Table
  *
  * @param drv
@@ -390,19 +418,6 @@ int
 rte_eal_pci_match(struct rte_driver *drv, struct rte_device *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.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 1a17891..2a20e90 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,7 @@ 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_eal_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 4a0207d..314effa 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>
@@ -228,7 +229,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_bus *bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -346,21 +348,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	} else {
 		struct rte_pci_device *dev2;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -370,15 +374,14 @@ 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_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 
@@ -386,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(bus, filename, addr);
 }
 
 /*
@@ -440,13 +443,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	if (!bus_p) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	/* 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",
@@ -465,7 +477,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+		if (pci_scan_one(bus_p, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -711,18 +723,9 @@ 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(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index abfe93e..239f2fc 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -192,5 +189,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
-- 
2.7.4

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

* [PATCH v4 11/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (9 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 10/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 12:50       ` [PATCH v4 12/12] eal/bus: add bus iteration macros Shreyansh Jain
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

These callbacks now act as first layer of PCI interfaces from the Bus.
Bus probe would enter the PMDs through the rte_driver->probe/remove
callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
drivers are rte_pci_driver).

This patch also changes QAT which is the only crypto PMD based on PCI.
All others would be changed in a separate patch focused on VDEV.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 drivers/crypto/qat/rte_qat_cryptodev.c  | 4 ++++
 drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
 drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
 drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
 drivers/net/e1000/em_ethdev.c           | 4 ++++
 drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
 drivers/net/ena/ena_ethdev.c            | 4 ++++
 drivers/net/enic/enic_ethdev.c          | 4 ++++
 drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
 drivers/net/i40e/i40e_ethdev.c          | 4 ++++
 drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
 drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
 drivers/net/mlx4/mlx4.c                 | 3 ++-
 drivers/net/mlx5/mlx5.c                 | 3 ++-
 drivers/net/nfp/nfp_net.c               | 4 ++++
 drivers/net/qede/qede_ethdev.c          | 8 ++++++++
 drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
 drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
 drivers/net/virtio/virtio_ethdev.c      | 2 ++
 drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
 20 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 1e7ee61..bc1a9c6 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -120,6 +120,10 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 
 static struct rte_cryptodev_driver rte_qat_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_qat_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_cryptodev_pci_probe,
diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 2735fd0..80ccff6 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -619,6 +619,10 @@ eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_bnx2x_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2x_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
@@ -633,6 +637,10 @@ static struct eth_driver rte_bnx2x_pmd = {
  */
 static struct eth_driver rte_bnx2xvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2xvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 7518b6b..57803df 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1166,6 +1166,10 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev) {
 
 static struct eth_driver bnxt_rte_pmd = {
 	.pci_drv = {
+		    .driver = {
+			    .probe = rte_eal_pci_probe,
+			    .remove = rte_eal_pci_remove,
+		    },
 		    .id_table = bnxt_pci_id_map,
 		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
 			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 64345e3..7718d02 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1041,6 +1041,10 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_cxgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = cxgb4_pci_tbl,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 436acbb..1d507df 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -390,6 +390,10 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_em_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_em_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 4a15447..8f518d8 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1080,6 +1080,10 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_igb_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igb_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1096,6 +1100,10 @@ static struct eth_driver rte_igb_pmd = {
  */
 static struct eth_driver rte_igbvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igbvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index dcee8ed..7af6492 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1707,6 +1707,10 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 static struct eth_driver rte_ena_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ena_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index e5ceb98..2c68d5a 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -635,6 +635,10 @@ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_enic_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_enic_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index b8257e4..236ae07 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3071,6 +3071,10 @@ static const struct rte_pci_id pci_id_fm10k_map[] = {
 
 static struct eth_driver rte_pmd_fm10k = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_fm10k_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8f63044..9f0cbc8 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -670,6 +670,10 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = {
 
 static struct eth_driver rte_i40e_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40e_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 0dc0af5..e32b9eb 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1528,6 +1528,10 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
  */
 static struct eth_driver rte_i40evf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40evf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ec2edad..d5794e6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1562,6 +1562,10 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_ixgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbe_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1578,6 +1582,10 @@ static struct eth_driver rte_ixgbe_pmd = {
  */
 static struct eth_driver rte_ixgbevf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbevf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index eb06f56..666ef41 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5906,7 +5906,8 @@ static const struct rte_pci_id mlx4_pci_id_map[] = {
 static struct eth_driver mlx4_driver = {
 	.pci_drv = {
 		.driver = {
-			.name = MLX4_DRIVER_NAME
+			.name = MLX4_DRIVER_NAME,
+			.probe = rte_eal_pci_probe,
 		},
 		.id_table = mlx4_pci_id_map,
 		.probe = mlx4_pci_probe,
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b97b6d1..6d873aa 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -726,7 +726,8 @@ static const struct rte_pci_id mlx5_pci_id_map[] = {
 static struct eth_driver mlx5_driver = {
 	.pci_drv = {
 		.driver = {
-			.name = MLX5_DRIVER_NAME
+			.name = MLX5_DRIVER_NAME,
+			.probe = rte_eal_pci_probe,
 		},
 		.id_table = mlx5_pci_id_map,
 		.probe = mlx5_pci_probe,
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index e85315f..ad08666 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2474,6 +2474,10 @@ static struct rte_pci_id pci_id_nfp_net_map[] = {
 
 static struct eth_driver rte_nfp_net_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nfp_net_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			     RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index e91e627..dced594 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1643,6 +1643,10 @@ static struct rte_pci_id pci_id_qede_map[] = {
 
 static struct eth_driver rte_qedevf_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qedevf_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
@@ -1656,6 +1660,10 @@ static struct eth_driver rte_qedevf_pmd = {
 
 static struct eth_driver rte_qede_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qede_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index fe7a6b3..43d6252 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1589,6 +1589,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
 
 static struct eth_driver szedata2_eth_driver = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = rte_szedata2_pci_id_table,
 		.probe = rte_eth_dev_pci_probe,
 		.remove = rte_eth_dev_pci_remove,
diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
index 1060319..987423f 100644
--- a/drivers/net/thunderx/nicvf_ethdev.c
+++ b/drivers/net/thunderx/nicvf_ethdev.c
@@ -2113,6 +2113,10 @@ static const struct rte_pci_id pci_id_nicvf_map[] = {
 
 static struct eth_driver rte_nicvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nicvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index b11bee6..bd04436 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1379,6 +1379,8 @@ static struct eth_driver rte_virtio_pmd = {
 	.pci_drv = {
 		.driver = {
 			.name = "net_virtio",
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
 		},
 		.id_table = pci_id_virtio_map,
 		.drv_flags = RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 9c4d93c..5ddbc3e 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -335,6 +335,10 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_vmxnet3_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_vmxnet3_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
-- 
2.7.4

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

* [PATCH v4 12/12] eal/bus: add bus iteration macros
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (10 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
@ 2016-12-26 12:50       ` Shreyansh Jain
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 12:50 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Three macros:
 FOREACH_BUS
 FOREACH_DEVICE_ON_BUS
 FOREACH_DRIVER_ON_BUS
are introduced to make looping over bus (on global list), devices and
drivers (on a specific bus) prettier.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     | 12 ++++++------
 lib/librte_eal/common/eal_common_bus.c  | 12 ++++++------
 lib/librte_eal/common/eal_common_pci.c  | 10 +++++-----
 lib/librte_eal/common/include/rte_bus.h | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index e95b758..6a413e8 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -129,7 +129,7 @@ do_pci_device_dump(FILE *f)
 	struct rte_pci_device *dev = NULL;
 	struct rte_device *r_dev = NULL;
 
-	TAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 
 		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
@@ -154,8 +154,8 @@ do_pci_bus_probe(void)
 	struct rte_device *device;
 	struct rte_driver *driver;
 
-	TAILQ_FOREACH(device, &pci_bus->device_list, next) {
-		TAILQ_FOREACH(driver, &pci_bus->driver_list, next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, device) {
+		FOREACH_DRIVER_ON_BUS(pci_bus, driver) {
 			ret = pci_bus->match(driver, device);
 			if (!ret) {
 				if (!driver->probe)
@@ -180,7 +180,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(device, &(pci_bus->device_list), next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, device) {
 		dev = container_of(device, struct rte_pci_device, device);
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
@@ -265,12 +265,12 @@ test_pci_cleanup(void)
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	TAILQ_FOREACH(dev, &(pci_bus->device_list), next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, dev) {
 		rte_eal_bus_remove_device(dev);
 		dev->driver = NULL;
 	}
 
-	TAILQ_FOREACH(dr, &(pci_bus->driver_list), next) {
+	FOREACH_DRIVER_ON_BUS(pci_bus, dr) {
 		rte_eal_bus_remove_driver(dr);
 	}
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 6dc7b73..f8c2e03 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -125,7 +125,7 @@ rte_eal_bus_get(const char *bus_name)
 
 	RTE_VERIFY(bus_name);
 
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+	FOREACH_BUS(bus) {
 		RTE_VERIFY(bus->name);
 
 		if (!strcmp(bus_name, bus->name))
@@ -179,7 +179,7 @@ rte_eal_bus_scan(void)
 	int ret;
 	struct rte_bus *bus = NULL;
 
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+	FOREACH_BUS(bus) {
 		ret = bus->scan(bus);
 		if (ret) {
 			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
@@ -228,9 +228,9 @@ rte_eal_bus_probe(void)
 	struct rte_driver *driver;
 
 	/* For each bus registered with EAL */
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
-		TAILQ_FOREACH(device, &bus->device_list, next) {
-			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+	FOREACH_BUS(bus) {
+		FOREACH_DEVICE_ON_BUS(bus, device) {
+			FOREACH_DRIVER_ON_BUS(bus, driver) {
 				ret = bus->match(driver, device);
 				if (!ret) {
 					ret = perform_probe(bus, driver,
@@ -273,7 +273,7 @@ rte_eal_bus_dump(FILE *f)
 	int ret;
 	struct rte_bus *bus;
 
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+	FOREACH_BUS(bus) {
 		ret = bus_dump_one(f, bus);
 		if (ret) {
 			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index ce19b9a..2d5a399 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -283,7 +283,7 @@ pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+	FOREACH_DRIVER_ON_BUS(bus, r_dr) {
 		rc = rte_eal_pci_probe(r_dr, &dev->device);
 		if (rc < 0)
 			/* negative value is an error */
@@ -311,7 +311,7 @@ pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+	FOREACH_DRIVER_ON_BUS(bus, r_dr) {
 		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
@@ -352,7 +352,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
@@ -391,7 +391,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		return -1;
 	}
 
-	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
@@ -517,7 +517,7 @@ rte_eal_pci_dump(FILE *f)
 		return;
 	}
 
-	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 3bd3ab5..07c30c4 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,39 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Helpers for Bus, device and driver list traversal */
+
+/**
+ * Iterate over all the buses registered
+ *
+ * @param bus
+ *	A rte_bus type NULL initialized pointer
+ */
+#define FOREACH_BUS(bus) \
+		TAILQ_FOREACH((bus), &rte_bus_list, next)
+
+/**
+ * Iterate over all the drivers registered with a particular bus
+ *
+ * @param bus
+ *	Valid reference of bus to iterate over
+ * @param drv
+ *	NULL initialized rte_driver type pointer
+ */
+#define FOREACH_DRIVER_ON_BUS(bus, drv) \
+		TAILQ_FOREACH((drv), &(bus)->driver_list, next)
+
+/**
+ * Iterate over all the devices scanned/found on a particular bus
+ *
+ * @param bus
+ *	Valid reference of bus to iterate over
+ * @param dev
+ *	NULL initialized rte_device type pointer
+ */
+#define FOREACH_DEVICE_ON_BUS(bus, dev) \
+		TAILQ_FOREACH((dev), &(bus)->device_list, next)
+
 /* Global Bus list */
 extern struct rte_bus_list rte_bus_list;
 
-- 
2.7.4

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

* [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model
  2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                         ` (11 preceding siblings ...)
  2016-12-26 12:50       ` [PATCH v4 12/12] eal/bus: add bus iteration macros Shreyansh Jain
@ 2016-12-26 13:23       ` Shreyansh Jain
  2016-12-26 13:23         ` [PATCH v5 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
                           ` (12 more replies)
  12 siblings, 13 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Link to v1: [10]
Link to v2: [11]
Link to v3: [13]
Link to v4: [14]

:: 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 context of DPDK EAL:
 - rte_bus, represents a Bus. An implementation of a physical bus would
   instantiate this class.
 - Buses are registered just like a PMD - RTE_REGISTER_BUS()
   `- Thus, implementation for PCI would instantiate a rte_bus, give it a
      name and provide scan/match hooks.
    - Currently, priority of RTE_REGISTER_BUS constructor has been set to
      101 to make sure bus is registered *before* drivers are.
 - Each registered bus is part of a doubly list.
   -- Each device refers to rte_bus on which it belongs
   -- Each driver refers to rte_bus with which it is associated
   -- Device and Drivers lists are part of rte_bus
   -- NO global device/driver list would exist
 - When a PMD wants to register itself, it would 'add' itself to an
   existing bus. Which essentially converts to adding the driver to
   a bus specific driver_list.
 - Bus would perform a scan and 'add' devices scanned to its list.
 - Bus would perform a probe and link devices and drivers on each bus and
   invoking a series of probes
   `-- There are some parallel work for combining scan/probe in EAL [5]
       and also for doing away with a independent scan function all
       together [6].


The view would be almost like:

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> device_list for this bus
                     | device_list----    
                     | scan()       | `-> driver_list for this bus
                     | match()      |
                     | probe()      |
                     |              |
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | *rte_bus    |                     | *rte_bus        |
    | rte_driver  |                     | probe()         |
    |             |                     | remove()        |
    |  devargs    |                     |                 |
    +---||--------+                     +---------|||-----+
        ||                                        '''      
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | PCI specific   | | xxx device    |               |||
 | info (mem,)    | | specific fns  |              / | \
 +----------------+ +---------------+             /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | PCI id table,  |    | <probably,     |    | ....          |
            | other driver   |    |  nothing>      |    +---------------+
            | data           |    |  ...           |
            |  probe()       |    +----------------+
            |  remove()      |
            +----------------+

In continuation to the RFC posted on 17/Nov [9],
A series of patches is being posted which attempts to create:
 1. A basic bus model
    `- define rte_bus and associated methods/helpers
    `- test infrastructure to test the Bus infra
 2. Changes in EAL to support PCI as a bus
    `- a "pci" bus is registered
    `- existing scan/match/probe are modified to allow for bus integration
    `- PCI Device and Driver list, which were global entities, have been
       moved to rte_bus->[device/driver]_list

:: Brief about Patch Layout ::

0001~0002: Introducing the basic Bus model and associated test case
0003~0004: Add scan, match and insert support for devices on bus
0005:      Add probe and remove for rte_driver
0006:      Enable probing of PCI Bus (devices) from EAL
0007:      Split the existing PCI probe into match and probe
0008:      Make PCI probe/match work on rte_driver/device rather than
           rte_pci_device/rte_pci_driver
0009:      Patch from Ben [8], part of series [2]
0010:      Enable Scan/Match/probe on Bus from EAL and remove unused
           functions and lists. PMDs still don't work (in fact, PCI PMD
           don't work after this patch - but without any compilation
           issues). Also, fix PCI test framework to reflect the bus
           integration.
0011:      Change PMDs to integrate with PCI bus
0012:      Introduce helper macros for iteration over bus resources

:: Pending Changes/Caveats ::

1. One of the major changes pending, as against proposed in RFC, is the
   removal of eth_driver.
   Being a large change, and independent one, this would be done in a
   separate series of patches.
   - some patches to support this have already been merged into master

2. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   - there was an open question in RFC about where to place the PCI bus
     instance - whether in drivers/bus/... or in lib/librte_bus/... or
     lib/librte_eal/...; This patch uses the last option. But, movement
     only impacts placement of Makefiles.
   - It also impacts the point (5) about priority use in constructor

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

4. The overall layout for driver probing has changed a little.
   earlier, it was:
    rte_eal_init()
     `-> rte_eal_pci_probe() (and parallel for VDEV)
         `-> rte_pci_driver->probe()
             `-> eth_driver->eth_dev_init()

   now, it would be:
   rte_eal_init()
     `-> rte_eal_bus_probe() <- Iterator for PCI device/driver
         `-> rte_driver->probe() <- devargs handling
             |                      old rte_eal_pci_probe()
             `-> rte_xxx_driver->probe() <- eth_dev allocation
                 `-> eth_driver->eth_dev_init <- eth_dev init

   Open Questions:
       Also, rte_driver->probe() creating eth_dev certainly sounds a little
       wrong - but, I would like to get your opinion on how to lay this
       order of which layer ethernet device corresponds to.
       1) Which layer should allocate eth_dev?
          `-> My take: rte_driver->probe()
       2) which layer should fill the eth_dev?
          `-> My take: rte_xxx_driver->probe()
       3) Is init/uninit better name for rte_xxx_driver()->probe() if all
          they do is initialize the ethernet device?

 5. 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
 - vdev changes
 - eth_device, eth_driver changes

:: 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

:: Version Changes ::
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)

Ben Walker (1):
  pci: Pass rte_pci_addr to functions instead of separate args

Shreyansh Jain (11):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  eal/bus: add scan, match and insert support
  eal: integrate bus scan and probe with EAL
  eal: add probe and remove support for rte_driver
  eal: enable probe from bus infrastructure
  pci: split match and probe function
  eal/pci: generalize args of PCI scan/match towards RTE device/driver
  eal: enable PCI bus and PCI test framework
  drivers: update PMDs to use rte_driver probe and remove
  eal/bus: add bus iteration macros

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 689 ++++++++++++++++++++++++
 app/test/test_pci.c                             | 154 ++++--
 drivers/crypto/qat/rte_qat_cryptodev.c          |   4 +
 drivers/net/bnx2x/bnx2x_ethdev.c                |   8 +
 drivers/net/bnxt/bnxt_ethdev.c                  |   4 +
 drivers/net/cxgbe/cxgbe_ethdev.c                |   4 +
 drivers/net/e1000/em_ethdev.c                   |   4 +
 drivers/net/e1000/igb_ethdev.c                  |   8 +
 drivers/net/ena/ena_ethdev.c                    |   4 +
 drivers/net/enic/enic_ethdev.c                  |   4 +
 drivers/net/fm10k/fm10k_ethdev.c                |   4 +
 drivers/net/i40e/i40e_ethdev.c                  |   4 +
 drivers/net/i40e/i40e_ethdev_vf.c               |   4 +
 drivers/net/ixgbe/ixgbe_ethdev.c                |   8 +
 drivers/net/mlx4/mlx4.c                         |   3 +-
 drivers/net/mlx5/mlx5.c                         |   3 +-
 drivers/net/nfp/nfp_net.c                       |   4 +
 drivers/net/qede/qede_ethdev.c                  |   8 +
 drivers/net/szedata2/rte_eth_szedata2.c         |   4 +
 drivers/net/thunderx/nicvf_ethdev.c             |   4 +
 drivers/net/virtio/virtio_ethdev.c              |   2 +
 drivers/net/vmxnet3/vmxnet3_ethdev.c            |   4 +
 lib/librte_eal/bsdapp/eal/Makefile              |   1 +
 lib/librte_eal/bsdapp/eal/eal.c                 |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  23 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 284 ++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 322 ++++++-----
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_bus.h         | 293 ++++++++++
 lib/librte_eal/common/include/rte_dev.h         |  14 +
 lib/librte_eal/common/include/rte_pci.h         |  58 +-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  13 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  84 ++-
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  23 +-
 39 files changed, 1847 insertions(+), 289 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] 132+ messages in thread

* [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
@ 2016-12-26 13:23         ` Shreyansh Jain
  2017-01-03 21:52           ` Thomas Monjalon
  2017-01-09 15:22           ` Ferruh Yigit
  2016-12-26 13:23         ` [PATCH v5 02/12] test: add basic bus infrastructure tests Shreyansh Jain
                           ` (11 subsequent siblings)
  12 siblings, 2 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

This patch introduces the rte_bus abstraction for devices and drivers in
EAL framework. 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' class which rte_driver and rte_device refer.
This way, each device (rte_xxx_device) would have reference to the bus
it is based on. As well as, each driver (rte_xxx_driver) would have link
to the bus and devices on it for servicing.

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> List of rte_bus specific
                     | device_list----    devices
                     |              | `-> List of rte_bus associated
                     |              |     drivers
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | rte_bus     |                     | rte_bus         |
    | rte_driver  |                     | ...             |
    | ...         |                     +---------...-----+
    |             |                               |||
    +---||--------+                               |||
        ||                                        |||
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | ....           | | ....          |               |||
 +----------------+ +---------------+              / | \
                                                  /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | ....           |    | ....           |    | ....          |
            +----------------+    +----------------+    +---------------+

This patch only enables the bus references on rte_driver and rte_driver.
EAL wide global device and driver list continue to exist until an instance
of bus is added in subsequent patches.

This patch also introduces RTE_REGISTER_BUS macro on the lines of
RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
been explicitly set to 101 so as to execute bus registration before PMD.

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   |  16 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 190 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 177 ++++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   2 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  16 ++
 8 files changed, 404 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..51115f4 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,19 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_bus_get;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_insert_device;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index a92c984..0c39414 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..01730f8
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,190 @@
+/*-
+ *   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);
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+	dev->bus = bus;
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev);
+	RTE_VERIFY(dev->bus);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+	dev->bus = NULL;
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+	drv->bus = bus;
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(drv);
+	RTE_VERIFY(drv->bus);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, drv, next);
+	drv->bus = NULL;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_bus_get(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strcmp(bus_name, bus->name))
+			return bus;
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_INIT(&(bus->driver_list));
+	TAILQ_INIT(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	/* TODO: For each device, call its rte_device->driver->remove()
+	 * and rte_eal_bus_remove_driver()
+	 */
+
+	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_eal_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..ad2873c
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,177 @@
+/*-
+ *   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);
+
+/* Global Bus list */
+extern struct rte_bus_list rte_bus_list;
+
+/**
+ * A structure describing a generic bus.
+ */
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	struct rte_driver_list driver_list;
+				     /**< List of all drivers on bus */
+	struct rte_device_list device_list;
+				     /**< List of all devices on bus */
+	const char *name;            /**< Name of the bus */
+};
+
+/** @internal
+ * Add a device to a bus.
+ *
+ * @param bus
+ *	Bus on which device is to be added
+ * @param dev
+ *	Device handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
+
+/** @internal
+ * Remove a device from its bus.
+ *
+ * @param dev
+ *	Device handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev);
+
+/** @internal
+ * Associate a driver with a bus.
+ *
+ * @param bus
+ *	Bus on which driver is to be added
+ * @param dev
+ *	Driver handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
+
+/** @internal
+ * Disassociate a driver from its bus.
+ *
+ * @param dev
+ *	Driver handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv);
+
+/**
+ * Register a Bus handler.
+ *
+ * @param bus
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_eal_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_eal_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Obtain handle for bus given its name.
+ *
+ * @param bus_name
+ *	Name of the bus handle to search
+ * @return
+ *	Pointer to Bus object if name matches any registered bus object
+ *	NULL, if no matching bus found
+ */
+struct rte_bus *rte_eal_bus_get(const char *bus_name);
+
+/**
+ * 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_eal_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_eal_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..8ac09e0 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 */
@@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
  */
 struct rte_driver {
 	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
+	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
 };
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..abfe93e 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,19 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_bus_get;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_insert_device;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

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

* [PATCH v5 02/12] test: add basic bus infrastructure tests
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-26 13:23         ` [PATCH v5 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2016-12-26 13:23         ` Shreyansh Jain
  2016-12-26 13:23         ` [PATCH v5 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
                           ` (10 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Verification of bus registration, driver registration on a bus.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile   |   2 +-
 app/test/test.h     |   2 +
 app/test/test_bus.c | 424 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 427 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..60950d3
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,424 @@
+/*-
+ *   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_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
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	const char *name;
+	struct rte_device dev;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus {
+	const char *name;
+	struct rte_bus *bus;
+	struct rte_driver *drivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *devices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct rte_bus busA = {
+	.name = "busA", /* "busA" */
+};
+
+struct rte_bus busB = {
+	.name = "busB", /* "busB */
+};
+
+struct rte_driver driverA = {
+	.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 rte_driver driverB = {
+	.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 dummy_buses[] = {
+	{
+		.name = "busA",
+		.bus = &busA,
+		.drivers = {&driverA, NULL},
+		.devices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.bus = &busB,
+		.drivers = {&driverB, NULL},
+		.devices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus *db;
+	struct rte_bus *bus;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; dummy_buses[i].name; i++) {
+		db = &dummy_buses[i];
+
+		bus = rte_eal_bus_get(db->name);
+		if (!bus)
+			return;
+
+		printf(" Bus: %s\n", bus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			printf("    %s\n", drv->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			printf("    Addr: %p\n", dev);
+			if (dev->driver)
+				printf("    Driver = %s\n", 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_eal_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);
+	}
+
+	dump_device_tree();
+	return 0;
+}
+
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = dummy_buses[i].bus;
+		rte_eal_bus_register(bus);
+		printf("Registered Bus %s\n", dummy_buses[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 dummy_buses */
+		ret = strcmp(bus->name, dummy_buses[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of dummy_buses[i] should be the NULL entry */
+	if (dummy_buses[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       dummy_buses[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_eal_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_eal_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;
+}
+
+/* Positive case: For each driver in dummy_buses, perform
+ * registration
+ */
+static int
+test_driver_registration_on_bus(void)
+{
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv, *drv2;
+
+	/* For each bus on the dummy_buses list:
+	 * 1. get the bus reference
+	 * 2. register all drivers from dummy_buses
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', register all drivers */
+		for (j = 0; dummy_buses[i].drivers[j]; j++) {
+			drv = dummy_buses[i].drivers[j];
+			rte_eal_bus_add_driver(bus, drv);
+		}
+	}
+
+	/* Drivers have been registered. Verify by parsing the list */
+	drv = NULL;
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		j = 0;
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			drv2 = dummy_buses[i].drivers[j++];
+			if (strcmp(drv2->name, drv->name)) {
+				printf("Incorrectly registered drivers."
+				       " Expected: %s; Available: %s\n",
+				       drv2->name, drv->name);
+				return -1;
+			}
+		}
+	}
+
+	printf("Driver registration test successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+static int
+test_driver_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all drivers */
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			rte_eal_bus_remove_driver(drv);
+		}
+	}
+
+	/* Verifying that all drivers have been removed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->driver_list)) {
+			printf("Unable to remove all drivers on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	printf("Unregistration of drivers on all buses is successful.\n");
+	/* All devices from all buses have been removed */
+	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;
+
+	/* Assuming that buses are already registered, register drivers
+	 * with them.
+	 */
+	if (test_driver_registration_on_bus())
+		return -1;
+
+	if (test_driver_unregistration_on_bus())
+		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);
-- 
2.7.4

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

* [PATCH v5 03/12] eal/bus: add scan, match and insert support
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
  2016-12-26 13:23         ` [PATCH v5 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
  2016-12-26 13:23         ` [PATCH v5 02/12] test: add basic bus infrastructure tests Shreyansh Jain
@ 2016-12-26 13:23         ` Shreyansh Jain
  2016-12-26 13:23         ` [PATCH v5 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
                           ` (9 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

When a PMD is registred, it will associate itself with a bus.

A bus is responsible for 'scan' of all the devices attached to it.
All the scanned devices are attached to bus specific device_list.
During the probe operation, 'match' of the drivers and devices would
be done.

Also, rather than adding a device to tail, a new device might be added to
the list (pivoted on bus) at a predefined position, for example, adding it
in order of addressing. Support for this is added as '*bus_insert'.

This patch also adds necessary test framework to test the scan and
match callbacks.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 60950d3..f8af5be 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -80,12 +80,32 @@ struct dummy_bus {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(struct rte_bus *bus);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(struct rte_bus *bus);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus busA = {
 	.name = "busA", /* "busA" */
+	.scan = scan_fn_for_busA,
+	.match = generic_match_fn,
 };
 
 struct rte_bus busB = {
 	.name = "busB", /* "busB */
+	.scan = scan_fn_for_busB,
+	.match = generic_match_fn,
 };
 
 struct rte_driver driverA = {
@@ -184,6 +204,92 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the dummy_buses and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that dummy_buses list, register.
+ *
+ * @param bus
+ *	bus to scan againt test entry
+ * @return
+ *	0 for successful scan, even if no devices are found
+ *	!0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+	int i = 0;
+	struct rte_device *dev = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		if (!strcmp(dummy_buses[i].name, bus->name)) {
+			db = &dummy_buses[i];
+			break;
+		}
+	}
+
+	if (!db)
+		return -1;
+
+	/* For all the devices in the device tree (dummy_buses), add device */
+	for (i = 0; db->devices[i]; i++) {
+		dev = &(db->devices[i]->dev);
+		rte_eal_bus_add_device(bus, dev);
+	}
+
+	return 0;
+}
+
+/* @internal
+ * Obtain bus from driver object. Match the address of rte_device object
+ * with all the devices associated with that bus.
+ *
+ * Being a test function, all this does is validate that device object
+ * provided is available on the same bus to which driver is registered.
+ *
+ * @param drv
+ *	driver to which matching is to be performed
+ * @param dev
+ *	device object to match with driver
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct rte_device *dev_p = NULL;
+
+	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
+	 * from bus->device_list.
+	 */
+
+	/* a driver is registered with the bus *before* the scan. */
+	bus = drv->bus;
+	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
+		if (dev == dev_p)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+scan_fn_for_busA(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
+int
+scan_fn_for_busB(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
 static int
 test_bus_setup(void)
 {
@@ -392,6 +498,155 @@ test_driver_unregistration_on_bus(void)
 
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			rte_eal_bus_remove_device(dev);
+		}
+	}
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_bus_get(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->device_list)) {
+			printf("Unable to remove all devices on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	/* All devices from all buses have been removed */
+	printf("All devices on all buses unregistered.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful scan
+ *	!0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Call the scan function for each bus */
+		ret = bus->scan(bus);
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * Function to perform 'probe' and link devices and drivers on a bus.
+ * This would work over all the buses registered, and all devices and drivers
+ * registered with it - call match on each pair.
+ * Aim is to test the match_fn for each bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_driver *drv = NULL;
+
+	/* In case of this test:
+	 * 1. for each bus in rte_bus_list
+	 * 2.  for each device in bus->device_list
+	 * 3.   for each driver in bus->driver_list
+	 * 4.    call match
+	 * 5.    link driver and device
+	 * 6. Verify the linkage.
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		/* get bus pointer from dummy_buses itself rather than
+		 * rte_eal_bus_get
+		 */
+		bus = dummy_buses[i].bus;
+
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			TAILQ_FOREACH(drv, &bus->driver_list, next) {
+				if (!bus->match) {
+					printf("Incorrect bus without match "
+					       "fn: (%s).\n", bus->name);
+					return -1;
+				}
+
+				ret = bus->match(drv, dev);
+				if (ret) {
+					printf("Device and driver don't "
+					       "belong to same bus.\n");
+					return -1;
+				}
+				dev->driver = drv;
+
+				/* As match is generic, it always results in
+				 * dev->drv pointing to first driver entry in
+				 * dummy_buses[i]
+				 */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a dummy_buses[i]
+	 * should have same driver (first driver entry of dummy_buses[i])
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		drv = dummy_buses[i].drivers[0];
+
+		for (j = 0; dummy_buses[i].devices[j]; j++) {
+			dev = &(dummy_buses[i].devices[j]->dev);
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
 int
 test_bus(void)
 {
@@ -408,6 +663,16 @@ test_bus(void)
 	if (test_driver_registration_on_bus())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	/* Now that the devices and drivers are registered, perform probe */
+	if (test_probe_on_bus())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_driver_unregistration_on_bus())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 01730f8..5a5ae75 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -58,6 +58,18 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
 	dev->bus = bus;
 }
 
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev,
+			  struct rte_device *new_dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(old_dev);
+	RTE_VERIFY(new_dev);
+
+	TAILQ_INSERT_BEFORE(old_dev, new_dev, next);
+	new_dev->bus = bus;
+}
+
 /** @internal
  * Remove a device from its bus.
  */
@@ -130,6 +142,9 @@ rte_eal_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan and match implemented */
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->match);
 
 	/* Initialize the driver and device list associated with the bus */
 	TAILQ_INIT(&(bus->driver_list));
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index ad2873c..da76db3 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,6 +60,49 @@ 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.
+ *
+ * Successful detection of a device results in rte_device object which is
+ * embedded within the respective device type (rte_pci_device, for example).
+ * Thereafter, PCI specific bus would need to perform
+ * container_of(rte_pci_device) to obtain PCI device object.
+ *
+ * Scan failure of a bus is not treated as exit criteria for application. Scan
+ * for all other buses would still continue.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param bus
+ *	Reference to the bus on which device is added
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*bus_scan_t)(struct rte_bus *bus);
+
+/**
+ * Bus specific match for devices and drivers which can service them.
+ * For each scanned device, rte_driver->probe would be called for driver
+ * specific initialization of the device.
+ *
+ * It is the work of each bus handler to obtain the specific device object
+ * using container_of (or typecasting, as a less preferred way).
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param drv
+ *	Driver object attached to the bus
+ * @param dev
+ *	Device object which is being probed.
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
@@ -69,6 +112,9 @@ struct rte_bus {
 	struct rte_device_list device_list;
 				     /**< List of all devices on bus */
 	const char *name;            /**< Name of the bus */
+	bus_scan_t scan;            /**< Scan for devices attached to bus */
+	bus_match_t match;
+	/**< Match device with drivers associated with the bus */
 };
 
 /** @internal
@@ -85,6 +131,24 @@ void
 rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
 
 /** @internal
+ * Rather than adding a device to tail, insert at a predefined location.
+ * This is specifically useful for update device cases, or where addition
+ * of devices in the list needs to be ordered (addressing, for example).
+ *
+ * @param bus
+ *	Handle for bus on which device is to be added
+ * @param old_dev
+ *	Existing rte_device object before which new device needs to be added
+ * @param new_dev
+ *	Object for device to be added before old_dev
+ * @return
+ *	void
+ */
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device,
+			  struct rte_device *new_device);
+
+/** @internal
  * Remove a device from its bus.
  *
  * @param dev
-- 
2.7.4

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

* [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (2 preceding siblings ...)
  2016-12-26 13:23         ` [PATCH v5 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
@ 2016-12-26 13:23         ` Shreyansh Jain
  2017-01-03 21:46           ` Thomas Monjalon
  2017-01-08 12:21           ` Rosen, Rami
  2016-12-26 13:23         ` [PATCH v5 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
                           ` (8 subsequent siblings)
  12 siblings, 2 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Still a dummy implementation as no real bus driver exists. This adds calls
from EAL to bus specific scan, match functions.
Once driver->probe is in place, and a bus handler has been installed,
the code would become effective.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  7 +++++++
 lib/librte_eal/common/eal_common_bus.c  | 30 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h | 19 +++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c       |  7 +++++++
 4 files changed, 63 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..2c223de 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_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -613,6 +617,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_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/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 5a5ae75..b7ccbd8 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -172,6 +172,36 @@ rte_eal_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_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Match driver<->device and call driver->probe() */
+int
+rte_eal_bus_probe(void)
+{
+	/* Until driver->probe is available, this is dummy implementation */
+	return 0;
+}
+
 /* dump one bus info */
 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 da76db3..3bd3ab5 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -212,6 +212,25 @@ void rte_eal_bus_unregister(struct rte_bus *bus);
  */
 struct rte_bus *rte_eal_bus_get(const char *bus_name);
 
+/** @internal
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);
+
+/** @internal
+ * For each device on the bus, perform a driver 'match' and call the
+ * driver's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_eal_bus_probe(void);
+
 /**
  * Dump information of all the buses registered with EAL.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 16dd5b9..1a17891 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_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
-- 
2.7.4

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

* [PATCH v5 05/12] eal: add probe and remove support for rte_driver
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (3 preceding siblings ...)
  2016-12-26 13:23         ` [PATCH v5 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2016-12-26 13:23         ` Shreyansh Jain
  2017-01-03 22:05           ` Thomas Monjalon
  2016-12-26 13:23         ` [PATCH v5 06/12] eal: enable probe from bus infrastructure Shreyansh Jain
                           ` (7 subsequent siblings)
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

rte_driver now supports probe and remove. These would be used for generic
device type (PCI, etc) probe and remove.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 8ac09e0..3a3dc9b 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -145,6 +145,16 @@ void rte_eal_device_insert(struct rte_device *dev);
 void rte_eal_device_remove(struct rte_device *dev);
 
 /**
+ * Initialisation function for the driver called during probing.
+ */
+typedef int (driver_probe_t)(struct rte_driver *, struct rte_device *);
+
+/**
+ * Uninitialisation function for the driver called during hotplugging.
+ */
+typedef int (driver_remove_t)(struct rte_device *);
+
+/**
  * A structure describing a device driver.
  */
 struct rte_driver {
@@ -152,6 +162,8 @@ struct rte_driver {
 	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
+	driver_probe_t *probe;         /**< Probe the device */
+	driver_remove_t *remove;       /**< Remove/hotplugging the device */
 };
 
 /**
-- 
2.7.4

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

* [PATCH v5 06/12] eal: enable probe from bus infrastructure
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (4 preceding siblings ...)
  2016-12-26 13:23         ` [PATCH v5 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
@ 2016-12-26 13:23         ` Shreyansh Jain
  2016-12-26 13:24         ` [PATCH v5 07/12] pci: split match and probe function Shreyansh Jain
                           ` (6 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:23 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

The model is:
 rte_eal_init
 `--> calls rte_eal_bus_probe()
      This iterates over all the drivers and devices and matches them. For
      matched bus specific device-driver and calls:
      `-> rte_driver->probe()
          for all matched device/drivers (rte_bus->match() successful)
          This would be responsible for devargs related checks, eventually
          calling:
          `-> rte_xxx_driver->probe()
              which does all the work from eth_dev allocation to init.
              (Currently, eth_dev init is done by eth_driver->eth_dev_init,
                which would be removed soon)

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c | 51 +++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index b7ccbd8..6dc7b73 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -194,11 +194,60 @@ rte_eal_bus_scan(void)
 	return 0;
 }
 
+static int
+perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+	      struct rte_device *device)
+{
+	int ret;
+
+	if (!driver->probe) {
+		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
+			driver->name);
+		/* This is not an error - just a badly implemented PMD */
+		return 0;
+	}
+
+	ret = driver->probe(driver, device);
+	if (ret < 0)
+		/* One of the probes failed */
+		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
+
+	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
+	 * success, return ret
+	 */
+	return ret;
+}
+
 /* Match driver<->device and call driver->probe() */
 int
 rte_eal_bus_probe(void)
 {
-	/* Until driver->probe is available, this is dummy implementation */
+	int ret;
+	struct rte_bus *bus;
+	struct rte_device *device;
+	struct rte_driver *driver;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		TAILQ_FOREACH(device, &bus->device_list, next) {
+			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+				ret = bus->match(driver, device);
+				if (!ret) {
+					ret = perform_probe(bus, driver,
+							    device);
+					if (ret < 0)
+						return ret;
+
+					device->driver = driver;
+					/* ret == 0 is success; ret >0 implies
+					 * driver doesn't support the device.
+					 * in either case, continue
+					 */
+				}
+			}
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4

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

* [PATCH v5 07/12] pci: split match and probe function
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (5 preceding siblings ...)
  2016-12-26 13:23         ` [PATCH v5 06/12] eal: enable probe from bus infrastructure Shreyansh Jain
@ 2016-12-26 13:24         ` Shreyansh Jain
  2017-01-03 22:08           ` Thomas Monjalon
  2016-12-26 13:24         ` [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
                           ` (5 subsequent siblings)
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:24 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 rte_eal_pci_match.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

--
v2:
 - Change default return in match function
---
 lib/librte_eal/common/eal_common_pci.c  | 176 ++++++++++++++++++--------------
 lib/librte_eal/common/include/rte_pci.h |  15 +++
 2 files changed, 114 insertions(+), 77 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 33485bc..f466448 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,71 +152,106 @@ 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_eal_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;
+		match = 0;
+		break;
+	}
 
-		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 match;
+}
 
-		/* 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 */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		}
+	loc = &dev->addr;
 
-		/* reference driver structure */
-		dev->driver = dr;
+	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);
 
-		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
-		if (ret)
-			dev->driver = NULL;
+	/* 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;
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_eal_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;
 	}
-	/* return positive value if driver doesn't support this device */
-	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) {
+		RTE_LOG(DEBUG, EAL, "Driver (%s) probe failed.\n",
+			dr->driver.name);
+		dev->driver = NULL;
+	}
+
+	return ret;
 }
 
 /*
@@ -227,51 +262,38 @@ static int
 rte_eal_pci_detach_dev(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++) {
-
-		/* 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;
+	ret = rte_eal_pci_match(dr, dev);
+	if (ret) {
+		/* 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;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 87cad59..34ff3d1 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -373,6 +373,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_eal_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
-- 
2.7.4

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

* [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (6 preceding siblings ...)
  2016-12-26 13:24         ` [PATCH v5 07/12] pci: split match and probe function Shreyansh Jain
@ 2016-12-26 13:24         ` Shreyansh Jain
  2017-01-03 22:13           ` Thomas Monjalon
  2016-12-26 13:24         ` [PATCH v5 09/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
                           ` (4 subsequent siblings)
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:24 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

PCI scan and match now work on rte_device/rte_driver rather than PCI
specific objects. These functions can now be plugged to the generic
bus callbacks for scanning and matching devices/drivers.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     |  2 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  4 ++--
 lib/librte_eal/common/eal_common_pci.c  | 28 +++++++++++++++++++++-------
 lib/librte_eal/common/include/rte_pci.h | 16 +++++++++-------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  4 ++--
 5 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..f9b84db 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -180,7 +180,7 @@ test_pci_setup(void)
 		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
 	}
 
-	ret = rte_eal_pci_scan();
+	ret = rte_eal_pci_scan(NULL);
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
 	rte_eal_pci_dump(stdout);
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..56b506e 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -352,7 +352,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -667,7 +667,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index f466448..b7be6aa 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -153,17 +153,22 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev)
+rte_eal_pci_match(struct rte_driver *drv,
+		  struct rte_device *dev)
 {
 	int match = 1;
 	const struct rte_pci_id *id_table;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 
-	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
-		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+	if (!drv || !dev) {
+		RTE_LOG(DEBUG, EAL, "Invalid Device/Driver\n");
 		return -1;
 	}
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
 	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
@@ -201,11 +206,15 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
+	driver = &dr->driver;
+	device = &dev->device;
 	loc = &dev->addr;
 
 	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -222,11 +231,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 	}
 
 	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(dr, dev);
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Match of device and driver failed */
 		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			dr->driver.name);
+			driver->name);
 		return 1;
 	}
 
@@ -263,12 +272,17 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
 	int ret;
+	struct rte_driver *driver = NULL;
+	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	ret = rte_eal_pci_match(dr, dev);
+	driver = &(dr->driver);
+	device = &(dev->device);
+
+	ret = rte_eal_pci_match(driver, device);
 	if (ret) {
 		/* Device and driver don't match */
 		return 1;
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 34ff3d1..e5e58dd 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -367,25 +367,27 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  * Scan the content of the PCI bus, and the devices in the devices
  * list
  *
+ * @param bus
+ *	Reference to the PCI bus
+ *
  * @return
  *  0 on success, negative on error
  */
-int rte_eal_pci_scan(void);
+int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
  * 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
+ * @param drv
+ *	driver from which ID table would be extracted
+ * @param dev
+ *	device to match against the driver
  * @return
  *	0 for successful match
  *	!0 for unsuccessful match
  */
 int
-rte_eal_pci_match(struct rte_pci_driver *pci_drv,
-		  struct rte_pci_device *pci_dev);
+rte_eal_pci_match(struct rte_driver *drv, struct rte_device *dev);
 
 /**
  * Probe the PCI bus for registered drivers.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 4350134..7e092d2 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -446,7 +446,7 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  * list
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 {
 	struct dirent *e;
 	DIR *dir;
@@ -724,7 +724,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
-- 
2.7.4

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

* [PATCH v5 09/12] pci: Pass rte_pci_addr to functions instead of separate args
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (7 preceding siblings ...)
  2016-12-26 13:24         ` [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
@ 2016-12-26 13:24         ` Shreyansh Jain
  2016-12-26 13:24         ` [PATCH v5 10/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
                           ` (3 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:24 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Ben Walker, Shreyansh Jain

From: Ben Walker <benjamin.walker@intel.com>

Instead of passing domain, bus, devid, func, just pass
an rte_pci_addr.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
[Shreyansh: Checkpatch error fix]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 7e092d2..4a0207d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -228,8 +228,7 @@ 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, uint16_t domain, uint8_t bus,
-	     uint8_t devid, uint8_t function)
+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -242,10 +241,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 		return -1;
 
 	memset(dev, 0, sizeof(*dev));
-	dev->addr.domain = domain;
-	dev->addr.bus = bus;
-	dev->addr.devid = devid;
-	dev->addr.function = function;
+	dev->addr = *addr;
 
 	/* get vendor id */
 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
@@ -390,16 +386,14 @@ 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->domain, addr->bus, addr->devid,
-				addr->function);
+	return pci_scan_one(filename, addr);
 }
 
 /*
  * split up a pci address into its constituent parts.
  */
 static int
-parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
-		uint8_t *bus, uint8_t *devid, uint8_t *function)
+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
 {
 	/* first split on ':' */
 	union splitaddr {
@@ -427,10 +421,10 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
 
 	/* now convert to int values */
 	errno = 0;
-	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
-	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
-	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
-	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	addr->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	addr->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	addr->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	addr->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
 	if (errno != 0)
 		goto error;
 
@@ -451,8 +445,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
-	uint16_t domain;
-	uint8_t bus, devid, function;
+	struct rte_pci_addr addr;
 
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
@@ -461,20 +454,22 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 		return -1;
 	}
 
+
 	while ((e = readdir(dir)) != NULL) {
 		if (e->d_name[0] == '.')
 			continue;
 
-		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
-				&bus, &devid, &function) != 0)
+		if (parse_pci_addr_format(e->d_name,
+					  sizeof(e->d_name), &addr) != 0)
 			continue;
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
+		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
+
 	return 0;
 
 error:
-- 
2.7.4

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

* [PATCH v5 10/12] eal: enable PCI bus and PCI test framework
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (8 preceding siblings ...)
  2016-12-26 13:24         ` [PATCH v5 09/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
@ 2016-12-26 13:24         ` Shreyansh Jain
  2016-12-26 13:24         ` [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
                           ` (2 subsequent siblings)
  12 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:24 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Changes to test_pci:
- use a dummy test_pci_bus for all PCI test driver registrations
- this reduces the need for cleaning global list
- add necessary callbacks for invoking scan and probing/matching
  using EAL PCI scan code

Note: With this patch, all PCI PMDs would cease to work because of lack
      rte_driver->probe/remove implementations. Next patch would do that.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                             | 154 +++++++++++------
 lib/librte_eal/bsdapp/eal/eal.c                 |   8 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  52 +++---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   7 +-
 lib/librte_eal/common/eal_common_pci.c          | 212 ++++++++++++++----------
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_pci.h         |  53 +++---
 lib/librte_eal/linuxapp/eal/eal.c               |   8 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  57 ++++---
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   7 +-
 10 files changed, 332 insertions(+), 240 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index f9b84db..e95b758 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,6 +38,7 @@
 #include <sys/queue.h>
 
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_ethdev.h>
 #include <rte_devargs.h>
@@ -61,10 +62,18 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+static struct rte_bus *pci_bus; /* global reference to a Test PCI bus */
 
 static int my_driver_init(struct rte_pci_driver *dr,
 			  struct rte_pci_device *dev);
 
+/* Test PCI bus. */
+struct rte_bus test_pci_bus = {
+	.name = "test_pci_bus",
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
 	{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +88,9 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
 	.driver = {
-		.name = "test_driver"
+		.name = "test_driver",
+		.probe = rte_eal_pci_probe,
+		.remove = rte_eal_pci_remove,
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id,
@@ -88,7 +99,9 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
 	.driver = {
-		.name = "test_driver2"
+		.name = "test_driver2",
+		.probe = rte_eal_pci_probe,
+		.remove = rte_eal_pci_remove,
 	},
 	.probe = my_driver_init,
 	.id_table = my_driver_id2,
@@ -108,14 +121,67 @@ 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;
+	struct rte_device *r_dev = NULL;
+
+	TAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
+
+		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_device *device;
+	struct rte_driver *driver;
+
+	TAILQ_FOREACH(device, &pci_bus->device_list, next) {
+		TAILQ_FOREACH(driver, &pci_bus->driver_list, next) {
+			ret = pci_bus->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)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *device = NULL;
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(device, &(pci_bus->device_list), next) {
+		dev = container_of(device, struct rte_pci_device, device);
 		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 +208,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 +225,19 @@ 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);
-	}
+	/* Create a new Bus called 'test_pci_bus' */
+	/* Bus doesn't exist; Create the test bus */
+	printf("Creating a Test PCI bus\n");
+	rte_eal_bus_register(&test_pci_bus);
+	pci_bus = &test_pci_bus;
 
-	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);
-	}
+	printf("Scan for Test devices and add to bus\n");
+	ret = pci_bus->scan(pci_bus);
 
-	ret = rte_eal_pci_scan(NULL);
 	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,8 +245,8 @@ test_pci_setup(void)
 static int
 test_pci_cleanup(void)
 {
-	struct rte_pci_device *dev;
-	struct rte_pci_driver *dr;
+	struct rte_device *dev = NULL;
+	struct rte_driver *dr = NULL;
 	const struct resource *r;
 	int ret;
 
@@ -203,28 +258,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(dev, &(pci_bus->device_list), next) {
+		rte_eal_bus_remove_device(dev);
+		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(dr, &(pci_bus->driver_list), next) {
+		rte_eal_bus_remove_driver(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);
-	}
+	rte_eal_bus_unregister(pci_bus);
 
 	return 0;
 }
@@ -234,16 +284,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");
+
+	TEST_ASSERT(TAILQ_EMPTY(&pci_bus->driver_list),
+		    "PCI Driver list not empty");
 
-	rte_eal_pci_register(&my_driver);
-	rte_eal_pci_register(&my_driver2);
+	/* Add test drivers to Bus */
+	rte_eal_bus_add_driver(pci_bus, &(my_driver.driver));
+	rte_eal_bus_add_driver(pci_bus, &(my_driver2.driver));
 
 	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 +310,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 +323,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 */
+	rte_eal_bus_remove_driver(&(my_driver.driver));
+	rte_eal_bus_remove_driver(&(my_driver2.driver));
 
 	return 0;
 }
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2c223de..f801076 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,7 @@ 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_eal_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 56b506e..2190d0d 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -240,7 +241,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
 	struct rte_pci_device *dev;
 	struct pci_bar_io bar;
@@ -313,19 +314,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -337,7 +342,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
@@ -352,7 +357,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -365,6 +370,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 			.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__);
@@ -380,7 +389,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 		}
 
 		for (i = 0; i < conf_io.num_matches; i++)
-			if (pci_scan_one(fd, &matches[i]) < 0)
+			if (pci_scan_one(bus, fd, &matches[i]) < 0)
 				goto error;
 
 		dev_count += conf_io.num_matches;
@@ -398,9 +407,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-	int fd;
+	int fd = -1;
 	struct pci_conf matches[2];
 	struct pci_match_conf match = {
 		.pc_sel = {
@@ -418,6 +427,9 @@ pci_update_device(const struct rte_pci_addr *addr)
 		.matches = &matches[0],
 	};
 
+	if (!bus)
+		goto error;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -433,7 +445,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 	if (conf_io.num_matches != 1)
 		goto error;
 
-	if (pci_scan_one(fd, &matches[0]) < 0)
+	if (pci_scan_one(bus, fd, &matches[0]) < 0)
 		goto error;
 
 	close(fd);
@@ -659,17 +671,9 @@ 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;
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	if (rte_eal_pci_scan(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 51115f4..4874902 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -188,5 +185,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index b7be6aa..ce19b9a 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>
@@ -82,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)
@@ -206,39 +202,10 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 			     struct rte_pci_device *dev)
 {
 	int ret;
-	struct rte_driver *driver;
-	struct rte_device *device;
-	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &dr->driver;
-	device = &dev->device;
-	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;
-	}
-
-	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Match of device and driver failed */
-		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			driver->name);
-		return 1;
-	}
-
 	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
 			dev->id.device_id, dr->driver.name);
 
@@ -271,23 +238,11 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
-	int ret;
-	struct rte_driver *driver = NULL;
-	struct rte_device *device;
 	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	driver = &(dr->driver);
-	device = &(dev->device);
-
-	ret = rte_eal_pci_match(driver, device);
-	if (ret) {
-		/* Device and driver don't match */
-		return 1;
-	}
-
 	loc = &dev->addr;
 
 	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
@@ -316,9 +271,9 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
-	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
@@ -328,8 +283,8 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
-		rc = rte_eal_pci_probe_one_driver(dr, dev);
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		rc = rte_eal_pci_probe(r_dr, &dev->device);
 		if (rc < 0)
 			/* negative value is an error */
 			return -1;
@@ -347,15 +302,17 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -376,22 +333,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
-	if (pci_update_device(addr) < 0)
+	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_probe_all_drivers(dev);
+		ret = pci_probe_all_drivers(bus, dev);
 		if (ret)
 			goto err_return;
 		return 0;
@@ -412,20 +378,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(bus, dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_bus_remove_device(r_dev);
 		free(dev);
 		return 0;
 	}
@@ -438,41 +413,73 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	return -1;
 }
 
-/*
- * 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.
- */
 int
-rte_eal_pci_probe(void)
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device)
 {
-	struct rte_pci_device *dev = NULL;
-	struct rte_devargs *devargs;
-	int probe_all = 0;
 	int ret = 0;
+	struct rte_devargs *devargs;
+	struct rte_pci_device *pci_dev;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_addr *loc;
 
-	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-		probe_all = 1;
+	if (!driver || !device)
+		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	pci_dev = container_of(device, struct rte_pci_device, device);
+	pci_drv = container_of(driver, struct rte_pci_driver, driver);
 
-		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
-		if (devargs != NULL)
-			dev->device.devargs = devargs;
+	loc = &pci_dev->addr;
 
-		/* probe all or only whitelisted devices */
-		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
-		else if (devargs != NULL &&
-			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			pci_dev->device.numa_node);
+
+	/* Fetch the devargs associated with the device */
+	devargs = pci_devargs_lookup(pci_dev);
+	if (devargs != NULL)
+		pci_dev->device.devargs = devargs;
+
+	/* no initialization when blacklisted, return without error */
+	if (pci_dev->device.devargs != NULL &&
+	    pci_dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
 	}
 
+	ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
+	return 0;
+}
+
+int
+rte_eal_pci_remove(struct rte_device *device)
+{
+	int ret = 0;
+	struct rte_pci_device *pci_dev;
+
+	if (!device)
+		return -1;
+
+	pci_dev = container_of(device, struct rte_pci_device, device);
+
+	if (!pci_dev->driver)
+		return -1;
+
+	ret = rte_eal_pci_detach_dev(pci_dev->driver, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
 	return 0;
 }
 
@@ -501,8 +508,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -511,14 +527,32 @@ 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);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = rte_eal_bus_get("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_add_driver(bus, &driver->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_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = driver->driver.bus;
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..06ec172 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;
 
@@ -126,13 +116,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *	The PCI bus on which device is connected
  * @param addr
  *	The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index e5e58dd..1647672 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.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);
 
@@ -376,6 +370,40 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
+ * Probe callback for the PCI bus
+ *
+ * For each matched pair of PCI device and driver on PCI bus, perform devargs
+ * check, and call a series of callbacks to allocate ethdev/cryptodev instances
+ * and intializing them.
+ *
+ * @param driver
+ *	Generic driver object matched with the device
+ * @param device
+ *	Generic device object to initialize
+ * @return
+ *   - 0 on success.
+ *   - !0 on error.
+ */
+int
+rte_eal_pci_probe(struct rte_driver *driver, struct rte_device *device);
+
+/**
+ * Remove callback for the PCI bus
+ *
+ * Called when a device needs to be removed from a bus; wraps around the
+ * PCI specific implementation layered over rte_pci_driver->remove. Default
+ * handler used by PCI PMDs
+ *
+ * @param device
+ *	rte_device object referring to device to be removed
+ * @return
+ *	- 0 for successful removal
+ *	- !0 for failure in removal of device
+ */
+int
+rte_eal_pci_remove(struct rte_device *device);
+
+/**
  * Match the PCI Driver and Device using the ID Table
  *
  * @param drv
@@ -390,19 +418,6 @@ int
 rte_eal_pci_match(struct rte_driver *drv, struct rte_device *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.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 1a17891..2a20e90 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,7 @@ 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_eal_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 4a0207d..314effa 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>
@@ -228,7 +229,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_bus *bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -346,21 +348,23 @@ 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(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	} else {
 		struct rte_pci_device *dev2;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			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_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
 				dev2->max_vfs = dev->max_vfs;
@@ -370,15 +374,14 @@ 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_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 
@@ -386,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(bus, filename, addr);
 }
 
 /*
@@ -440,13 +443,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	if (!bus_p) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	/* 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",
@@ -465,7 +477,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+		if (pci_scan_one(bus_p, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -711,18 +723,9 @@ 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(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match,
+};
 
-	return 0;
-}
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index abfe93e..239f2fc 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;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
@@ -192,5 +189,9 @@ DPDK_17.02 {
 	rte_eal_bus_remove_device;
 	rte_eal_bus_remove_driver;
 	rte_eal_bus_unregister;
+	rte_eal_pci_match;
+	rte_eal_pci_probe;
+	rte_eal_pci_remove;
+	rte_eal_pci_scan;
 
 } DPDK_16.11;
-- 
2.7.4

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

* [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (9 preceding siblings ...)
  2016-12-26 13:24         ` [PATCH v5 10/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
@ 2016-12-26 13:24         ` Shreyansh Jain
  2017-01-09 15:19           ` Ferruh Yigit
  2016-12-26 13:24         ` [PATCH v5 12/12] eal/bus: add bus iteration macros Shreyansh Jain
  2017-01-03 22:22         ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:24 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

These callbacks now act as first layer of PCI interfaces from the Bus.
Bus probe would enter the PMDs through the rte_driver->probe/remove
callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
drivers are rte_pci_driver).

This patch also changes QAT which is the only crypto PMD based on PCI.
All others would be changed in a separate patch focused on VDEV.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 drivers/crypto/qat/rte_qat_cryptodev.c  | 4 ++++
 drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
 drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
 drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
 drivers/net/e1000/em_ethdev.c           | 4 ++++
 drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
 drivers/net/ena/ena_ethdev.c            | 4 ++++
 drivers/net/enic/enic_ethdev.c          | 4 ++++
 drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
 drivers/net/i40e/i40e_ethdev.c          | 4 ++++
 drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
 drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
 drivers/net/mlx4/mlx4.c                 | 3 ++-
 drivers/net/mlx5/mlx5.c                 | 3 ++-
 drivers/net/nfp/nfp_net.c               | 4 ++++
 drivers/net/qede/qede_ethdev.c          | 8 ++++++++
 drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
 drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
 drivers/net/virtio/virtio_ethdev.c      | 2 ++
 drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
 20 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 1e7ee61..bc1a9c6 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -120,6 +120,10 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 
 static struct rte_cryptodev_driver rte_qat_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_qat_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_cryptodev_pci_probe,
diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 2735fd0..80ccff6 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -619,6 +619,10 @@ eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_bnx2x_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2x_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
@@ -633,6 +637,10 @@ static struct eth_driver rte_bnx2x_pmd = {
  */
 static struct eth_driver rte_bnx2xvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_bnx2xvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 7518b6b..57803df 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1166,6 +1166,10 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev) {
 
 static struct eth_driver bnxt_rte_pmd = {
 	.pci_drv = {
+		    .driver = {
+			    .probe = rte_eal_pci_probe,
+			    .remove = rte_eal_pci_remove,
+		    },
 		    .id_table = bnxt_pci_id_map,
 		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
 			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index 64345e3..7718d02 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1041,6 +1041,10 @@ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_cxgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = cxgb4_pci_tbl,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 436acbb..1d507df 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -390,6 +390,10 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_em_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_em_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 4a15447..8f518d8 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1080,6 +1080,10 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_igb_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igb_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1096,6 +1100,10 @@ static struct eth_driver rte_igb_pmd = {
  */
 static struct eth_driver rte_igbvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_igbvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index dcee8ed..7af6492 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1707,6 +1707,10 @@ static uint16_t eth_ena_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 static struct eth_driver rte_ena_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ena_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index e5ceb98..2c68d5a 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -635,6 +635,10 @@ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_enic_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_enic_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index b8257e4..236ae07 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3071,6 +3071,10 @@ static const struct rte_pci_id pci_id_fm10k_map[] = {
 
 static struct eth_driver rte_pmd_fm10k = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_fm10k_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8f63044..9f0cbc8 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -670,6 +670,10 @@ static const struct rte_i40e_xstats_name_off rte_i40e_txq_prio_strings[] = {
 
 static struct eth_driver rte_i40e_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40e_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 0dc0af5..e32b9eb 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1528,6 +1528,10 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
  */
 static struct eth_driver rte_i40evf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_i40evf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ec2edad..d5794e6 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1562,6 +1562,10 @@ eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_ixgbe_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbe_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
@@ -1578,6 +1582,10 @@ static struct eth_driver rte_ixgbe_pmd = {
  */
 static struct eth_driver rte_ixgbevf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_ixgbevf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index eb06f56..666ef41 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5906,7 +5906,8 @@ static const struct rte_pci_id mlx4_pci_id_map[] = {
 static struct eth_driver mlx4_driver = {
 	.pci_drv = {
 		.driver = {
-			.name = MLX4_DRIVER_NAME
+			.name = MLX4_DRIVER_NAME,
+			.probe = rte_eal_pci_probe,
 		},
 		.id_table = mlx4_pci_id_map,
 		.probe = mlx4_pci_probe,
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b97b6d1..6d873aa 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -726,7 +726,8 @@ static const struct rte_pci_id mlx5_pci_id_map[] = {
 static struct eth_driver mlx5_driver = {
 	.pci_drv = {
 		.driver = {
-			.name = MLX5_DRIVER_NAME
+			.name = MLX5_DRIVER_NAME,
+			.probe = rte_eal_pci_probe,
 		},
 		.id_table = mlx5_pci_id_map,
 		.probe = mlx5_pci_probe,
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index e85315f..ad08666 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2474,6 +2474,10 @@ static struct rte_pci_id pci_id_nfp_net_map[] = {
 
 static struct eth_driver rte_nfp_net_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nfp_net_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			     RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index e91e627..dced594 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1643,6 +1643,10 @@ static struct rte_pci_id pci_id_qede_map[] = {
 
 static struct eth_driver rte_qedevf_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qedevf_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
@@ -1656,6 +1660,10 @@ static struct eth_driver rte_qedevf_pmd = {
 
 static struct eth_driver rte_qede_pmd = {
 	.pci_drv = {
+		    .driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		    },
 		    .id_table = pci_id_qede_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index fe7a6b3..43d6252 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1589,6 +1589,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
 
 static struct eth_driver szedata2_eth_driver = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = rte_szedata2_pci_id_table,
 		.probe = rte_eth_dev_pci_probe,
 		.remove = rte_eth_dev_pci_remove,
diff --git a/drivers/net/thunderx/nicvf_ethdev.c b/drivers/net/thunderx/nicvf_ethdev.c
index 1060319..987423f 100644
--- a/drivers/net/thunderx/nicvf_ethdev.c
+++ b/drivers/net/thunderx/nicvf_ethdev.c
@@ -2113,6 +2113,10 @@ static const struct rte_pci_id pci_id_nicvf_map[] = {
 
 static struct eth_driver rte_nicvf_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_nicvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 		.probe = rte_eth_dev_pci_probe,
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index b11bee6..bd04436 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1379,6 +1379,8 @@ static struct eth_driver rte_virtio_pmd = {
 	.pci_drv = {
 		.driver = {
 			.name = "net_virtio",
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
 		},
 		.id_table = pci_id_virtio_map,
 		.drv_flags = RTE_PCI_DRV_DETACHABLE,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 9c4d93c..5ddbc3e 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -335,6 +335,10 @@ eth_vmxnet3_dev_uninit(struct rte_eth_dev *eth_dev)
 
 static struct eth_driver rte_vmxnet3_pmd = {
 	.pci_drv = {
+		.driver = {
+			.probe = rte_eal_pci_probe,
+			.remove = rte_eal_pci_remove,
+		},
 		.id_table = pci_id_vmxnet3_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
 		.probe = rte_eth_dev_pci_probe,
-- 
2.7.4

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

* [PATCH v5 12/12] eal/bus: add bus iteration macros
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (10 preceding siblings ...)
  2016-12-26 13:24         ` [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
@ 2016-12-26 13:24         ` Shreyansh Jain
  2017-01-03 22:15           ` Thomas Monjalon
  2017-01-03 22:22         ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
  12 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:24 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon, Shreyansh Jain

Three macros:
 FOREACH_BUS
 FOREACH_DEVICE_ON_BUS
 FOREACH_DRIVER_ON_BUS
are introduced to make looping over bus (on global list), devices and
drivers (on a specific bus) prettier.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     | 12 ++++++------
 lib/librte_eal/common/eal_common_bus.c  | 12 ++++++------
 lib/librte_eal/common/eal_common_pci.c  | 10 +++++-----
 lib/librte_eal/common/include/rte_bus.h | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index e95b758..6a413e8 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -129,7 +129,7 @@ do_pci_device_dump(FILE *f)
 	struct rte_pci_device *dev = NULL;
 	struct rte_device *r_dev = NULL;
 
-	TAILQ_FOREACH(r_dev, &pci_bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 
 		fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
@@ -154,8 +154,8 @@ do_pci_bus_probe(void)
 	struct rte_device *device;
 	struct rte_driver *driver;
 
-	TAILQ_FOREACH(device, &pci_bus->device_list, next) {
-		TAILQ_FOREACH(driver, &pci_bus->driver_list, next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, device) {
+		FOREACH_DRIVER_ON_BUS(pci_bus, driver) {
 			ret = pci_bus->match(driver, device);
 			if (!ret) {
 				if (!driver->probe)
@@ -180,7 +180,7 @@ blacklist_all_devices(void)
 	unsigned i = 0;
 	char pci_addr_str[16];
 
-	TAILQ_FOREACH(device, &(pci_bus->device_list), next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, device) {
 		dev = container_of(device, struct rte_pci_device, device);
 		snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
 			dev->addr.domain, dev->addr.bus, dev->addr.devid,
@@ -265,12 +265,12 @@ test_pci_cleanup(void)
 	 * cannot free the devices in the right way. Let's assume that we
 	 * don't care for tests.
 	 */
-	TAILQ_FOREACH(dev, &(pci_bus->device_list), next) {
+	FOREACH_DEVICE_ON_BUS(pci_bus, dev) {
 		rte_eal_bus_remove_device(dev);
 		dev->driver = NULL;
 	}
 
-	TAILQ_FOREACH(dr, &(pci_bus->driver_list), next) {
+	FOREACH_DRIVER_ON_BUS(pci_bus, dr) {
 		rte_eal_bus_remove_driver(dr);
 	}
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 6dc7b73..f8c2e03 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -125,7 +125,7 @@ rte_eal_bus_get(const char *bus_name)
 
 	RTE_VERIFY(bus_name);
 
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+	FOREACH_BUS(bus) {
 		RTE_VERIFY(bus->name);
 
 		if (!strcmp(bus_name, bus->name))
@@ -179,7 +179,7 @@ rte_eal_bus_scan(void)
 	int ret;
 	struct rte_bus *bus = NULL;
 
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+	FOREACH_BUS(bus) {
 		ret = bus->scan(bus);
 		if (ret) {
 			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
@@ -228,9 +228,9 @@ rte_eal_bus_probe(void)
 	struct rte_driver *driver;
 
 	/* For each bus registered with EAL */
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
-		TAILQ_FOREACH(device, &bus->device_list, next) {
-			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+	FOREACH_BUS(bus) {
+		FOREACH_DEVICE_ON_BUS(bus, device) {
+			FOREACH_DRIVER_ON_BUS(bus, driver) {
 				ret = bus->match(driver, device);
 				if (!ret) {
 					ret = perform_probe(bus, driver,
@@ -273,7 +273,7 @@ rte_eal_bus_dump(FILE *f)
 	int ret;
 	struct rte_bus *bus;
 
-	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+	FOREACH_BUS(bus) {
 		ret = bus_dump_one(f, bus);
 		if (ret) {
 			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index ce19b9a..2d5a399 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -283,7 +283,7 @@ pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+	FOREACH_DRIVER_ON_BUS(bus, r_dr) {
 		rc = rte_eal_pci_probe(r_dr, &dev->device);
 		if (rc < 0)
 			/* negative value is an error */
@@ -311,7 +311,7 @@ pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+	FOREACH_DRIVER_ON_BUS(bus, r_dr) {
 		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
@@ -352,7 +352,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
@@ -391,7 +391,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 		return -1;
 	}
 
-	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
@@ -517,7 +517,7 @@ rte_eal_pci_dump(FILE *f)
 		return;
 	}
 
-	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+	FOREACH_DEVICE_ON_BUS(bus, r_dev) {
 		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 3bd3ab5..07c30c4 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,39 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Helpers for Bus, device and driver list traversal */
+
+/**
+ * Iterate over all the buses registered
+ *
+ * @param bus
+ *	A rte_bus type NULL initialized pointer
+ */
+#define FOREACH_BUS(bus) \
+		TAILQ_FOREACH((bus), &rte_bus_list, next)
+
+/**
+ * Iterate over all the drivers registered with a particular bus
+ *
+ * @param bus
+ *	Valid reference of bus to iterate over
+ * @param drv
+ *	NULL initialized rte_driver type pointer
+ */
+#define FOREACH_DRIVER_ON_BUS(bus, drv) \
+		TAILQ_FOREACH((drv), &(bus)->driver_list, next)
+
+/**
+ * Iterate over all the devices scanned/found on a particular bus
+ *
+ * @param bus
+ *	Valid reference of bus to iterate over
+ * @param dev
+ *	NULL initialized rte_device type pointer
+ */
+#define FOREACH_DEVICE_ON_BUS(bus, dev) \
+		TAILQ_FOREACH((dev), &(bus)->device_list, next)
+
 /* Global Bus list */
 extern struct rte_bus_list rte_bus_list;
 
-- 
2.7.4

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

* Re: [PATCH v4 03/12] eal/bus: add scan, match and insert support
  2016-12-26 12:50       ` [PATCH v4 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
@ 2016-12-26 13:27         ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2016-12-26 13:27 UTC (permalink / raw)
  To: david.marchand; +Cc: dev, thomas.monjalon

On Monday 26 December 2016 06:20 PM, Shreyansh Jain wrote:
> When a PMD is registred, it will associate itself with a bus.
>
> A bus is responsible for 'scan' of all the devices attached to it.
> All the scanned devices are attached to bus specific device_list.
> During the probe operation, 'match' of the drivers and devices would
> be done.
>
> Also, rather than adding a device to tail, a new device might be added to
> the list (pivoted on bus) at a predefined position, for example, adding it
> in order of addressing. Support for this is added as '*bus_insert'.
>
> This patch also adds necessary test framework to test the scan and
> match callbacks.
>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  app/test/test_bus.c                     | 265 ++++++++++++++++++++++++++++++++
>  lib/librte_eal/common/eal_common_bus.c  |  15 ++
>  lib/librte_eal/common/include/rte_bus.h |  64 ++++++++
>  3 files changed, 344 insertions(+)
>
> diff --git a/app/test/test_bus.c b/app/test/test_bus.c
> index 60950d3..98250c8 100644
> --- a/app/test/test_bus.c
> +++ b/app/test/test_bus.c
> @@ -80,12 +80,32 @@ struct dummy_bus {
>  struct rte_bus_list orig_bus_list =
>  	TAILQ_HEAD_INITIALIZER(orig_bus_list);
>

Checkpatch reported an error for this patch. I have sent v5 with the
fix.

-
Shreyansh

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2016-12-26 13:23         ` [PATCH v5 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
@ 2017-01-03 21:46           ` Thomas Monjalon
  2017-01-06 10:38             ` Shreyansh Jain
  2017-01-08 12:21           ` Rosen, Rami
  1 sibling, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 21:46 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:53, Shreyansh Jain:
> --- a/lib/librte_eal/linuxapp/eal/eal.c
> +++ b/lib/librte_eal/linuxapp/eal/eal.c
> @@ -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_eal_bus_scan())
> +               rte_panic("Cannot scan the buses for devices\n");

Yes, definitely. Just one scan functions which scan registered bus.

> @@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
>         if (rte_eal_pci_probe())
>                 rte_panic("Cannot probe PCI\n");
>  
> +       if (rte_eal_bus_probe())
> +               rte_panic("Cannot probe devices\n");
> +
>         if (rte_eal_dev_init() < 0)
>                 rte_panic("Cannot init pmd devices\n");

What is the benefit of initializing (probe) a device outside of the scan?
Currently, it is done in two steps, so you are keeping the same behaviour.

I imagine a model where the scan function decide to initialize the
device and can require some help from a callback to make this decision.
So the whitelist/blacklist policy can be implemented with callbacks at
the scan level and possibly the responsibility of the application.
Note that the callback model would be a change for a next release.

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

* Re: [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2016-12-26 13:23         ` [PATCH v5 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
@ 2017-01-03 21:52           ` Thomas Monjalon
  2017-01-06 10:31             ` Shreyansh Jain
  2017-01-09 15:22           ` Ferruh Yigit
  1 sibling, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 21:52 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:53, Shreyansh Jain:
> +DPDK_17.02 {
> +	global:
> +
> +	rte_bus_list;
> +	rte_eal_bus_add_device;
> +	rte_eal_bus_add_driver;
> +	rte_eal_bus_get;
> +	rte_eal_bus_dump;
> +	rte_eal_bus_register;
> +	rte_eal_bus_insert_device;
> +	rte_eal_bus_remove_device;
> +	rte_eal_bus_remove_driver;
> +	rte_eal_bus_unregister;

I think the prefix can be just rte_bus_ instead of rte_eal_bus_.

> +/** Double linked list of buses */
> +TAILQ_HEAD(rte_bus_list, rte_bus);
> +
> +/* Global Bus list */
> +extern struct rte_bus_list rte_bus_list;

Why the bus list is public?

> +/**
> + * A structure describing a generic bus.
> + */
> +struct rte_bus {
> +	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
> +	struct rte_driver_list driver_list;
> +				     /**< List of all drivers on bus */
> +	struct rte_device_list device_list;
> +				     /**< List of all devices on bus */
> +	const char *name;            /**< Name of the bus */
> +};

I am not convinced we should link a generic bus to drivers and devices.
What do you think of having rte_pci_bus being a rte_bus and linking
with rte_pci_device and rte_pci_driver lists?

I'm thinking to something like that:

struct rte_bus {
	TAILQ_ENTRY(rte_bus) next;
	const char *name;
	rte_bus_scan_t scan;
	rte_bus_match_t match;
};
struct rte_pci_bus {
	struct rte_bus bus;
	struct rte_pci_driver_list pci_drivers;
	struct rte_pci_device_list pci_devices;
};

> +/** 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_eal_bus_register(&bus); \
> +}

By removing the lists from rte_bus as suggested above, do you still need
a priority for this constructor?

>  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 */
> @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
>   */
>  struct rte_driver {
>  	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
> +	struct rte_bus *bus;           /**< Bus serviced by this driver */
>  	const char *name;                   /**< Driver name. */
>  	const char *alias;              /**< Driver alias. */
>  };

Do we need to know the bus associated to a driver in rte_driver?
Bus and driver are already associated in rte_device.

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

* Re: [PATCH v5 05/12] eal: add probe and remove support for rte_driver
  2016-12-26 13:23         ` [PATCH v5 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
@ 2017-01-03 22:05           ` Thomas Monjalon
  2017-01-06 11:44             ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 22:05 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:53, Shreyansh Jain:
> --- a/lib/librte_eal/common/include/rte_dev.h
> +++ b/lib/librte_eal/common/include/rte_dev.h
> @@ -152,6 +162,8 @@ struct rte_driver {
>  	struct rte_bus *bus;           /**< Bus serviced by this driver */
>  	const char *name;                   /**< Driver name. */
>  	const char *alias;              /**< Driver alias. */
> +	driver_probe_t *probe;         /**< Probe the device */
> +	driver_remove_t *remove;       /**< Remove/hotplugging the device */
>  };

If I understand well, this probe function does neither scan nor match.
So it could be named init.

I think the probe (init) and remove ops must be specific to the bus.
We can have them in rte_bus, and as an example, the pci implementation
would call the pci probe and remove ops of rte_pci_driver.

Please use rte_ prefix in public headers.

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

* Re: [PATCH v5 07/12] pci: split match and probe function
  2016-12-26 13:24         ` [PATCH v5 07/12] pci: split match and probe function Shreyansh Jain
@ 2017-01-03 22:08           ` Thomas Monjalon
  0 siblings, 0 replies; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 22:08 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:54, Shreyansh Jain:
> --- a/lib/librte_eal/common/include/rte_pci.h
> +++ b/lib/librte_eal/common/include/rte_pci.h
> @@ -373,6 +373,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_eal_pci_match(struct rte_pci_driver *pci_drv,
> +		  struct rte_pci_device *pci_dev);

Yes we definitely need this function.

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

* Re: [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2016-12-26 13:24         ` [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
@ 2017-01-03 22:13           ` Thomas Monjalon
  2017-01-06 12:03             ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 22:13 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:54, Shreyansh Jain:
> PCI scan and match now work on rte_device/rte_driver rather than PCI
> specific objects. These functions can now be plugged to the generic
> bus callbacks for scanning and matching devices/drivers.

These sentences looks weird :)
PCI functions must work with PCI objects, it's simpler.
However I agree to register PCI scan, match, init and remove functions
with the generic rte_bus. Then the rte_device object is casted into
rte_pci_device inside these functions.

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

* Re: [PATCH v5 12/12] eal/bus: add bus iteration macros
  2016-12-26 13:24         ` [PATCH v5 12/12] eal/bus: add bus iteration macros Shreyansh Jain
@ 2017-01-03 22:15           ` Thomas Monjalon
  0 siblings, 0 replies; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 22:15 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:54, Shreyansh Jain:
> Three macros:
>  FOREACH_BUS
>  FOREACH_DEVICE_ON_BUS
>  FOREACH_DRIVER_ON_BUS
> are introduced to make looping over bus (on global list), devices and
> drivers (on a specific bus) prettier.

Nice

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

* Re: [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model
  2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
                           ` (11 preceding siblings ...)
  2016-12-26 13:24         ` [PATCH v5 12/12] eal/bus: add bus iteration macros Shreyansh Jain
@ 2017-01-03 22:22         ` Thomas Monjalon
  2017-01-06  6:27           ` Shreyansh Jain
  12 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-03 22:22 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2016-12-26 18:53, Shreyansh Jain:
> Link to v1: [10]
> Link to v2: [11]
> Link to v3: [13]
> Link to v4: [14]
> 
> :: 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.

It is a very important work to make DPDK growing.

I am sorry to not have done a lot of public comments before today.
I have sent some thoughts about moving some things from generic objects to
specialized ones. I think they are not so much big changes in your work
and I hope we could converge to something in the git tree really soon.

Thanks Shreyansh.

PS: reviews from others are more than welcome!

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

* Re: [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model
  2017-01-03 22:22         ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
@ 2017-01-06  6:27           ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-06  6:27 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Wednesday 04 January 2017 03:52 AM, Thomas Monjalon wrote:
> 2016-12-26 18:53, Shreyansh Jain:
>> Link to v1: [10]
>> Link to v2: [11]
>> Link to v3: [13]
>> Link to v4: [14]
>>
>> :: 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.
>
> It is a very important work to make DPDK growing.
>
> I am sorry to not have done a lot of public comments before today.
> I have sent some thoughts about moving some things from generic objects to
> specialized ones. I think they are not so much big changes in your work
> and I hope we could converge to something in the git tree really soon.

Thanks a lot for spending time on this.
I will reply to all your emails and if possible, with updated code, 
within today (6/Jan)

>
> Thanks Shreyansh.
>
> PS: reviews from others are more than welcome!
>

Yes please. this change impacts framework very widely (even though the 
lines changed is not much). More reviews would really help.

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

* Re: [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2017-01-03 21:52           ` Thomas Monjalon
@ 2017-01-06 10:31             ` Shreyansh Jain
  2017-01-06 14:55               ` Thomas Monjalon
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-06 10:31 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Wednesday 04 January 2017 03:22 AM, Thomas Monjalon wrote:
> 2016-12-26 18:53, Shreyansh Jain:
>> +DPDK_17.02 {
>> +	global:
>> +
>> +	rte_bus_list;
>> +	rte_eal_bus_add_device;
>> +	rte_eal_bus_add_driver;
>> +	rte_eal_bus_get;
>> +	rte_eal_bus_dump;
>> +	rte_eal_bus_register;
>> +	rte_eal_bus_insert_device;
>> +	rte_eal_bus_remove_device;
>> +	rte_eal_bus_remove_driver;
>> +	rte_eal_bus_unregister;
>
> I think the prefix can be just rte_bus_ instead of rte_eal_bus_.

Ok. I will change these.
I thought as these symbols are part of librte_eal/*, naming should 
reflect that.

>
>> +/** Double linked list of buses */
>> +TAILQ_HEAD(rte_bus_list, rte_bus);
>> +
>> +/* Global Bus list */
>> +extern struct rte_bus_list rte_bus_list;
>
> Why the bus list is public?

I will revisit this. When I made it public, intention was that some
element external to EAL (e.g. drivers/bus) might require to iterate
over this list. But, as of now I don't think any such user/case exists
(except test*).

>
>> +/**
>> + * A structure describing a generic bus.
>> + */
>> +struct rte_bus {
>> +	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
>> +	struct rte_driver_list driver_list;
>> +				     /**< List of all drivers on bus */
>> +	struct rte_device_list device_list;
>> +				     /**< List of all devices on bus */
>> +	const char *name;            /**< Name of the bus */
>> +};
>
> I am not convinced we should link a generic bus to drivers and devices.
> What do you think of having rte_pci_bus being a rte_bus and linking
> with rte_pci_device and rte_pci_driver lists?

This is different from what I had in mind.
You are saying:

  Class: rte_bus
       `-> No object instantiated for this class
  Class: rte_pci_bus inheriting rte_bus
       `-> object instantiated for this class.

Here, rte_bus is being treated as an abstract class which is only 
inherited and rte_pci_bus is the base class which is instantiated.

And I was thinking:

  Class: rte_bus
       `-> Object: pci_bus (defined in */eal/eal_pci.c)

Here, rte_bus is that base class which is instantiated.

I agree that what you are suggesting is inline with current model:
  rte_device -> abstract class (no one instantiates it)
   `-> rte_pci_device -> Base class which inherits rte_device and
                         is instantiated.

When I choose not to create rte_pci_bus, it was because I didn't want 
another indirection in form of rte_bus->rte_pci_bus->object.
There were no 'non-generic' bus functions which were only applicable for 
rte_pci_bus. Eventually, rte_pci_bus ended up being a direct inheritance 
of rte_bus.

>
> I'm thinking to something like that:
>
> struct rte_bus {
> 	TAILQ_ENTRY(rte_bus) next;
> 	const char *name;
> 	rte_bus_scan_t scan;
> 	rte_bus_match_t match;
> };
> struct rte_pci_bus {
> 	struct rte_bus bus;
> 	struct rte_pci_driver_list pci_drivers;
> 	struct rte_pci_device_list pci_devices;
> };

if we go by rte_bus->rte_pci_bus->(instance of rte_pci_bus), above is 
fine. Though, I am in favor of rte_bus->(instance of rte_bus for PCI) 
because I don't see any 'non-generic' information in rte_pci_bus which 
can't be put in rte_bus.

>
>> +/** 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_eal_bus_register(&bus); \
>> +}
>
> By removing the lists from rte_bus as suggested above, do you still need
> a priority for this constructor?

I think yes.
Even if we have rte_pci_bus as a class, object of rte_bus should be part 
of Bus list *before* registration of a driver (because, driver 
registration searches for bus by name).

(This is assuming that no global PCI/VDEV/XXX bus object is created 
which is directly used within all PCI specific bus operations).

There was another suggestion on list which was to check for existence of 
bus _within_ each driver registration and create/instantiate an object 
in case no bus is registered. I didn't like the approach so I didn't use 
it. From David [1], and me [2]

[1] http://dpdk.org/ml/archives/dev/2016-December/051689.html
[2] http://dpdk.org/ml/archives/dev/2016-December/051698.html


>
>>  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 */
>> @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
>>   */
>>  struct rte_driver {
>>  	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
>> +	struct rte_bus *bus;           /**< Bus serviced by this driver */
>>  	const char *name;                   /**< Driver name. */
>>  	const char *alias;              /**< Driver alias. */
>>  };
>
> Do we need to know the bus associated to a driver in rte_driver?
> Bus and driver are already associated in rte_device.
>
>

Two reasons:
1/ A driver should be associated with a bus so that if required, all bus 
can be directly extracted - even when probing has not been done.
2/ device->driver would only be updated after probe. device->driver->bus 
would not be valid in such cases, if required.

Overall, I don't have objections for rte_bus->rte_pci_bus=>object as 
compared to rte_bus=>PCI-object. But, I would still like to get a final 
confirmation of a more preferred way.

Meanwhile, I will make changes to accommodate this change to save time 
in case rte_pci_bus class is final/preferred method.

-
Shreyansh

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2017-01-03 21:46           ` Thomas Monjalon
@ 2017-01-06 10:38             ` Shreyansh Jain
  2017-01-06 12:00               ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-06 10:38 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Wednesday 04 January 2017 03:16 AM, Thomas Monjalon wrote:
> 2016-12-26 18:53, Shreyansh Jain:
>> --- a/lib/librte_eal/linuxapp/eal/eal.c
>> +++ b/lib/librte_eal/linuxapp/eal/eal.c
>> @@ -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_eal_bus_scan())
>> +               rte_panic("Cannot scan the buses for devices\n");
>
> Yes, definitely. Just one scan functions which scan registered bus.
>
>> @@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
>>         if (rte_eal_pci_probe())
>>                 rte_panic("Cannot probe PCI\n");
>>
>> +       if (rte_eal_bus_probe())
>> +               rte_panic("Cannot probe devices\n");
>> +
>>         if (rte_eal_dev_init() < 0)
>>                 rte_panic("Cannot init pmd devices\n");
>
> What is the benefit of initializing (probe) a device outside of the scan?
> Currently, it is done in two steps, so you are keeping the same behaviour.

Yes, only for compatibility to existing model of two-step process.
Ideally, only a single step is enough (init->probe).

During the discussion in [1] also this point was raised - at that time
for VDEV and applicability to PCI.

[1] http://dpdk.org/ml/archives/dev/2016-December/051306.html

If you want, I can merge these two. I postponed it because 1) it is an
independent change and should really impact bus and 2) I was not sure
of dependency of init *before* pthread_create for all workers.

>
> I imagine a model where the scan function decide to initialize the
> device and can require some help from a callback to make this decision.
> So the whitelist/blacklist policy can be implemented with callbacks at
> the scan level and possibly the responsibility of the application.
> Note that the callback model would be a change for a next release.
>

Agree. But, that is not really part of Bus patches - isn't it? Or, you
want to change that with this series?

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

* Re: [PATCH v5 05/12] eal: add probe and remove support for rte_driver
  2017-01-03 22:05           ` Thomas Monjalon
@ 2017-01-06 11:44             ` Shreyansh Jain
  2017-01-06 15:26               ` Thomas Monjalon
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-06 11:44 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Wednesday 04 January 2017 03:35 AM, Thomas Monjalon wrote:
> 2016-12-26 18:53, Shreyansh Jain:
>> --- a/lib/librte_eal/common/include/rte_dev.h
>> +++ b/lib/librte_eal/common/include/rte_dev.h
>> @@ -152,6 +162,8 @@ struct rte_driver {
>>  	struct rte_bus *bus;           /**< Bus serviced by this driver */
>>  	const char *name;                   /**< Driver name. */
>>  	const char *alias;              /**< Driver alias. */
>> +	driver_probe_t *probe;         /**< Probe the device */
>> +	driver_remove_t *remove;       /**< Remove/hotplugging the device */
>>  };
>
> If I understand well, this probe function does neither scan nor match.
> So it could be named init.

Current model is:

After scanning for devices and populating bus->device_list,
Bus probe does:
  `-> bus->match()
  `-> rte_driver->probe() for matched driver

For PCI drivers, '.probe = rte_eal_pci_probe'.

For example, igb_ethdev.c:

--->8---
static struct eth_driver rte_igb_pmd = {
         .pci_drv = {
                 .driver = {
                         .probe = rte_eal_pci_probe,
                         .remove = rte_eal_pci_remove,
                 },
...
--->8---

>
> I think the probe (init) and remove ops must be specific to the bus.
> We can have them in rte_bus, and as an example, the pci implementation
> would call the pci probe and remove ops of rte_pci_driver.

So,
---
After scanning for devices (bus->scan()):
Bus probe (rte_eal_bus_probe()):
  `-> bus->match()
  `-> bus->init() - a new fn rte_bus_pci_init()
      -> which calls rte_eal_pci_probe()
      -> and rte_pci_driver->probe()

and remove rte_driver probe and remove callbacks because they are now
redundant. (they were added in bus patches itself)
---

Is the above correct understanding of your statement?

Somehow I don't remember why I didn't do this in first place - it seems
to be better option than introducing a rte_driver->probe()/remove()
layer. I will change it (and think again why I rejected this idea in
first place). Thanks.

>
> Please use rte_ prefix in public headers.
>

I am assuming you are referring to driver_probe_t/driver_remove_t.

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2017-01-06 10:38             ` Shreyansh Jain
@ 2017-01-06 12:00               ` Shreyansh Jain
  2017-01-06 13:46                 ` Thomas Monjalon
  0 siblings, 1 reply; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-06 12:00 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Friday 06 January 2017 04:08 PM, Shreyansh Jain wrote:
> On Wednesday 04 January 2017 03:16 AM, Thomas Monjalon wrote:
>> 2016-12-26 18:53, Shreyansh Jain:
>>> --- a/lib/librte_eal/linuxapp/eal/eal.c
>>> +++ b/lib/librte_eal/linuxapp/eal/eal.c
>>> @@ -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_eal_bus_scan())
>>> +               rte_panic("Cannot scan the buses for devices\n");
>>
>> Yes, definitely. Just one scan functions which scan registered bus.
>>
>>> @@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
>>>         if (rte_eal_pci_probe())
>>>                 rte_panic("Cannot probe PCI\n");
>>>
>>> +       if (rte_eal_bus_probe())
>>> +               rte_panic("Cannot probe devices\n");
>>> +
>>>         if (rte_eal_dev_init() < 0)
>>>                 rte_panic("Cannot init pmd devices\n");
>>
>> What is the benefit of initializing (probe) a device outside of the scan?
>> Currently, it is done in two steps, so you are keeping the same
>> behaviour.
>
> Yes, only for compatibility to existing model of two-step process.
> Ideally, only a single step is enough (init->probe).
>
> During the discussion in [1] also this point was raised - at that time
> for VDEV and applicability to PCI.
>
> [1] http://dpdk.org/ml/archives/dev/2016-December/051306.html
>
> If you want, I can merge these two. I postponed it because 1) it is an
> independent change and should really impact bus and 2) I was not sure
> of dependency of init *before* pthread_create for all workers.

I forgot _not_ in above - rephrasing:

If you want, I can merge these two. I postponed it because 1) it is an
independent change and should _not_ really impact bus and 2) I was not 
sure of dependency of init *before* pthread_create for all workers.

>
>>
>> I imagine a model where the scan function decide to initialize the
>> device and can require some help from a callback to make this decision.
>> So the whitelist/blacklist policy can be implemented with callbacks at
>> the scan level and possibly the responsibility of the application.
>> Note that the callback model would be a change for a next release.
>>
>
> Agree. But, that is not really part of Bus patches - isn't it? Or, you
> want to change that with this series?
>
>
>

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

* Re: [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver
  2017-01-03 22:13           ` Thomas Monjalon
@ 2017-01-06 12:03             ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-06 12:03 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Wednesday 04 January 2017 03:43 AM, Thomas Monjalon wrote:
> 2016-12-26 18:54, Shreyansh Jain:
>> PCI scan and match now work on rte_device/rte_driver rather than PCI
>> specific objects. These functions can now be plugged to the generic
>> bus callbacks for scanning and matching devices/drivers.
>
> These sentences looks weird :)
> PCI functions must work with PCI objects, it's simpler.
> However I agree to register PCI scan, match, init and remove functions
> with the generic rte_bus. Then the rte_device object is casted into
> rte_pci_device inside these functions.
>

Ok. I will rephrase.

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2017-01-06 12:00               ` Shreyansh Jain
@ 2017-01-06 13:46                 ` Thomas Monjalon
  2017-01-09  6:35                   ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-06 13:46 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2017-01-06 17:30, Shreyansh Jain:
> On Friday 06 January 2017 04:08 PM, Shreyansh Jain wrote:
> > On Wednesday 04 January 2017 03:16 AM, Thomas Monjalon wrote:
> >> 2016-12-26 18:53, Shreyansh Jain:
> >>> --- a/lib/librte_eal/linuxapp/eal/eal.c
> >>> +++ b/lib/librte_eal/linuxapp/eal/eal.c
> >>> @@ -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_eal_bus_scan())
> >>> +               rte_panic("Cannot scan the buses for devices\n");
> >>
> >> Yes, definitely. Just one scan functions which scan registered bus.
> >>
> >>> @@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
> >>>         if (rte_eal_pci_probe())
> >>>                 rte_panic("Cannot probe PCI\n");
> >>>
> >>> +       if (rte_eal_bus_probe())
> >>> +               rte_panic("Cannot probe devices\n");
> >>> +
> >>>         if (rte_eal_dev_init() < 0)
> >>>                 rte_panic("Cannot init pmd devices\n");
> >>
> >> What is the benefit of initializing (probe) a device outside of the scan?
> >> Currently, it is done in two steps, so you are keeping the same
> >> behaviour.
> >
> > Yes, only for compatibility to existing model of two-step process.
> > Ideally, only a single step is enough (init->probe).
> >
> > During the discussion in [1] also this point was raised - at that time
> > for VDEV and applicability to PCI.
> >
> > [1] http://dpdk.org/ml/archives/dev/2016-December/051306.html
> >
> > If you want, I can merge these two. I postponed it because 1) it is an
> > independent change and should really impact bus and 2) I was not sure
> > of dependency of init *before* pthread_create for all workers.
> 
> I forgot _not_ in above - rephrasing:
> 
> If you want, I can merge these two. I postponed it because 1) it is an
> independent change and should _not_ really impact bus and 2) I was not 
> sure of dependency of init *before* pthread_create for all workers.

I'm OK with your approach.

> >> I imagine a model where the scan function decide to initialize the
> >> device and can require some help from a callback to make this decision.
> >> So the whitelist/blacklist policy can be implemented with callbacks at
> >> the scan level and possibly the responsibility of the application.
> >> Note that the callback model would be a change for a next release.
> >
> > Agree. But, that is not really part of Bus patches - isn't it? Or, you
> > want to change that with this series?

No it is not the scope of this series.
Please could you add it in the cover letter as a next step?
Thanks

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

* Re: [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2017-01-06 10:31             ` Shreyansh Jain
@ 2017-01-06 14:55               ` Thomas Monjalon
  2017-01-09  6:24                 ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-06 14:55 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2017-01-06 16:01, Shreyansh Jain:
> On Wednesday 04 January 2017 03:22 AM, Thomas Monjalon wrote:
> > 2016-12-26 18:53, Shreyansh Jain:
> >> +/**
> >> + * A structure describing a generic bus.
> >> + */
> >> +struct rte_bus {
> >> +	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
> >> +	struct rte_driver_list driver_list;
> >> +				     /**< List of all drivers on bus */
> >> +	struct rte_device_list device_list;
> >> +				     /**< List of all devices on bus */
> >> +	const char *name;            /**< Name of the bus */
> >> +};
> >
> > I am not convinced we should link a generic bus to drivers and devices.
> > What do you think of having rte_pci_bus being a rte_bus and linking
> > with rte_pci_device and rte_pci_driver lists?
> 
> This is different from what I had in mind.
> You are saying:
> 
>   Class: rte_bus
>        `-> No object instantiated for this class
>   Class: rte_pci_bus inheriting rte_bus
>        `-> object instantiated for this class.
> 
> Here, rte_bus is being treated as an abstract class which is only 
> inherited and rte_pci_bus is the base class which is instantiated.
> 
> And I was thinking:
> 
>   Class: rte_bus
>        `-> Object: pci_bus (defined in */eal/eal_pci.c)
> 
> Here, rte_bus is that base class which is instantiated.
> 
> I agree that what you are suggesting is inline with current model:
>   rte_device -> abstract class (no one instantiates it)
>    `-> rte_pci_device -> Base class which inherits rte_device and
>                          is instantiated.

Yes

> When I choose not to create rte_pci_bus, it was because I didn't want 
> another indirection in form of rte_bus->rte_pci_bus->object.
> There were no 'non-generic' bus functions which were only applicable for 
> rte_pci_bus. Eventually, rte_pci_bus ended up being a direct inheritance 
> of rte_bus.
> 
> > I'm thinking to something like that:
> >
> > struct rte_bus {
> > 	TAILQ_ENTRY(rte_bus) next;
> > 	const char *name;
> > 	rte_bus_scan_t scan;
> > 	rte_bus_match_t match;
> > };
> > struct rte_pci_bus {
> > 	struct rte_bus bus;
> > 	struct rte_pci_driver_list pci_drivers;
> > 	struct rte_pci_device_list pci_devices;
> > };
> 
> if we go by rte_bus->rte_pci_bus->(instance of rte_pci_bus), above is 
> fine. Though, I am in favor of rte_bus->(instance of rte_bus for PCI) 
> because I don't see any 'non-generic' information in rte_pci_bus which 
> can't be put in rte_bus.

The lists of drivers and devices are specific to the bus.
Your proposal was to list them as generic rte_driver/rte_device and
cast them. I'm just saying we can directly declare them with the right type,
e.g. rte_pci_driver/rte_pci_device.

In the same logic, the functions probe/remove are specifics for the bus and
should be declared in rte_pci_driver instead of the generic rte_driver.


> >> +/** 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_eal_bus_register(&bus); \
> >> +}
> >
> > By removing the lists from rte_bus as suggested above, do you still need
> > a priority for this constructor?
> 
> I think yes.
> Even if we have rte_pci_bus as a class, object of rte_bus should be part 
> of Bus list *before* registration of a driver (because, driver 
> registration searches for bus by name).
> 
> (This is assuming that no global PCI/VDEV/XXX bus object is created 
> which is directly used within all PCI specific bus operations).
> 
> There was another suggestion on list which was to check for existence of 
> bus _within_ each driver registration and create/instantiate an object 
> in case no bus is registered. I didn't like the approach so I didn't use 
> it. From David [1], and me [2]
> 
> [1] http://dpdk.org/ml/archives/dev/2016-December/051689.html
> [2] http://dpdk.org/ml/archives/dev/2016-December/051698.html

OK, we can keep your approach of prioritize bus registrations.
If we see an issue later, we could switch to a bus registration done
when a first driver is registered on the bus.


> >>  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 */
> >> @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
> >>   */
> >>  struct rte_driver {
> >>  	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
> >> +	struct rte_bus *bus;           /**< Bus serviced by this driver */
> >>  	const char *name;                   /**< Driver name. */
> >>  	const char *alias;              /**< Driver alias. */
> >>  };
> >
> > Do we need to know the bus associated to a driver in rte_driver?
> > Bus and driver are already associated in rte_device.
> 
> Two reasons:
> 1/ A driver should be associated with a bus so that if required, all bus 
> can be directly extracted - even when probing has not been done.

I do not understand this need.

> 2/ device->driver would only be updated after probe. device->driver->bus 
> would not be valid in such cases, if required.

We can update device->driver on match.

Please let's do not over-engineer if not needed.
In this case, I think we can skip rte_driver->bus.


> Overall, I don't have objections for rte_bus->rte_pci_bus=>object as 
> compared to rte_bus=>PCI-object. But, I would still like to get a final 
> confirmation of a more preferred way.
> 
> Meanwhile, I will make changes to accommodate this change to save time 
> in case rte_pci_bus class is final/preferred method.

It looks more natural to me to avoid class casting and use specialized classes
when possible. So yes I prefer instantiating rte_pci_bus.
However, I could be wrong, and will consider any argument.

Thanks

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

* Re: [PATCH v5 05/12] eal: add probe and remove support for rte_driver
  2017-01-06 11:44             ` Shreyansh Jain
@ 2017-01-06 15:26               ` Thomas Monjalon
  2017-01-09  6:28                 ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Thomas Monjalon @ 2017-01-06 15:26 UTC (permalink / raw)
  To: Shreyansh Jain; +Cc: david.marchand, dev

2017-01-06 17:14, Shreyansh Jain:
> On Wednesday 04 January 2017 03:35 AM, Thomas Monjalon wrote:
> > 2016-12-26 18:53, Shreyansh Jain:
> >> --- a/lib/librte_eal/common/include/rte_dev.h
> >> +++ b/lib/librte_eal/common/include/rte_dev.h
> >> @@ -152,6 +162,8 @@ struct rte_driver {
> >>  	struct rte_bus *bus;           /**< Bus serviced by this driver */
> >>  	const char *name;                   /**< Driver name. */
> >>  	const char *alias;              /**< Driver alias. */
> >> +	driver_probe_t *probe;         /**< Probe the device */
> >> +	driver_remove_t *remove;       /**< Remove/hotplugging the device */
> >>  };
> >
> > If I understand well, this probe function does neither scan nor match.
> > So it could be named init.
> 
> Current model is:
> 
> After scanning for devices and populating bus->device_list,
> Bus probe does:
>   `-> bus->match()
>   `-> rte_driver->probe() for matched driver
> 
> For PCI drivers, '.probe = rte_eal_pci_probe'.
> 
> For example, igb_ethdev.c:
> 
> --->8---
> static struct eth_driver rte_igb_pmd = {
>          .pci_drv = {
>                  .driver = {
>                          .probe = rte_eal_pci_probe,
>                          .remove = rte_eal_pci_remove,
>                  },
> ...
> --->8---

Yes
I'm just having some doubts about the naming "probe" compared to "init".
And yes I know I was advocating to unify naming to "probe" recently :)
I would like to be sure it is not confusing for anyone.
Do you agree that "init" refers to global driver initialization and
"probe" refers to instantiating a device?

If yes, the comment could be changed from "Probe the device" to
"Check and instantiate a device".

> > I think the probe (init) and remove ops must be specific to the bus.
> > We can have them in rte_bus, and as an example, the pci implementation
> > would call the pci probe and remove ops of rte_pci_driver.

I do not understand clearly what I was saying here :/

> So,
> ---
> After scanning for devices (bus->scan()):
> Bus probe (rte_eal_bus_probe()):
>   `-> bus->match()
>   `-> bus->init() - a new fn rte_bus_pci_init()

I suggest the naming bus->probe().
It is currently implemented in rte_eal_pci_probe_one_driver().

>       -> which calls rte_eal_pci_probe()

Not needed here, this function is converted into the PCI match function.

>       -> and rte_pci_driver->probe()

Yes, bus->probe() makes some processing and calls rte_pci_driver->probe().


> and remove rte_driver probe and remove callbacks because they are now
> redundant. (they were added in bus patches itself)
> ---
> 
> Is the above correct understanding of your statement?

I think we just need to move probe/remove in rte_pci_driver.

> Somehow I don't remember why I didn't do this in first place - it seems
> to be better option than introducing a rte_driver->probe()/remove()
> layer. I will change it (and think again why I rejected this idea in
> first place). Thanks.

Thanks

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2016-12-26 13:23         ` [PATCH v5 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
  2017-01-03 21:46           ` Thomas Monjalon
@ 2017-01-08 12:21           ` Rosen, Rami
  2017-01-09  6:34             ` Shreyansh Jain
  1 sibling, 1 reply; 132+ messages in thread
From: Rosen, Rami @ 2017-01-08 12:21 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

Hi,
...
...

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c index 2206277..2c223de 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
...

+/* Scan all the buses for registering devices */ int
+rte_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+

Nitpick - the return type of rte_eal_bus_scan() is int and not void:

* Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);


Rami Rosen

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

* Re: [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2017-01-06 14:55               ` Thomas Monjalon
@ 2017-01-09  6:24                 ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-09  6:24 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Friday 06 January 2017 08:25 PM, Thomas Monjalon wrote:
> 2017-01-06 16:01, Shreyansh Jain:
>> On Wednesday 04 January 2017 03:22 AM, Thomas Monjalon wrote:
>>> 2016-12-26 18:53, Shreyansh Jain:
>>>> +/**
>>>> + * A structure describing a generic bus.
>>>> + */
>>>> +struct rte_bus {
>>>> +	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
>>>> +	struct rte_driver_list driver_list;
>>>> +				     /**< List of all drivers on bus */
>>>> +	struct rte_device_list device_list;
>>>> +				     /**< List of all devices on bus */
>>>> +	const char *name;            /**< Name of the bus */
>>>> +};
>>>
>>> I am not convinced we should link a generic bus to drivers and devices.
>>> What do you think of having rte_pci_bus being a rte_bus and linking
>>> with rte_pci_device and rte_pci_driver lists?
>>
>> This is different from what I had in mind.
>> You are saying:
>>
>>   Class: rte_bus
>>        `-> No object instantiated for this class
>>   Class: rte_pci_bus inheriting rte_bus
>>        `-> object instantiated for this class.
>>
>> Here, rte_bus is being treated as an abstract class which is only
>> inherited and rte_pci_bus is the base class which is instantiated.
>>
>> And I was thinking:
>>
>>   Class: rte_bus
>>        `-> Object: pci_bus (defined in */eal/eal_pci.c)
>>
>> Here, rte_bus is that base class which is instantiated.
>>
>> I agree that what you are suggesting is inline with current model:
>>   rte_device -> abstract class (no one instantiates it)
>>    `-> rte_pci_device -> Base class which inherits rte_device and
>>                          is instantiated.
>
> Yes
>
>> When I choose not to create rte_pci_bus, it was because I didn't want
>> another indirection in form of rte_bus->rte_pci_bus->object.
>> There were no 'non-generic' bus functions which were only applicable for
>> rte_pci_bus. Eventually, rte_pci_bus ended up being a direct inheritance
>> of rte_bus.
>>
>>> I'm thinking to something like that:
>>>
>>> struct rte_bus {
>>> 	TAILQ_ENTRY(rte_bus) next;
>>> 	const char *name;
>>> 	rte_bus_scan_t scan;
>>> 	rte_bus_match_t match;
>>> };
>>> struct rte_pci_bus {
>>> 	struct rte_bus bus;
>>> 	struct rte_pci_driver_list pci_drivers;
>>> 	struct rte_pci_device_list pci_devices;
>>> };
>>
>> if we go by rte_bus->rte_pci_bus->(instance of rte_pci_bus), above is
>> fine. Though, I am in favor of rte_bus->(instance of rte_bus for PCI)
>> because I don't see any 'non-generic' information in rte_pci_bus which
>> can't be put in rte_bus.
>
> The lists of drivers and devices are specific to the bus.
> Your proposal was to list them as generic rte_driver/rte_device and
> cast them. I'm just saying we can directly declare them with the right type,
> e.g. rte_pci_driver/rte_pci_device.

Ok. I get your point. Already changing the code to reflect this.

>
> In the same logic, the functions probe/remove are specifics for the bus and
> should be declared in rte_pci_driver instead of the generic rte_driver.

Yes, I agree with this after above argument.

>
>
>>>> +/** 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_eal_bus_register(&bus); \
>>>> +}
>>>
>>> By removing the lists from rte_bus as suggested above, do you still need
>>> a priority for this constructor?
>>
>> I think yes.
>> Even if we have rte_pci_bus as a class, object of rte_bus should be part
>> of Bus list *before* registration of a driver (because, driver
>> registration searches for bus by name).
>>
>> (This is assuming that no global PCI/VDEV/XXX bus object is created
>> which is directly used within all PCI specific bus operations).
>>
>> There was another suggestion on list which was to check for existence of
>> bus _within_ each driver registration and create/instantiate an object
>> in case no bus is registered. I didn't like the approach so I didn't use
>> it. From David [1], and me [2]
>>
>> [1] http://dpdk.org/ml/archives/dev/2016-December/051689.html
>> [2] http://dpdk.org/ml/archives/dev/2016-December/051698.html
>
> OK, we can keep your approach of prioritize bus registrations.
> If we see an issue later, we could switch to a bus registration done
> when a first driver is registered on the bus.

Thanks for confirmation.

>
>
>>>>  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 */
>>>> @@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
>>>>   */
>>>>  struct rte_driver {
>>>>  	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
>>>> +	struct rte_bus *bus;           /**< Bus serviced by this driver */
>>>>  	const char *name;                   /**< Driver name. */
>>>>  	const char *alias;              /**< Driver alias. */
>>>>  };
>>>
>>> Do we need to know the bus associated to a driver in rte_driver?
>>> Bus and driver are already associated in rte_device.
>>
>> Two reasons:
>> 1/ A driver should be associated with a bus so that if required, all bus
>> can be directly extracted - even when probing has not been done.
>
> I do not understand this need.

For example, Looping over all drivers for plugging them out. We need to 
know which bus a driver is on so that we can unplug the devices 
associated with the driver on that bus.

>
>> 2/ device->driver would only be updated after probe. device->driver->bus
>> would not be valid in such cases, if required.
>
> We can update device->driver on match.

Yes, we can.

>
> Please let's do not over-engineer if not needed.
> In this case, I think we can skip rte_driver->bus.

Hm, Ok. This was more of prospective step. We can avoid it without much 
impact. I will change the code.

>
>
>> Overall, I don't have objections for rte_bus->rte_pci_bus=>object as
>> compared to rte_bus=>PCI-object. But, I would still like to get a final
>> confirmation of a more preferred way.
>>
>> Meanwhile, I will make changes to accommodate this change to save time
>> in case rte_pci_bus class is final/preferred method.
>
> It looks more natural to me to avoid class casting and use specialized classes
> when possible. So yes I prefer instantiating rte_pci_bus.
> However, I could be wrong, and will consider any argument.

Ok. I will go with your argument - mostly because I am OK either way and 
we can always come back if framework changes are stable.

>
> Thanks
>

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

* Re: [PATCH v5 05/12] eal: add probe and remove support for rte_driver
  2017-01-06 15:26               ` Thomas Monjalon
@ 2017-01-09  6:28                 ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-09  6:28 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Friday 06 January 2017 08:56 PM, Thomas Monjalon wrote:
> 2017-01-06 17:14, Shreyansh Jain:
>> On Wednesday 04 January 2017 03:35 AM, Thomas Monjalon wrote:
>>> 2016-12-26 18:53, Shreyansh Jain:
>>>> --- a/lib/librte_eal/common/include/rte_dev.h
>>>> +++ b/lib/librte_eal/common/include/rte_dev.h
>>>> @@ -152,6 +162,8 @@ struct rte_driver {
>>>>  	struct rte_bus *bus;           /**< Bus serviced by this driver */
>>>>  	const char *name;                   /**< Driver name. */
>>>>  	const char *alias;              /**< Driver alias. */
>>>> +	driver_probe_t *probe;         /**< Probe the device */
>>>> +	driver_remove_t *remove;       /**< Remove/hotplugging the device */
>>>>  };
>>>
>>> If I understand well, this probe function does neither scan nor match.
>>> So it could be named init.
>>
>> Current model is:
>>
>> After scanning for devices and populating bus->device_list,
>> Bus probe does:
>>   `-> bus->match()
>>   `-> rte_driver->probe() for matched driver
>>
>> For PCI drivers, '.probe = rte_eal_pci_probe'.
>>
>> For example, igb_ethdev.c:
>>
>> --->8---
>> static struct eth_driver rte_igb_pmd = {
>>          .pci_drv = {
>>                  .driver = {
>>                          .probe = rte_eal_pci_probe,
>>                          .remove = rte_eal_pci_remove,
>>                  },
>> ...
>> --->8---
>
> Yes
> I'm just having some doubts about the naming "probe" compared to "init".
> And yes I know I was advocating to unify naming to "probe" recently :)
> I would like to be sure it is not confusing for anyone.
> Do you agree that "init" refers to global driver initialization and
> "probe" refers to instantiating a device?

Ok. Makes sense as a standardized way of differentiating 'init' from 
'probe'.

>
> If yes, the comment could be changed from "Probe the device" to
> "Check and instantiate a device".

Now that probe if removed from rte_driver, I think this would no longer 
be valid. [1]

[1] http://dpdk.org/ml/archives/dev/2017-January/054140.html

>
>>> I think the probe (init) and remove ops must be specific to the bus.
>>> We can have them in rte_bus, and as an example, the pci implementation
>>> would call the pci probe and remove ops of rte_pci_driver.
>
> I do not understand clearly what I was saying here :/

:)

>
>> So,
>> ---
>> After scanning for devices (bus->scan()):
>> Bus probe (rte_eal_bus_probe()):
>>   `-> bus->match()
>>   `-> bus->init() - a new fn rte_bus_pci_init()
>
> I suggest the naming bus->probe().
> It is currently implemented in rte_eal_pci_probe_one_driver().
>
>>       -> which calls rte_eal_pci_probe()
>
> Not needed here, this function is converted into the PCI match function.
>
>>       -> and rte_pci_driver->probe()
>
> Yes, bus->probe() makes some processing and calls rte_pci_driver->probe().

I have made some changes on similar lines. Will share them soon. Then we 
can discuss again.

>
>
>> and remove rte_driver probe and remove callbacks because they are now
>> redundant. (they were added in bus patches itself)
>> ---
>>
>> Is the above correct understanding of your statement?
>
> I think we just need to move probe/remove in rte_pci_driver.
>
>> Somehow I don't remember why I didn't do this in first place - it seems
>> to be better option than introducing a rte_driver->probe()/remove()
>> layer. I will change it (and think again why I rejected this idea in
>> first place). Thanks.
>
> Thanks
>

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2017-01-08 12:21           ` Rosen, Rami
@ 2017-01-09  6:34             ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-09  6:34 UTC (permalink / raw)
  To: Rosen, Rami, david.marchand; +Cc: dev, thomas.monjalon

Hello,

On Sunday 08 January 2017 05:51 PM, Rosen, Rami wrote:
> Hi,
> ....
> ....
>
> diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c index 2206277..2c223de 100644
> --- a/lib/librte_eal/bsdapp/eal/eal.c
> +++ b/lib/librte_eal/bsdapp/eal/eal.c
> ....
>
> +/* Scan all the buses for registering devices */ int
> +rte_eal_bus_scan(void)
> +{
> +	int ret;
> +	struct rte_bus *bus = NULL;
> +
> +	TAILQ_FOREACH(bus, &rte_bus_list, next) {
> +		ret = bus->scan(bus);
> +		if (ret) {
> +			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
> +				bus->name);
> +			/* TODO: Should error on a particular bus block scan
> +			 * for all others?
> +			 */
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>
> Nitpick - the return type of rte_eal_bus_scan() is int and not void:

Thanks for review. I will fix this before sending v6.

>
> * Scan all the buses attached to the framework.
> + *
> + * @param void
> + * @return void
> + */
> +int rte_eal_bus_scan(void);
>
>
> Rami Rosen
>

-
Shreyansh

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

* Re: [PATCH v5 04/12] eal: integrate bus scan and probe with EAL
  2017-01-06 13:46                 ` Thomas Monjalon
@ 2017-01-09  6:35                   ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-09  6:35 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: david.marchand, dev

On Friday 06 January 2017 07:16 PM, Thomas Monjalon wrote:
> 2017-01-06 17:30, Shreyansh Jain:
>> On Friday 06 January 2017 04:08 PM, Shreyansh Jain wrote:
>>> On Wednesday 04 January 2017 03:16 AM, Thomas Monjalon wrote:
>>>> 2016-12-26 18:53, Shreyansh Jain:
>>>>> --- a/lib/librte_eal/linuxapp/eal/eal.c
>>>>> +++ b/lib/librte_eal/linuxapp/eal/eal.c
>>>>> @@ -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_eal_bus_scan())
>>>>> +               rte_panic("Cannot scan the buses for devices\n");
>>>>
>>>> Yes, definitely. Just one scan functions which scan registered bus.
>>>>
>>>>> @@ -884,6 +888,9 @@ rte_eal_init(int argc, char **argv)
>>>>>         if (rte_eal_pci_probe())
>>>>>                 rte_panic("Cannot probe PCI\n");
>>>>>
>>>>> +       if (rte_eal_bus_probe())
>>>>> +               rte_panic("Cannot probe devices\n");
>>>>> +
>>>>>         if (rte_eal_dev_init() < 0)
>>>>>                 rte_panic("Cannot init pmd devices\n");
>>>>
>>>> What is the benefit of initializing (probe) a device outside of the scan?
>>>> Currently, it is done in two steps, so you are keeping the same
>>>> behaviour.
>>>
>>> Yes, only for compatibility to existing model of two-step process.
>>> Ideally, only a single step is enough (init->probe).
>>>
>>> During the discussion in [1] also this point was raised - at that time
>>> for VDEV and applicability to PCI.
>>>
>>> [1] http://dpdk.org/ml/archives/dev/2016-December/051306.html
>>>
>>> If you want, I can merge these two. I postponed it because 1) it is an
>>> independent change and should really impact bus and 2) I was not sure
>>> of dependency of init *before* pthread_create for all workers.
>>
>> I forgot _not_ in above - rephrasing:
>>
>> If you want, I can merge these two. I postponed it because 1) it is an
>> independent change and should _not_ really impact bus and 2) I was not
>> sure of dependency of init *before* pthread_create for all workers.
>
> I'm OK with your approach.
>
>>>> I imagine a model where the scan function decide to initialize the
>>>> device and can require some help from a callback to make this decision.
>>>> So the whitelist/blacklist policy can be implemented with callbacks at
>>>> the scan level and possibly the responsibility of the application.
>>>> Note that the callback model would be a change for a next release.
>>>
>>> Agree. But, that is not really part of Bus patches - isn't it? Or, you
>>> want to change that with this series?
>
> No it is not the scope of this series.
> Please could you add it in the cover letter as a next step?

Yes, I will add to cover letter as Pending Item.

> Thanks
>

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

* Re: [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove
  2016-12-26 13:24         ` [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
@ 2017-01-09 15:19           ` Ferruh Yigit
  2017-01-09 16:18             ` Ferruh Yigit
  0 siblings, 1 reply; 132+ messages in thread
From: Ferruh Yigit @ 2017-01-09 15:19 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 12/26/2016 1:24 PM, Shreyansh Jain wrote:
> These callbacks now act as first layer of PCI interfaces from the Bus.
> Bus probe would enter the PMDs through the rte_driver->probe/remove
> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
> drivers are rte_pci_driver).
> 
> This patch also changes QAT which is the only crypto PMD based on PCI.
> All others would be changed in a separate patch focused on VDEV.
> 
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> ---
>  drivers/crypto/qat/rte_qat_cryptodev.c  | 4 ++++
>  drivers/net/bnx2x/bnx2x_ethdev.c        | 8 ++++++++
>  drivers/net/bnxt/bnxt_ethdev.c          | 4 ++++
>  drivers/net/cxgbe/cxgbe_ethdev.c        | 4 ++++
>  drivers/net/e1000/em_ethdev.c           | 4 ++++
>  drivers/net/e1000/igb_ethdev.c          | 8 ++++++++
>  drivers/net/ena/ena_ethdev.c            | 4 ++++
>  drivers/net/enic/enic_ethdev.c          | 4 ++++
>  drivers/net/fm10k/fm10k_ethdev.c        | 4 ++++
>  drivers/net/i40e/i40e_ethdev.c          | 4 ++++
>  drivers/net/i40e/i40e_ethdev_vf.c       | 4 ++++
>  drivers/net/ixgbe/ixgbe_ethdev.c        | 8 ++++++++
>  drivers/net/mlx4/mlx4.c                 | 3 ++-
>  drivers/net/mlx5/mlx5.c                 | 3 ++-
>  drivers/net/nfp/nfp_net.c               | 4 ++++
>  drivers/net/qede/qede_ethdev.c          | 8 ++++++++
>  drivers/net/szedata2/rte_eth_szedata2.c | 4 ++++
>  drivers/net/thunderx/nicvf_ethdev.c     | 4 ++++
>  drivers/net/virtio/virtio_ethdev.c      | 2 ++
>  drivers/net/vmxnet3/vmxnet3_ethdev.c    | 4 ++++
>  20 files changed, 90 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
> index 1e7ee61..bc1a9c6 100644
> --- a/drivers/crypto/qat/rte_qat_cryptodev.c
> +++ b/drivers/crypto/qat/rte_qat_cryptodev.c
> @@ -120,6 +120,10 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
>  
>  static struct rte_cryptodev_driver rte_qat_pmd = {
>  	.pci_drv = {
> +		.driver = {
> +			.probe = rte_eal_pci_probe,
> +			.remove = rte_eal_pci_remove,
> +		},

Since this part is common for all PCI drivers, why not make this part of
RTE_PMD_REGISTER_PCI macro?

<...>

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

* Re: [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2016-12-26 13:23         ` [PATCH v5 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
  2017-01-03 21:52           ` Thomas Monjalon
@ 2017-01-09 15:22           ` Ferruh Yigit
  2017-01-10  4:07             ` Shreyansh Jain
  1 sibling, 1 reply; 132+ messages in thread
From: Ferruh Yigit @ 2017-01-09 15:22 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 12/26/2016 1:23 PM, Shreyansh Jain wrote:

<...>

> +
> +DPDK_17.02 {
> +	global:
> +
> +	rte_bus_list;
> +	rte_eal_bus_add_device;
> +	rte_eal_bus_add_driver;
> +	rte_eal_bus_get;
> +	rte_eal_bus_dump;
> +	rte_eal_bus_register;

> +	rte_eal_bus_insert_device;

This function added in patch 3/12, it can be good to add this function
into .map file in that patch.

<...>

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

* Re: [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove
  2017-01-09 15:19           ` Ferruh Yigit
@ 2017-01-09 16:18             ` Ferruh Yigit
  2017-01-10  4:09               ` Shreyansh Jain
  0 siblings, 1 reply; 132+ messages in thread
From: Ferruh Yigit @ 2017-01-09 16:18 UTC (permalink / raw)
  To: Shreyansh Jain, david.marchand; +Cc: dev, thomas.monjalon

On 1/9/2017 3:19 PM, Ferruh Yigit wrote:
> On 12/26/2016 1:24 PM, Shreyansh Jain wrote:
>> These callbacks now act as first layer of PCI interfaces from the Bus.
>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>> drivers are rte_pci_driver).
>>
>> This patch also changes QAT which is the only crypto PMD based on PCI.
>> All others would be changed in a separate patch focused on VDEV.
>>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>> ---
<...>
>>
>> diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
>> index 1e7ee61..bc1a9c6 100644
>> --- a/drivers/crypto/qat/rte_qat_cryptodev.c
>> +++ b/drivers/crypto/qat/rte_qat_cryptodev.c
>> @@ -120,6 +120,10 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
>>  
>>  static struct rte_cryptodev_driver rte_qat_pmd = {
>>  	.pci_drv = {
>> +		.driver = {
>> +			.probe = rte_eal_pci_probe,
>> +			.remove = rte_eal_pci_remove,
>> +		},
> 
> Since this part is common for all PCI drivers, why not make this part of
> RTE_PMD_REGISTER_PCI macro?
> 

I have seen your comment [1] which looks like better idea.

providing a rte_bus->probe(),

and rte_eal_bus_probe() calls rte_bus->probe()

for pci devices, rte_bus->probe = rte_eal_pci_probe ..


[1]
http://dpdk.org/ml/archives/dev/2017-January/054125.html

Thanks,
ferruh

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

* Re: [PATCH v5 01/12] eal/bus: introduce bus abstraction
  2017-01-09 15:22           ` Ferruh Yigit
@ 2017-01-10  4:07             ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-10  4:07 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: david.marchand, dev, thomas.monjalon

Hello Ferruh,

On Monday 09 January 2017 08:52 PM, Ferruh Yigit wrote:
> On 12/26/2016 1:23 PM, Shreyansh Jain wrote:
>
> <...>
>
>> +
>> +DPDK_17.02 {
>> +	global:
>> +
>> +	rte_bus_list;
>> +	rte_eal_bus_add_device;
>> +	rte_eal_bus_add_driver;
>> +	rte_eal_bus_get;
>> +	rte_eal_bus_dump;
>> +	rte_eal_bus_register;
>
>> +	rte_eal_bus_insert_device;
>
> This function added in patch 3/12, it can be good to add this function
> into .map file in that patch.

Yes, I caught this while rebasing for v6. In fact, now this function 
itself has been removed.
Nevertheless, thanks for reviewing.

>
> <...>
>
>

-
Shreyansh

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

* Re: [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove
  2017-01-09 16:18             ` Ferruh Yigit
@ 2017-01-10  4:09               ` Shreyansh Jain
  0 siblings, 0 replies; 132+ messages in thread
From: Shreyansh Jain @ 2017-01-10  4:09 UTC (permalink / raw)
  To: Ferruh Yigit, david.marchand; +Cc: dev, thomas.monjalon

On Monday 09 January 2017 09:48 PM, Ferruh Yigit wrote:
> On 1/9/2017 3:19 PM, Ferruh Yigit wrote:
>> On 12/26/2016 1:24 PM, Shreyansh Jain wrote:
>>> These callbacks now act as first layer of PCI interfaces from the Bus.
>>> Bus probe would enter the PMDs through the rte_driver->probe/remove
>>> callbacks, falling to rte_xxx_driver->probe/remove (Currently, all the
>>> drivers are rte_pci_driver).
>>>
>>> This patch also changes QAT which is the only crypto PMD based on PCI.
>>> All others would be changed in a separate patch focused on VDEV.
>>>
>>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
>>> ---
> <...>
>>>
>>> diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
>>> index 1e7ee61..bc1a9c6 100644
>>> --- a/drivers/crypto/qat/rte_qat_cryptodev.c
>>> +++ b/drivers/crypto/qat/rte_qat_cryptodev.c
>>> @@ -120,6 +120,10 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
>>>
>>>  static struct rte_cryptodev_driver rte_qat_pmd = {
>>>  	.pci_drv = {
>>> +		.driver = {
>>> +			.probe = rte_eal_pci_probe,
>>> +			.remove = rte_eal_pci_remove,
>>> +		},
>>
>> Since this part is common for all PCI drivers, why not make this part of
>> RTE_PMD_REGISTER_PCI macro?
>>
>
> I have seen your comment [1] which looks like better idea.

Thanks.
And, actually, it is mostly Thomas's idea :)

>
> providing a rte_bus->probe(),
>
> and rte_eal_bus_probe() calls rte_bus->probe()
>
> for pci devices, rte_bus->probe = rte_eal_pci_probe ..
>
>
> [1]
> http://dpdk.org/ml/archives/dev/2017-January/054125.html
>
> Thanks,
> ferruh
>

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

end of thread, other threads:[~2017-01-10  4:05 UTC | newest]

Thread overview: 132+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-04 10:11 [PATCH 00/13] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
2016-12-04 10:11 ` [PATCH 01/13] eal: define container_of macro Shreyansh Jain
2016-12-04 10:11 ` [PATCH 02/13] eal/bus: introduce bus abstraction Shreyansh Jain
2016-12-04 10:11 ` [PATCH 03/13] test: add basic bus infrastructure tests Shreyansh Jain
2016-12-04 10:11 ` [PATCH 04/13] eal/bus: add scan and match support Shreyansh Jain
2016-12-04 10:11 ` [PATCH 05/13] eal/bus: add support for inserting a device on a bus Shreyansh Jain
2016-12-04 10:11 ` [PATCH 06/13] eal: integrate bus scan and probe with EAL Shreyansh Jain
2016-12-04 10:11 ` [PATCH 07/13] pci: replace probe and remove handlers with rte_driver Shreyansh Jain
2016-12-08 17:50   ` Ferruh Yigit
2016-12-09  4:59     ` Shreyansh Jain
2016-12-04 10:11 ` [PATCH 08/13] eal: enable probe and remove from bus infrastructure Shreyansh Jain
2016-12-06 10:45   ` Shreyansh Jain
2016-12-04 10:11 ` [PATCH 09/13] pci: split match and probe function Shreyansh Jain
2016-12-04 10:11 ` [PATCH 10/13] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
2016-12-04 10:11 ` [PATCH 11/13] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
2016-12-04 10:11 ` [PATCH 12/13] eal: enable PCI bus Shreyansh Jain
2016-12-04 10:11 ` [PATCH 13/13] eal/pci: remove PCI probe and init calls Shreyansh Jain
2016-12-06 20:52 ` [PATCH 00/13] Introducing EAL Bus-Device-Driver Model David Marchand
2016-12-07  9:55   ` Shreyansh Jain
2016-12-07 12:17     ` David Marchand
2016-12-07 13:10       ` Shreyansh Jain
2016-12-07 13:24         ` Thomas Monjalon
2016-12-08  5:04           ` Shreyansh Jain
2016-12-08  7:21             ` Thomas Monjalon
2016-12-08  7:53               ` Shreyansh Jain
2016-12-12 14:35         ` Jianbo Liu
2016-12-13  6:56           ` Shreyansh Jain
2016-12-13 13:37 ` [PATCH v2 00/12] " Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 01/12] eal: define container_of macro Shreyansh Jain
2016-12-13 22:24     ` Jan Blunck
2016-12-14  5:12       ` Shreyansh Jain
2016-12-16  8:14         ` Jan Blunck
2016-12-16  9:23           ` Adrien Mazarguil
2016-12-16 10:47             ` Jan Blunck
2016-12-16 11:21               ` Adrien Mazarguil
2016-12-16 11:54                 ` Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 03/12] test: add basic bus infrastructure tests Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 05/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 06/12] eal: add probe and remove support for rte_driver Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 07/12] eal: enable probe from bus infrastructure Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 08/12] pci: split match and probe function Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 10/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 11/12] eal: enable PCI bus Shreyansh Jain
2016-12-13 13:37   ` [PATCH v2 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
2016-12-13 13:52     ` Andrew Rybchenko
2016-12-13 15:07       ` Ferruh Yigit
2016-12-14  5:14         ` Shreyansh Jain
2016-12-14  5:11       ` Shreyansh Jain
2016-12-14  9:49     ` Shreyansh Jain
2016-12-15 21:36       ` Jan Blunck
2016-12-26  9:14         ` Shreyansh Jain
2016-12-16 13:10   ` [PATCH v3 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 01/12] eal: define container_of macro Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 02/12] eal/bus: introduce bus abstraction Shreyansh Jain
2016-12-20 12:37       ` Hemant Agrawal
2016-12-20 13:17       ` Jan Blunck
2016-12-20 13:51         ` Shreyansh Jain
2016-12-20 17:11         ` Stephen Hemminger
2016-12-21  7:11           ` Shreyansh Jain
2016-12-21 15:38           ` Jan Blunck
2016-12-21 23:33             ` Stephen Hemminger
2016-12-22  5:12               ` Shreyansh Jain
2016-12-22  5:52                 ` Shreyansh Jain
2016-12-25 17:39         ` Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 03/12] test: add basic bus infrastructure tests Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 04/12] eal/bus: add scan, match and insert support Shreyansh Jain
2016-12-16 13:25       ` Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 05/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 06/12] eal: add probe and remove support for rte_driver Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 07/12] eal: enable probe from bus infrastructure Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 08/12] pci: split match and probe function Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 09/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 10/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 11/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
2016-12-16 13:20       ` Shreyansh Jain
2016-12-16 13:10     ` [PATCH v3 12/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
2016-12-26 12:50     ` [PATCH v4 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 02/12] test: add basic bus infrastructure tests Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
2016-12-26 13:27         ` Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 06/12] eal: enable probe from bus infrastructure Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 07/12] pci: split match and probe function Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 09/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 10/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
2016-12-26 12:50       ` [PATCH v4 12/12] eal/bus: add bus iteration macros Shreyansh Jain
2016-12-26 13:23       ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Shreyansh Jain
2016-12-26 13:23         ` [PATCH v5 01/12] eal/bus: introduce bus abstraction Shreyansh Jain
2017-01-03 21:52           ` Thomas Monjalon
2017-01-06 10:31             ` Shreyansh Jain
2017-01-06 14:55               ` Thomas Monjalon
2017-01-09  6:24                 ` Shreyansh Jain
2017-01-09 15:22           ` Ferruh Yigit
2017-01-10  4:07             ` Shreyansh Jain
2016-12-26 13:23         ` [PATCH v5 02/12] test: add basic bus infrastructure tests Shreyansh Jain
2016-12-26 13:23         ` [PATCH v5 03/12] eal/bus: add scan, match and insert support Shreyansh Jain
2016-12-26 13:23         ` [PATCH v5 04/12] eal: integrate bus scan and probe with EAL Shreyansh Jain
2017-01-03 21:46           ` Thomas Monjalon
2017-01-06 10:38             ` Shreyansh Jain
2017-01-06 12:00               ` Shreyansh Jain
2017-01-06 13:46                 ` Thomas Monjalon
2017-01-09  6:35                   ` Shreyansh Jain
2017-01-08 12:21           ` Rosen, Rami
2017-01-09  6:34             ` Shreyansh Jain
2016-12-26 13:23         ` [PATCH v5 05/12] eal: add probe and remove support for rte_driver Shreyansh Jain
2017-01-03 22:05           ` Thomas Monjalon
2017-01-06 11:44             ` Shreyansh Jain
2017-01-06 15:26               ` Thomas Monjalon
2017-01-09  6:28                 ` Shreyansh Jain
2016-12-26 13:23         ` [PATCH v5 06/12] eal: enable probe from bus infrastructure Shreyansh Jain
2016-12-26 13:24         ` [PATCH v5 07/12] pci: split match and probe function Shreyansh Jain
2017-01-03 22:08           ` Thomas Monjalon
2016-12-26 13:24         ` [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver Shreyansh Jain
2017-01-03 22:13           ` Thomas Monjalon
2017-01-06 12:03             ` Shreyansh Jain
2016-12-26 13:24         ` [PATCH v5 09/12] pci: Pass rte_pci_addr to functions instead of separate args Shreyansh Jain
2016-12-26 13:24         ` [PATCH v5 10/12] eal: enable PCI bus and PCI test framework Shreyansh Jain
2016-12-26 13:24         ` [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove Shreyansh Jain
2017-01-09 15:19           ` Ferruh Yigit
2017-01-09 16:18             ` Ferruh Yigit
2017-01-10  4:09               ` Shreyansh Jain
2016-12-26 13:24         ` [PATCH v5 12/12] eal/bus: add bus iteration macros Shreyansh Jain
2017-01-03 22:15           ` Thomas Monjalon
2017-01-03 22:22         ` [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model Thomas Monjalon
2017-01-06  6:27           ` Shreyansh Jain

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.