xref: /dpdk/drivers/net/ionic/ionic_dev_pci.c (revision 8eaafff38fccb37357fe6bd8275cd7331a8cec97)
1*8eaafff3SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
2*8eaafff3SAndrew Boyer  * Copyright 2018-2022 Advanced Micro Devices, Inc.
3*8eaafff3SAndrew Boyer  */
4*8eaafff3SAndrew Boyer 
5*8eaafff3SAndrew Boyer #include <stdio.h>
6*8eaafff3SAndrew Boyer #include <errno.h>
7*8eaafff3SAndrew Boyer #include <string.h>
8*8eaafff3SAndrew Boyer #include <stdint.h>
9*8eaafff3SAndrew Boyer 
10*8eaafff3SAndrew Boyer #include <rte_common.h>
11*8eaafff3SAndrew Boyer #include <rte_interrupts.h>
12*8eaafff3SAndrew Boyer #include <rte_log.h>
13*8eaafff3SAndrew Boyer #include <rte_pci.h>
14*8eaafff3SAndrew Boyer #include <bus_pci_driver.h>
15*8eaafff3SAndrew Boyer #include <rte_eal.h>
16*8eaafff3SAndrew Boyer #include <ethdev_pci.h>
17*8eaafff3SAndrew Boyer #include <rte_dev.h>
18*8eaafff3SAndrew Boyer 
19*8eaafff3SAndrew Boyer #include "ionic.h"
20*8eaafff3SAndrew Boyer #include "ionic_if.h"
21*8eaafff3SAndrew Boyer #include "ionic_dev.h"
22*8eaafff3SAndrew Boyer #include "ionic_ethdev.h"
23*8eaafff3SAndrew Boyer #include "ionic_logs.h"
24*8eaafff3SAndrew Boyer 
25*8eaafff3SAndrew Boyer static const struct rte_pci_id pci_id_ionic_map[] = {
26*8eaafff3SAndrew Boyer 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) },
27*8eaafff3SAndrew Boyer 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) },
28*8eaafff3SAndrew Boyer 	{ RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) },
29*8eaafff3SAndrew Boyer 	{ .vendor_id = 0, /* sentinel */ },
30*8eaafff3SAndrew Boyer };
31*8eaafff3SAndrew Boyer 
32*8eaafff3SAndrew Boyer static int
33*8eaafff3SAndrew Boyer ionic_pci_setup(struct ionic_adapter *adapter)
34*8eaafff3SAndrew Boyer {
35*8eaafff3SAndrew Boyer 	struct ionic_dev_bar *bar = adapter->bars.bar;
36*8eaafff3SAndrew Boyer 	unsigned int num_bars = adapter->bars.num_bars;
37*8eaafff3SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
38*8eaafff3SAndrew Boyer 	struct rte_pci_device *bus_dev = adapter->bus_dev;
39*8eaafff3SAndrew Boyer 	uint32_t sig;
40*8eaafff3SAndrew Boyer 	u_char *bar0_base;
41*8eaafff3SAndrew Boyer 	unsigned int i;
42*8eaafff3SAndrew Boyer 
43*8eaafff3SAndrew Boyer 	/* BAR0: dev_cmd and interrupts */
44*8eaafff3SAndrew Boyer 	if (num_bars < 1) {
45*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "No bars found, aborting\n");
46*8eaafff3SAndrew Boyer 		return -EFAULT;
47*8eaafff3SAndrew Boyer 	}
48*8eaafff3SAndrew Boyer 
49*8eaafff3SAndrew Boyer 	if (bar->len < IONIC_BAR0_SIZE) {
50*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR,
51*8eaafff3SAndrew Boyer 			"Resource bar size %lu too small, aborting\n",
52*8eaafff3SAndrew Boyer 			bar->len);
53*8eaafff3SAndrew Boyer 		return -EFAULT;
54*8eaafff3SAndrew Boyer 	}
55*8eaafff3SAndrew Boyer 
56*8eaafff3SAndrew Boyer 	bar0_base = bar->vaddr;
57*8eaafff3SAndrew Boyer 	idev->dev_info = (union ionic_dev_info_regs *)
58*8eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET];
59*8eaafff3SAndrew Boyer 	idev->dev_cmd = (union ionic_dev_cmd_regs *)
60*8eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET];
61*8eaafff3SAndrew Boyer 	idev->intr_status = (struct ionic_intr_status *)
62*8eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET];
63*8eaafff3SAndrew Boyer 	idev->intr_ctrl = (struct ionic_intr *)
64*8eaafff3SAndrew Boyer 		&bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET];
65*8eaafff3SAndrew Boyer 
66*8eaafff3SAndrew Boyer 	sig = ioread32(&idev->dev_info->signature);
67*8eaafff3SAndrew Boyer 	if (sig != IONIC_DEV_INFO_SIGNATURE) {
68*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Incompatible firmware signature %#x",
69*8eaafff3SAndrew Boyer 			sig);
70*8eaafff3SAndrew Boyer 		return -EFAULT;
71*8eaafff3SAndrew Boyer 	}
72*8eaafff3SAndrew Boyer 
73*8eaafff3SAndrew Boyer 	for (i = 0; i < IONIC_DEVINFO_FWVERS_BUFLEN; i++)
74*8eaafff3SAndrew Boyer 		adapter->fw_version[i] =
75*8eaafff3SAndrew Boyer 			ioread8(&idev->dev_info->fw_version[i]);
76*8eaafff3SAndrew Boyer 	adapter->fw_version[IONIC_DEVINFO_FWVERS_BUFLEN - 1] = '\0';
77*8eaafff3SAndrew Boyer 
78*8eaafff3SAndrew Boyer 	adapter->name = bus_dev->device.name;
79*8eaafff3SAndrew Boyer 
80*8eaafff3SAndrew Boyer 	IONIC_PRINT(DEBUG, "%s firmware version: %s",
81*8eaafff3SAndrew Boyer 		adapter->name, adapter->fw_version);
82*8eaafff3SAndrew Boyer 
83*8eaafff3SAndrew Boyer 	/* BAR1: doorbells */
84*8eaafff3SAndrew Boyer 	bar++;
85*8eaafff3SAndrew Boyer 	if (num_bars < 2) {
86*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Doorbell bar missing, aborting\n");
87*8eaafff3SAndrew Boyer 		return -EFAULT;
88*8eaafff3SAndrew Boyer 	}
89*8eaafff3SAndrew Boyer 
90*8eaafff3SAndrew Boyer 	idev->db_pages = bar->vaddr;
91*8eaafff3SAndrew Boyer 
92*8eaafff3SAndrew Boyer 	return 0;
93*8eaafff3SAndrew Boyer }
94*8eaafff3SAndrew Boyer 
95*8eaafff3SAndrew Boyer static void
96*8eaafff3SAndrew Boyer ionic_pci_copy_bus_info(struct ionic_adapter *adapter,
97*8eaafff3SAndrew Boyer 	struct rte_eth_dev *eth_dev)
98*8eaafff3SAndrew Boyer {
99*8eaafff3SAndrew Boyer 	rte_eth_copy_pci_info(eth_dev, adapter->bus_dev);
100*8eaafff3SAndrew Boyer }
101*8eaafff3SAndrew Boyer 
102*8eaafff3SAndrew Boyer static int
103*8eaafff3SAndrew Boyer ionic_pci_configure_intr(struct ionic_adapter *adapter)
104*8eaafff3SAndrew Boyer {
105*8eaafff3SAndrew Boyer 	struct rte_pci_device *pci_dev =
106*8eaafff3SAndrew Boyer 		(struct rte_pci_device *)(adapter->bus_dev);
107*8eaafff3SAndrew Boyer 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
108*8eaafff3SAndrew Boyer 	int err;
109*8eaafff3SAndrew Boyer 
110*8eaafff3SAndrew Boyer 	IONIC_PRINT(ERR, "Configuring %u intrs", adapter->nintrs);
111*8eaafff3SAndrew Boyer 
112*8eaafff3SAndrew Boyer 	if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
113*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Fail to create eventfd");
114*8eaafff3SAndrew Boyer 		return -1;
115*8eaafff3SAndrew Boyer 	}
116*8eaafff3SAndrew Boyer 
117*8eaafff3SAndrew Boyer 	if (rte_intr_dp_is_en(intr_handle)) {
118*8eaafff3SAndrew Boyer 		IONIC_PRINT(NOTICE,
119*8eaafff3SAndrew Boyer 			"Packet I/O interrupt on datapath is enabled");
120*8eaafff3SAndrew Boyer 		if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
121*8eaafff3SAndrew Boyer 						adapter->nintrs)) {
122*8eaafff3SAndrew Boyer 			IONIC_PRINT(ERR, "Failed to allocate %u vectors",
123*8eaafff3SAndrew Boyer 						adapter->nintrs);
124*8eaafff3SAndrew Boyer 			return -ENOMEM;
125*8eaafff3SAndrew Boyer 		}
126*8eaafff3SAndrew Boyer 	}
127*8eaafff3SAndrew Boyer 
128*8eaafff3SAndrew Boyer 	err = rte_intr_callback_register(intr_handle,
129*8eaafff3SAndrew Boyer 		ionic_dev_interrupt_handler,
130*8eaafff3SAndrew Boyer 		adapter);
131*8eaafff3SAndrew Boyer 	if (err) {
132*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR,
133*8eaafff3SAndrew Boyer 			"Failure registering interrupts handler (%d)", err);
134*8eaafff3SAndrew Boyer 		return err;
135*8eaafff3SAndrew Boyer 	}
136*8eaafff3SAndrew Boyer 
137*8eaafff3SAndrew Boyer 	/* enable intr mapping */
138*8eaafff3SAndrew Boyer 	err = rte_intr_enable(intr_handle);
139*8eaafff3SAndrew Boyer 	if (err) {
140*8eaafff3SAndrew Boyer 		IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
141*8eaafff3SAndrew Boyer 		return err;
142*8eaafff3SAndrew Boyer 	}
143*8eaafff3SAndrew Boyer 
144*8eaafff3SAndrew Boyer 	return 0;
145*8eaafff3SAndrew Boyer }
146*8eaafff3SAndrew Boyer 
147*8eaafff3SAndrew Boyer static void
148*8eaafff3SAndrew Boyer ionic_pci_unconfigure_intr(struct ionic_adapter *adapter)
149*8eaafff3SAndrew Boyer {
150*8eaafff3SAndrew Boyer 	struct rte_pci_device *pci_dev =
151*8eaafff3SAndrew Boyer 		(struct rte_pci_device *)(adapter->bus_dev);
152*8eaafff3SAndrew Boyer 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
153*8eaafff3SAndrew Boyer 
154*8eaafff3SAndrew Boyer 	rte_intr_disable(intr_handle);
155*8eaafff3SAndrew Boyer 
156*8eaafff3SAndrew Boyer 	rte_intr_callback_unregister(intr_handle,
157*8eaafff3SAndrew Boyer 		ionic_dev_interrupt_handler,
158*8eaafff3SAndrew Boyer 		adapter);
159*8eaafff3SAndrew Boyer }
160*8eaafff3SAndrew Boyer 
161*8eaafff3SAndrew Boyer static const struct ionic_dev_intf ionic_pci_intf = {
162*8eaafff3SAndrew Boyer 	.setup = ionic_pci_setup,
163*8eaafff3SAndrew Boyer 	.copy_bus_info = ionic_pci_copy_bus_info,
164*8eaafff3SAndrew Boyer 	.configure_intr = ionic_pci_configure_intr,
165*8eaafff3SAndrew Boyer 	.unconfigure_intr = ionic_pci_unconfigure_intr,
166*8eaafff3SAndrew Boyer };
167*8eaafff3SAndrew Boyer 
168*8eaafff3SAndrew Boyer static int
169*8eaafff3SAndrew Boyer eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
170*8eaafff3SAndrew Boyer 		struct rte_pci_device *pci_dev)
171*8eaafff3SAndrew Boyer {
172*8eaafff3SAndrew Boyer 	struct rte_mem_resource *resource;
173*8eaafff3SAndrew Boyer 	struct ionic_bars bars;
174*8eaafff3SAndrew Boyer 	unsigned long i;
175*8eaafff3SAndrew Boyer 
176*8eaafff3SAndrew Boyer 	IONIC_PRINT(NOTICE, "Initializing device %s %s",
177*8eaafff3SAndrew Boyer 		pci_dev->device.name,
178*8eaafff3SAndrew Boyer 		rte_eal_process_type() == RTE_PROC_SECONDARY ?
179*8eaafff3SAndrew Boyer 		"[SECONDARY]" : "");
180*8eaafff3SAndrew Boyer 
181*8eaafff3SAndrew Boyer 	bars.num_bars = 0;
182*8eaafff3SAndrew Boyer 	for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
183*8eaafff3SAndrew Boyer 		resource = &pci_dev->mem_resource[i];
184*8eaafff3SAndrew Boyer 		if (resource->phys_addr == 0 || resource->len == 0)
185*8eaafff3SAndrew Boyer 			continue;
186*8eaafff3SAndrew Boyer 
187*8eaafff3SAndrew Boyer 		bars.bar[bars.num_bars].vaddr = resource->addr;
188*8eaafff3SAndrew Boyer 		bars.bar[bars.num_bars].bus_addr = resource->phys_addr;
189*8eaafff3SAndrew Boyer 		bars.bar[bars.num_bars].len = resource->len;
190*8eaafff3SAndrew Boyer 		bars.num_bars++;
191*8eaafff3SAndrew Boyer 	}
192*8eaafff3SAndrew Boyer 
193*8eaafff3SAndrew Boyer 	return eth_ionic_dev_probe((void *)pci_dev,
194*8eaafff3SAndrew Boyer 			&pci_dev->device,
195*8eaafff3SAndrew Boyer 			&bars,
196*8eaafff3SAndrew Boyer 			&ionic_pci_intf,
197*8eaafff3SAndrew Boyer 			pci_dev->id.device_id,
198*8eaafff3SAndrew Boyer 			pci_dev->id.vendor_id);
199*8eaafff3SAndrew Boyer }
200*8eaafff3SAndrew Boyer 
201*8eaafff3SAndrew Boyer static int
202*8eaafff3SAndrew Boyer eth_ionic_pci_remove(struct rte_pci_device *pci_dev)
203*8eaafff3SAndrew Boyer {
204*8eaafff3SAndrew Boyer 	return eth_ionic_dev_remove(&pci_dev->device);
205*8eaafff3SAndrew Boyer }
206*8eaafff3SAndrew Boyer 
207*8eaafff3SAndrew Boyer static struct rte_pci_driver rte_pci_ionic_pmd = {
208*8eaafff3SAndrew Boyer 	.id_table = pci_id_ionic_map,
209*8eaafff3SAndrew Boyer 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
210*8eaafff3SAndrew Boyer 	.probe = eth_ionic_pci_probe,
211*8eaafff3SAndrew Boyer 	.remove = eth_ionic_pci_remove,
212*8eaafff3SAndrew Boyer };
213*8eaafff3SAndrew Boyer 
214*8eaafff3SAndrew Boyer RTE_PMD_REGISTER_PCI(net_ionic_pci, rte_pci_ionic_pmd);
215*8eaafff3SAndrew Boyer RTE_PMD_REGISTER_PCI_TABLE(net_ionic_pci, pci_id_ionic_map);
216*8eaafff3SAndrew Boyer RTE_PMD_REGISTER_KMOD_DEP(net_ionic_pci, "* igb_uio | uio_pci_generic | vfio-pci");
217