Re: [dpdk-dev] [PATCH v2 7/7] pci: Clarify interfaces for dynamic attach/detach of drivers
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
> -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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
> -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
> -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
> -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
> -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
> -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
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
] 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
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
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
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
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
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
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
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
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
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
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
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
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
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
> -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
> -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
://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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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