Re: [dpdk-dev] [PATCH v2 7/7] pci: Clarify interfaces for dynamic attach/detach of drivers

2016-12-02 Thread Shreyansh Jain

On Thursday 24 November 2016 01:37 AM, Ben Walker wrote:

There are now two functions - rte_eal_pci_attach_driver and
rte_eal_pci_detach_driver - that dynamically attempt to attach
and detach drivers from PCI devices. These only control
whether a registered PCI driver is loaded or not - they are
independent of whether the PCI device exists on the system.

Signed-off-by: Ben Walker 
---
 lib/librte_eal/common/eal_common_dev.c  |   4 +-
 lib/librte_eal/common/eal_common_pci.c  | 109 +---
 lib/librte_eal/common/include/rte_pci.h |  22 ---
 3 files changed, 43 insertions(+), 92 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..1c6834e 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -114,7 +114,7 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)
}

if (eal_parse_pci_DomBDF(name, &addr) == 0) {


IMO, ideally all the PCI specific code should be within eal_common_pci. 
For example, the above function (eal_common_pci_DomBDF) shouldn't be 
part of the generic fn rte_eal_dev_attach. Somehow this should be 
hidden/closed with PCI specific files.


In the eal_common_dev, rte_eal_dev_attach and rte_eal_dev_detach are 
directly referring to PCI as devices.


isn't it?


-   if (rte_eal_pci_probe_one(&addr) < 0)
+   if (rte_eal_pci_attach_driver(&addr) < 0)
goto err;

} else {
@@ -139,7 +139,7 @@ int rte_eal_dev_detach(const char *name)
}

if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   if (rte_eal_pci_detach_driver(&addr) < 0)
goto err;
} else {
if (rte_eal_vdev_uninit(name))
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index d50a534..67c6ce6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -228,59 +228,36 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, 
struct rte_pci_device *d
return 1;
 }

-/*
- * 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)
+rte_eal_pci_remove_driver(struct rte_pci_device *dev)
 {
-   const struct rte_pci_id *id_table;
+   struct rte_pci_driver *driver;
+   struct rte_pci_addr *loc;

-   if ((dr == NULL) || (dev == NULL))
-   return -EINVAL;
+   loc = &dev->addr;
+   driver = dev->driver;

-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-   /* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
-   id_table->vendor_id != PCI_ANY_ID)
-   continue;
-   if (id_table->device_id != dev->id.device_id &&
-   id_table->device_id != PCI_ANY_ID)
-   continue;
-   if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id 
&&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
-   continue;
-   if (id_table->subsystem_device_id != dev->id.subsystem_device_id 
&&
-   id_table->subsystem_device_id != PCI_ANY_ID)
-   continue;
-
-   struct rte_pci_addr *loc = &dev->addr;
+   if (driver == NULL)
+   return 0;

-   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, driver->driver.name);

-   if (dr->remove && (dr->remove(dev) < 0))
-   return -1;  /* negative value is an error */
+   if (driver->remove && (driver->remove(dev) < 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

Re: [dpdk-dev] [PATCH v5 00/12] Introducing EAL Bus-Device-Driver Model

2017-01-05 Thread Shreyansh Jain

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.




Re: [dpdk-dev] [PATCH v5 01/12] eal/bus: introduce bus abstraction

2017-01-06 Thread Shreyansh Jain

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;  /*

Re: [dpdk-dev] [PATCH v5 04/12] eal: integrate bus scan and probe with EAL

2017-01-06 Thread Shreyansh Jain

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?




Re: [dpdk-dev] [PATCH v5 05/12] eal: add probe and remove support for rte_driver

2017-01-06 Thread 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---



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.


Re: [dpdk-dev] [PATCH v5 04/12] eal: integrate bus scan and probe with EAL

2017-01-06 Thread 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 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?







Re: [dpdk-dev] [PATCH v5 08/12] eal/pci: generalize args of PCI scan/match towards RTE device/driver

2017-01-06 Thread Shreyansh Jain

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.


Re: [dpdk-dev] [PATCH v5 01/12] eal/bus: introduce bus abstraction

2017-01-08 Thread Shreyansh Jain

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; 

Re: [dpdk-dev] [PATCH v5 05/12] eal: add probe and remove support for rte_driver

2017-01-08 Thread Shreyansh Jain

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





Re: [dpdk-dev] [PATCH v5 04/12] eal: integrate bus scan and probe with EAL

2017-01-08 Thread Shreyansh Jain

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


Re: [dpdk-dev] [PATCH v5 04/12] eal: integrate bus scan and probe with EAL

2017-01-08 Thread Shreyansh Jain

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





Re: [dpdk-dev] [PATCH v5 01/12] eal/bus: introduce bus abstraction

2017-01-09 Thread Shreyansh Jain

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


Re: [dpdk-dev] [PATCH v5 11/12] drivers: update PMDs to use rte_driver probe and remove

2017-01-09 Thread Shreyansh Jain

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

<...>


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





Re: [dpdk-dev] [PATCH v3 00/33] NXP DPAA2 PMD

2017-01-09 Thread Shreyansh Jain

On Monday 09 January 2017 11:12 PM, Ferruh Yigit wrote:

On 12/29/2016 5:16 AM, Shreyansh Jain wrote:

 ** Sending v3 on behalf of Hemant Agrawal **



<...>

Hi,

Getting compile error for shared library [1] build.
Not investigated, copying here.

Thanks,
ferruh


[1]
== Build drivers/net/dpaa2
  LD librte_pmd_dpaa2.so.1.1
/usr/bin/ld: cannot find -lrte_pmd_dpaa2_qbman
/usr/bin/ld: cannot find -lrte_pmd_dpaa2_pool



I think this would be coming for parallel builds. Serial build for 
shared library is working as far as I know.
For parallel, somehow the rte_pmd_dpaa2_qbman dependency for net/dpaa2 
is not getting clearly defined because of which net/dpaa2 linking is 
attempted even before rte_pmd_dpaa2_qbman is ready.


I found that this might be because of the way scripts/depdirs-rule.sh 
forms the common-est directory. It works fine when dependent libraries 
are within lib/*, but when a drivers/net is dependent on driver/common 
or driver/bus, it somehow isn't working.


I am still investigating this.

-
Shreyansh



Re: [dpdk-dev] [PATCH 1/2] add rte_bus->probe

2017-01-10 Thread Shreyansh Jain

On Tuesday 10 January 2017 11:32 PM, Ferruh Yigit wrote:

Signed-off-by: Ferruh Yigit 
---
 lib/librte_eal/common/eal_common_bus.c  | 7 ---
 lib/librte_eal/common/include/rte_bus.h | 3 +++
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 1 +
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
index f8c2e03..e8d1143 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -145,6 +145,7 @@ rte_eal_bus_register(struct rte_bus *bus)
/* A bus should mandatorily have the scan and match implemented */
RTE_VERIFY(bus->scan);
RTE_VERIFY(bus->match);
+   RTE_VERIFY(bus->probe);


v6 of my patches would include the above.



/* Initialize the driver and device list associated with the bus */
TAILQ_INIT(&(bus->driver_list));
@@ -195,19 +196,19 @@ 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;

-   if (!driver->probe) {
+   if (!bus->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);
+   ret = bus->probe(driver, device);
if (ret < 0)
/* One of the probes failed */
RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);


Substantial code has shuffled in v6, including removal of this function.
But again, I agree with your changes.


diff --git a/lib/librte_eal/common/include/rte_bus.h 
b/lib/librte_eal/common/include/rte_bus.h
index 07c30c4..ce1f56a 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -135,6 +135,8 @@ typedef int (*bus_scan_t)(struct rte_bus *bus);
  */
 typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);

+typedef int (*bus_probe_t)(struct rte_driver *drv, struct rte_device *dev);
+
 /**
  * A structure describing a generic bus.
  */
@@ -147,6 +149,7 @@ struct rte_bus {
const char *name;/**< Name of the bus */
bus_scan_t scan;/**< Scan for devices attached to bus */
bus_match_t match;
+   bus_probe_t probe;
/**< Match device with drivers associated with the bus */
 };

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c 
b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 314effa..837adf6 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -726,6 +726,7 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 struct rte_bus pci_bus = {
.scan = rte_eal_pci_scan,
.match = rte_eal_pci_match,
+   .probe = rte_eal_pci_probe,
 };

 RTE_REGISTER_BUS(pci, pci_bus);





Re: [dpdk-dev] [PATCH 1/2] add rte_bus->probe

2017-01-11 Thread Shreyansh Jain
> -Original Message-
> From: Ferruh Yigit [mailto:ferruh.yi...@intel.com]
> Sent: Wednesday, January 11, 2017 8:34 PM
> To: Shreyansh Jain ; dev@dpdk.org
> Cc: Stephen Hemminger ; Jan Blunck
> 
> Subject: Re: [PATCH 1/2] add rte_bus->probe
> 
> On 1/11/2017 4:53 AM, Shreyansh Jain wrote:
> > On Tuesday 10 January 2017 11:32 PM, Ferruh Yigit wrote:
> >> Signed-off-by: Ferruh Yigit 
> >> ---
> >>  lib/librte_eal/common/eal_common_bus.c  | 7 ---
> >>  lib/librte_eal/common/include/rte_bus.h | 3 +++
> >>  lib/librte_eal/linuxapp/eal/eal_pci.c   | 1 +
> >>  3 files changed, 8 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/lib/librte_eal/common/eal_common_bus.c
> b/lib/librte_eal/common/eal_common_bus.c
> >> index f8c2e03..e8d1143 100644
> >> --- a/lib/librte_eal/common/eal_common_bus.c
> >> +++ b/lib/librte_eal/common/eal_common_bus.c
> >> @@ -145,6 +145,7 @@ rte_eal_bus_register(struct rte_bus *bus)
> >>/* A bus should mandatorily have the scan and match implemented */
> >>RTE_VERIFY(bus->scan);
> >>RTE_VERIFY(bus->match);
> >> +  RTE_VERIFY(bus->probe);
> >
> > v6 of my patches would include the above.
> 
> Since I am aware of you are working on something similar, I added this
> (in a dirty way) just to able to test next patch.

:) I understood this after sending my mail. I understand your point.

> 
> Thanks,
> ferruh
> 
> <...>


[dpdk-dev] [PATCH v6 1/8] eal/bus: introduce bus abstraction

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

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

An example implementation would be like:

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

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

diff --git a/lib/librte_eal/bsdapp/eal/Makefile 
b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+   global:
+
+   rte_bus_list;
+   rte_bus_dump;
+   rte_bus_register;
+   rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 000..c891392
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or othe

[dpdk-dev] [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model

2017-01-16 Thread Shreyansh Jain
ttp://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html

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

v5:
 - Fix checkpatch error in Patch 0003

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

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

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

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

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

-- 
2.7.4



[dpdk-dev] [PATCH v6 2/8] test: add basic bus infrastructure tests

2017-01-16 Thread Shreyansh Jain
Verification of bus registration, deregistration methods.

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

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of NXP nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===.===.=,= busA
+ * |   |   . |
+ *   devA1   devA2 . 'CPU_
+ *`---`---> driverA  |
+ *   '
+ *  ===.===.===.=|= busB
+ * |   |   .
+ *   devB1   devB2 .
+ *`---`---> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS 10
+#define MAX_DRIVERS_ON_BUS 10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+   TAILQ_ENTRY(dummy_device) next;
+   const char *name;
+   struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+   TAILQ_ENTRY(dummy_driver) next;
+   const char *name;
+   struct rte_driver drv;
+};
+
+struct dummy_bus {
+   TAILQ_ENTRY(dummy_bus) next;
+   const char *name;
+   struct rte_bus bus;
+   struct dummy_driver_list driver_list;
+   struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+   const char *name;
+   struct dummy_bus *dbus;
+   struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+   struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+   TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+   .name = "busA_impl", /* busA */
+   .bus = {
+   .name = &qu

[dpdk-dev] [PATCH v6 4/8] eal/bus: support for scanning of bus

2017-01-16 Thread Shreyansh Jain
Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
.name = "busA_impl", /* busA */
.bus = {
.name = "busA",
+   .scan = scan_fn_for_busA,
},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
.name = "busB_impl", /* busB */
.bus = {
.name = "busB",
+   .scan = scan_fn_for_busB,
},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
printf("-->8---\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map list, register.
+ *
+ * @param bus
+ * bus to scan againt test entry
+ * @return
+ * 0 for successful scan, even if no devices are found
+ * !0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+   int i = 0;
+   struct dummy_device *ddev = NULL;
+   struct dummy_bus_map *dbmap = NULL;
+   struct dummy_bus *db = NULL;
+
+   if (!bus)
+   return -1;
+
+   /* Extract the device tree node using the bus passed */
+   for (i = 0; bus_map[i].name; i++) {
+   if (!strcmp(bus_map[i].name, bus->name)) {
+   dbmap = &bus_map[i];
+   break;
+   }
+   }
+
+   if (!dbmap)
+   return -1;
+
+   db = dbmap->dbus;
+
+   /* For all the devices in the device tree (bus_map), add device */
+   for (i = 0; dbmap->ddevices[i]; i++) {
+   ddev = dbmap->ddevices[i];
+   TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+   ddev->dev.bus = bus;
+   }
+
+   return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busA") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busB") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+   int i = 0;
struct rte_bus *bus_p = NULL;
 
/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
}
 
+   /* Initialize the bus lists */
+   for (i = 0; bus_map[i].name; i++) {
+   TAILQ_INIT(&bus_map[i].dbus->device_list);
+   TAILQ_INIT(&bus_map[i].dbus->driver_list);
+   }
+
+   dump_device_tree();
return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+   int i;
+   struct rte_bus *bus = NULL;
+   struct dummy_device *ddev;
+   struct dummy_bus *dbus;
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus = &(bus_map[i].dbus->bus);
+   if (!bus) {
+   printf("Unable to find bus (%s)\n",
+  bus_map[i].name);
+   return -1;
+   }
+
+   dbus = container_of(bus, struct dummy_bus, bus);
+   /* For bus 'bus', unregister all devices */
+   TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+   TAILQ_REMOVE(&dbus->device_list, ddev, next);
+   }
+   }
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus

[dpdk-dev] [PATCH v6 7/8] eal: enable PCI bus

2017-01-16 Thread Shreyansh Jain
Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_timer_init() < 0)
rte_panic("Cannot init HPET or TSC timers\n");
 
