Signed-off-by: Jan Viktorin <viktorin at rehivetech.com> --- lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++- lib/librte_ether/rte_ethdev.h | 31 +++++++++++ 2 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 4af2e5f..9259c2c 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev) } int +rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv, + struct rte_soc_device *soc_dev) +{ + struct eth_driver *eth_drv; + struct rte_eth_dev *eth_dev; + char ethdev_name[RTE_ETH_NAME_MAX_LEN]; + + int diag; + + eth_drv = container_of(soc_drv, struct eth_driver, soc_drv); + + rte_eal_soc_device_name(&soc_dev->addr, ethdev_name, + sizeof(ethdev_name)); + + 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", + eth_drv->dev_private_size, + RTE_CACHE_LINE_SIZE); + if (eth_dev->data->dev_private == NULL) + rte_panic("Cannot allocate memzone for private port data\n"); + } + eth_dev->soc_dev = soc_dev; + eth_dev->driver = eth_drv; + eth_dev->data->rx_mbuf_alloc_failed = 0; + + /* init user callbacks */ + TAILQ_INIT(&(eth_dev->link_intr_cbs)); + + /* + * Set the default MTU. + */ + eth_dev->data->mtu = ETHER_MTU; + + /* Invoke PMD device initialization function */ + diag = (*eth_drv->eth_dev_init)(eth_dev); + if (diag == 0) + return 0; + + RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(%s) failed\n", + soc_drv->name, + soc_dev->id.name); + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_free(eth_dev->data->dev_private); + rte_eth_dev_release_port(eth_dev); + return diag; +} + +int +rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev) +{ + const struct eth_driver *eth_drv; + struct rte_eth_dev *eth_dev; + char ethdev_name[RTE_ETH_NAME_MAX_LEN]; + int ret; + + if (soc_dev == NULL) + return -EINVAL; + + rte_eal_soc_device_name(&soc_dev->addr, ethdev_name, + sizeof(ethdev_name)); + + eth_dev = rte_eth_dev_allocated(ethdev_name); + if (eth_dev == NULL) + return -ENODEV; + + eth_drv = container_of(soc_dev->driver, struct eth_driver, soc_drv); + + /* Invoke PMD device uninit function */ + if (*eth_drv->eth_dev_uninit) { + ret = (*eth_drv->eth_dev_uninit)(eth_dev); + if (ret) + return ret; + } + + /* free ether device */ + rte_eth_dev_release_port(eth_dev); + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_free(eth_dev->data->dev_private); + + eth_dev->soc_dev = NULL; + eth_dev->driver = NULL; + eth_dev->data = NULL; + + return 0; +} + + +int rte_eth_dev_is_valid_port(uint8_t port_id) { if (port_id >= RTE_MAX_ETHPORTS || @@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info) RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get); (*dev->dev_ops->dev_infos_get)(dev, dev_info); - dev_info->pci_dev = dev->pci_dev; + dev_info->soc_dev = dev->soc_dev; dev_info->driver_name = dev->data->drv_name; } @@ -2408,8 +2501,13 @@ static inline struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev) { if (dev->pci_dev) { + RTE_VERIFY(dev->soc_dev == NULL); return &dev->pci_dev->intr_handle; } + if (dev->soc_dev) { + RTE_VERIFY(dev->pci_dev == NULL); + return &dev->soc_dev->intr_handle; + } RTE_VERIFY(0); return NULL; @@ -2453,8 +2551,13 @@ static inline const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev) { if (dev->pci_dev) { + RTE_VERIFY(dev->soc_dev == NULL); return dev->driver->pci_drv.name; } + if (dev->soc_dev) { + RTE_VERIFY(dev->pci_dev == NULL); + return dev->driver->soc_drv.name; + } RTE_VERIFY(0); return NULL; @@ -3114,6 +3217,28 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de eth_dev->data->drv_name = pci_dev->driver->name; } +void +rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev, struct rte_soc_device *soc_dev) +{ + if ((eth_dev == NULL) || (soc_dev == NULL)) { + RTE_PMD_DEBUG_TRACE("NULL pointer eth_dev=%p soc_dev=%p\n", + eth_dev, soc_dev); + return; + } + + RTE_VERIFY(eth_dev->soc_dev != NULL); + + eth_dev->data->dev_flags = 0; + if (soc_dev->driver->drv_flags & RTE_SOC_DRV_INTR_LSC) + eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC; + if (soc_dev->driver->drv_flags & RTE_SOC_DRV_DETACHABLE) + eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; + + eth_dev->data->kdrv = soc_dev->kdrv; + eth_dev->data->numa_node = soc_dev->numa_node; + eth_dev->data->drv_name = soc_dev->driver->name; +} + int rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id, struct rte_eth_l2_tunnel_conf *l2_tunnel) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 622c9d8..9ecc3b8 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -180,6 +180,7 @@ extern "C" { #include <rte_log.h> #include <rte_interrupts.h> #include <rte_pci.h> +#include <rte_soc.h> #include <rte_dev.h> #include <rte_devargs.h> #include "rte_ether.h" @@ -855,6 +856,7 @@ struct rte_eth_conf { */ struct rte_eth_dev_info { struct rte_pci_device *pci_dev; /**< Device PCI information. */ + struct rte_soc_device *soc_dev; /**< Device SoC information. */ const char *driver_name; /**< Device Driver name. */ unsigned int if_index; /**< Index to bound host interface, or 0 if none. Use if_indextoname() to translate into an interface name. */ @@ -1590,6 +1592,7 @@ struct rte_eth_dev { const struct eth_driver *driver;/**< Driver for this device */ const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */ struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */ + struct rte_soc_device *soc_dev; /**< SoC info. supplied by probing */ /** User application callbacks for NIC interrupts */ struct rte_eth_dev_cb_list link_intr_cbs; /** @@ -1823,6 +1826,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev); */ struct eth_driver { struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */ + struct rte_soc_driver soc_drv; /**< The PMD is also a SoC driver. */ eth_dev_init_t eth_dev_init; /**< Device init function. */ eth_dev_uninit_t eth_dev_uninit; /**< Device uninit function. */ unsigned int dev_private_size; /**< Size of device private data. */ @@ -4158,6 +4162,20 @@ void rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_dev); /** + * Copy SoC device info to the Ethernet device data. + * + * @param eth_dev + * The *eth_dev* pointer is the address of the *rte_eth_dev* structure. + * @param soc_dev + * The *soc_dev* pointer is the address of the *rte_soc_device* structure. + * + * @return + * - 0 on success, negative on error + */ +void rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev, + struct rte_soc_device *soc_dev); + +/** * Create memzone for HW rings. * malloc can't be used as the physical address is needed. * If the memzone is already created, then this function returns a ptr @@ -4241,6 +4259,19 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv, */ int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev); +/** + * Wrapper for use by SoC drivers as a .devinit function to attach to a ethdev + * interface. + */ +int rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv, + struct rte_soc_device *soc_dev); + +/** + * Wrapper for use by SoC drivers as a .devuninit function to detach a ethdev + * interface. + */ +int rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev); + #ifdef __cplusplus } #endif -- 2.8.0