@@ -556,7 +556,7 @@ virtual_ethdev_create(const char *name, struct ether_addr *mac_addr,
goto err;
/* reserve an ethdev entry */
- eth_dev = rte_eth_dev_allocate(name);
+ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PHYSICAL);
if (eth_dev == NULL)
goto err;
@@ -322,4 +322,38 @@ err:
RTE_LOG(ERR, EAL, "Drver, cannot detach the device\n");
return -1;
}
+
+/* attach the new device, then store port_id of the device */
+int
+rte_eal_dev_attach(const char *devargs, uint8_t *port_id)
+{
+ struct rte_pci_addr addr;
+
+ if (eal_parse_pci_DomBDF(devargs, &addr) == 0)
+ return rte_eal_dev_attach_pdev(&addr, port_id);
+ else
+ return rte_eal_dev_attach_vdev(devargs, port_id);
+}
+
+/* detach the device, then store the name of the device */
+int
+rte_eal_dev_detach(uint8_t port_id, char *name)
+{
+ struct rte_pci_addr addr;
+ int ret;
+
+ if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PHYSICAL) {
+ ret = rte_eth_dev_get_addr_by_port(port_id, &addr);
+ if (ret < 0)
+ return ret;
+
+ ret = rte_eal_dev_detach_pdev(port_id, &addr);
+ if (ret == 0)
+ snprintf(name, RTE_ETH_NAME_MAX_LEN, "%04x.%02x.%02x.%d",
+ addr.domain, addr.bus, addr.devid, addr.function);
+
+ return ret;
+ } else
+ return rte_eal_dev_detach_vdev(port_id, name);
+}
#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */
@@ -151,6 +151,31 @@ int rte_eal_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr);
*/
int rte_eal_dev_detach_vdev(uint8_t port_id, char *vdevname);
+/**
+ * Attach a new device.
+ *
+ * @param devargs
+ * A pointer to a strings array 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(const char *devargs, uint8_t *port_id);
+
+/**
+ * Detach a device.
+ *
+ * @param port_id
+ * The port identifier of the device to detach.
+ * @param addr
+ * A pointer to a device name actually detached.
+ * @return
+ * 0 on success and devname is filled, negative on error
+ */
+int rte_eal_dev_detach(uint8_t port_id, char *devname);
+
#endif /* RTE_LIBRTE_EAL_HOTPLUG & RTE_LIBRTE_EAL_LINUXAPP */
/**
@@ -232,7 +232,7 @@ rte_eth_dev_allocate_new_port(void)
}
struct rte_eth_dev *
-rte_eth_dev_allocate(const char *name)
+rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type)
{
uint8_t port_id;
struct rte_eth_dev *eth_dev;
@@ -256,6 +256,7 @@ rte_eth_dev_allocate(const char *name)
snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name);
eth_dev->data->port_id = port_id;
eth_dev->attached = DEV_CONNECTED;
+ eth_dev->dev_type = type;
nb_ports++;
return eth_dev;
}
@@ -273,6 +274,7 @@ rte_eth_dev_free(const char *name)
}
eth_dev->attached = 0;
+ eth_dev->dev_type = RTE_ETH_DEV_UNKNOWN;
nb_ports--;
return eth_dev;
}
@@ -293,7 +295,7 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv,
snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "%d:%d.%d",
pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function);
- eth_dev = rte_eth_dev_allocate(ethdev_name);
+ eth_dev = rte_eth_dev_allocate(ethdev_name, RTE_ETH_DEV_PHYSICAL);
if (eth_dev == NULL)
return -ENOMEM;
@@ -416,6 +418,14 @@ rte_eth_dev_count(void)
return (nb_ports);
}
+enum rte_eth_dev_type
+rte_eth_dev_get_device_type(uint8_t port_id)
+{
+ if (rte_eth_dev_validate_port(port_id) == DEV_INVALID)
+ return -1;
+ return rte_eth_devices[port_id].dev_type;
+}
+
void
rte_eth_dev_save(struct rte_eth_dev *devs)
{
@@ -1548,6 +1548,16 @@ struct eth_dev_ops {
};
/**
+ * The eth device type
+ */
+enum rte_eth_dev_type {
+ RTE_ETH_DEV_UNKNOWN, /**< unknown device type */
+ RTE_ETH_DEV_PHYSICAL, /**< physical device type */
+ RTE_ETH_DEV_VIRTUAL, /**< virtual device type */
+ RTE_ETH_DEV_MAX /**< max value of this enum */
+};
+
+/**
* @internal
* The generic data structure associated with each ethernet device.
*
@@ -1566,6 +1576,7 @@ struct rte_eth_dev {
struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
struct rte_eth_dev_cb_list callbacks; /**< User application callbacks */
uint8_t attached; /**< Flag indicating the port is attached */
+ enum rte_eth_dev_type dev_type; /**< Flag indicating the device type */
};
struct rte_eth_dev_sriov {
@@ -1643,6 +1654,15 @@ extern uint8_t rte_eth_dev_count(void);
/**
* Function for internal use by port hotplug functions.
+ * Get the device type to know whether the device is physical or virtual.
+ *
+ * @return
+ * - Device type.
+ */
+extern enum rte_eth_dev_type rte_eth_dev_get_device_type(uint8_t port_id);
+
+/**
+ * Function for internal use by port hotplug functions.
* Copies current ethdev structures to the specified pointer.
*
* @param devs The pointer to the ethdev structures
@@ -1728,10 +1748,12 @@ extern struct rte_eth_dev *rte_eth_dev_allocated(const char *name);
* to that slot for the driver to use.
*
* @param name Unique identifier name for each Ethernet device
+ * @param type Device type of this Ethernet device
* @return
* - Slot in the rte_dev_devices array for a new device;
*/
-struct rte_eth_dev *rte_eth_dev_allocate(const char *name);
+struct rte_eth_dev *rte_eth_dev_allocate(const char *name,
+ enum rte_eth_dev_type type);
/**
* Function for internal use by dummy drivers primarily, e.g. ring-based
@@ -642,7 +642,7 @@ rte_pmd_init_internals(const char *name,
}
/* reserve an ethdev entry */
- *eth_dev = rte_eth_dev_allocate(name);
+ *eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
if (*eth_dev == NULL)
goto error;
@@ -231,7 +231,7 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
}
/* reserve an ethdev entry */
- eth_dev = rte_eth_dev_allocate(name);
+ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
if (eth_dev == NULL) {
RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev");
goto err;
@@ -710,7 +710,7 @@ rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues,
goto error;
/* reserve an ethdev entry */
- *eth_dev = rte_eth_dev_allocate(name);
+ *eth_dev = rte_eth_dev_allocate(name, VIRTUAL);
if (*eth_dev == NULL)
goto error;
@@ -256,7 +256,7 @@ rte_eth_from_rings(const char *name, struct rte_ring *const rx_queues[],
goto error;
/* reserve an ethdev entry */
- eth_dev = rte_eth_dev_allocate(name);
+ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL);
if (eth_dev == NULL)
goto error;
@@ -647,7 +647,7 @@ eth_dev_xenvirt_create(const char *name, const char *params,
goto err;
/* reserve an ethdev entry */
- eth_dev = rte_eth_dev_allocate(name);
+ eth_dev = rte_eth_dev_allocate(name, VIRTUAL);
if (eth_dev == NULL)
goto err;