-   if (rte_eal_pci_init() < 0)
-   rte_panic("Cannot init PCI\n");
-
eal_check_mem_on_local_socket();
 
if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
 
-   /* Probe & Initialize PCI devices */
-   if (rte_eal_pci_probe())
-   rte_panic("Cannot probe PCI\n");
-
/* Probe all the buses and devices/drivers on them */
if (rte_bus_probe())
rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
eal_parse_sysfs_value;
eal_timer_source;
lcore_config;
-   pci_device_list;
-   pci_driver_list;
per_lcore__lcore_id;
per_lcore__rte_errno;
rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 35da451..1d283d2 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-   TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
if (dev->driver != NULL)
return 0;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_probe_one_driver(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -342,7 +337,7 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
if (dev == NULL)
return -1;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_detach_dev(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -363,6 +358,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
struct rte_pci_device *dev = NULL;
+
int ret = 0;
 
if (addr == NULL)
@@ -374,7 +370,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
if (pci_update_device(addr) < 0)
goto err_return;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -404,7 +400,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
if (addr == NULL)
return -1;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -412,7 +408,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
if (ret < 0)
goto err_return;
 
-   TAILQ_REMOVE(&pci_device_list, dev, next);
+   rte_eal_pci_remove_device(dev);
free(dev);
return 0;
}
@@ -441,7 +437,7 @@ rte_eal_pci_probe(void)
if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
probe_all = 1;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
 
/* set devargs in PCI structure */
devargs = pci_devargs_lookup(dev);
@@ -489,7 +

[dpdk-dev] [PATCH v6 6/8] test: update bus and pci unit test cases

2017-01-16 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
---
 app/test/test_bus.c | 152 
 app/test/test_pci.c | 164 
 2 files changed, 266 insertions(+), 50 deletions(-)

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

[dpdk-dev] [PATCH v6 3/8] pci: split match and probe function

2017-01-16 Thread Shreyansh Jain
Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

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

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..0d799be 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device 
*dev)
+int
+rte_pci_match(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
 {
-   int ret;
+   int match = 1;
const struct rte_pci_id *id_table;
 
-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+   RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+   return -1;
+   }
 
+   for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+id_table++) {
/* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
+   if (id_table->vendor_id != pci_dev->id.vendor_id &&
id_table->vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->device_id != dev->id.device_id &&
+   if (id_table->device_id != pci_dev->id.device_id &&
id_table->device_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_vendor_id != 
dev->id.subsystem_vendor_id &&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
+   if (id_table->subsystem_vendor_id !=
+   pci_dev->id.subsystem_vendor_id &&
+   id_table->subsystem_vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_device_id != 
dev->id.subsystem_device_id &&
-   id_table->subsystem_device_id != PCI_ANY_ID)
+   if (id_table->subsystem_device_id !=
+   pci_dev->id.subsystem_device_id &&
+   id_table->subsystem_device_id != PCI_ANY_ID)
continue;
-   if (id_table->class_id != dev->id.class_id &&
+   if (id_table->class_id != pci_dev->id.class_id &&
id_table->class_id != RTE_CLASS_ANY_ID)
continue;
 
-   struct rte_pci_addr *loc = &dev->addr;
-
-   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid, 
loc->function,
-   dev->device.numa_node);
-
-   /* no initialization when blacklisted, return without error */
-   if (dev->device.devargs != NULL &&
-   dev->device.devargs->type ==
-   RTE_DEVTYPE_BLACKLISTED_PCI) {
-   RTE_LOG(INFO, EAL, "  Device is blacklisted, not 
initializing\n");
-   return 1;
-   }
-
-   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
-
-   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-   /* map resources for devices that use igb_uio */
-   ret = rte_eal_pci_map_device(dev);
-   if (ret != 0)
-   return ret;
-   }
-
-   /* reference d

[dpdk-dev] [PATCH v6 5/8] eal: introduce bus scan and probe in EAL

2017-01-16 Thread Shreyansh Jain
Each bus implementation defines their own callbacks for scanning bus
and probing devices available on the bus. Enable EAL to call bus specific
scan and probe functions during DPDK initialization.

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

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -577,6 +578,9 @@ rte_eal_init(int argc, char **argv)
rte_config.master_lcore, thread_id, cpuset,
ret == 0 ? "" : "...");
 
+   if (rte_bus_scan())
+   rte_panic("Cannot scan the buses for devices\n");
+
RTE_LCORE_FOREACH_SLAVE(i) {
 
/*
@@ -613,6 +617,10 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");
 
+   /* Probe all the buses and devices/drivers on them */
+   if (rte_bus_probe())
+   rte_panic("Cannot probe devices\n");
+
if (rte_eal_dev_init() < 0)
rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
}
return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+   .bus = {
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+   .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+   .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_bus_probe;
+   rte_bus_scan;
rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
index 35baff8..9c91ca6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -53,6 +53,7 @@ rte_bus_register(struct rte_bus *bus)
RTE_VERIFY(bus->name && strlen(bus->name));
/* A bus should mandatorily have the scan implemented */
RTE_VERIFY(bus->scan);
+   RTE_VERIFY(bus->probe);
 
TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
@@ -66,6 +67,46 @@ rte_bus_unregister(struct rte_bus *bus)
RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+   int ret;
+   struct rte_bus *bus = NULL;
+
+   TAILQ_FOREACH(bus, &rte_bus_list, next) {
+   ret = bus->scan();
+   if (ret) {
+   RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+   bus->name);
+   /* Error in scanning any bus stops the EAL init. */
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+   int ret;
+   struct rte_bus *bus;
+
+   /* For each bus registered with EAL */
+   TAILQ_FOREACH(bus, &rte_bus_list, next) {
+   ret = bus->probe();
+   if (ret) {
+   RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+   bus->name);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/e

[dpdk-dev] [PATCH v6 8/8] eal: enable hotplugging of devices on bus

2017-01-16 Thread Shreyansh Jain
Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..17a04d9 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -678,6 +678,8 @@ struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_eal_pci_scan,
.probe = rte_eal_pci_probe,
+   .attach = rte_eal_pci_attach,
+   .detach = rte_eal_pci_detach,
},
.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..b363fa9 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_probe_one(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->attach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " attach.\n", bus->name);
+   continue;
+   }
+   ret = bus->attach(bus, name);
+   if (!ret) /* device successfully attached */
+   return ret;
+   if (ret > 0) /* device not found on bus */
+   continue;
+   else
goto err;
+   }
 
-   } else {
-   if (rte_eal_vdev_init(name, devargs))
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_init(name, devargs);
+   if (ret)
goto err;
}
 
-   return 0;
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->detach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " detach.\n", bus->name);
+   continue;
+   }
+
+   ret = bus->detach(bus, name);
+   if (!ret) /* device successfully detached */
+   return ret;
+   if (ret > 0) /* device not found on the bus */
+   continue;
+   else
goto err;
-   } else {
-   if (rte_eal_vdev_uninit(name))
+   }
+
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_uninit(name);
+   if (ret)
goto err;
}
-   return 0;
+
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 1d283d2..1c205bd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,95 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(struct rte_bus *bus __rte_unused, const char *device_name)
+{
+   struct rte_pci_device *dev = NULL;
+  

Re: [dpdk-dev] [PATCH v6 3/8] pci: split match and probe function

2017-01-16 Thread Shreyansh Jain

Hello Ferruh,

On Tuesday 17 January 2017 01:23 AM, Ferruh Yigit wrote:

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:

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

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain 


<...>


 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-   struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+struct rte_pci_device *dev)
 {
-   const struct rte_pci_id *id_table;
+   int ret;
+   struct rte_pci_addr *loc;

if ((dr == NULL) || (dev == NULL))
return -EINVAL;

-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   loc = &dev->addr;

-   /* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
-   id_table->vendor_id != PCI_ANY_ID)
-   continue;
-   if (id_table->device_id != dev->id.device_id &&
-   id_table->device_id != PCI_ANY_ID)
-   continue;
-   if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id 
&&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
-   continue;
-   if (id_table->subsystem_device_id != dev->id.subsystem_device_id 
&&
-   id_table->subsystem_device_id != PCI_ANY_ID)
-   continue;
+   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+   loc->domain, loc->bus, loc->devid, loc->function,
+   dev->device.numa_node);


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


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






-   struct rte_pci_addr *loc = &dev->addr;
+   /* The device is not blacklisted; Check if driver supports it */
+   ret = rte_pci_match(dr, dev);
+   if (ret) {
+   /* Match of device and driver failed */
+   RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+   dr->driver.name);
+   return 1;
+   }
+
+   /* no initialization when blacklisted, return without error */
+   if (dev->device.devargs != NULL &&
+   dev->device.devargs->type ==
+   RTE_DEVTYPE_BLACKLISTED_PCI) {
+   RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+   " initializing\n");
+   return 1;
+   }

-   RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid,
-   loc->function, dev->device.numa_node);
+   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+   dev->id.device_id, dr->driver.name);


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


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





-   RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
+   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+   /* map resources for devices that use igb_uio */
+   ret = rte_eal_pci_map_device(dev);
+   if (ret != 0)
+   return ret;
+   }

-   if (dr->remove && (dr->remove(dev) < 0))
-   return -1;  /* negative value is an error */
+   /* reference driver structure */
+   dev->driver = dr;

-   /* clear driver structure */
+   /* call the driver probe() function */
+   ret = dr->probe(dr, dev);
+   if (ret) {
dev->driver = NULL;
-
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-   /* unmap resources for devices that use igb_uio */
rte_eal_pci_unmap_

Re: [dpdk-dev] [PATCH v6 5/8] eal: introduce bus scan and probe in EAL

2017-01-16 Thread Shreyansh Jain

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:

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

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

Signed-off-by: Shreyansh Jain 


<...>


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


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


No issues - any review comment is welcome.



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


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

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


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




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


I agree with this.




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


<...>


diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 0d799be..35da451 100644

<...>

+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+  struct rte_pci_device *pci_dev)


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


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


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


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





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


<...>



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


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


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



<...>


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


Minor issue in document compilation:

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

- parameter 'new_pci_dev' not documented

Similar warnings exists for rte_eal_pci_remove_device() too.

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


I will fix and post v7 very shortly.




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


<...>






Re: [dpdk-dev] [PATCH v6 7/8] eal: enable PCI bus

2017-01-16 Thread Shreyansh Jain

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:

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

Signed-off-by: Shreyansh Jain 
---


<...>


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


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


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

Thanks for highlighting.



<...>






Re: [dpdk-dev] [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model

2017-01-16 Thread Shreyansh Jain

On Monday 16 January 2017 11:57 PM, Stephen Hemminger wrote:

On Mon, 16 Jan 2017 21:08:19 +0530
Shreyansh Jain  wrote:


Link to v5: [15]

:: Introduction ::

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

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

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


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

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

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

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

And example implementation would look like:

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


:: Brief about Patch Layout ::

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


:: Pending Changes/Caveats ::

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

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

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

:: ToDo list ::

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

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] h

Re: [dpdk-dev] [PATCH v6 0/8] Introducing EAL Bus-Device-Driver Model

2017-01-16 Thread Shreyansh Jain

On Monday 16 January 2017 11:57 PM, Stephen Hemminger wrote:

On Mon, 16 Jan 2017 21:08:19 +0530
Shreyansh Jain  wrote:


Link to v5: [15]

:: Introduction ::

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

(Check 'Version Changes' section for changes)

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

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


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

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

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

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

And example implementation would look like:

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


:: Brief about Patch Layout ::

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


:: Pending Changes/Caveats ::

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

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

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

:: ToDo list ::

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

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] h

Re: [dpdk-dev] [PATCH v6 8/8] eal: enable hotplugging of devices on bus

2017-01-16 Thread Shreyansh Jain

On Monday 16 January 2017 09:08 PM, Shreyansh Jain wrote:

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

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

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..17a04d9 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -678,6 +678,8 @@ struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_eal_pci_scan,
.probe = rte_eal_pci_probe,
+   .attach = rte_eal_pci_attach,
+   .detach = rte_eal_pci_detach,
},
.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..b363fa9 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include 

 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)

 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;

if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}

-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_probe_one(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->attach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " attach.\n", bus->name);
+   continue;
+   }
+   ret = bus->attach(bus, name);
+   if (!ret) /* device successfully attached */
+   return ret;
+   if (ret > 0) /* device not found on bus */
+   continue;
+   else
goto err;
+   }

-   } else {
-   if (rte_eal_vdev_init(name, devargs))
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_init(name, devargs);
+   if (ret)
goto err;
}

-   return 0;
+   return ret;

 err:
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)

 int rte_eal_dev_detach(const char *name)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;

if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}

-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->detach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " detach.\n", bus->name);
+   continue;
+   }
+
+   ret = bus->detach(bus, name);
+   if (!ret) /* device successfully detached */
+   return ret;
+   if (ret > 0) /* device not found on the bus */
+   continue;
+   else
goto err;
-   } else {
-   if (rte_eal_vdev_uninit(name))
+   }
+
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_uninit(name);
+   if (ret)
goto err;
}
-   return 0;
+
+   return ret;

 err:
RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 1d283d2..1c205bd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,95 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }

 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(struct rte_bus *bus __rte_unused, const char *device_name)
+

[dpdk-dev] [PATCH v7 0/9] Introducing EAL Bus-Device-Driver Model

2017-01-17 Thread Shreyansh Jain
chives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html - v1
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html - v2
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html - v3
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html - v4
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html - v5
[16] http://dpdk.org/ml/archives/dev/2017-January/055120.html  - v6

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

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

v5:
 - Fix checkpatch error in Patch 0003

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

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

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

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

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

-- 
2.7.4



[dpdk-dev] [PATCH v7 1/9] eal/bus: introduce bus abstraction

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

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

An example implementation would be like:

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

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

diff --git a/lib/librte_eal/bsdapp/eal/Makefile 
b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+   global:
+
+   rte_bus_list;
+   rte_bus_dump;
+   rte_bus_register;
+   rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 000..c891392
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or othe

[dpdk-dev] [PATCH v7 3/9] pci: split match and probe function

2017-01-17 Thread Shreyansh Jain
Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

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

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device 
*dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+ const struct rte_pci_device *pci_dev)
 {
-   int ret;
+   int match = 1;
const struct rte_pci_id *id_table;
 
-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+   RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+   return -1;
+   }
 
