[dpdk-dev] [PATCH 07/14] lib/ether: generalize rte_eth_dev_init/uninit

Jan Viktorin viktorin at rehivetech.com
Mon Jan 4 21:08:19 CET 2016


Generalize strict PCI-specific initialization and uninitialization steps and
prepare the code to be easily reused for other infrastructures. API of the
eth_driver stays backwards compatible. The previously introduced magic is
utilized to test whether we are working with a PCI device or not.

Signed-off-by: Jan Viktorin <viktorin at rehivetech.com>
---
 lib/librte_ether/rte_ethdev.c | 118 ++++++++++++++++++++++++++++--------------
 lib/librte_ether/rte_ethdev.h |   9 ++--
 2 files changed, 85 insertions(+), 42 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 21fc0d7..826d4b9 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -216,16 +216,23 @@ rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type)
 
 static int
 rte_eth_dev_create_unique_device_name(char *name, size_t size,
-		struct rte_pci_device *pci_dev)
+		union rte_device *dev)
 {
 	int ret;
 
-	if ((name == NULL) || (pci_dev == NULL))
+	if ((name == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	ret = snprintf(name, size, "%d:%d.%d",
-			pci_dev->addr.bus, pci_dev->addr.devid,
-			pci_dev->addr.function);
+	switch (dev->magic) {
+	case RTE_PCI_DEVICE_MAGIC:
+		ret = snprintf(name, size, "%d:%d.%d",
+			dev->pci.addr.bus, dev->pci.addr.devid,
+			dev->pci.addr.function);
+		break;
+	default:
+		ret = -ENODEV;
+	}
+
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -243,33 +250,41 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 }
 
 static int
-rte_eth_dev_init(struct rte_pci_driver *pci_drv,
-		 struct rte_pci_device *pci_dev)
+rte_device_get_dev_type(union rte_device *dev)
+{
+	switch (dev->magic) {
+	case RTE_PCI_DEVICE_MAGIC:
+		return RTE_ETH_DEV_PCI;
+	default:
+		return RTE_ETH_DEV_UNKNOWN;
+	}
+}
+
+static int
+rte_eth_dev_init(struct eth_driver *eth_drv, union rte_device *dev)
 {
-	struct eth_driver    *eth_drv;
 	struct rte_eth_dev *eth_dev;
 	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
-
 	int diag;
 
-	eth_drv = (struct eth_driver *)pci_drv;
-
-	/* Create unique Ethernet device name using PCI address */
+	/* Create unique Ethernet device name */
 	rte_eth_dev_create_unique_device_name(ethdev_name,
-			sizeof(ethdev_name), pci_dev);
+			sizeof(ethdev_name), dev);
 
-	eth_dev = rte_eth_dev_allocate(ethdev_name, RTE_ETH_DEV_PCI);
+	eth_dev = rte_eth_dev_allocate(ethdev_name,
+			rte_device_get_dev_type(dev));
 	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);
+				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->pci_dev = pci_dev;
+
+	eth_dev->dev = dev;
 	eth_dev->driver = eth_drv;
 	eth_dev->data->rx_mbuf_alloc_failed = 0;
 
@@ -286,10 +301,6 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv,
 	if (diag == 0)
 		return 0;
 
-	RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(vendor_id=0x%u device_id=0x%x) failed\n",
-			pci_drv->name,
-			(unsigned) pci_dev->id.vendor_id,
-			(unsigned) pci_dev->id.device_id);
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
 		rte_free(eth_dev->data->dev_private);
 	rte_eth_dev_release_port(eth_dev);
@@ -297,29 +308,41 @@ rte_eth_dev_init(struct rte_pci_driver *pci_drv,
 }
 
 static int
