From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from wes1-so2.wedos.net (wes1-so2.wedos.net [46.28.106.16]) by dpdk.org (Postfix) with ESMTP id AC08A5592 for ; Fri, 6 May 2016 15:50:09 +0200 (CEST) Received: from pcviktorin.fit.vutbr.cz (pcviktorin.fit.vutbr.cz [147.229.13.147]) by wes1-so2.wedos.net (Postfix) with ESMTPSA id 3r1Y7P3DwFz7Cj; Fri, 6 May 2016 15:50:09 +0200 (CEST) From: Jan Viktorin To: dev@dpdk.org Cc: Jan Viktorin , David Marchand , Thomas Monjalon , Bruce Richardson , Declan Doherty , jianbo.liu@linaro.org, jerin.jacob@caviumnetworks.com, Keith Wiles , Stephen Hemminger Date: Fri, 6 May 2016 15:47:53 +0200 Message-Id: <1462542490-15556-12-git-send-email-viktorin@rehivetech.com> X-Mailer: git-send-email 2.8.0 In-Reply-To: <1462542490-15556-1-git-send-email-viktorin@rehivetech.com> References: <1462542490-15556-1-git-send-email-viktorin@rehivetech.com> In-Reply-To: <1451682326-5834-1-git-send-email-viktorin@rehivetech.com> References: <1451682326-5834-1-git-send-email-viktorin@rehivetech.com> Subject: [dpdk-dev] [PATCH v1 11/28] eal/soc: implement probing of drivers X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 May 2016 13:50:09 -0000 Signed-off-by: Jan Viktorin --- lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 + lib/librte_eal/common/eal_common_soc.c | 200 ++++++++++++++++++++++++ lib/librte_eal/common/include/rte_soc.h | 25 +++ lib/librte_eal/linuxapp/eal/eal.c | 4 + lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 + 5 files changed, 235 insertions(+) diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index 4a2eeaf..bd3dd11 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -163,5 +163,8 @@ DPDK_16.07 { rte_eal_soc_unregister; rte_eal_soc_scan; rte_eal_soc_dump; + rte_eal_soc_detach; + rte_eal_soc_probe; + rte_eal_soc_probe_one; } DPDK_16.04; diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c index d8bb6d6..d8f0c00 100644 --- a/lib/librte_eal/common/eal_common_soc.c +++ b/lib/librte_eal/common/eal_common_soc.c @@ -36,6 +36,8 @@ #include #include +#include +#include #include "eal_private.h" @@ -58,6 +60,204 @@ const char *soc_get_sysfs_path(void) return path; } +static int soc_id_match(const struct rte_soc_id *drv_id, + const struct rte_soc_id *dev_id) +{ + int i; + int j; + + RTE_VERIFY(drv_id != NULL); + RTE_VERIFY(dev_id != NULL); + + for (i = 0; drv_id[i].compatible; ++i) { + const char *drv_compat = drv_id[i].compatible; + + for (j = 0; dev_id[j].compatible; ++j) { + const char *dev_compat = dev_id[j].compatible; + + if (!strcmp(drv_compat, dev_compat)) + return 1; + } + } + + return 0; +} + +static int +rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr, + struct rte_soc_device *dev) +{ + int ret; + + if (!soc_id_match(dr->id_table, dev->id)) + return 1; + + RTE_LOG(DEBUG, EAL, "SoC device %s\n", + dev->addr.name); + RTE_LOG(DEBUG, EAL, " probe driver %s\n", dr->name); + + dev->driver = dr; + RTE_VERIFY(dr->devinit != NULL); + return dr->devinit(dr, dev); +} + +static int +soc_probe_all_drivers(struct rte_soc_device *dev) +{ + struct rte_soc_driver *dr = NULL; + int rc = 0; + + if (dev == NULL) + return -1; + + TAILQ_FOREACH(dr, &soc_driver_list, next) { + rc = rte_eal_soc_probe_one_driver(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; +} + +/* If the IDs match, call the devuninit() function of the driver. */ +static int +rte_eal_soc_detach_dev(struct rte_soc_driver *dr, + struct rte_soc_device *dev) +{ + if ((dr == NULL) || (dev == NULL)) + return -EINVAL; + + if (!soc_id_match(dr->id_table, dev->id)) + return 1; + + RTE_LOG(DEBUG, EAL, "SoC device %s\n", + dev->addr.name); + + RTE_LOG(DEBUG, EAL, " remove driver: %s\n", dr->name); + + if (dr->devuninit && (dr->devuninit(dev) < 0)) + return -1; /* negative value is an error */ + + /* clear driver structure */ + dev->driver = NULL; + + return 0; +} + +/* + * Call the devuninit() function of all registered drivers for the given + * device if their IDs match. + * + * @return + * 0 when successful + * -1 if deinitialization fails + * 1 if no driver is found for this device. + */ +static int +soc_detach_all_drivers(struct rte_soc_device *dev) +{ + struct rte_soc_driver *dr = NULL; + int rc = 0; + + if (dev == NULL) + return -1; + + TAILQ_FOREACH(dr, &soc_driver_list, next) { + rc = rte_eal_soc_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; +} + +/* + * Detach device specified by its SoC address. + */ +int +rte_eal_soc_detach(const struct rte_soc_addr *addr) +{ + struct rte_soc_device *dev = NULL; + int ret = 0; + + if (addr == NULL) + return -1; + + TAILQ_FOREACH(dev, &soc_device_list, next) { + if (rte_eal_compare_soc_addr(&dev->addr, addr)) + continue; + + ret = soc_detach_all_drivers(dev); + if (ret < 0) + goto err_return; + + TAILQ_REMOVE(&soc_device_list, dev, next); + return 0; + } + return -1; + +err_return: + RTE_LOG(WARNING, EAL, "Requested device %s cannot be used\n", + dev->addr.name); + return -1; +} + +int +rte_eal_soc_probe_one(const struct rte_soc_addr *addr) +{ + struct rte_soc_device *dev = NULL; + int ret = 0; + + if (addr == NULL) + return -1; + + TAILQ_FOREACH(dev, &soc_device_list, next) { + if (rte_eal_compare_soc_addr(&dev->addr, addr)) + continue; + + ret = soc_probe_all_drivers(dev); + if (ret < 0) + goto err_return; + return 0; + } + return -1; + +err_return: + RTE_LOG(WARNING, EAL, + "Requested device %s cannot be used\n", addr->name); + return -1; +} + +/* + * Scan the SoC devices and call the devinit() function for all registered + * drivers that have a matching entry in its id_table for discovered devices. + */ +int +rte_eal_soc_probe(void) +{ + struct rte_soc_device *dev = NULL; + int probe_all = 0; + int ret = 0; + + TAILQ_FOREACH(dev, &soc_device_list, next) { + + ret = soc_probe_all_drivers(dev); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Requested device %s" + " cannot be used\n", dev->addr.name); + } + + return 0; +} + /* dump one device */ static int soc_dump_one_device(FILE *f, struct rte_soc_device *dev) diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h index 6278295..4117ffb 100644 --- a/lib/librte_eal/common/include/rte_soc.h +++ b/lib/librte_eal/common/include/rte_soc.h @@ -147,6 +147,31 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0, int rte_eal_soc_scan(void); /** + * Probe SoC devices for registered drivers. + */ +int rte_eal_soc_probe(void); + +/** + * Probe the single SoC device. + */ +int rte_eal_soc_probe_one(const struct rte_soc_addr *addr); + +/** + * Close the single SoC device. + * + * Scan the SoC devices and find the SoC device specified by the SoC + * address, then call the devuninit() function for registered driver + * that has a matching entry in its id_table for discovered device. + * + * @param addr + * The SoC address to close. + * @return + * - 0 on success. + * - Negative on error. + */ +int rte_eal_soc_detach(const struct rte_soc_addr *addr); + +/** * Dump discovered SoC devices. */ void rte_eal_soc_dump(FILE *f); diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c index 5f190ff..e697bb0 100644 --- a/lib/librte_eal/linuxapp/eal/eal.c +++ b/lib/librte_eal/linuxapp/eal/eal.c @@ -896,6 +896,10 @@ rte_eal_init(int argc, char **argv) if (rte_eal_pci_probe()) rte_panic("Cannot probe PCI\n"); + /* Probe & Initialize SoC devices */ + if (rte_eal_soc_probe()) + rte_panic("Cannot probe SoC\n"); + rte_eal_mcfg_complete(); return fctret; diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 280622f..811cbf8 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -168,5 +168,8 @@ DPDK_16.07 { rte_eal_soc_unregister; rte_eal_soc_scan; rte_eal_soc_dump; + rte_eal_soc_detach; + rte_eal_soc_probe; + rte_eal_soc_probe_one; } DPDK_16.04; -- 2.8.0