+   for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+id_table++) {
/* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
+   if (id_table->vendor_id != pci_dev->id.vendor_id &&
id_table->vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->device_id != dev->id.device_id &&
+   if (id_table->device_id != pci_dev->id.device_id &&
id_table->device_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_vendor_id != 
dev->id.subsystem_vendor_id &&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
+   if (id_table->subsystem_vendor_id !=
+   pci_dev->id.subsystem_vendor_id &&
+   id_table->subsystem_vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_device_id != 
dev->id.subsystem_device_id &&
-   id_table->subsystem_device_id != PCI_ANY_ID)
+   if (id_table->subsystem_device_id !=
+   pci_dev->id.subsystem_device_id &&
+   id_table->subsystem_device_id != PCI_ANY_ID)
continue;
-   if (id_table->class_id != dev->id.class_id &&
+   if (id_table->class_id != pci_dev->id.class_id &&
id_table->class_id != RTE_CLASS_ANY_ID)
continue;
 
-   struct rte_pci_addr *loc = &dev->addr;
-
-   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid, 
loc->function,
-   dev->device.numa_node);
-
-   /* no initialization when blacklisted, return without error */
-   if (dev->device.devargs != NULL &&
-   dev->device.devargs->type ==
-   RTE_DEVTYPE_BLACKLISTED_PCI) {
-   RTE_LOG(INFO, EAL, "  Device is blacklisted, not 
initializing\n");
-   return 1;
-   }
-
-   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
-
-   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-   /* map resources for devices that use igb_uio */
-   ret = rte_eal_pci_map_device(dev);
-   if (ret != 0)
-   return ret;
-   }
-
-  

[dpdk-dev] [PATCH v7 4/9] eal/bus: support for scanning of bus

2017-01-17 Thread Shreyansh Jain
Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

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

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
.name = "busA_impl", /* busA */
.bus = {
.name = "busA",
+   .scan = scan_fn_for_busA,
},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
.name = "busB_impl", /* busB */
.bus = {
.name = "busB",
+   .scan = scan_fn_for_busB,
},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
printf("-->8---\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map list, register.
+ *
+ * @param bus
+ * bus to scan againt test entry
+ * @return
+ * 0 for successful scan, even if no devices are found
+ * !0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+   int i = 0;
+   struct dummy_device *ddev = NULL;
+   struct dummy_bus_map *dbmap = NULL;
+   struct dummy_bus *db = NULL;
+
+   if (!bus)
+   return -1;
+
+   /* Extract the device tree node using the bus passed */
+   for (i = 0; bus_map[i].name; i++) {
+   if (!strcmp(bus_map[i].name, bus->name)) {
+   dbmap = &bus_map[i];
+   break;
+   }
+   }
+
+   if (!dbmap)
+   return -1;
+
+   db = dbmap->dbus;
+
+   /* For all the devices in the device tree (bus_map), add device */
+   for (i = 0; dbmap->ddevices[i]; i++) {
+   ddev = dbmap->ddevices[i];
+   TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+   ddev->dev.bus = bus;
+   }
+
+   return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busA") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busB") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+   int i = 0;
struct rte_bus *bus_p = NULL;
 
/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
}
 
+   /* Initialize the bus lists */
+   for (i = 0; bus_map[i].name; i++) {
+   TAILQ_INIT(&bus_map[i].dbus->device_list);
+   TAILQ_INIT(&bus_map[i].dbus->driver_list);
+   }
+
+   dump_device_tree();
return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+   int i;
+   struct rte_bus *bus = NULL;
+   struct dummy_device *ddev;
+   struct dummy_bus *dbus;
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus = &(bus_map[i].dbus->bus);
+   if (!bus) {
+   printf("Unable to find bus (%s)\n",
+  bus_map[i].name);
+   return -1;
+   }
+
+   dbus = container_of(bus, struct dummy_bus, bus);
+   /* For bus 'bus', unregister all devices */
+   TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+   TAILQ_REMOVE(&dbus->device_list, ddev, next);
+   }
+   }
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus

[dpdk-dev] [PATCH v7 6/9] eal: integrate bus scan and probe with EAL

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

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

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -577,6 +578,9 @@ rte_eal_init(int argc, char **argv)
rte_config.master_lcore, thread_id, cpuset,
ret == 0 ? "" : "...");
 
+   if (rte_bus_scan())
+   rte_panic("Cannot scan the buses for devices\n");
+
RTE_LCORE_FOREACH_SLAVE(i) {
 
/*
@@ -613,6 +617,10 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");
 
+   /* Probe all the buses and devices/drivers on them */
+   if (rte_bus_probe())
+   rte_panic("Cannot probe devices\n");
+
if (rte_eal_dev_init() < 0)
rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
}
return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+   .bus = {
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+   .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+   .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_bus_probe;
+   rte_bus_scan;
rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
index 9c4b014..9c91ca6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -67,6 +67,46 @@ rte_bus_unregister(struct rte_bus *bus)
RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+   int ret;
+   struct rte_bus *bus = NULL;
+
+   TAILQ_FOREACH(bus, &rte_bus_list, next) {
+   ret = bus->scan();
+   if (ret) {
+   RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+   bus->name);
+   /* Error in scanning any bus stops the EAL init. */
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+   int ret;
+   struct rte_bus *bus;
+
+   /* For each bus registered with EAL */
+   TAILQ_FOREACH(bus, &rte_bus_list, next) {
+   ret = bus->probe();
+   if (ret) {
+   RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+   bus->name);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..5f2cab5 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -508,3 +509,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
rte_eal_driver_unregister(&driver->driver);

[dpdk-dev] [PATCH v7 2/9] test: add basic bus infrastructure tests

2017-01-17 Thread Shreyansh Jain
Verification of bus registration, deregistration methods.

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

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of NXP nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===.===.=,= busA
+ * |   |   . |
+ *   devA1   devA2 . 'CPU_
+ *`---`---> driverA  |
+ *   '
+ *  ===.===.===.=|= busB
+ * |   |   .
+ *   devB1   devB2 .
+ *`---`---> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS 10
+#define MAX_DRIVERS_ON_BUS 10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+   TAILQ_ENTRY(dummy_device) next;
+   const char *name;
+   struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+   TAILQ_ENTRY(dummy_driver) next;
+   const char *name;
+   struct rte_driver drv;
+};
+
+struct dummy_bus {
+   TAILQ_ENTRY(dummy_bus) next;
+   const char *name;
+   struct rte_bus bus;
+   struct dummy_driver_list driver_list;
+   struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+   const char *name;
+   struct dummy_bus *dbus;
+   struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+   struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+   TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+   .name = "busA_impl", /* busA */
+   .bus = {
+   .name = &qu

[dpdk-dev] [PATCH v7 9/9] eal: enable hotplugging of devices on bus

2017-01-17 Thread Shreyansh Jain
Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_eal_pci_scan,
.probe = rte_eal_pci_probe,
+   .attach = rte_eal_pci_attach,
+   .detach = rte_eal_pci_detach,
},
.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_probe_one(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->attach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " attach.\n", bus->name);
+   continue;
+   }
+   ret = bus->attach(name);
+   if (!ret) /* device successfully attached */
+   return ret;
+   if (ret > 0) /* device not found on bus */
+   continue;
+   else
goto err;
+   }
 
-   } else {
-   if (rte_eal_vdev_init(name, devargs))
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_init(name, devargs);
+   if (ret)
goto err;
}
 
-   return 0;
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->detach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " detach.\n", bus->name);
+   continue;
+   }
+
+   ret = bus->detach(name);
+   if (!ret) /* device successfully detached */
+   return ret;
+   if (ret > 0) /* device not found on the bus */
+   continue;
+   else
goto err;
-   } else {
-   if (rte_eal_vdev_uninit(name))
+   }
+
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_uninit(name);
+   if (ret)
goto err;
}
-   return 0;
+
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index d8c1350..f4866da 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,99 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+   struct rte_pci_device *dev = NULL;
+   struct rte_pci_driver *drv = NULL;
+  

[dpdk-dev] [PATCH v7 5/9] eal/bus: introduce support for bus probing

2017-01-17 Thread Shreyansh Jain
Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

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

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

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



Re: [dpdk-dev] [PATCH v6 3/8] pci: split match and probe function

2017-01-17 Thread Shreyansh Jain

On Monday 16 January 2017 11:54 PM, Stephen Hemminger wrote:

On Mon, 16 Jan 2017 21:08:22 +0530
Shreyansh Jain  wrote:


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


Use const?



Done in v7. Thanks


[dpdk-dev] [PATCH v7 8/9] eal: enable PCI bus

2017-01-17 Thread Shreyansh Jain
Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_timer_init() < 0)
rte_panic("Cannot init HPET or TSC timers\n");
 
-   if (rte_eal_pci_init() < 0)
-   rte_panic("Cannot init PCI\n");
-
eal_check_mem_on_local_socket();
 
if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
 
-   /* Probe & Initialize PCI devices */
-   if (rte_eal_pci_probe())
-   rte_panic("Cannot probe PCI\n");
-
/* Probe all the buses and devices/drivers on them */
if (rte_bus_probe())
rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
.matches = &matches[0],
};
 
+   /* for debug purposes, PCI can be disabled */
+   if (internal_config.no_pci)
+   return 0;
+
fd = open("/dev/pci", O_RDONLY);
if (fd < 0) {
RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
eal_parse_sysfs_value;
eal_timer_source;
lcore_config;
-   pci_device_list;
-   pci_driver_list;
per_lcore__lcore_id;
per_lcore__rte_errno;
rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 5f2cab5..d8c1350 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-   TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
if (dev->driver != NULL)
return 0;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_probe_one_driver(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -342,7 +337,7 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
if (dev == NULL)
return -1;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_detach_dev(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -363,6 +358,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
struct rte_pci_device *dev = NULL;
+
int ret = 0;
 
if (addr == NULL)
@@ -374,7 +370,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
if (pci_update_device(addr) < 0)
goto err_return;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -404,7 +400,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
if (addr == NULL)
return -1;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -412,7 +408,7 @@ rte_eal_pc

[dpdk-dev] [PATCH v7 7/9] test: update bus and pci unit test cases

2017-01-17 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
---
 app/test/test_bus.c | 152 
 app/test/test_pci.c | 164 
 2 files changed, 266 insertions(+), 50 deletions(-)

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

Re: [dpdk-dev] [PATCH v6 7/8] eal: enable PCI bus

2017-01-17 Thread Shreyansh Jain

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:

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

Signed-off-by: Shreyansh Jain 
---


<...>


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


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

<...>




Fixed in v7. Thanks for comments.


Re: [dpdk-dev] [PATCH v6 5/8] eal: introduce bus scan and probe in EAL

2017-01-17 Thread Shreyansh Jain

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

On Tuesday 17 January 2017 01:28 AM, Ferruh Yigit wrote:

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:

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

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

Signed-off-by: Shreyansh Jain 


<...>


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


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

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

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


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




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


<...>


diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 0d799be..35da451 100644

<...>

+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+  struct rte_pci_device *pci_dev)


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


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


<...>



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


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

<...>


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


Minor issue in document compilation:

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

- parameter 'new_pci_dev' not documented

Similar warnings exists for rte_eal_pci_remove_device() too.

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


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




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


<...>






Re: [dpdk-dev] [PATCH v6 3/8] pci: split match and probe function

2017-01-17 Thread Shreyansh Jain

On Tuesday 17 January 2017 03:28 PM, Ferruh Yigit wrote:

On 1/17/2017 4:54 AM, Shreyansh Jain wrote:

Hello Ferruh,

On Tuesday 17 January 2017 01:23 AM, Ferruh Yigit wrote:

On 1/16/2017 3:38 PM, Shreyansh Jain wrote:

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

Splitting the matching function into a public fn rte_pci_match.

Signed-off-by: Shreyansh Jain 


<...>


 /*
- * If vendor/device ID match, call the remove() function of the
+ * If vendor/device ID match, call the probe() function of the
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-   struct rte_pci_device *dev)
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+struct rte_pci_device *dev)
 {
-   const struct rte_pci_id *id_table;
+   int ret;
+   struct rte_pci_addr *loc;

if ((dr == NULL) || (dev == NULL))
return -EINVAL;

-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   loc = &dev->addr;

-   /* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
-   id_table->vendor_id != PCI_ANY_ID)
-   continue;
-   if (id_table->device_id != dev->id.device_id &&
-   id_table->device_id != PCI_ANY_ID)
-   continue;
-   if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id 
&&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
-   continue;
-   if (id_table->subsystem_device_id != dev->id.subsystem_device_id 
&&
-   id_table->subsystem_device_id != PCI_ANY_ID)
-   continue;
+   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+   loc->domain, loc->bus, loc->devid, loc->function,
+   dev->device.numa_node);


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


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





-   struct rte_pci_addr *loc = &dev->addr;
+   /* The device is not blacklisted; Check if driver supports it */
+   ret = rte_pci_match(dr, dev);
+   if (ret) {
+   /* Match of device and driver failed */
+   RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+   dr->driver.name);
+   return 1;
+   }
+
+   /* no initialization when blacklisted, return without error */
+   if (dev->device.devargs != NULL &&
+   dev->device.devargs->type ==
+   RTE_DEVTYPE_BLACKLISTED_PCI) {
+   RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+   " initializing\n");
+   return 1;
+   }

-   RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid,
-   loc->function, dev->device.numa_node);
+   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+   dev->id.device_id, dr->driver.name);


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


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


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


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









-   RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
+   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+   /* map resources for devices that use igb_uio */
+   ret = rte_eal_pci_map_device(dev);
+   if (ret != 0)
+   return ret;
+   }

-   if (dr->remove && (dr->remove(dev) < 0))
-   return -1;  /* negative value is an error */
+   /* reference driver structure */
+   dev->driver = dr;

-   /

Re: [dpdk-dev] [PATCH v7 9/9] eal: enable hotplugging of devices on bus

2017-01-17 Thread Shreyansh Jain
Hi Ferruh,

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

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

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



[dpdk-dev] [PATCH v8 0/9] Introducing EAL Bus-Device-Driver Model

2017-01-17 Thread Shreyansh Jain
vember/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html
[10] http://dpdk.org/ml/archives/dev/2016-December/051349.html - v1
[12] http://dpdk.org/ml/archives/dev/2016-December/052092.html - v2
[13] http://dpdk.org/ml/archives/dev/2016-December/052381.html - v3
[14] http://dpdk.org/ml/archives/dev/2016-December/053302.html - v4
[15] http://dpdk.org/ml/archives/dev/2016-December/053315.html - v5
[16] http://dpdk.org/ml/archives/dev/2017-January/055120.html  - v6
[17] http://dpdk.org/ml/archives/dev/2017-January/055320.html  - v7

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

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

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

