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 #include <rte_kvargs.h>
19
20 #include "ionic.h"
21 #include "ionic_if.h"
22 #include "ionic_dev.h"
23 #include "ionic_ethdev.h"
24 #include "ionic_logs.h"
25
26 static const struct rte_pci_id pci_id_ionic_map[] = {
27 { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_PF) },
28 { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_VF) },
29 { RTE_PCI_DEVICE(IONIC_PENSANDO_VENDOR_ID, IONIC_DEV_ID_ETH_MGMT) },
30 { .vendor_id = 0, /* sentinel */ },
31 };
32
33 static int
ionic_pci_setup(struct ionic_adapter * adapter)34 ionic_pci_setup(struct ionic_adapter *adapter)
35 {
36 struct ionic_dev_bar *bar = adapter->bars.bar;
37 unsigned int num_bars = adapter->bars.num_bars;
38 struct ionic_dev *idev = &adapter->idev;
39 struct rte_pci_device *bus_dev = adapter->bus_dev;
40 uint32_t sig;
41 uint8_t *bar0_base;
42 unsigned int i;
43
44 /* BAR0: dev_cmd and interrupts */
45 if (num_bars < 1) {
46 IONIC_PRINT(ERR, "No bars found, aborting");
47 return -EFAULT;
48 }
49
50 if (bar->len < IONIC_BAR0_SIZE) {
51 IONIC_PRINT(ERR, "Resource bar size %lu too small, aborting",
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 < IONIC_BARS_MIN) {
86 IONIC_PRINT(ERR, "Doorbell bar missing, aborting");
87 return -EFAULT;
88 }
89
90 idev->db_pages = bar->vaddr;
91
92 return 0;
93 }
94
95 const char *ionic_pci_devargs_arr[] = {
96 PMD_IONIC_CMB_KVARG,
97 NULL,
98 };
99
100 static int
ionic_pci_devarg_cmb(const char * key __rte_unused,const char * val,void * arg)101 ionic_pci_devarg_cmb(const char *key __rte_unused, const char *val, void *arg)
102 {
103 struct ionic_adapter *adapter = arg;
104
105 if (!strcmp(val, "1")) {
106 IONIC_PRINT(NOTICE, "%s enabled", PMD_IONIC_CMB_KVARG);
107 adapter->q_in_cmb = true;
108 } else if (!strcmp(val, "0")) {
109 IONIC_PRINT(DEBUG, "%s disabled (default)",
110 PMD_IONIC_CMB_KVARG);
111 } else {
112 IONIC_PRINT(ERR, "%s=%s invalid, use 1 or 0",
113 PMD_IONIC_CMB_KVARG, val);
114 return -ERANGE;
115 }
116
117 return 0;
118 }
119
120 static int
ionic_pci_devargs(struct ionic_adapter * adapter,struct rte_devargs * devargs)121 ionic_pci_devargs(struct ionic_adapter *adapter, struct rte_devargs *devargs)
122 {
123 struct rte_kvargs *kvlist;
124 int err = 0;
125
126 if (!devargs)
127 return 0;
128
129 kvlist = rte_kvargs_parse(devargs->args, ionic_pci_devargs_arr);
130 if (!kvlist) {
131 IONIC_PRINT(ERR, "Couldn't parse args '%s'", devargs->args);
132 return -EINVAL;
133 }
134
135 if (rte_kvargs_count(kvlist, PMD_IONIC_CMB_KVARG) == 1) {
136 err = rte_kvargs_process(kvlist, PMD_IONIC_CMB_KVARG,
137 ionic_pci_devarg_cmb, adapter);
138 if (err < 0)
139 goto free_kvlist;
140 }
141
142 free_kvlist:
143 rte_kvargs_free(kvlist);
144 return err;
145 }
146
147 static void
ionic_pci_copy_bus_info(struct ionic_adapter * adapter,struct rte_eth_dev * eth_dev)148 ionic_pci_copy_bus_info(struct ionic_adapter *adapter,
149 struct rte_eth_dev *eth_dev)
150 {
151 rte_eth_copy_pci_info(eth_dev, adapter->bus_dev);
152 }
153
154 static int
ionic_pci_configure_intr(struct ionic_adapter * adapter)155 ionic_pci_configure_intr(struct ionic_adapter *adapter)
156 {
157 struct rte_pci_device *pci_dev =
158 (struct rte_pci_device *)(adapter->bus_dev);
159 struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
160 int err;
161
162 IONIC_PRINT(ERR, "Configuring %u intrs", adapter->nintrs);
163
164 if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
165 IONIC_PRINT(ERR, "Fail to create eventfd");
166 return -1;
167 }
168
169 if (rte_intr_dp_is_en(intr_handle)) {
170 IONIC_PRINT(NOTICE,
171 "Packet I/O interrupt on datapath is enabled");
172 if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
173 adapter->nintrs)) {
174 IONIC_PRINT(ERR, "Failed to allocate %u vectors",
175 adapter->nintrs);
176 return -ENOMEM;
177 }
178 }
179
180 err = rte_intr_callback_register(intr_handle,
181 ionic_dev_interrupt_handler,
182 adapter);
183 if (err) {
184 IONIC_PRINT(ERR,
185 "Failure registering interrupts handler (%d)", err);
186 return err;
187 }
188
189 /* enable intr mapping */
190 err = rte_intr_enable(intr_handle);
191 if (err) {
192 IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
193 return err;
194 }
195
196 return 0;
197 }
198
199 static void
ionic_pci_unconfigure_intr(struct ionic_adapter * adapter)200 ionic_pci_unconfigure_intr(struct ionic_adapter *adapter)
201 {
202 struct rte_pci_device *pci_dev =
203 (struct rte_pci_device *)(adapter->bus_dev);
204 struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
205
206 rte_intr_disable(intr_handle);
207
208 rte_intr_callback_unregister(intr_handle,
209 ionic_dev_interrupt_handler,
210 adapter);
211 }
212
213 static const struct ionic_dev_intf ionic_pci_intf = {
214 .setup = ionic_pci_setup,
215 .devargs = ionic_pci_devargs,
216 .copy_bus_info = ionic_pci_copy_bus_info,
217 .configure_intr = ionic_pci_configure_intr,
218 .unconfigure_intr = ionic_pci_unconfigure_intr,
219 };
220
221 static int
eth_ionic_pci_probe(struct rte_pci_driver * pci_drv __rte_unused,struct rte_pci_device * pci_dev)222 eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
223 struct rte_pci_device *pci_dev)
224 {
225 struct rte_mem_resource *resource;
226 struct ionic_bars bars;
227 unsigned long i;
228
229 IONIC_PRINT(NOTICE, "Initializing device %s %s",
230 pci_dev->device.name,
231 rte_eal_process_type() == RTE_PROC_SECONDARY ?
232 "[SECONDARY]" : "");
233
234 bars.num_bars = 0;
235 for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
236 resource = &pci_dev->mem_resource[i];
237 if (resource->phys_addr == 0 || resource->len == 0)
238 continue;
239
240 bars.bar[bars.num_bars].vaddr = resource->addr;
241 bars.bar[bars.num_bars].bus_addr = resource->phys_addr;
242 bars.bar[bars.num_bars].len = resource->len;
243 bars.num_bars++;
244 }
245
246 return eth_ionic_dev_probe((void *)pci_dev,
247 &pci_dev->device,
248 &bars,
249 &ionic_pci_intf,
250 pci_dev->id.device_id,
251 pci_dev->id.vendor_id);
252 }
253
254 static int
eth_ionic_pci_remove(struct rte_pci_device * pci_dev)255 eth_ionic_pci_remove(struct rte_pci_device *pci_dev)
256 {
257 return eth_ionic_dev_remove(&pci_dev->device);
258 }
259
260 static struct rte_pci_driver rte_pci_ionic_pmd = {
261 .id_table = pci_id_ionic_map,
262 .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
263 RTE_PCI_DRV_WC_ACTIVATE,
264 .probe = eth_ionic_pci_probe,
265 .remove = eth_ionic_pci_remove,
266 };
267
268 RTE_PMD_REGISTER_PCI(net_ionic_pci, rte_pci_ionic_pmd);
269 RTE_PMD_REGISTER_PCI_TABLE(net_ionic_pci, pci_id_ionic_map);
270 RTE_PMD_REGISTER_KMOD_DEP(net_ionic_pci, "* igb_uio | uio_pci_generic | vfio-pci");
271 RTE_PMD_REGISTER_PARAM_STRING(net_ionic_pci,
272 PMD_IONIC_CMB_KVARG "=<0|1>"
273 );
274