xref: /dpdk/drivers/net/ionic/ionic_dev_pci.c (revision 9de21005e201af6ba8dc3836c09384e0b40b4a89)
18eaafff3SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
28eaafff3SAndrew Boyer  * Copyright 2018-2022 Advanced Micro Devices, Inc.
38eaafff3SAndrew Boyer  */
48eaafff3SAndrew Boyer 
58eaafff3SAndrew Boyer #include <stdio.h>
68eaafff3SAndrew Boyer #include <errno.h>
78eaafff3SAndrew Boyer #include <string.h>
88eaafff3SAndrew Boyer #include <stdint.h>
98eaafff3SAndrew Boyer 
108eaafff3SAndrew Boyer #include <rte_common.h>
118eaafff3SAndrew Boyer #include <rte_interrupts.h>
128eaafff3SAndrew Boyer #include <rte_log.h>
138eaafff3SAndrew Boyer #include <rte_pci.h>
148eaafff3SAndrew Boyer #include <bus_pci_driver.h>
158eaafff3SAndrew Boyer #include <rte_eal.h>
168eaafff3SAndrew Boyer #include <ethdev_pci.h>
178eaafff3SAndrew Boyer #include <rte_dev.h>
18*9de21005SAndrew Boyer #include <rte_kvargs.h>
198eaafff3SAndrew Boyer 
208eaafff3SAndrew Boyer #include "ionic.h"
218eaafff3SAndrew Boyer #include "ionic_if.h"
228eaafff3SAndrew Boyer #include "ionic_dev.h"
238eaafff3SAndrew Boyer #include "ionic_ethdev.h"
248eaafff3SAndrew Boyer #include "ionic_logs.h"
258eaafff3SAndrew Boyer 
268eaafff3SAndrew Boyer static const struct rte_pci_id pci_id_ionic_map[] = {
278eaafff3SAndrew Boyer 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) },
288eaafff3SAndrew Boyer 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) },
298eaafff3SAndrew Boyer 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) },
308eaafff3SAndrew Boyer 	{ .vendor_id = 0, /* sentinel */ },
318eaafff3SAndrew Boyer };
328eaafff3SAndrew Boyer 
338eaafff3SAndrew Boyer static int
348eaafff3SAndrew Boyer ionic_pci_setup(struct ionic_adapter *adapter)
358eaafff3SAndrew Boyer {
368eaafff3SAndrew Boyer 	struct ionic_dev_bar *bar = adapter->bars.bar;
378eaafff3SAndrew Boyer 	unsigned int num_bars = adapter->bars.num_bars;
388eaafff3SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
398eaafff3SAndrew Boyer 	struct rte_pci_device *bus_dev = adapter->bus_dev;
408eaafff3SAndrew Boyer 	uint32_t sig;
418eaafff3SAndrew Boyer 	u_char *bar0_base;
428eaafff3SAndrew Boyer 	unsigned int i;
438eaafff3SAndrew Boyer 
448eaafff3SAndrew Boyer 	/* BAR0: dev_cmd and interrupts */
458eaafff3SAndrew Boyer 	if (num_bars < 1) {
468eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "No bars found, aborting\n");
478eaafff3SAndrew Boyer 		return -EFAULT;
488eaafff3SAndrew Boyer 	}
498eaafff3SAndrew Boyer 
508eaafff3SAndrew Boyer 	if (bar->len < IONIC_BAR0_SIZE) {
518eaafff3SAndrew Boyer 		IONIC_PRINT(ERR,
528eaafff3SAndrew Boyer 			"Resource bar size %lu too small, aborting\n",
538eaafff3SAndrew Boyer 			bar->len);
548eaafff3SAndrew Boyer 		return -EFAULT;
558eaafff3SAndrew Boyer 	}
568eaafff3SAndrew Boyer 
578eaafff3SAndrew Boyer 	bar0_base = bar->vaddr;
588eaafff3SAndrew Boyer 	idev->dev_info = (union ionic_dev_info_regs *)
598eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET];
608eaafff3SAndrew Boyer 	idev->dev_cmd = (union ionic_dev_cmd_regs *)
618eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET];
628eaafff3SAndrew Boyer 	idev->intr_status = (struct ionic_intr_status *)
638eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET];
648eaafff3SAndrew Boyer 	idev->intr_ctrl = (struct ionic_intr *)
658eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET];
668eaafff3SAndrew Boyer 
678eaafff3SAndrew Boyer 	sig = ioread32(&idev->dev_info->signature);
688eaafff3SAndrew Boyer 	if (sig != IONIC_DEV_INFO_SIGNATURE) {
698eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Incompatible firmware signature %#x",
708eaafff3SAndrew Boyer 			sig);
718eaafff3SAndrew Boyer 		return -EFAULT;
728eaafff3SAndrew Boyer 	}
738eaafff3SAndrew Boyer 
748eaafff3SAndrew Boyer 	for (i = 0; i < IONIC_DEVINFO_FWVERS_BUFLEN; i++)
758eaafff3SAndrew Boyer 		adapter->fw_version[i] =
768eaafff3SAndrew Boyer 			ioread8(&idev->dev_info->fw_version[i]);
778eaafff3SAndrew Boyer 	adapter->fw_version[IONIC_DEVINFO_FWVERS_BUFLEN - 1] = '\0';
788eaafff3SAndrew Boyer 
798eaafff3SAndrew Boyer 	adapter->name = bus_dev->device.name;
808eaafff3SAndrew Boyer 
818eaafff3SAndrew Boyer 	IONIC_PRINT(DEBUG, "%s firmware version: %s",
828eaafff3SAndrew Boyer 		adapter->name, adapter->fw_version);
838eaafff3SAndrew Boyer 
848eaafff3SAndrew Boyer 	/* BAR1: doorbells */
858eaafff3SAndrew Boyer 	bar++;
868eaafff3SAndrew Boyer 	if (num_bars < 2) {
878eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Doorbell bar missing, aborting\n");
888eaafff3SAndrew Boyer 		return -EFAULT;
898eaafff3SAndrew Boyer 	}
908eaafff3SAndrew Boyer 
918eaafff3SAndrew Boyer 	idev->db_pages = bar->vaddr;
928eaafff3SAndrew Boyer 
938eaafff3SAndrew Boyer 	return 0;
948eaafff3SAndrew Boyer }
958eaafff3SAndrew Boyer 
96*9de21005SAndrew Boyer const char *ionic_pci_devargs_arr[] = {
97*9de21005SAndrew Boyer 	PMD_IONIC_CMB_KVARG,
98*9de21005SAndrew Boyer 	NULL,
99*9de21005SAndrew Boyer };
100*9de21005SAndrew Boyer 
101*9de21005SAndrew Boyer static int
102*9de21005SAndrew Boyer ionic_pci_devarg_cmb(const char *key __rte_unused, const char *val, void *arg)
103*9de21005SAndrew Boyer {
104*9de21005SAndrew Boyer 	struct ionic_adapter *adapter = arg;
105*9de21005SAndrew Boyer 
106*9de21005SAndrew Boyer 	if (!strcmp(val, "1")) {
107*9de21005SAndrew Boyer 		IONIC_PRINT(NOTICE, "%s enabled", PMD_IONIC_CMB_KVARG);
108*9de21005SAndrew Boyer 		adapter->q_in_cmb = true;
109*9de21005SAndrew Boyer 	} else if (!strcmp(val, "0")) {
110*9de21005SAndrew Boyer 		IONIC_PRINT(DEBUG, "%s disabled (default)",
111*9de21005SAndrew Boyer 			PMD_IONIC_CMB_KVARG);
112*9de21005SAndrew Boyer 	} else {
113*9de21005SAndrew Boyer 		IONIC_PRINT(ERR, "%s=%s invalid, use 1 or 0",
114*9de21005SAndrew Boyer 			PMD_IONIC_CMB_KVARG, val);
115*9de21005SAndrew Boyer 		return -ERANGE;
116*9de21005SAndrew Boyer 	}
117*9de21005SAndrew Boyer 
118*9de21005SAndrew Boyer 	return 0;
119*9de21005SAndrew Boyer }
120*9de21005SAndrew Boyer 
121*9de21005SAndrew Boyer static int
122*9de21005SAndrew Boyer ionic_pci_devargs(struct ionic_adapter *adapter, struct rte_devargs *devargs)
123*9de21005SAndrew Boyer {
124*9de21005SAndrew Boyer 	struct rte_kvargs *kvlist;
125*9de21005SAndrew Boyer 	int err = 0;
126*9de21005SAndrew Boyer 
127*9de21005SAndrew Boyer 	if (!devargs)
128*9de21005SAndrew Boyer 		return 0;
129*9de21005SAndrew Boyer 
130*9de21005SAndrew Boyer 	kvlist = rte_kvargs_parse(devargs->args, ionic_pci_devargs_arr);
131*9de21005SAndrew Boyer 	if (!kvlist) {
132*9de21005SAndrew Boyer 		IONIC_PRINT(ERR, "Couldn't parse args '%s'", devargs->args);
133*9de21005SAndrew Boyer 		return -EINVAL;
134*9de21005SAndrew Boyer 	}
135*9de21005SAndrew Boyer 
136*9de21005SAndrew Boyer 	if (rte_kvargs_count(kvlist, PMD_IONIC_CMB_KVARG) == 1) {
137*9de21005SAndrew Boyer 		err = rte_kvargs_process(kvlist, PMD_IONIC_CMB_KVARG,
138*9de21005SAndrew Boyer 				ionic_pci_devarg_cmb, adapter);
139*9de21005SAndrew Boyer 		if (err < 0)
140*9de21005SAndrew Boyer 			goto free_kvlist;
141*9de21005SAndrew Boyer 	}
142*9de21005SAndrew Boyer 
143*9de21005SAndrew Boyer free_kvlist:
144*9de21005SAndrew Boyer 	rte_kvargs_free(kvlist);
145*9de21005SAndrew Boyer 	return err;
146*9de21005SAndrew Boyer }
147*9de21005SAndrew Boyer 
1488eaafff3SAndrew Boyer static void
1498eaafff3SAndrew Boyer ionic_pci_copy_bus_info(struct ionic_adapter *adapter,
1508eaafff3SAndrew Boyer 	struct rte_eth_dev *eth_dev)
1518eaafff3SAndrew Boyer {
1528eaafff3SAndrew Boyer 	rte_eth_copy_pci_info(eth_dev, adapter->bus_dev);
1538eaafff3SAndrew Boyer }
1548eaafff3SAndrew Boyer 
1558eaafff3SAndrew Boyer static int
1568eaafff3SAndrew Boyer ionic_pci_configure_intr(struct ionic_adapter *adapter)
1578eaafff3SAndrew Boyer {
1588eaafff3SAndrew Boyer 	struct rte_pci_device *pci_dev =
1598eaafff3SAndrew Boyer 		(struct rte_pci_device *)(adapter->bus_dev);
1608eaafff3SAndrew Boyer 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
1618eaafff3SAndrew Boyer 	int err;
1628eaafff3SAndrew Boyer 
1638eaafff3SAndrew Boyer 	IONIC_PRINT(ERR, "Configuring %u intrs", adapter->nintrs);
1648eaafff3SAndrew Boyer 
1658eaafff3SAndrew Boyer 	if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
1668eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Fail to create eventfd");
1678eaafff3SAndrew Boyer 		return -1;
1688eaafff3SAndrew Boyer 	}
1698eaafff3SAndrew Boyer 
1708eaafff3SAndrew Boyer 	if (rte_intr_dp_is_en(intr_handle)) {
1718eaafff3SAndrew Boyer 		IONIC_PRINT(NOTICE,
1728eaafff3SAndrew Boyer 			"Packet I/O interrupt on datapath is enabled");
1738eaafff3SAndrew Boyer 		if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
1748eaafff3SAndrew Boyer 						adapter->nintrs)) {
1758eaafff3SAndrew Boyer 			IONIC_PRINT(ERR, "Failed to allocate %u vectors",
1768eaafff3SAndrew Boyer 						adapter->nintrs);
1778eaafff3SAndrew Boyer 			return -ENOMEM;
1788eaafff3SAndrew Boyer 		}
1798eaafff3SAndrew Boyer 	}
1808eaafff3SAndrew Boyer 
1818eaafff3SAndrew Boyer 	err = rte_intr_callback_register(intr_handle,
1828eaafff3SAndrew Boyer 		ionic_dev_interrupt_handler,
1838eaafff3SAndrew Boyer 		adapter);
1848eaafff3SAndrew Boyer 	if (err) {
1858eaafff3SAndrew Boyer 		IONIC_PRINT(ERR,
1868eaafff3SAndrew Boyer 			"Failure registering interrupts handler (%d)", err);
1878eaafff3SAndrew Boyer 		return err;
1888eaafff3SAndrew Boyer 	}
1898eaafff3SAndrew Boyer 
1908eaafff3SAndrew Boyer 	/* enable intr mapping */
1918eaafff3SAndrew Boyer 	err = rte_intr_enable(intr_handle);
1928eaafff3SAndrew Boyer 	if (err) {
1938eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
1948eaafff3SAndrew Boyer 		return err;
1958eaafff3SAndrew Boyer 	}
1968eaafff3SAndrew Boyer 
1978eaafff3SAndrew Boyer 	return 0;
1988eaafff3SAndrew Boyer }
1998eaafff3SAndrew Boyer 
2008eaafff3SAndrew Boyer static void
2018eaafff3SAndrew Boyer ionic_pci_unconfigure_intr(struct ionic_adapter *adapter)
2028eaafff3SAndrew Boyer {
2038eaafff3SAndrew Boyer 	struct rte_pci_device *pci_dev =
2048eaafff3SAndrew Boyer 		(struct rte_pci_device *)(adapter->bus_dev);
2058eaafff3SAndrew Boyer 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
2068eaafff3SAndrew Boyer 
2078eaafff3SAndrew Boyer 	rte_intr_disable(intr_handle);
2088eaafff3SAndrew Boyer 
2098eaafff3SAndrew Boyer 	rte_intr_callback_unregister(intr_handle,
2108eaafff3SAndrew Boyer 		ionic_dev_interrupt_handler,
2118eaafff3SAndrew Boyer 		adapter);
2128eaafff3SAndrew Boyer }
2138eaafff3SAndrew Boyer 
2148eaafff3SAndrew Boyer static const struct ionic_dev_intf ionic_pci_intf = {
2158eaafff3SAndrew Boyer 	.setup = ionic_pci_setup,
216*9de21005SAndrew Boyer 	.devargs = ionic_pci_devargs,
2178eaafff3SAndrew Boyer 	.copy_bus_info = ionic_pci_copy_bus_info,
2188eaafff3SAndrew Boyer 	.configure_intr = ionic_pci_configure_intr,
2198eaafff3SAndrew Boyer 	.unconfigure_intr = ionic_pci_unconfigure_intr,
2208eaafff3SAndrew Boyer };
2218eaafff3SAndrew Boyer 
2228eaafff3SAndrew Boyer static int
2238eaafff3SAndrew Boyer eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
2248eaafff3SAndrew Boyer 		struct rte_pci_device *pci_dev)
2258eaafff3SAndrew Boyer {
2268eaafff3SAndrew Boyer 	struct rte_mem_resource *resource;
2278eaafff3SAndrew Boyer 	struct ionic_bars bars;
2288eaafff3SAndrew Boyer 	unsigned long i;
2298eaafff3SAndrew Boyer 
2308eaafff3SAndrew Boyer 	IONIC_PRINT(NOTICE, "Initializing device %s %s",
2318eaafff3SAndrew Boyer 		pci_dev->device.name,
2328eaafff3SAndrew Boyer 		rte_eal_process_type() == RTE_PROC_SECONDARY ?
2338eaafff3SAndrew Boyer 		"[SECONDARY]" : "");
2348eaafff3SAndrew Boyer 
2358eaafff3SAndrew Boyer 	bars.num_bars = 0;
2368eaafff3SAndrew Boyer 	for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
2378eaafff3SAndrew Boyer 		resource = &pci_dev->mem_resource[i];
2388eaafff3SAndrew Boyer 		if (resource->phys_addr == 0 || resource->len == 0)
2398eaafff3SAndrew Boyer 			continue;
2408eaafff3SAndrew Boyer 
2418eaafff3SAndrew Boyer 		bars.bar[bars.num_bars].vaddr = resource->addr;
2428eaafff3SAndrew Boyer 		bars.bar[bars.num_bars].bus_addr = resource->phys_addr;
2438eaafff3SAndrew Boyer 		bars.bar[bars.num_bars].len = resource->len;
2448eaafff3SAndrew Boyer 		bars.num_bars++;
2458eaafff3SAndrew Boyer 	}
2468eaafff3SAndrew Boyer 
2478eaafff3SAndrew Boyer 	return eth_ionic_dev_probe((void *)pci_dev,
2488eaafff3SAndrew Boyer 			&pci_dev->device,
2498eaafff3SAndrew Boyer 			&bars,
2508eaafff3SAndrew Boyer 			&ionic_pci_intf,
2518eaafff3SAndrew Boyer 			pci_dev->id.device_id,
2528eaafff3SAndrew Boyer 			pci_dev->id.vendor_id);
2538eaafff3SAndrew Boyer }
2548eaafff3SAndrew Boyer 
2558eaafff3SAndrew Boyer static int
2568eaafff3SAndrew Boyer eth_ionic_pci_remove(struct rte_pci_device *pci_dev)
2578eaafff3SAndrew Boyer {
2588eaafff3SAndrew Boyer 	return eth_ionic_dev_remove(&pci_dev->device);
2598eaafff3SAndrew Boyer }
2608eaafff3SAndrew Boyer 
2618eaafff3SAndrew Boyer static struct rte_pci_driver rte_pci_ionic_pmd = {
2628eaafff3SAndrew Boyer 	.id_table = pci_id_ionic_map,
263*9de21005SAndrew Boyer 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
264*9de21005SAndrew Boyer 			RTE_PCI_DRV_WC_ACTIVATE,
2658eaafff3SAndrew Boyer 	.probe = eth_ionic_pci_probe,
2668eaafff3SAndrew Boyer 	.remove = eth_ionic_pci_remove,
2678eaafff3SAndrew Boyer };
2688eaafff3SAndrew Boyer 
2698eaafff3SAndrew Boyer RTE_PMD_REGISTER_PCI(net_ionic_pci, rte_pci_ionic_pmd);
2708eaafff3SAndrew Boyer RTE_PMD_REGISTER_PCI_TABLE(net_ionic_pci, pci_id_ionic_map);
2718eaafff3SAndrew Boyer RTE_PMD_REGISTER_KMOD_DEP(net_ionic_pci, "* igb_uio | uio_pci_generic | vfio-pci");
272*9de21005SAndrew Boyer RTE_PMD_REGISTER_PARAM_STRING(net_ionic_pci,
273*9de21005SAndrew Boyer 	PMD_IONIC_CMB_KVARG "=<0|1>"
274*9de21005SAndrew Boyer );
275