v5:
 - Fix checkpatch error in Patch 0003

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

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

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

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

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

-- 
2.7.4



[dpdk-dev] [PATCH v8 3/9] pci: split match and probe function

2017-01-17 Thread Shreyansh Jain
Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

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

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device 
*dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+ const struct rte_pci_device *pci_dev)
 {
-   int ret;
+   int match = 1;
const struct rte_pci_id *id_table;
 
-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+   RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+   return -1;
+   }
 
+   for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+id_table++) {
/* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
+   if (id_table->vendor_id != pci_dev->id.vendor_id &&
id_table->vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->device_id != dev->id.device_id &&
+   if (id_table->device_id != pci_dev->id.device_id &&
id_table->device_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_vendor_id != 
dev->id.subsystem_vendor_id &&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
+   if (id_table->subsystem_vendor_id !=
+   pci_dev->id.subsystem_vendor_id &&
+   id_table->subsystem_vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_device_id != 
dev->id.subsystem_device_id &&
-   id_table->subsystem_device_id != PCI_ANY_ID)
+   if (id_table->subsystem_device_id !=
+   pci_dev->id.subsystem_device_id &&
+   id_table->subsystem_device_id != PCI_ANY_ID)
continue;
-   if (id_table->class_id != dev->id.class_id &&
+   if (id_table->class_id != pci_dev->id.class_id &&
id_table->class_id != RTE_CLASS_ANY_ID)
continue;
 
-   struct rte_pci_addr *loc = &dev->addr;
-
-   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid, 
loc->function,
-   dev->device.numa_node);
-
-   /* no initialization when blacklisted, return without error */
-   if (dev->device.devargs != NULL &&
-   dev->device.devargs->type ==
-   RTE_DEVTYPE_BLACKLISTED_PCI) {
-   RTE_LOG(INFO, EAL, "  Device is blacklisted, not 
initializing\n");
-   return 1;
-   }
-
-   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
-
-   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-   /* map resources for devices that use igb_uio */
-   ret = rte_eal_pci_map_device(dev);
-   if (ret != 0)
-   return ret;
-   

[dpdk-dev] [PATCH v8 1/9] eal/bus: introduce bus abstraction

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

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

An example implementation would be like:

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

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 

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

diff --git a/lib/librte_eal/bsdapp/eal/Makefile 
b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+   global:
+
+   rte_bus_list;
+   rte_bus_dump;
+   rte_bus_register;
+   rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 000..c891392
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,97 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   t

[dpdk-dev] [PATCH v8 4/9] eal/bus: support for scanning of bus

2017-01-17 Thread Shreyansh Jain
Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_bus.c | 175 
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  18 
 3 files changed, 195 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
.name = "busA_impl", /* busA */
.bus = {
.name = "busA",
+   .scan = scan_fn_for_busA,
},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
.name = "busB_impl", /* busB */
.bus = {
.name = "busB",
+   .scan = scan_fn_for_busB,
},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
printf("-->8---\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map list, register.
+ *
+ * @param bus
+ * bus to scan againt test entry
+ * @return
+ * 0 for successful scan, even if no devices are found
+ * !0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+   int i = 0;
+   struct dummy_device *ddev = NULL;
+   struct dummy_bus_map *dbmap = NULL;
+   struct dummy_bus *db = NULL;
+
+   if (!bus)
+   return -1;
+
+   /* Extract the device tree node using the bus passed */
+   for (i = 0; bus_map[i].name; i++) {
+   if (!strcmp(bus_map[i].name, bus->name)) {
+   dbmap = &bus_map[i];
+   break;
+   }
+   }
+
+   if (!dbmap)
+   return -1;
+
+   db = dbmap->dbus;
+
+   /* For all the devices in the device tree (bus_map), add device */
+   for (i = 0; dbmap->ddevices[i]; i++) {
+   ddev = dbmap->ddevices[i];
+   TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+   ddev->dev.bus = bus;
+   }
+
+   return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busA") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busB") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+   int i = 0;
struct rte_bus *bus_p = NULL;
 
/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
}
 
+   /* Initialize the bus lists */
+   for (i = 0; bus_map[i].name; i++) {
+   TAILQ_INIT(&bus_map[i].dbus->device_list);
+   TAILQ_INIT(&bus_map[i].dbus->driver_list);
+   }
+
+   dump_device_tree();
return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+   int i;
+   struct rte_bus *bus = NULL;
+   struct dummy_device *ddev;
+   struct dummy_bus *dbus;
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus = &(bus_map[i].dbus->bus);
+   if (!bus) {
+   printf("Unable to find bus (%s)\n",
+  bus_map[i].name);
+   return -1;
+   }
+
+   dbus = container_of(bus, struct dummy_bus, bus);
+   /* For bus 'bus', unregister all devices */
+   TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+   TAILQ_REMOVE(&dbus->device_list, ddev, next);
+   }
+   }
+
+   for (i = 

[dpdk-dev] [PATCH v8 5/9] eal/bus: introduce support for bus probing

2017-01-17 Thread Shreyansh Jain
Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

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

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 18 ++
 2 files changed, 19 insertions(+)

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



[dpdk-dev] [PATCH v8 2/9] test: add basic bus infrastructure tests

2017-01-17 Thread Shreyansh Jain
Verification of bus registration, deregistration methods.

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

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of NXP nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===.===.=,= busA
+ * |   |   . |
+ *   devA1   devA2 . 'CPU_
+ *`---`---> driverA  |
+ *   '
+ *  ===.===.===.=|= busB
+ * |   |   .
+ *   devB1   devB2 .
+ *`---`---> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS 10
+#define MAX_DRIVERS_ON_BUS 10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+   TAILQ_ENTRY(dummy_device) next;
+   const char *name;
+   struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+   TAILQ_ENTRY(dummy_driver) next;
+   const char *name;
+   struct rte_driver drv;
+};
+
+struct dummy_bus {
+   TAILQ_ENTRY(dummy_bus) next;
+   const char *name;
+   struct rte_bus bus;
+   struct dummy_driver_list driver_list;
+   struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+   const char *name;
+   struct dummy_bus *dbus;
+   struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+   struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+   TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+   .name = "busA_impl", /* busA */
+   .bu

[dpdk-dev] [PATCH v8 7/9] test: update bus and pci unit test cases

2017-01-17 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_bus.c | 152 
 app/test/test_pci.c | 164 
 2 files changed, 266 insertions(+), 50 deletions(-)

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

[dpdk-dev] [PATCH v8 8/9] eal: enable PCI bus

2017-01-17 Thread Shreyansh Jain
Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_timer_init() < 0)
rte_panic("Cannot init HPET or TSC timers\n");
 
-   if (rte_eal_pci_init() < 0)
-   rte_panic("Cannot init PCI\n");
-
eal_check_mem_on_local_socket();
 
if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
 
-   /* Probe & Initialize PCI devices */
-   if (rte_eal_pci_probe())
-   rte_panic("Cannot probe PCI\n");
-
/* Probe all the buses and devices/drivers on them */
if (rte_bus_probe())
rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
.matches = &matches[0],
};
 
+   /* for debug purposes, PCI can be disabled */
+   if (internal_config.no_pci)
+   return 0;
+
fd = open("/dev/pci", O_RDONLY);
if (fd < 0) {
RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
eal_parse_sysfs_value;
eal_timer_source;
lcore_config;
-   pci_device_list;
-   pci_driver_list;
per_lcore__lcore_id;
per_lcore__rte_errno;
rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 5f2cab5..d8c1350 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-   TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -315,7 +310,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
if (dev->driver != NULL)
return 0;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_probe_one_driver(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -342,7 +337,7 @@ pci_detach_all_drivers(struct rte_pci_device *dev)
if (dev == NULL)
return -1;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_detach_dev(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -363,6 +358,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
struct rte_pci_device *dev = NULL;
+
int ret = 0;
 
if (addr == NULL)
@@ -374,7 +370,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
if (pci_update_device(addr) < 0)
goto err_return;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -404,7 +400,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
if (addr == NULL)
return -1;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;

[dpdk-dev] [PATCH v8 9/9] eal: enable hotplugging of devices on bus

2017-01-17 Thread Shreyansh Jain
Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_eal_pci_scan,
.probe = rte_eal_pci_probe,
+   .attach = rte_eal_pci_attach,
+   .detach = rte_eal_pci_detach,
},
.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_probe_one(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->attach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " attach.\n", bus->name);
+   continue;
+   }
+   ret = bus->attach(name);
+   if (!ret) /* device successfully attached */
+   return ret;
+   if (ret > 0) /* device not found on bus */
+   continue;
+   else
goto err;
+   }
 
-   } else {
-   if (rte_eal_vdev_init(name, devargs))
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_init(name, devargs);
+   if (ret)
goto err;
}
 
-   return 0;
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->detach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " detach.\n", bus->name);
+   continue;
+   }
+
+   ret = bus->detach(name);
+   if (!ret) /* device successfully detached */
+   return ret;
+   if (ret > 0) /* device not found on the bus */
+   continue;
+   else
goto err;
-   } else {
-   if (rte_eal_vdev_uninit(name))
+   }
+
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_uninit(name);
+   if (ret)
goto err;
}
-   return 0;
+
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index d8c1350..8eed8d1 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -389,19 +389,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+   struct rte_pci_device *dev = NULL;
+   struct rte_pci_driver *drv = NULL;
+   struct r

[dpdk-dev] [PATCH v8 6/9] eal: integrate bus scan and probe with EAL

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

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

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 2206277..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -577,6 +578,9 @@ rte_eal_init(int argc, char **argv)
rte_config.master_lcore, thread_id, cpuset,
ret == 0 ? "" : "...");
 