-rte_eth_dev_uninit(struct rte_pci_device *pci_dev)
+rte_eth_dev_pci_init(struct rte_pci_driver *pci_drv,
+		 struct rte_pci_device *pci_dev)
+{
+	struct eth_driver *eth_drv = (struct eth_driver *)pci_drv;
+	union rte_device *dev = (union rte_device *) pci_dev;
+	int rc;
+
+	if ((rc = rte_eth_dev_init(eth_drv, dev))) {
+		RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(vendor_id=0x%u device_id=0x%x) failed\n",
+				pci_drv->name,
+				(unsigned) pci_dev->id.vendor_id,
+				(unsigned) pci_dev->id.device_id);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+rte_eth_dev_uninit(struct eth_driver *eth_drv)
 {
-	const struct eth_driver *eth_drv;
+	union rte_device *dev = (union rte_device *) eth_drv;
 	struct rte_eth_dev *eth_dev;
 	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
-	int ret;
 
-	if (pci_dev == NULL)
-		return -EINVAL;
-
-	/* Create unique Ethernet device name using PCI address */
+	/* Create unique Ethernet device name */
 	rte_eth_dev_create_unique_device_name(ethdev_name,
-			sizeof(ethdev_name), pci_dev);
+			sizeof(ethdev_name), dev);
 
 	eth_dev = rte_eth_dev_allocated(ethdev_name);
 	if (eth_dev == NULL)
 		return -ENODEV;
 
-	eth_drv = (const struct eth_driver *)pci_dev->driver;
-
-	/* Invoke PMD device uninit function */
 	if (*eth_drv->eth_dev_uninit) {
-		ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+		int ret = (*eth_drv->eth_dev_uninit)(eth_dev);
 		if (ret)
 			return ret;
 	}
@@ -330,13 +353,26 @@ rte_eth_dev_uninit(struct rte_pci_device *pci_dev)
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
 		rte_free(eth_dev->data->dev_private);
 
-	eth_dev->pci_dev = NULL;
+	eth_dev->dev = NULL;
 	eth_dev->driver = NULL;
 	eth_dev->data = NULL;
 
 	return 0;
 }
 
+static int
+rte_eth_dev_pci_uninit(struct rte_pci_device *pci_dev)
+{
+	struct eth_driver *eth_drv;
+
+	if (pci_dev == NULL || pci_dev->driver == NULL)
+		return -EINVAL;
+
+	eth_drv = (struct eth_driver *) pci_dev->driver;
+
+	return rte_eth_dev_uninit(eth_drv);
+}
+
 /**
  * Register an Ethernet [Poll Mode] driver.
  *
@@ -345,18 +381,22 @@ rte_eth_dev_uninit(struct rte_pci_device *pci_dev)
  * Poll Mode Driver.
  * Invokes the rte_eal_pci_register() function to register the *pci_drv*
  * structure embedded in the *eth_drv* structure, after having stored the
- * address of the rte_eth_dev_init() function in the *devinit* field of
+ * address of the rte_eth_dev_pci_init() function in the *devinit* field of
  * the *pci_drv* structure.
- * During the PCI probing phase, the rte_eth_dev_init() function is
+ * During the PCI probing phase, the rte_eth_dev_pci_init() function is
  * invoked for each PCI [Ethernet device] matching the embedded PCI
  * identifiers provided by the driver.
  */
 void
 rte_eth_driver_register(struct eth_driver *eth_drv)
 {
-	eth_drv->pci_drv.devinit = rte_eth_dev_init;
-	eth_drv->pci_drv.devuninit = rte_eth_dev_uninit;
-	rte_eal_pci_register(&eth_drv->pci_drv);
+	if (eth_drv->magic == RTE_PCI_DRV_MAGIC) {
+		eth_drv->pci_drv.devinit = rte_eth_dev_pci_init;
+		eth_drv->pci_drv.devuninit = rte_eth_dev_pci_uninit;
+		rte_eal_pci_register(&eth_drv->pci_drv);
+	} else {
+		rte_panic("%s(): bad magic: %08x\n", __func__, eth_drv->magic);
+	}
 }
 
 int
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 5a267e4..5dd2e1a 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -824,7 +824,7 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_QINQ_INSERT 0x00000100
 
 struct rte_eth_dev_info {
-	struct rte_pci_device *pci_dev; /**< Device PCI information. */
+	RTE_DEVICE_PTR_DECL(pci_dev); /**< Device 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. */
@@ -1534,7 +1534,7 @@ struct rte_eth_dev {
 	struct rte_eth_dev_data *data;  /**< Pointer to device data */
 	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 */
+	RTE_DEVICE_PTR_DECL(pci_dev); /**< Device information. */
 	/** User application callbacks for NIC interrupts */
 	struct rte_eth_dev_cb_list link_intr_cbs;
 	/**
@@ -1767,7 +1767,10 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
  * - The size of the private data to allocate for each matching device.
  */
 struct eth_driver {
-	struct rte_pci_driver pci_drv;    /**< The PMD is also a PCI driver. */
+	union {
+		unsigned int magic;
+		struct rte_pci_driver pci_drv; /**< The PMD is a PCI 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. */
-- 
2.6.3



More information about the dev mailing list