[dpdk-dev,24/25] eal/pci: Add port hotplug functions for physical devices.
Commit Message
The patch adds rte_eal_dev_attach_pdev() and rte_eal_dev_detach_pdev().
rte_eal_dev_attach_pdev() receives a PCI address of the device and
returns an attached port number.
rte_eal_dev_detach_pdev() receives a port number, and returns a PCI
address actually detached.
Signed-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>
---
lib/librte_eal/common/eal_common_dev.c | 58 +++++++++++++++++++++++++++++++++
lib/librte_eal/common/include/rte_dev.h | 25 ++++++++++++++
2 files changed, 83 insertions(+)
@@ -181,6 +181,64 @@ rte_eal_dev_close_one(const char *name)
return rte_eal_dev_find_and_invoke(name, INVOKE_CLOSE);
}
+/* attach the new physical device, then store port_id of the device */
+int
+rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id)
+{
+ uint8_t new_port_id;
+ struct rte_eth_dev devs[RTE_MAX_ETHPORTS];
+
+ /* save current port status */
+ rte_eth_dev_save(devs);
+ /* re-construct pci_device_list */
+ if (rte_eal_pci_scan())
+ goto err;
+ /* invoke probe func of the driver can handle the new device */
+ if (rte_eal_pci_probe_one(addr))
+ goto err;
+ /* get port_id enabled by above procedures */
+ if (rte_eth_dev_get_changed_port(devs, &new_port_id))
+ goto err;
+
+ *port_id = new_port_id;
+ return 0;
+err:
+ RTE_LOG(ERR, EAL, "Drver, cannot attach the device\n");
+ return -1;
+}
+
+/* detach the new physical device, then store pci_addr of the device */
+int
+rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr)
+{
+ struct rte_pci_addr freed_addr;
+ struct rte_pci_addr vp;
+
+ /* check whether the driver supports detach feature, or not */
+ if (!rte_eth_dev_check_detachable(port_id))
+ goto err;
+
+ /* get pci address by port id */
+ if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr))
+ goto err;
+
+ /* Zerod pci addr means the port comes from virtual device */
+ vp.domain = vp.bus = vp.devid = vp.function = 0;
+ if (eal_compare_pci_addr(&vp, &freed_addr) == 0)
+ goto err;
+
+ /* invoke close func of the driver,
+ * also remove the device from pci_device_list */
+ if (rte_eal_pci_close_one(&freed_addr))
+ goto err;
+
+ *addr = freed_addr;
+ return 0;
+err:
+ RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n");
+ return -1;
+}
+
static void
get_vdev_name(char *vdevargs)
{
@@ -101,6 +101,19 @@ void rte_eal_driver_unregister(struct rte_driver *driver);
#if defined(RTE_LIBRTE_EAL_HOTPLUG) && defined(RTE_LIBRTE_EAL_LINUXAPP)
/**
+ * Attach a new physical device.
+ *
+ * @param addr
+ * A pointer to a pci address structure describing the new
+ * device to be attached.
+ * @param port_id
+ * A pointer to a port identifier actually attached.
+ * @return
+ * 0 on success and port_id is filled, negative on error
+ */
+int rte_eal_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id);
+
+/**
* Attach a new virtual device.
*
* @param vdevargs
@@ -114,6 +127,18 @@ void rte_eal_driver_unregister(struct rte_driver *driver);
int rte_eal_dev_attach_vdev(const char *vdevargs, uint8_t *port_id);
/**
+ * Detach a physical device.
+ *
+ * @param port_id
+ * The port identifier of the physical device to detach.
+ * @param addr
+ * A pointer to a pci address structure actually detached.
+ * @return
+ * 0 on success and addr is filled, negative on error
+ */
+int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr);
+
+/**
* Detach a virtual device.
*
* @param port_id