+   if (rte_bus_scan())
+   rte_panic("Cannot scan the buses for devices\n");
+
RTE_LCORE_FOREACH_SLAVE(i) {
 
/*
@@ -613,6 +617,10 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");
 
+   /* Probe all the buses and devices/drivers on them */
+   if (rte_bus_probe())
+   rte_panic("Cannot probe devices\n");
+
if (rte_eal_dev_init() < 0)
rte_panic("Cannot init pmd devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
}
return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+   .bus = {
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+   .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+   .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c015889..c43140c 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,6 +182,8 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_bus_probe;
+   rte_bus_scan;
rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
index 9c4b014..9c91ca6 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -67,6 +67,46 @@ rte_bus_unregister(struct rte_bus *bus)
RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_bus_scan(void)
+{
+   int ret;
+   struct rte_bus *bus = NULL;
+
+   TAILQ_FOREACH(bus, &rte_bus_list, next) {
+   ret = bus->scan();
+   if (ret) {
+   RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+   bus->name);
+   /* Error in scanning any bus stops the EAL init. */
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+/* Call bus specific probe */
+int
+rte_bus_probe(void)
+{
+   int ret;
+   struct rte_bus *bus;
+
+   /* For each bus registered with EAL */
+   TAILQ_FOREACH(bus, &rte_bus_list, next) {
+   ret = bus->probe();
+   if (ret) {
+   RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
+   bus->name);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..5f2cab5 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -508,3 +509,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
rte_eal_driver_unr

Re: [dpdk-dev] [PATCH v7 9/9] eal: enable hotplugging of devices on bus

2017-01-17 Thread Shreyansh Jain

Hello Ferruh,

On Tuesday 17 January 2017 04:34 PM, Shreyansh Jain wrote:

Hi Ferruh,


-Original Message-
From: Ferruh Yigit [mailto:ferruh.yi...@intel.com]
Sent: Tuesday, January 17, 2017 4:18 PM
To: Shreyansh Jain ; david.march...@6wind.com
Cc: dev@dpdk.org; thomas.monja...@6wind.com
Subject: Re: [dpdk-dev] [PATCH v7 9/9] eal: enable hotplugging of devices on
bus

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

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

Signed-off-by: Shreyansh Jain 


<...>


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


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

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


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


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






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


<...>







Re: [dpdk-dev] [PATCH v8 1/9] eal/bus: introduce bus abstraction

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

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

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

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

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

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

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

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

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

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


Re: [dpdk-dev] [PATCH v8 2/9] test: add basic bus infrastructure tests

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

Ok. I will do that.

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

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


Re: [dpdk-dev] [PATCH v8 4/9] eal/bus: support for scanning of bus

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

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

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



Re: [dpdk-dev] [PATCH v8 3/9] pci: split match and probe function

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

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

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


Re: [dpdk-dev] [PATCH v8 2/9] test: add basic bus infrastructure tests

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

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

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

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

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

You still interested in this change?


Re: [dpdk-dev] [PATCH v8 2/9] test: add basic bus infrastructure tests

2017-01-18 Thread Shreyansh Jain

On Wednesday 18 January 2017 12:58 PM, Thomas Monjalon wrote:

2017-01-18 06:56, Shreyansh Jain:

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


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


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


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


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


When I stated rte_eal_pci_register required global lists, I meant in 
previous code base (pre bus), the pci_device_list and pci_driver_list

were public because registration function used them and test cases used
the registration function.




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

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

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

You still interested in this change?


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



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



[dpdk-dev] [PATCH v9 00/12] Introducing EAL Bus-Device-Driver Model

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

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

v8:
 - fix return value bug in rte_eal_pci_attach and rte_eal_pci_detach

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

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

v5:
 - Fix checkpatch error in Patch 0003

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

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

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

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

 app/test/Makefile   |   2 +-
 app/test/autotest_data.py   |   6 +
 app/test/test.h |   2 +
 app/test/test_bus.c | 686 
 app/test/test_pci.c | 164 --
 lib/librte_eal/bsdapp/eal/Makefile  |   1 +
 lib/librte_eal/bsdapp/eal/eal.c |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c |  17 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/common/Makefile  |   2 +-
 lib/librte_eal/common/eal_common_bus.c  | 138 +
 lib/librte_eal/common/eal_common_dev.c  |  56 +-
 lib/librte_eal/common/eal_common_pci.c  | 374 -
 lib/librte_eal/common/eal_private.h |  10 -
 lib/librte_eal/common/include/rte_bus.h | 191 +++
 lib/librte_eal/common/include/rte_dev.h |   1 +
 lib/lib

[dpdk-dev] [PATCH v9 02/12] test: add basic bus infrastructure tests

2017-01-18 Thread Shreyansh Jain
Verification of bus registration, deregistration methods.

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

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0cd598b..ea8f9ca 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -239,6 +239,12 @@ def per_sockets(num):
 "Func":default_autotest,
 "Report":  None,
 },
+{
+"Name":"Bus autotest",
+"Command": "bus_autotest",
+"Func":default_autotest,
+"Report":  None,
+},
 ]
 },
 {
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of NXP nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===.===.=,= busA
+ * |   |   . |
+ *   devA1   devA2 . 'CPU_
+ *`---`---> driverA  |
+ *   '
+ *  ===.===.===.=|= busB
+ * |   |   .
+ *   devB1   devB2 .
+ *`---`---> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS 10
+#define MAX_DRIVERS_ON_BUS 10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+   TAILQ_ENTRY(dummy_device) next;
+   const char *name;
+   struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+   TAILQ_ENTRY(dummy_driver) next;
+   const char *name;
+   struct rte_driver drv;
+};
+
+struct dummy_bus {
+   TAILQ_ENTRY

[dpdk-dev] [PATCH v9 01/12] eal/bus: introduce bus abstraction

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

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

An example implementation would be like:

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

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

diff --git a/lib/librte_eal/bsdapp/eal/Makefile 
b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..cce99f7 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..4dcf653 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,13 @@ DPDK_16.11 {
rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+   global:
+
+   rte_bus_list;
+   rte_bus_dump;
+   rte_bus_register;
+   rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 000..6e09448
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,95 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   t

[dpdk-dev] [PATCH v9 03/12] pci: split match and probe function

2017-01-18 Thread Shreyansh Jain
Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

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

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device 
*dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+ const struct rte_pci_device *pci_dev)
 {
-   int ret;
+   int match = 1;
const struct rte_pci_id *id_table;
 
-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+   RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+   return -1;
+   }
 
+   for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+id_table++) {
/* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
+   if (id_table->vendor_id != pci_dev->id.vendor_id &&
id_table->vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->device_id != dev->id.device_id &&
+   if (id_table->device_id != pci_dev->id.device_id &&
id_table->device_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_vendor_id != 
dev->id.subsystem_vendor_id &&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
+   if (id_table->subsystem_vendor_id !=
+   pci_dev->id.subsystem_vendor_id &&
+   id_table->subsystem_vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_device_id != 
dev->id.subsystem_device_id &&
-   id_table->subsystem_device_id != PCI_ANY_ID)
+   if (id_table->subsystem_device_id !=
+   pci_dev->id.subsystem_device_id &&
+   id_table->subsystem_device_id != PCI_ANY_ID)
continue;
-   if (id_table->class_id != dev->id.class_id &&
+   if (id_table->class_id != pci_dev->id.class_id &&
id_table->class_id != RTE_CLASS_ANY_ID)
continue;
 
-   struct rte_pci_addr *loc = &dev->addr;
-
-   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid, 
loc->function,
-   dev->device.numa_node);
-
-   /* no initialization when blacklisted, return without error */
-   if (dev->device.devargs != NULL &&
-   dev->device.devargs->type ==
-   RTE_DEVTYPE_BLACKLISTED_PCI) {
-   RTE_LOG(INFO, EAL, "  Device is blacklisted, not 
initializing\n");
-   return 1;
-   }
-
-   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
-
-   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-   /* map resources for devices that use igb_uio */
-   ret = rte_eal_pci_map_device(dev);
-   if (ret != 0)
-   return ret;
-   

[dpdk-dev] [PATCH v9 05/12] eal/bus: support for scanning of bus

2017-01-18 Thread Shreyansh Jain
Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_bus.c | 175 
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  14 +++
 3 files changed, 191 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
.name = "busA_impl", /* busA */
.bus = {
.name = "busA",
+   .scan = scan_fn_for_busA,
},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
.name = "busB_impl", /* busB */
.bus = {
.name = "busB",
+   .scan = scan_fn_for_busB,
},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
printf("-->8---\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map list, register.
+ *
+ * @param bus
+ * bus to scan againt test entry
+ * @return
+ * 0 for successful scan, even if no devices are found
+ * !0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+   int i = 0;
+   struct dummy_device *ddev = NULL;
+   struct dummy_bus_map *dbmap = NULL;
+   struct dummy_bus *db = NULL;
+
+   if (!bus)
+   return -1;
+
+   /* Extract the device tree node using the bus passed */
+   for (i = 0; bus_map[i].name; i++) {
+   if (!strcmp(bus_map[i].name, bus->name)) {
+   dbmap = &bus_map[i];
+   break;
+   }
+   }
+
+   if (!dbmap)
+   return -1;
+
+   db = dbmap->dbus;
+
+   /* For all the devices in the device tree (bus_map), add device */
+   for (i = 0; dbmap->ddevices[i]; i++) {
+   ddev = dbmap->ddevices[i];
+   TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+   ddev->dev.bus = bus;
+   }
+
+   return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busA") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busB") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+   int i = 0;
struct rte_bus *bus_p = NULL;
 
/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
}
 
+   /* Initialize the bus lists */
+   for (i = 0; bus_map[i].name; i++) {
+   TAILQ_INIT(&bus_map[i].dbus->device_list);
+   TAILQ_INIT(&bus_map[i].dbus->driver_list);
+   }
+
+   dump_device_tree();
return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+   int i;
+   struct rte_bus *bus = NULL;
+   struct dummy_device *ddev;
+   struct dummy_bus *dbus;
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus = &(bus_map[i].dbus->bus);
+   if (!bus) {
+   printf("Unable to find bus (%s)\n",
+  bus_map[i].name);
+   return -1;
+   }
+
+   dbus = container_of(bus, struct dummy_bus, bus);
+   /* For bus 'bus', unregister all devices */
+   TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+   TAILQ_REMOVE(&dbus->device_list, ddev, next);
+   }
+   }
+
+   for (i = 

[dpdk-dev] [PATCH v9 04/12] eal: remove loop over drivers in device detach

2017-01-18 Thread Shreyansh Jain
rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

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

Signed-off-by: Shreyansh Jain 
---
 lib/librte_eal/common/eal_common_pci.c | 41 +-
 1 file changed, 10 insertions(+), 31 deletions(-)

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



[dpdk-dev] [PATCH v9 06/12] eal/bus: introduce support for bus probing

2017-01-18 Thread Shreyansh Jain
Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

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

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 13 +
 2 files changed, 14 insertions(+)

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



[dpdk-dev] [PATCH v9 07/12] eal: integrate bus scan and probe with EAL

2017-01-18 Thread Shreyansh Jain
Add functions for scanning all the buses and performing probe on all
the buses on EAL initialization.

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

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

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

[dpdk-dev] [PATCH v9 08/12] eal/pci: add support for PCI bus

2017-01-18 Thread Shreyansh Jain
Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

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

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 lib/librte_eal/bsdapp/eal/eal.c |  1 +
 lib/librte_eal/bsdapp/eal/eal_pci.c | 11 ++
 lib/librte_eal/common/eal_common_pci.c  | 33 
 lib/librte_eal/common/include/rte_pci.h | 68 +
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 15 
 5 files changed, 128 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index f0abd82..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
}
return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+   .bus = {
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+   .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+   .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 7548ab0..d2699bd 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -487,3 +488,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
rte_eal_driver_unregister(&driver->driver);
TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+  struct rte_pci_device *pci_dev)
+{
+   TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+   /* Update Bus references */
+   pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+ struct rte_pci_device *new_pci_dev)
+{
+   TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+   /* Update Bus references */
+   new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+   struct rte_pci_bus *pci_bus;
+
+   pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+   TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+   /* Update Bus references */
+   pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_pci.h 
b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..05cf693 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include 
 #include 
 #include 
+#include 
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)\
+   TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)\
+   TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
TAILQ_ENTRY(rte_pci_driver) next;   /**< Next in list. */
struct rte_driver driver;   /**< Inherit core driver. */
+   struct rte_pci_bus *pci_bus;/**< PCI bus reference */
pci_probe_t *probe; /**< Device Probe function. */
pci_remove_t *remove;   /**< Device Remove function. */
const struct rte_pci_id *id_table;  /**< ID table, NULL terminated. 
*/
uint32_t dr

[dpdk-dev] [PATCH v9 10/12] test: add Bus based scan and probe test cases for PCI

2017-01-18 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_pci.c | 164 
 1 file changed, 114 insertions(+), 50 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+   struct rte_bus bus;
+   struct test_pci_device_list test_device_list;
+   struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+   .bus = {
+   .name = "test_pci_bus",
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
.driver = {
-   .name = "test_driver"
+   .name = "test_driver",
},
.probe = my_driver_init,
.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
.driver = {
-   .name = "test_driver2"
+   .name = "test_driver2",
},
.probe = my_driver_init,
.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct 
rte_pci_driver *dr,
return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+   int i;
+   struct rte_pci_device *dev = NULL;
+
+   TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+   fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+  dev->addr.devid, dev->addr.function);
+   fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+  dev->id.device_id);
+
+   for (i = 0; i != sizeof(dev->mem_resource) /
+   sizeof(dev->mem_resource[0]); i++) {
+   fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+   dev->mem_resource[i].phys_addr,
+   dev->mem_resource[i].len);
+   }
+   }
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+   int ret;
+   struct rte_pci_device *device;
+   struct rte_pci_driver *driver;
+
+   TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+   TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+   ret = rte_pci_match(driver, device);
+   if (!ret) {
+   if (!driver->probe)
+   continue;
+
+   device->driver = driver;
+   ret = driver->probe(driver, device);
+   if (ret != 0)
+   return ret;
+   }
+   }
+   }
+
+   return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
unsigned i = 0;
char pci_addr_str[16];
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
dev->addr.domain, dev->addr.bus, dev->addr.devid,
dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-   TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-   struct rte_pci_device *dev;
-   struct rte_pci_driver *dr;
const struct resource *r;
int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 

[dpdk-dev] [PATCH v9 09/12] test: add test cases for scan and probe on BUS

2017-01-18 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_bus.c | 152 
 1 file changed, 152 insertions(+)

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

[dpdk-dev] [PATCH v9 11/12] eal: enable PCI bus

2017-01-18 Thread Shreyansh Jain
Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_timer_init() < 0)
rte_panic("Cannot init HPET or TSC timers\n");
 
-   if (rte_eal_pci_init() < 0)
-   rte_panic("Cannot init PCI\n");
-
eal_check_mem_on_local_socket();
 
if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
 
-   /* Probe & Initialize PCI devices */
-   if (rte_eal_pci_probe())
-   rte_panic("Cannot probe PCI\n");
-
/* Probe all the buses and devices/drivers on them */
if (rte_bus_probe())
rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
.matches = &matches[0],
};
 
+   /* for debug purposes, PCI can be disabled */
+   if (internal_config.no_pci)
+   return 0;
+
fd = open("/dev/pci", O_RDONLY);
if (fd < 0) {
RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
eal_parse_sysfs_value;
eal_timer_source;
lcore_config;
-   pci_device_list;
-   pci_driver_list;
per_lcore__lcore_id;
per_lcore__rte_errno;
rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index d2699bd..a17ecaf 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-   TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -317,7 +312,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
if (dev->driver != NULL)
return 0;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_probe_one_driver(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -338,6 +333,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
struct rte_pci_device *dev = NULL;
+
int ret = 0;
 
if (addr == NULL)
@@ -349,7 +345,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
if (pci_update_device(addr) < 0)
goto err_return;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -379,7 +375,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
if (addr == NULL)
return -1;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -391,7 +387,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
/* positive value means driver doesn't support it */
continue;
 
-   TAILQ_REMOVE(&pci_device_list, dev, next);
+   rte_eal_pci_remove_device(dev);
free(dev);
return 0;
}
@@ 

Re: [dpdk-dev] [PATCH v9 04/12] eal: remove loop over drivers in device detach

2017-01-18 Thread Shreyansh Jain

Thomas,

On Wednesday 18 January 2017 04:07 PM, Shreyansh Jain wrote:

diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 4f155c6..7548ab0 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -259,15 +259,17 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
  * driver.
  */
 static int
-rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
-   struct rte_pci_device *dev)
+rte_eal_pci_detach_dev(struct rte_pci_device *dev)
 {
int ret;
struct rte_pci_addr *loc;
+   struct rte_pci_driver *dr;

-   if ((dr == NULL) || (dev == NULL))
+   if ((dev == NULL))


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


return -EINVAL;

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


-
Shreyansh


[dpdk-dev] [PATCH v9 12/12] eal: enable hotplugging of devices on bus

2017-01-18 Thread Shreyansh Jain
Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_eal_pci_scan,
.probe = rte_eal_pci_probe,
+   .attach = rte_eal_pci_attach,
+   .detach = rte_eal_pci_detach,
},
.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_probe_one(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->attach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " attach.\n", bus->name);
+   continue;
+   }
+   ret = bus->attach(name);
+   if (!ret) /* device successfully attached */
+   return ret;
+   if (ret > 0) /* device not found on bus */
+   continue;
+   else
goto err;
+   }
 
-   } else {
-   if (rte_eal_vdev_init(name, devargs))
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_init(name, devargs);
+   if (ret)
goto err;
}
 
-   return 0;
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->detach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " detach.\n", bus->name);
+   continue;
+   }
+
+   ret = bus->detach(name);
+   if (!ret) /* device successfully detached */
+   return ret;
+   if (ret > 0) /* device not found on the bus */
+   continue;
+   else
goto err;
-   } else {
-   if (rte_eal_vdev_uninit(name))
+   }
+
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_uninit(name);
+   if (ret)
goto err;
}
-   return 0;
+
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index a17ecaf..e4f37f3 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -364,19 +364,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+   struct rte_pci_device *dev = NULL;
+   struct rte_pci_driver *d

Re: [dpdk-dev] [PATCH v9 01/12] eal/bus: introduce bus abstraction

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

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

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


Re: [dpdk-dev] [PATCH v9 04/12] eal: remove loop over drivers in device detach

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

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


[dpdk-dev] [PATCH v10 00/13] Introducing EAL Bus-Device-Driver Model

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

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

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

v8:
 - fix return value bug in rte_eal_pci_attach and rte_eal_pci_detach

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

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

