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