From mboxrd@z Thu Jan 1 00:00:00 1970 From: Shreyansh Jain Subject: Re: [PATCH v6 8/8] eal: enable hotplugging of devices on bus Date: Tue, 17 Jan 2017 12:54:49 +0530 Message-ID: References: <1484581107-2025-1-git-send-email-shreyansh.jain@nxp.com> <1484581107-2025-9-git-send-email-shreyansh.jain@nxp.com> Mime-Version: 1.0 Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Cc: , To: Return-path: Received: from NAM03-DM3-obe.outbound.protection.outlook.com (mail-dm3nam03on0043.outbound.protection.outlook.com [104.47.41.43]) by dpdk.org (Postfix) with ESMTP id 83A9514EC for ; Tue, 17 Jan 2017 08:21:25 +0100 (CET) In-Reply-To: <1484581107-2025-9-git-send-email-shreyansh.jain@nxp.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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) > +{ > + struct rte_pci_device *dev = NULL; > + struct rte_pci_driver *drv = NULL; > + struct rte_pci_addr addr; > + int ret = -1; > + > + if (!device_name) > + return -1; > + > + memset(&addr, 0, sizeof(addr)); > + if (eal_parse_pci_DomBDF(device_name, &addr) == 0) { > + /* Device doesn't match PCI BDF naming format */ > + return -1; > + } > + > + FOREACH_DEVICE_ON_PCIBUS(dev) { > + if (rte_eal_compare_pci_addr(&dev->addr, &addr)) > + continue; > + > + FOREACH_DRIVER_ON_PCIBUS(drv) { > + ret = rte_pci_match(drv, dev); > + if (ret) { > + /* Match of device and driver failed */ > + RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match" > + " the device (%s)\n", drv->driver.name, > + device_name); > + continue; > + } > + > + RTE_LOG(INFO, EAL, " probe driver: %x:%x %s\n", > + dev->id.vendor_id, dev->id.device_id, > + drv->driver.name); > + > + if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) { > + /* map resources for devices that use > + * igb_uio > + */ > + ret = rte_eal_pci_map_device(dev); > + if (ret != 0) > + goto err_return; > + } > + > + /* reference driver structure */ > + dev->driver = drv; > + > + /* call the driver probe() function */ > + ret = drv->probe(drv, dev); > + if (ret) { > + dev->driver = NULL; > + if (drv->drv_flags & RTE_PCI_DRV_NEED_MAPPING) > + rte_eal_pci_unmap_device(dev); > + } > + } > + } > + > + return ret; > + > +err_return: > + RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT > + " cannot be used\n", dev->addr.domain, dev->addr.bus, > + dev->addr.devid, dev->addr.function); > + return -1; > +} > + > +/* > * Detach device specified by its pci address. > */ > int > -rte_eal_pci_detach(const struct rte_pci_addr *addr) > +rte_eal_pci_detach(struct rte_bus *bus __rte_unused, const char *device_name) > { > struct rte_pci_device *dev = NULL; > + struct rte_pci_addr addr; > int ret = 0; > > - if (addr == NULL) > + if (!device_name) > return -1; > > + memset(&addr, 0, sizeof(addr)); > + if (eal_parse_pci_DomBDF(device_name, &addr) == 0) { > + /* Device doesn't match PCI BDF naming format */ > + return -1; > + } > + > FOREACH_DEVICE_ON_PCIBUS(dev) { > - if (rte_eal_compare_pci_addr(&dev->addr, addr)) > + if (rte_eal_compare_pci_addr(&dev->addr, &addr)) > continue; > > ret = pci_detach_all_drivers(dev); > diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h > index f1d4c2c..5b7ae0c 100644 > --- a/lib/librte_eal/common/include/rte_bus.h > +++ b/lib/librte_eal/common/include/rte_bus.h > @@ -59,6 +59,8 @@ TAILQ_HEAD(rte_bus_list, rte_bus); > /* Bus list exposed */ > extern struct rte_bus_list rte_bus_list; > > +#define FOREACH_BUS(bus_p) TAILQ_FOREACH(bus_p, &rte_bus_list, next) > + > /** > * Bus specific scan for devices attached on the bus. > * For each bus object, the scan would be reponsible for finding devices and > @@ -94,6 +96,37 @@ typedef int (*rte_bus_scan_t)(void); > typedef int (*rte_bus_probe_t)(void); > > /** > + * Attach a device to a bus, assuming it is 'connected' to the bus. > + * A bus is responsible for scanning for devices. Attaching a new device is > + * for reenabling the device after being detached/removed. > + * > + * @param bus > + * Generic bus object which was registered with EAL > + * @param device_name > + * Name of the device to attach. > + * > + * @return > + * 0 for successful attach > + * !0 for unsuccessful attach (or incorrect device name) > + */ > +typedef int (*rte_bus_attach_t)(struct rte_bus *bus, const char *device_name); > + > +/** > + * Detach a named device from a bus. Implementation would check the existence > + * of device on the bus and detach it. > + * > + * @param bus > + * Generic bus object which was registered with EAL > + * @param device_name > + * Name of the device to detach > + * > + * @return > + * 0 for successful detaching > + * !0 if device not found or can't detach > + */ > +typedef int (*rte_bus_detach_t)(struct rte_bus *bus, const char *device_name); > + > +/** > * A structure describing a generic bus. > */ > struct rte_bus { > @@ -101,6 +134,8 @@ struct rte_bus { > const char *name; /**< Name of the bus */ > rte_bus_scan_t scan; /**< Scan for devices attached to bus */ > rte_bus_probe_t probe; /**< Probe devices on bus */ > + rte_bus_attach_t attach; /**< Attach a named device */ > + rte_bus_detach_t detach; /**< Detach a named device */ > }; > > /** > diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h > index 5f8d679..6369584 100644 > --- a/lib/librte_eal/common/include/rte_pci.h > +++ b/lib/librte_eal/common/include/rte_pci.h > @@ -421,6 +421,40 @@ int > rte_eal_pci_probe(void); > > /** > + * Search and attach a PCI device to PCI Bus > + * Implements rte_bus->attach > + * > + * @param bus > + * Generic bus object representing PCI bus > + * @param device_name > + * Name of the device to search and attach > + * > + * @return > + * 0 for successful removal of device > + * >0 if device not found on bus > + * <0 in case of error in removal. > + */ > +int > +rte_eal_pci_attach(struct rte_bus *bus, const char *device_name); The first argument, rte_bus, is not required. I will remove this in v7. > + > +/** > + * Search and detach a PCI device from PCI Bus > + * Implements rte_bus->detach > + * > + * @param bus > + * Generic bus object representing PCI bus > + * @param device_name > + * Name of the device to search and detach > + * > + * @return > + * 0 for successful detaching of device > + * >0 if device not found on bus > + * <0 in case of error in removal. > + */ > +int > +rte_eal_pci_detach(struct rte_bus *bus, const char *device_name); Same as above, rte_bus argument is not required and will be removed in v7. > + > +/** > * Map the PCI device resources in user space virtual memory address > * > * Note that driver should not call this function when flag > @@ -494,19 +528,27 @@ void pci_unmap_resource(void *requested_addr, size_t size); > int rte_eal_pci_probe_one(const struct rte_pci_addr *addr); > > /** > - * Close the single PCI device. > - * > - * Scan the content of the PCI bus, and find the pci device specified by pci > - * address, then call the remove() function for registered driver that has a > - * matching entry in its id_table for discovered device. > + * Attach a PCI device on PCI Bus > + * @param bus > + * Generic Bus object for PCI Bus. If passed NULL, PCI bus is extracted > + * using Bus APIs. > + * @param device_name > + * Device Name, which would be converted into BDF. > + */ > +int rte_eal_pci_attach(struct rte_bus *bus, const char *device_name); > + > +/** > + * Detach a single PCI device. > * > - * @param addr > - * The PCI Bus-Device-Function address to close. > + * @param bus > + * Generic bus object for PCI bus. > + * @param device_name > + * Device Name, which would be converted into BDF. > * @return > * - 0 on success. > * - Negative on error. > */ > -int rte_eal_pci_detach(const struct rte_pci_addr *addr); > +int rte_eal_pci_detach(struct rte_bus *bus, const char *device_name); > > /** > * Dump the content of the PCI bus. > diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c > index 50ad9f7..8084996 100644 > --- a/lib/librte_eal/linuxapp/eal/eal_pci.c > +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c > @@ -716,6 +716,8 @@ struct rte_pci_bus rte_pci_bus = { > .bus = { > .scan = rte_eal_pci_scan, > .probe = rte_eal_pci_probe, > + .attach = rte_eal_pci_attach, > + .detach = rte_eal_pci_detach, > }, > .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), > .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list), >