v5:
 - Fix checkpatch error in Patch 0003

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

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

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

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

 app/test/Makefile   |   2 +-
 app/test/autotest_data.py   |   6 +
 app/test/test.h |   2 +
 app/test/test_bus.c | 686 
 app/test/test_pci.c | 164 --
 doc/guides/rel_notes/deprecation.rst|   5 -
 lib/librte_eal/bsdapp/eal/Makefile  |   3 +-
 lib/librte_eal/bsdapp/eal/eal.c |  13 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c |  17 +
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 +-
 lib/librte_eal/com

[dpdk-dev] [PATCH v10 01/13] eal/bus: introduce bus abstraction

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

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

An example implementation would be like:

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

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

diff --git a/lib/librte_eal/bsdapp/eal/Makefile 
b/lib/librte_eal/bsdapp/eal/Makefile
index a15b762..63c1fda 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -48,7 +48,7 @@ LDLIBS += -lgcc_s
 
 EXPORT_MAP := rte_eal_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 # specific to bsdapp exec-env
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
@@ -78,6 +78,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..12298f2 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,12 @@ DPDK_16.11 {
rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+   global:
+
+   rte_bus_dump;
+   rte_bus_register;
+   rte_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index 09a3d3a..240995c 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 000..49b3516
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,95 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.

[dpdk-dev] [PATCH v10 02/13] test: add basic bus infrastructure tests

2017-01-18 Thread Shreyansh Jain
Verification of bus registration, deregistration methods.

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

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0cd598b..ea8f9ca 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -239,6 +239,12 @@ def per_sockets(num):
 "Func":default_autotest,
 "Report":  None,
 },
+{
+"Name":"Bus autotest",
+"Command": "bus_autotest",
+"Func":default_autotest,
+"Report":  None,
+},
 ]
 },
 {
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of NXP nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===.===.=,= busA
+ * |   |   . |
+ *   devA1   devA2 . 'CPU_
+ *`---`---> driverA  |
+ *   '
+ *  ===.===.===.=|= busB
+ * |   |   .
+ *   devB1   devB2 .
+ *`---`---> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS 10
+#define MAX_DRIVERS_ON_BUS 10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+   TAILQ_ENTRY(dummy_device) next;
+   const char *name;
+   struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dum

[dpdk-dev] [PATCH v10 03/13] pci: split match and probe function

2017-01-18 Thread Shreyansh Jain
Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into a public fn rte_pci_match.

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

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4dcf653..c015889 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -182,5 +182,6 @@ DPDK_17.02 {
rte_bus_dump;
rte_bus_register;
rte_bus_unregister;
+   rte_pci_match;
 
 } DPDK_16.11;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 72547bd..4f155c6 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,129 +152,148 @@ pci_unmap_resource(void *requested_addr, size_t size)
requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device 
*dev)
+int
+rte_pci_match(const struct rte_pci_driver *pci_drv,
+ const struct rte_pci_device *pci_dev)
 {
-   int ret;
+   int match = 1;
const struct rte_pci_id *id_table;
 
-   for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+   if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+   RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+   return -1;
+   }
 
+   for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+id_table++) {
/* check if device's identifiers match the driver's ones */
-   if (id_table->vendor_id != dev->id.vendor_id &&
+   if (id_table->vendor_id != pci_dev->id.vendor_id &&
id_table->vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->device_id != dev->id.device_id &&
+   if (id_table->device_id != pci_dev->id.device_id &&
id_table->device_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_vendor_id != 
dev->id.subsystem_vendor_id &&
-   id_table->subsystem_vendor_id != PCI_ANY_ID)
+   if (id_table->subsystem_vendor_id !=
+   pci_dev->id.subsystem_vendor_id &&
+   id_table->subsystem_vendor_id != PCI_ANY_ID)
continue;
-   if (id_table->subsystem_device_id != 
dev->id.subsystem_device_id &&
-   id_table->subsystem_device_id != PCI_ANY_ID)
+   if (id_table->subsystem_device_id !=
+   pci_dev->id.subsystem_device_id &&
+   id_table->subsystem_device_id != PCI_ANY_ID)
continue;
-   if (id_table->class_id != dev->id.class_id &&
+   if (id_table->class_id != pci_dev->id.class_id &&
id_table->class_id != RTE_CLASS_ANY_ID)
continue;
 
-   struct rte_pci_addr *loc = &dev->addr;
-
-   RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket 
%i\n",
-   loc->domain, loc->bus, loc->devid, 
loc->function,
-   dev->device.numa_node);
-
-   /* no initialization when blacklisted, return without error */
-   if (dev->device.devargs != NULL &&
-   dev->device.devargs->type ==
-   RTE_DEVTYPE_BLACKLISTED_PCI) {
-   RTE_LOG(INFO, EAL, "  Device is blacklisted, not 
initializing\n");
-   return 1;
-   }
-
-   RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", 
dev->id.vendor_id,
-   dev->id.device_id, dr->driver.name);
-
-   if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-   /* map resources for devices that use igb_uio */
-   ret = rte_eal_pci_map_device(dev);
-   if (ret != 0)
-   return ret;
-   

[dpdk-dev] [PATCH v10 05/13] eal/bus: support for scanning of bus

2017-01-18 Thread Shreyansh Jain
Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_bus.c | 175 
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  14 +++
 3 files changed, 191 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
.name = "busA_impl", /* busA */
.bus = {
.name = "busA",
+   .scan = scan_fn_for_busA,
},
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
.name = "busB_impl", /* busB */
.bus = {
.name = "busB",
+   .scan = scan_fn_for_busB,
},
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
printf("-->8---\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map list, register.
+ *
+ * @param bus
+ * bus to scan againt test entry
+ * @return
+ * 0 for successful scan, even if no devices are found
+ * !0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+   int i = 0;
+   struct dummy_device *ddev = NULL;
+   struct dummy_bus_map *dbmap = NULL;
+   struct dummy_bus *db = NULL;
+
+   if (!bus)
+   return -1;
+
+   /* Extract the device tree node using the bus passed */
+   for (i = 0; bus_map[i].name; i++) {
+   if (!strcmp(bus_map[i].name, bus->name)) {
+   dbmap = &bus_map[i];
+   break;
+   }
+   }
+
+   if (!dbmap)
+   return -1;
+
+   db = dbmap->dbus;
+
+   /* For all the devices in the device tree (bus_map), add device */
+   for (i = 0; dbmap->ddevices[i]; i++) {
+   ddev = dbmap->ddevices[i];
+   TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+   ddev->dev.bus = bus;
+   }
+
+   return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busA") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+   struct dummy_bus_map *dbm;
+
+   dbm = &bus_map[0];
+   while (dbm) {
+   if (strcmp(dbm->name, "busB") == 0)
+   return generic_scan_fn(&dbm->dbus->bus);
+   dbm++;
+   }
+   return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+   int i = 0;
struct rte_bus *bus_p = NULL;
 
/* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
}
 
+   /* Initialize the bus lists */
+   for (i = 0; bus_map[i].name; i++) {
+   TAILQ_INIT(&bus_map[i].dbus->device_list);
+   TAILQ_INIT(&bus_map[i].dbus->driver_list);
+   }
+
+   dump_device_tree();
return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+   int i;
+   struct rte_bus *bus = NULL;
+   struct dummy_device *ddev;
+   struct dummy_bus *dbus;
+
+   for (i = 0; bus_map[i].name; i++) {
+   bus = &(bus_map[i].dbus->bus);
+   if (!bus) {
+   printf("Unable to find bus (%s)\n",
+  bus_map[i].name);
+   return -1;
+   }
+
+   dbus = container_of(bus, struct dummy_bus, bus);
+   /* For bus 'bus', unregister all devices */
+   TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+   TAILQ_REMOVE(&dbus->device_list, ddev, next);
+   }
+   }
+
+   for (i = 

[dpdk-dev] [PATCH v10 06/13] eal/bus: introduce support for bus probing

2017-01-18 Thread Shreyansh Jain
Bus implementations can implement a probe handler to match the devices
scanned against the drivers registered.

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

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 lib/librte_eal/common/eal_common_bus.c  |  1 +
 lib/librte_eal/common/include/rte_bus.h | 13 +
 2 files changed, 14 insertions(+)

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



[dpdk-dev] [PATCH v10 04/13] eal: remove loop over drivers in device detach

2017-01-18 Thread Shreyansh Jain
rte_eal_pci_detach calls pci_detach_all_drivers which loops over all
PCI drivers for detaching the device. This is unnecessary as the device
already has the PCI driver reference which can be used directly.

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

Signed-off-by: Shreyansh Jain 
---
 lib/librte_eal/common/eal_common_pci.c | 47 +++---
 1 file changed, 9 insertions(+), 38 deletions(-)

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



[dpdk-dev] [PATCH v10 07/13] eal: integrate bus scan and probe with EAL

2017-01-18 Thread Shreyansh Jain
Add functions for scanning all the buses and performing probe on all
the buses on EAL initialization.

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

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

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

[dpdk-dev] [PATCH v10 08/13] eal/pci: add support for PCI bus

2017-01-18 Thread Shreyansh Jain
Based on EAL Bus APIs, PCI bus callbacks and support functions are
introduced in this patch.

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

Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 lib/librte_eal/bsdapp/eal/eal.c |  1 +
 lib/librte_eal/bsdapp/eal/eal_pci.c | 11 ++
 lib/librte_eal/common/eal_common_pci.c  | 33 
 lib/librte_eal/common/include/rte_pci.h | 68 +
 lib/librte_eal/linuxapp/eal/eal_pci.c   | 15 
 5 files changed, 128 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index f0abd82..a584447 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 3a5c315..48bfe24 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -673,3 +673,14 @@ rte_eal_pci_init(void)
}
return 0;
 }
+
+struct rte_pci_bus rte_pci_bus = {
+   .bus = {
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+   .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
+   .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
+};
+
+RTE_REGISTER_BUS(PCI_BUS_NAME, rte_pci_bus.bus);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 8b4ae2d..4cde957 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -479,3 +480,35 @@ rte_eal_pci_unregister(struct rte_pci_driver *driver)
rte_eal_driver_unregister(&driver->driver);
TAILQ_REMOVE(&pci_driver_list, driver, next);
 }
+
+/* Add a PCI device to PCI Bus */
+void
+rte_eal_pci_add_device(struct rte_pci_bus *pci_bus,
+  struct rte_pci_device *pci_dev)
+{
+   TAILQ_INSERT_TAIL(&pci_bus->device_list, pci_dev, next);
+   /* Update Bus references */
+   pci_dev->device.bus = &pci_bus->bus;
+}
+
+/* Insert a PCI device into a predefined position in PCI bus */
+void
+rte_eal_pci_insert_device(struct rte_pci_device *exist_pci_dev,
+ struct rte_pci_device *new_pci_dev)
+{
+   TAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);
+   /* Update Bus references */
+   new_pci_dev->device.bus = exist_pci_dev->device.bus;
+}
+
+/* Remove a PCI device from PCI bus */
+void
+rte_eal_pci_remove_device(struct rte_pci_device *pci_dev)
+{
+   struct rte_pci_bus *pci_bus;
+
+   pci_bus = container_of(pci_dev->device.bus, struct rte_pci_bus, bus);
+   TAILQ_REMOVE(&pci_bus->device_list, pci_dev, next);
+   /* Update Bus references */
+   pci_dev->device.bus = NULL;
+}
diff --git a/lib/librte_eal/common/include/rte_pci.h 
b/lib/librte_eal/common/include/rte_pci.h
index adc20b9..05cf693 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -85,6 +85,7 @@ extern "C" {
 #include 
 #include 
 #include 
+#include 
 
 TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
 TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
@@ -111,6 +112,25 @@ const char *pci_get_sysfs_path(void);
 /** Maximum number of PCI resources. */
 #define PCI_MAX_RESOURCE 6
 
+/** Name of PCI Bus */
+#define PCI_BUS_NAME "PCI"
+
+/* Forward declarations */
+struct rte_pci_device;
+struct rte_pci_driver;
+
+/** List of PCI devices */
+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);
+
+/* PCI Bus iterators */
+#define FOREACH_DEVICE_ON_PCIBUS(p)\
+   TAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)
+
+#define FOREACH_DRIVER_ON_PCIBUS(p)\
+   TAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)
+
 /**
  * A structure describing an ID for a PCI driver. Each driver provides a
  * table of these IDs for each device that it supports.
@@ -206,12 +226,22 @@ typedef int (pci_remove_t)(struct rte_pci_device *);
 struct rte_pci_driver {
TAILQ_ENTRY(rte_pci_driver) next;   /**< Next in list. */
struct rte_driver driver;   /**< Inherit core driver. */
+   struct rte_pci_bus *pci_bus;/**< PCI bus reference */
pci_probe_t *probe; /**< Device Probe function. */
pci_remove_t *remove;   /**< Device Remove function. */
const struct rte_pci_id *id_table;  /**< ID table, NULL terminated. 
*/
uint32_t dr

[dpdk-dev] [PATCH v10 09/13] test: add test cases for scan and probe on BUS

2017-01-18 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_bus.c | 152 
 1 file changed, 152 insertions(+)

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

[dpdk-dev] [PATCH v10 10/13] test: add Bus based scan and probe test cases for PCI

2017-01-18 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
Reviewed-by: Ferruh Yigit 
---
 app/test/test_pci.c | 164 
 1 file changed, 114 insertions(+), 50 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..09261cc 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -38,9 +38,11 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #include "test.h"
 #include "resource.h"
@@ -61,10 +63,31 @@
 
 int test_pci_run = 0; /* value checked by the multiprocess test */
 static unsigned pci_dev_count;
+struct test_pci_bus;
+static struct test_pci_bus *pci_bus; /* global reference to a Test PCI bus */
+
+/** List of PCI devices */
+TAILQ_HEAD(test_pci_device_list, rte_pci_device);
+/** List of PCI drivers */
+TAILQ_HEAD(test_pci_driver_list, rte_pci_driver);
 
 static int my_driver_init(struct rte_pci_driver *dr,
  struct rte_pci_device *dev);
 
+struct test_pci_bus {
+   struct rte_bus bus;
+   struct test_pci_device_list test_device_list;
+   struct test_pci_driver_list test_driver_list;
+};
+
+struct test_pci_bus test_pci_bus = {
+   .bus = {
+   .name = "test_pci_bus",
+   .scan = rte_eal_pci_scan,
+   .probe = rte_eal_pci_probe,
+   },
+};
+
 /* IXGBE NICS */
 struct rte_pci_id my_driver_id[] = {
{RTE_PCI_DEVICE(0x0001, 0x1234)},
@@ -79,7 +102,7 @@ struct rte_pci_id my_driver_id2[] = {
 
 struct rte_pci_driver my_driver = {
.driver = {
-   .name = "test_driver"
+   .name = "test_driver",
},
.probe = my_driver_init,
.id_table = my_driver_id,
@@ -88,7 +111,7 @@ struct rte_pci_driver my_driver = {
 
 struct rte_pci_driver my_driver2 = {
.driver = {
-   .name = "test_driver2"
+   .name = "test_driver2",
},
.probe = my_driver_init,
.id_table = my_driver_id2,
@@ -108,6 +131,55 @@ my_driver_init(__attribute__((unused)) struct 
rte_pci_driver *dr,
return 0;
 }
 
+/* dump devices on the bus */
+static void
+do_pci_device_dump(FILE *f)
+{
+   int i;
+   struct rte_pci_device *dev = NULL;
+
+   TAILQ_FOREACH(dev, &test_pci_bus.test_device_list, next) {
+
+   fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
+  dev->addr.devid, dev->addr.function);
+   fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
+  dev->id.device_id);
+
+   for (i = 0; i != sizeof(dev->mem_resource) /
+   sizeof(dev->mem_resource[0]); i++) {
+   fprintf(f, "   %16.16"PRIx64" %16.16"PRIx64"\n",
+   dev->mem_resource[i].phys_addr,
+   dev->mem_resource[i].len);
+   }
+   }
+}
+
+/* Dummy implementation for rte_eal_pci_probe() over test_pci_bus */
+static int
+do_pci_bus_probe(void)
+{
+   int ret;
+   struct rte_pci_device *device;
+   struct rte_pci_driver *driver;
+
+   TAILQ_FOREACH(device, &test_pci_bus.test_device_list, next) {
+   TAILQ_FOREACH(driver, &test_pci_bus.test_driver_list, next) {
+   ret = rte_pci_match(driver, device);
+   if (!ret) {
+   if (!driver->probe)
+   continue;
+
+   device->driver = driver;
+   ret = driver->probe(driver, device);
+   if (ret != 0)
+   return ret;
+   }
+   }
+   }
+
+   return 0;
+}
+
 static void
 blacklist_all_devices(void)
 {
@@ -115,7 +187,7 @@ blacklist_all_devices(void)
unsigned i = 0;
char pci_addr_str[16];
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   TAILQ_FOREACH(dev, &(test_pci_bus.test_device_list), next) {
snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT,
dev->addr.domain, dev->addr.bus, dev->addr.devid,
dev->addr.function);
@@ -142,19 +214,11 @@ static void free_devargs_list(void)
}
 }
 
-/* backup real devices & drivers (not used for testing) */
-struct pci_driver_list real_pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
-struct pci_device_list real_pci_device_list =
-   TAILQ_HEAD_INITIALIZER(real_pci_device_list);
-
 REGISTER_LINKED_RESOURCE(test_pci_sysfs);
 
 static int
 test_pci_setup(void)
 {
-   struct rte_pci_device *dev;
-   struct rte_pci_driver *dr;
const struct resource *r;
int ret;
 
@@ -167,22 +231,22 @@ test_pci_setup(void)
 

[dpdk-dev] [PATCH v10 11/13] eal: enable PCI bus

2017-01-18 Thread Shreyansh Jain
Remove EAL initiated direct PCI scan/probe and enable PCI Bus linkage.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a584447..a7f2671 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_timer_init() < 0)
rte_panic("Cannot init HPET or TSC timers\n");
 
-   if (rte_eal_pci_init() < 0)
-   rte_panic("Cannot init PCI\n");
-
eal_check_mem_on_local_socket();
 
if (eal_plugins_init() < 0)
@@ -613,10 +610,6 @@ rte_eal_init(int argc, char **argv)
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
 
-   /* Probe & Initialize PCI devices */
-   if (rte_eal_pci_probe())
-   rte_panic("Cannot probe PCI\n");
-
/* Probe all the buses and devices/drivers on them */
if (rte_bus_probe())
rte_panic("Cannot probe devices\n");
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 48bfe24..e0deded 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -365,6 +365,10 @@ rte_eal_pci_scan(void)
.matches = &matches[0],
};
 
+   /* for debug purposes, PCI can be disabled */
+   if (internal_config.no_pci)
+   return 0;
+
fd = open("/dev/pci", O_RDONLY);
if (fd < 0) {
RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map 
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c43140c..f9ec086 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
eal_parse_sysfs_value;
eal_timer_source;
lcore_config;
-   pci_device_list;
-   pci_driver_list;
per_lcore__lcore_id;
per_lcore__rte_errno;
rte_calloc;
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index 4cde957..ca7c0ce 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-   TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-   TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -309,7 +304,7 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
if (dev->driver != NULL)
return 0;
 
-   TAILQ_FOREACH(dr, &pci_driver_list, next) {
+   FOREACH_DRIVER_ON_PCIBUS(dr) {
rc = rte_eal_pci_probe_one_driver(dr, dev);
if (rc < 0)
/* negative value is an error */
@@ -330,6 +325,7 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
struct rte_pci_device *dev = NULL;
+
int ret = 0;
 
if (addr == NULL)
@@ -341,7 +337,7 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
if (pci_update_device(addr) < 0)
goto err_return;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -371,7 +367,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
if (addr == NULL)
return -1;
 
-   TAILQ_FOREACH(dev, &pci_device_list, next) {
+   FOREACH_DEVICE_ON_PCIBUS(dev) {
if (rte_eal_compare_pci_addr(&dev->addr, addr))
continue;
 
@@ -383,7 +379,7 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
/* positive value means driver doesn't support it */
continue;
 
-   TAILQ_REMOVE(&pci_device_list, dev, next);
+   rte_eal_pci_remove_device(dev);
free(dev);
return 0;
}
@@ 

[dpdk-dev] [PATCH v10 12/13] eal: enable hotplugging of devices on bus

2017-01-18 Thread Shreyansh Jain
Given a bus, attach and detach callbacks allow the implementation to
handles calls from EAL for attaching or detaching a named device.

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

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c 
b/lib/librte_eal/bsdapp/eal/eal_pci.c
index e0deded..7d7f90c 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -682,6 +682,8 @@ struct rte_pci_bus rte_pci_bus = {
.bus = {
.scan = rte_eal_pci_scan,
.probe = rte_eal_pci_probe,
+   .attach = rte_eal_pci_attach,
+   .detach = rte_eal_pci_detach,
},
.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
diff --git a/lib/librte_eal/common/eal_common_dev.c 
b/lib/librte_eal/common/eal_common_dev.c
index 4f3b493..97d0cf5 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -38,6 +38,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -106,23 +107,37 @@ rte_eal_dev_init(void)
 
 int rte_eal_dev_attach(const char *name, const char *devargs)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_probe_one(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->attach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " attach.\n", bus->name);
+   continue;
+   }
+   ret = bus->attach(name);
+   if (!ret) /* device successfully attached */
+   return ret;
+   if (ret > 0) /* device not found on bus */
+   continue;
+   else
goto err;
+   }
 
-   } else {
-   if (rte_eal_vdev_init(name, devargs))
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_init(name, devargs);
+   if (ret)
goto err;
}
 
-   return 0;
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n", name);
@@ -131,21 +146,38 @@ int rte_eal_dev_attach(const char *name, const char 
*devargs)
 
 int rte_eal_dev_detach(const char *name)
 {
-   struct rte_pci_addr addr;
+   int ret = 1;
+   struct rte_bus *bus;
 
if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}
 
-   if (eal_parse_pci_DomBDF(name, &addr) == 0) {
-   if (rte_eal_pci_detach(&addr) < 0)
+   FOREACH_BUS(bus) {
+   if (!bus->detach) {
+   RTE_LOG(DEBUG, EAL, "Bus (%s) doesn't implement"
+   " detach.\n", bus->name);
+   continue;
+   }
+
+   ret = bus->detach(name);
+   if (!ret) /* device successfully detached */
+   return ret;
+   if (ret > 0) /* device not found on the bus */
+   continue;
+   else
goto err;
-   } else {
-   if (rte_eal_vdev_uninit(name))
+   }
+
+   if (ret > 0) {
+   /* In case the device was not found on any bus, search VDEV */
+   ret = rte_eal_vdev_uninit(name);
+   if (ret)
goto err;
}
-   return 0;
+
+   return ret;
 
 err:
RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n", name);
diff --git a/lib/librte_eal/common/eal_common_pci.c 
b/lib/librte_eal/common/eal_common_pci.c
index ca7c0ce..7991645 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -356,19 +356,98 @@ rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 }
 
 /*
+ * Attach device specific by its name
+ */
+int
+rte_eal_pci_attach(const char *device_name)
+{
+   struct rte_pci_device *dev = NULL;
+   struct rte_pci_driver *d

[dpdk-dev] [PATCH v10 13/13] doc: remove deprecation notice for rte_bus

2017-01-18 Thread Shreyansh Jain
Signed-off-by: Shreyansh Jain 
---
 doc/guides/rel_notes/deprecation.rst | 5 -
 1 file changed, 5 deletions(-)

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



Re: [dpdk-dev] [PATCHv5 04/33] bus/fslmc: introducing fsl-mc bus driver

2017-01-19 Thread Shreyansh Jain

On Friday 20 January 2017 12:38 AM, Ferruh Yigit wrote:

On 1/19/2017 1:23 PM, Hemant Agrawal wrote:

The fslmc bus driver is a rte_bus driver which scans the fsl-mc bus
for NXP DPAA2 SoCs.

Signed-off-by: Hemant Agrawal 
---


<...>


+#
+# library name
+#
+LIB = librte_pmd_fslmcbus.a


Since now there is a bus folder/driver, what do you think nameming
library with librte_bus_ prefix, like: librte_bus_fslmc.a

<...>


+
+static int
+rte_fslmc_probe(void)
+{
+   int ret = -1;


If any bus->probe() fails, rte_bus_probe() breaks and returns error,
which cause app to exit.
Here if there is no device or driver in the bus, function is returning
error, I guess it should be returning zero for this case.


It is a nice point of discussion (even in the bus patch). Should Bus 
iteration for scan/probe fail if any bus implementation fails?


In the initial series I had placed a 'TODO' in the bus patch to get some 
comments - I couldn't make a decision so the final bus scan/probe loop 
'fails if any bus fails whether in scan or probe'.


I think that EAL should continue looping over buses irrespective of bus 
failure - specially removing such dependencies on bus implementations to 
return a valid code compatible with EAL's design.





+   struct rte_dpaa2_device *dev;
+   struct rte_dpaa2_driver *drv;
+
+   TAILQ_FOREACH(dev, &rte_fslmc_bus.device_list, next) {
+   TAILQ_FOREACH(drv, &rte_fslmc_bus.driver_list, next) {
+   ret = rte_fslmc_match(drv, dev);
+   if (ret)
+   continue;
+
+   if (!drv->probe)
+   continue;
+
+   ret = drv->probe(drv, dev);
+   if (ret)
+   FSLMC_BUS_LOG(ERR, "Unable to probe.\n");
+   break;
+   }
+   }
+   return ret;
+}


<...>





Re: [dpdk-dev] [PATCHv5 13/33] net/dpaa2: introducing NXP dpaa2 pmd driver

2017-01-20 Thread Shreyansh Jain

Hello Ferruh,

On Friday 20 January 2017 12:45 AM, Ferruh Yigit wrote:

On 1/19/2017 1:23 PM, Hemant Agrawal wrote:

add support for fsl-mc bus based dpaa2 pmd driver.

Signed-off-by: Hemant Agrawal 


<...>


diff --git a/drivers/common/Makefile b/drivers/common/Makefile
index e5bfecb..76ec2d1 100644
--- a/drivers/common/Makefile
+++ b/drivers/common/Makefile
@@ -31,6 +31,8 @@

 include $(RTE_SDK)/mk/rte.vars.mk

+CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_DPAA2_PMD)


This logic make sense, is there any reason DPAA2_COMMON to be a config
option, it doesn't look like something a user would like to change on
its own.


I am assuming you wanted to say "The logic _doesn't_ make sense, ..." :)



Instead, as done here, if there is a user of common folder it is enabled
in Makefile. For this DPAA2_COMMON doesn't need to be a config option
itself I think.


Aim of drivers/common was to introduce libraries which may be used by
more than one sub-system. These can be other than dpaa2 and may even
be external to DPDK framework itself.

But for now, we will remove it and keep it toggleable with rte.app.mk
changes. Maybe in future, if need for configurable option exist, we will
introduce.




+
 DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_COMMON) += dpaa2

 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 40fc333..f716ca0 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -57,7 +57,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt
-
+DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2


Add alphabetically please.


Agree.




 ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost
 endif # $(CONFIG_RTE_LIBRTE_VHOST)


<...>


diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c
new file mode 100644
index 000..2295f82
--- /dev/null
+++ b/drivers/net/dpaa2/dpaa2_ethdev.c

<...>

+/* Name of the DPAA2 Net PMD */
+static const char *drivername = "DPAA2 PMD";


Custom names not preferred, please check any other PMD to be consistent.


Yes, this should be changed.



<...>


+static int
+rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv,
+   struct rte_dpaa2_device *dpaa2_dev)
+{
+   struct eth_driver*eth_drv;


whitespace error.


Fixed. Thanks.




+   struct rte_eth_dev *eth_dev;
+   char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+   int diag;
+
+   eth_drv = (struct eth_driver *)dpaa2_drv;


How this suppose to work?


Actually, a not-so-clean-logic coupled with the above line which 
probably got added in one of our rebasing attempts. And you have pointed

out correctly - because of eth_driver<->pci_driver restriction.

(more below)



struct eth_driver {

struct rte_pci_driver pci_drv;
eth_dev_init_t eth_dev_init;
eth_dev_uninit_t eth_dev_uninit;
unsigned int dev_private_size;
};

struct rte_dpaa2_driver {
TAILQ_ENTRY(rte_dpaa2_driver) next;
struct rte_driver driver;
struct rte_fslmc_bus *fslmc_bus;
uint32_t drv_flags;
uint16_t drv_type;
rte_dpaa2_probe_t probe
rte_dpaa2_remove_t remove;
};


dpaa2 driver is not using eth_drv - it is more of a dummy.

If we had used rte_eth_dev_pci_probe, we would have faced this issue of
delinking eth_driver from pci_probe. So, we have leveraged the
bus->probe and created our own probing routine (rather than use 
rte_eth_dev_pci_probe).


Then, because it is our own probe routine, we simply allocate the
eth_dev (which luckily is free from pci_dev), and call our dev_init,
which rte_eth_dev_pci_probe would have done using eth_drv->init().

(More below)





+
+   sprintf(ethdev_name, "dpni-%d", dpaa2_dev->object_id);
+
+   eth_dev = rte_eth_dev_allocate(ethdev_name);
+   if (eth_dev == NULL)
+   return -ENOMEM;
+
+   if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+   eth_dev->data->dev_private = rte_zmalloc(
+   "ethdev private structure",
+   sizeof(struct dpaa2_dev_priv),
+   RTE_CACHE_LINE_SIZE);
+   if (eth_dev->data->dev_private == NULL) {
+   RTE_LOG(CRIT, PMD, "Cannot allocate memzone for"
+   " private port data\n");
+   return -ENOMEM;


release allocated port?


Yes, I will fix this.




+   }
+   }
+   eth_dev->device = &dpaa2_dev->device;
+   dpaa2_dev->eth_dev = eth_dev;
+   eth_dev->driver = eth_drv;
+   eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+   /* init user callbacks */
+   TAILQ_INIT(ð_dev->link_intr_cbs);


This is no more required, since done by rte_eth_dev_allocate()


yes, through eth_de

Re: [dpdk-dev] [PATCHv6 02/33] drivers/common/dpaa2: adding qbman driver

2017-01-23 Thread Shreyansh Jain

Hello Ferruh,

On Monday 23 January 2017 11:00 PM, Ferruh Yigit wrote:

On 1/23/2017 11:59 AM, Hemant Agrawal wrote:

QBMAN, is a hardware block which interfaces with the other
accelerating hardware blocks (For e.g., WRIOP) on NXP's DPAA2
SoC for queue, buffer and packet scheduling.

This patch introduces a userspace driver for interfacing with
the QBMAN hw block.

The qbman-portal component provides APIs to do the low level
hardware bit twiddling for operations such as:
  -initializing Qman software portals
  -building and sending portal commands
  -portal interrupt configuration and processing

This same/similar code is used in kernel and compat file is used
to make it working in user space.

Signed-off-by: Geoff Thorpe 
Signed-off-by: Roy Pledge 
Signed-off-by: Hemant Agrawal 
---

<...>


--- a/config/common_base
+++ b/config/common_base
@@ -287,7 +287,6 @@ CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_TX=n
 CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_DRIVER=n
 CONFIG_RTE_LIBRTE_THUNDERX_NICVF_DEBUG_MBOX=n

-#


Ah, yes, stray removal. We will remove it.
(Thanks for review - really appreciate your help).



Minor typo ..


 # Compile burst-oriented VIRTIO PMD driver
 #
 CONFIG_RTE_LIBRTE_VIRTIO_PMD=y


<...>


--- /dev/null
+++ b/drivers/common/dpaa2/qbman/rte_common_dpaa2_qbman_version.map
@@ -0,0 +1,27 @@
+DPDK_17.02 {
+   global:
+
+   qbman_check_command_complete;
+   qbman_eq_desc_clear;
+   qbman_eq_desc_set_fq;
+   qbman_eq_desc_set_no_orp;
+   qbman_eq_desc_set_qd;
+   qbman_eq_desc_set_response;
+   qbman_get_version;
+   qbman_pull_desc_clear;
+   qbman_pull_desc_set_fq;
+   qbman_pull_desc_set_numframes;
+   qbman_pull_desc_set_storage;
+   qbman_release_desc_clear;
+   qbman_release_desc_set_bpid;
+   qbman_result_DQ_fd;
+   qbman_result_DQ_flags;
+   qbman_result_has_new_result;
+   qbman_swp_acquire;
+   qbman_swp_init;
+   qbman_swp_pull;
+   qbman_swp_release;
+   qbman_swp_send_multiple;


Overall, dpdk library exported APIs not having DPDK prefix (rte_) is a
concern, which already pointed by Thomas.

I guess only user of this library will be other dpaa2 code, so these are
not really APIs. Not sure how to proceed.
I think I have seen "_rte" prefix used in some APIs to say that is
internal API, does it make sense to use that API here?


We had a detailed discussion on this internally after Thomas' comments.
It is very difficult to convert all such symbols - primarily because it
will break the 'linkage' between our Linux upstream candidate code,
internal repositories and what we are pushing to DPDK.

This is happening because we are spreading our common libraries beyond
the drivers/net/* scope. If we combine all of them together (no
drivers/common, drivers/pool etc), these symbols would not be exposed.

There was a discussion on ML as well for this kind of structure on our
first RFC submission.
We were in favor of a split design because that makes the overall PMD
look clean. But, this rte_* prefix issue is something we never
anticipated.

Further, we took hint from existing map files which also had similar
non rte_* symbols (per_lcore_*, devargs_list, pci_device_list etc) to
convince ourselves that this is not a strict rule.

As for "_rte" - once again, we need to define what internal is when it
comes to drivers/common, drivers/bus, drivers/pool .. kind of code
layout having functionality divided. It might be internal to framework
(limited to drivers/*) but would be external for a drivers/net/*.

Overall, a serious discussion on this is indeed needed for clarity as
more non-PCI drivers might contributed in near future with basic bus
infra in place.




+
+   local: *;
+};








Re: [dpdk-dev] [PATCHv6 12/33] net/dpaa2: introducing NXP dpaa2 pmd driver

2017-01-24 Thread Shreyansh Jain

On Monday 23 January 2017 11:02 PM, Ferruh Yigit wrote:

On 1/23/2017 11:59 AM, Hemant Agrawal wrote:

add support for fsl-mc bus based dpaa2 pmd driver.

Signed-off-by: Hemant Agrawal 
---

<...>


diff --git a/drivers/net/dpaa2/Makefile b/drivers/net/dpaa2/Makefile
new file mode 100644
index 000..f85aa9f
--- /dev/null
+++ b/drivers/net/dpaa2/Makefile

<...>

+
+# library dependencies
+DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += lib/librte_eal lib/librte_ether
+DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += lib/librte_bus_fslmc


Is this dependency correct?


I think yes.
- Without Bus, dpaa2 PMD wouldn't work and being a configurable option,
  user can set CONFIG_RTE_LIBRTE_DPAA2_PMD=n and
  CONFIG_RTE_LIBRTE_DPAA2_PMD=y.

- If you referring to whether lib/librte_bus_fslmc is correct or not, I
  have replied to your response on 16/33 patch. In short, I think this
  is correct assuming that librte_bus_fslmc is valid LIB name and not
  expected to be a folder in lib/




+
+include $(RTE_SDK)/mk/rte.lib.mk


<...>





Re: [dpdk-dev] [PATCHv6 16/33] drivers/pool/dpaa2: adding hw offloaded mempool

2017-01-24 Thread Shreyansh Jain

On Monday 23 January 2017 11:04 PM, Ferruh Yigit wrote:

On 1/23/2017 11:59 AM, Hemant Agrawal wrote:

Adding NXP DPAA2 architecture specific mempool support
Each mempool instance is represented by a DPBP object
from the FSL-MC bus.

This patch also registers a dpaa2 type MEMPOOL OPS

Signed-off-by: Hemant Agrawal 
---

<...>


diff --git a/drivers/common/Makefile b/drivers/common/Makefile
index b52931c..0bb75b5 100644
--- a/drivers/common/Makefile
+++ b/drivers/common/Makefile
@@ -35,7 +35,11 @@ ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_PMD),y)
 CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_DPAA2_PMD)
 endif

-ifeq ($(CONFIG_RTE_LIBRTE_FSLMC_BUS),y)
+ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_POOL),y)
+CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_DPAA2_POOL)
+endif
+
+ifneq ($(CONFIG_RTE_LIBRTE_FSLMC_BUS),y)


I guess this is a typo, but this prevents DPAA2_COMMON to be compiled !!


It should be 'ifeq' rather than 'ifneq'. And it will prevent COMMON
compilation only if CONFIG_RTE_LIBRTE_FSLMC_BUS=n which is not the case
right now.

We will fix it.




 CONFIG_RTE_LIBRTE_DPAA2_COMMON = $(CONFIG_RTE_LIBRTE_FSLMC_BUS)
 endif



<...>

+# library dependencies
+DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_POOL) += lib/librte_eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_POOL) += lib/librte_mempool
+DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_POOL) += lib/librte_common_dpaa2_qbman


This dependeny doesn not looks correct, there is no folder like that.


This is something even I need to understand. From the DEPDIRS what I
understood was that though it refers to a directory, it essentially
links libraries in build/lib/*.

Further, somehow the development is deploying drivers/bus,
drivers/common and drivers/pool in lib/* under the name specified as
LIB in Makefile. My understanding was that it is expected behavior and
not special because of drivers folder.

Thus, above line only links lib/librte_common_dpaa2_qbman generated by
drivers/common/dpaa2/qbman code.

In fact, I think, this might also one of the issues why a parallel 
shared build fails for DPAA2 PMD (added in Cover letter).

The dependency graph cannot create a graph for drivers/common
as dependency for drivers/net or drivers/bus and hence parallel build
fails because of missing libraries which are being parallely compiled.




+DEPDIRS-$(CONFIG_RTE_LIBRTE_DPAA2_POOL) += lib/librte_bus_fslmc
+
+include $(RTE_SDK)/mk/rte.lib.mk


<...>





[dpdk-dev] NXP DPAA2: Symbol renaming issue: Request for Suggestions

2017-01-24 Thread Shreyansh Jain
Hello,

We are facing a peculiar problem with respect to symbol namespace in DPDK. I
think Ferruh and Thomas would have fair idea about it as they have already
reviewed and commented on it. I was hoping to get some input to take it
forward from here.

Brief Intro to DPAA2 Architecture:

This is brief about NXP's DPAA2 PMD to start with:
(A lot more information is available at [1])


 
 +---+   
 | Application   | 
 +..-+ 
  ||   
 +'--+   +-'-+ 
drivers/>|   DPIO|   |   DPIO|<---drivers/bus/fslmc
 bus/fslmc   +.--+   +--.+
  | |  
 +/-||--||--/+ 
 |   Queue/Buffer Manager|<--- drivers/common/dpaa2 
 
 +\-||--||--\+  qbman
  | | 
 +'--+   +--'+ 
drivers/ --->|   DPNI|   |   DPSEC   |<---drivers/cyrpto
 net/dpaa2   +|--+   +-|-+ dpaa2_sec
  ||  
 +|--+  +--|-+   ++
 | PHY H/W   |  |   SEC H/W  |  .> FSL MC BUS |
 +---+  ++ / ++
  drivers/bus/fslmc
  
  
If we consider the above layout, drivers/crypto/dpaa_sec (NXP's DPAA2 Crypto
PMD, already available on ML [2]), and drivers/net/dpaa2 (NXP's DPAA2 PMD) are
using a common code (drivers/common/dpaa2/qbman).

QBMAN (drivers/common/dpaa2/qbman) is essentially a Queue and Buffer Manager
set of APIs which allow DPIO (Data Path IO interfaces) to communicate with the
Hardware through queues (and buffers).

At the scan time, FSLMC bus is scanned and all devices (Phy or Sec) are
identified and added to a list. For each such device, appropriate I/O portals
are opened which are essentially gateway between user-space and DP* devices
using the hardware queues/buffers (qbman)

Problem:

You might have noticed that we have exposed a lot of symbols from
drivers/common and drivers/bus for drivers/net and drivers/crypto. All these 
symbols are not rte_* as what has been suggested for exported symbols.

Review comments have been received for renaming these to make them rte_* or
_rte_* prefixed.

Just as a side note, these symbols are being exposed _internally_ within
drivers/* area. 

There are (3) possible solutions we have:

1/ Rename all the symbols:
  - This is a difficult option for us. Renaming means breaking our linkage
with existing code (Linux Kernel upstream candidate as well as internal
repository).
  - Changing it means maintaining this change set internally/independently
which is not a feasible long term solution.

2/ Merge all the libraries together:
  - In the initial RFC days, there were review comments which suggested that
we should break the PMD into common libraries and place it in drivers/*
parallel folders.
  - This is precisely the reason we are facing the situation.
  - Another possibility is to start duplicating the code for common. But, this
too has a technical limitation for us as some data structures are shared
across net and crypto and it is not possible to have multiple instances of
those.
  - One more offshoot option could have been to keep the library external
of the DPDK framework (external location and linked on demand basis,
manually). We don't prefer this as this will make it difficult for any user
to use DPAA2 easily.

3/ Finding a way to keep symbols internal to drivers/* independent of rte_*
   prefix:
   - For example, allowing symbols to be exposed limited to drivers/* area
 and not allowing them to be available across lib/* (not sure how, though!)
   
   
   
   My argument for this:
  - With new bus infra in place, there would be more drivers being contributed.
It also means that there would be PMDs having their own code and symbol
models. It would be difficult to ask all of them to mandatorily adhere
to a naming scheme.
This argument bodes well for lib/* because that is core (libraries) which
should be controlled for uniformity and performance.

[1] https://www.kernel.org/doc/readme/drivers-staging-fsl-mc-README.txt
[2] http://dpdk.org/ml/archives/dev/2017-January/054251.html



Re: [dpdk-dev] [PATCH] cryptodev: decouple from PCI device

2017-01-24 Thread Shreyansh Jain

On Wednesday 18 January 2017 02:46 PM, Hemant Agrawal wrote:

This makes struct rte_cryptodev independent of struct rte_pci_device by
replacing it with a pointer to the generic struct rte_device.

This is inline with the recent changes in ethdev

Signed-off-by: Hemant Agrawal 
---
 drivers/crypto/qat/qat_qp.c| 12 +---
 drivers/crypto/qat/rte_qat_cryptodev.c |  6 +++---
 lib/librte_cryptodev/rte_cryptodev.c   |  6 +++---
 lib/librte_cryptodev/rte_cryptodev.h   |  4 ++--
 4 files changed, 17 insertions(+), 11 deletions(-)



Next step would be to remove rte_pci_driver from eth_driver
and rte_cryptodev_driver and make it generic.

Reviewed-by: Shreyansh Jain 



  1   2   3   4   5   6   7   8   9   10   >