Branch data Line data Source code
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
34 : 0 : ionic_pci_setup(struct ionic_adapter *adapter)
35 : : {
36 : : struct ionic_dev_bar *bar = adapter->bars.bar;
37 : 0 : unsigned int num_bars = adapter->bars.num_bars;
38 : : struct ionic_dev *idev = &adapter->idev;
39 : 0 : 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 [ # # ]: 0 : if (num_bars < 1) {
46 : 0 : IONIC_PRINT(ERR, "No bars found, aborting\n");
47 : 0 : return -EFAULT;
48 : : }
49 : :
50 [ # # ]: 0 : if (bar->len < IONIC_BAR0_SIZE) {
51 : 0 : IONIC_PRINT(ERR,
52 : : "Resource bar size %lu too small, aborting\n",
53 : : bar->len);
54 : 0 : return -EFAULT;
55 : : }
56 : :
57 : 0 : bar0_base = bar->vaddr;
58 : 0 : idev->dev_info = (union ionic_dev_info_regs *)
59 : : &bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET];
60 : 0 : idev->dev_cmd = (union ionic_dev_cmd_regs *)
61 : 0 : &bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET];
62 : 0 : idev->intr_status = (struct ionic_intr_status *)
63 : 0 : &bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET];
64 : 0 : idev->intr_ctrl = (struct ionic_intr *)
65 : 0 : &bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET];
66 : :
67 : : sig = ioread32(&idev->dev_info->signature);
68 [ # # ]: 0 : if (sig != IONIC_DEV_INFO_SIGNATURE) {
69 : 0 : IONIC_PRINT(ERR, "Incompatible firmware signature %#x",
70 : : sig);
71 : 0 : return -EFAULT;
72 : : }
73 : :
74 [ # # ]: 0 : for (i = 0; i < IONIC_DEVINFO_FWVERS_BUFLEN; i++)
75 : 0 : adapter->fw_version[i] =
76 : 0 : ioread8(&idev->dev_info->fw_version[i]);
77 : 0 : adapter->fw_version[IONIC_DEVINFO_FWVERS_BUFLEN - 1] = '\0';
78 : :
79 : 0 : adapter->name = bus_dev->device.name;
80 : :
81 : 0 : IONIC_PRINT(DEBUG, "%s firmware version: %s",
82 : : adapter->name, adapter->fw_version);
83 : :
84 : : /* BAR1: doorbells */
85 : : bar++;
86 [ # # ]: 0 : if (num_bars < IONIC_BARS_MIN) {
87 : 0 : IONIC_PRINT(ERR, "Doorbell bar missing, aborting\n");
88 : 0 : return -EFAULT;
89 : : }
90 : :
91 : 0 : idev->db_pages = bar->vaddr;
92 : :
93 : 0 : return 0;
94 : : }
95 : :
96 : : const char *ionic_pci_devargs_arr[] = {
97 : : PMD_IONIC_CMB_KVARG,
98 : : NULL,
99 : : };
100 : :
101 : : static int
102 : 0 : ionic_pci_devarg_cmb(const char *key __rte_unused, const char *val, void *arg)
103 : : {
104 : : struct ionic_adapter *adapter = arg;
105 : :
106 [ # # ]: 0 : if (!strcmp(val, "1")) {
107 : 0 : IONIC_PRINT(NOTICE, "%s enabled", PMD_IONIC_CMB_KVARG);
108 : 0 : adapter->q_in_cmb = true;
109 [ # # ]: 0 : } else if (!strcmp(val, "0")) {
110 : 0 : IONIC_PRINT(DEBUG, "%s disabled (default)",
111 : : PMD_IONIC_CMB_KVARG);
112 : : } else {
113 : 0 : IONIC_PRINT(ERR, "%s=%s invalid, use 1 or 0",
114 : : PMD_IONIC_CMB_KVARG, val);
115 : 0 : return -ERANGE;
116 : : }
117 : :
118 : : return 0;
119 : : }
120 : :
121 : : static int
122 : 0 : ionic_pci_devargs(struct ionic_adapter *adapter, struct rte_devargs *devargs)
123 : : {
124 : : struct rte_kvargs *kvlist;
125 : : int err = 0;
126 : :
127 [ # # ]: 0 : if (!devargs)
128 : : return 0;
129 : :
130 : 0 : kvlist = rte_kvargs_parse(devargs->args, ionic_pci_devargs_arr);
131 [ # # ]: 0 : if (!kvlist) {
132 : 0 : IONIC_PRINT(ERR, "Couldn't parse args '%s'", devargs->args);
133 : 0 : return -EINVAL;
134 : : }
135 : :
136 [ # # ]: 0 : if (rte_kvargs_count(kvlist, PMD_IONIC_CMB_KVARG) == 1) {
137 : 0 : err = rte_kvargs_process(kvlist, PMD_IONIC_CMB_KVARG,
138 : : ionic_pci_devarg_cmb, adapter);
139 [ # # ]: 0 : if (err < 0)
140 : 0 : goto free_kvlist;
141 : : }
142 : :
143 : 0 : free_kvlist:
144 : 0 : rte_kvargs_free(kvlist);
145 : 0 : return err;
146 : : }
147 : :
148 : : static void
149 : 0 : ionic_pci_copy_bus_info(struct ionic_adapter *adapter,
150 : : struct rte_eth_dev *eth_dev)
151 : : {
152 : 0 : rte_eth_copy_pci_info(eth_dev, adapter->bus_dev);
153 : 0 : }
154 : :
155 : : static int
156 : 0 : ionic_pci_configure_intr(struct ionic_adapter *adapter)
157 : : {
158 : 0 : struct rte_pci_device *pci_dev =
159 : : (struct rte_pci_device *)(adapter->bus_dev);
160 : 0 : struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
161 : : int err;
162 : :
163 : 0 : IONIC_PRINT(ERR, "Configuring %u intrs", adapter->nintrs);
164 : :
165 [ # # ]: 0 : if (rte_intr_efd_enable(intr_handle, adapter->nintrs)) {
166 : 0 : IONIC_PRINT(ERR, "Fail to create eventfd");
167 : 0 : return -1;
168 : : }
169 : :
170 [ # # ]: 0 : if (rte_intr_dp_is_en(intr_handle)) {
171 : 0 : IONIC_PRINT(NOTICE,
172 : : "Packet I/O interrupt on datapath is enabled");
173 [ # # ]: 0 : if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
174 : 0 : adapter->nintrs)) {
175 : 0 : IONIC_PRINT(ERR, "Failed to allocate %u vectors",
176 : : adapter->nintrs);
177 : 0 : return -ENOMEM;
178 : : }
179 : : }
180 : :
181 : 0 : err = rte_intr_callback_register(intr_handle,
182 : : ionic_dev_interrupt_handler,
183 : : adapter);
184 [ # # ]: 0 : if (err) {
185 : 0 : IONIC_PRINT(ERR,
186 : : "Failure registering interrupts handler (%d)", err);
187 : 0 : return err;
188 : : }
189 : :
190 : : /* enable intr mapping */
191 : 0 : err = rte_intr_enable(intr_handle);
192 [ # # ]: 0 : if (err) {
193 : 0 : IONIC_PRINT(ERR, "Failure enabling interrupts (%d)", err);
194 : 0 : return err;
195 : : }
196 : :
197 : : return 0;
198 : : }
199 : :
200 : : static void
201 : 0 : ionic_pci_unconfigure_intr(struct ionic_adapter *adapter)
202 : : {
203 : 0 : struct rte_pci_device *pci_dev =
204 : : (struct rte_pci_device *)(adapter->bus_dev);
205 : 0 : struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
206 : :
207 : 0 : rte_intr_disable(intr_handle);
208 : :
209 : 0 : rte_intr_callback_unregister(intr_handle,
210 : : ionic_dev_interrupt_handler,
211 : : adapter);
212 : 0 : }
213 : :
214 : : static const struct ionic_dev_intf ionic_pci_intf = {
215 : : .setup = ionic_pci_setup,
216 : : .devargs = ionic_pci_devargs,
217 : : .copy_bus_info = ionic_pci_copy_bus_info,
218 : : .configure_intr = ionic_pci_configure_intr,
219 : : .unconfigure_intr = ionic_pci_unconfigure_intr,
220 : : };
221 : :
222 : : static int
223 : 0 : eth_ionic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
224 : : struct rte_pci_device *pci_dev)
225 : : {
226 : : struct rte_mem_resource *resource;
227 : : struct ionic_bars bars;
228 : : unsigned long i;
229 : :
230 [ # # ]: 0 : IONIC_PRINT(NOTICE, "Initializing device %s %s",
231 : : pci_dev->device.name,
232 : : rte_eal_process_type() == RTE_PROC_SECONDARY ?
233 : : "[SECONDARY]" : "");
234 : :
235 : 0 : bars.num_bars = 0;
236 [ # # ]: 0 : for (i = 0; i < PCI_MAX_RESOURCE && i < IONIC_BARS_MAX; i++) {
237 : : resource = &pci_dev->mem_resource[i];
238 [ # # # # ]: 0 : if (resource->phys_addr == 0 || resource->len == 0)
239 : 0 : continue;
240 : :
241 : 0 : bars.bar[bars.num_bars].vaddr = resource->addr;
242 : 0 : bars.bar[bars.num_bars].bus_addr = resource->phys_addr;
243 : 0 : bars.bar[bars.num_bars].len = resource->len;
244 : 0 : bars.num_bars++;
245 : : }
246 : :
247 : 0 : return eth_ionic_dev_probe((void *)pci_dev,
248 : : &pci_dev->device,
249 : : &bars,
250 : : &ionic_pci_intf,
251 : 0 : pci_dev->id.device_id,
252 : 0 : pci_dev->id.vendor_id);
253 : : }
254 : :
255 : : static int
256 : 0 : eth_ionic_pci_remove(struct rte_pci_device *pci_dev)
257 : : {
258 : 0 : return eth_ionic_dev_remove(&pci_dev->device);
259 : : }
260 : :
261 : : static struct rte_pci_driver rte_pci_ionic_pmd = {
262 : : .id_table = pci_id_ionic_map,
263 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
264 : : RTE_PCI_DRV_WC_ACTIVATE,
265 : : .probe = eth_ionic_pci_probe,
266 : : .remove = eth_ionic_pci_remove,
267 : : };
268 : :
269 : 238 : RTE_PMD_REGISTER_PCI(net_ionic_pci, rte_pci_ionic_pmd);
270 : : RTE_PMD_REGISTER_PCI_TABLE(net_ionic_pci, pci_id_ionic_map);
271 : : RTE_PMD_REGISTER_KMOD_DEP(net_ionic_pci, "* igb_uio | uio_pci_generic | vfio-pci");
272 : : RTE_PMD_REGISTER_PARAM_STRING(net_ionic_pci,
273 : : PMD_IONIC_CMB_KVARG "=<0|1>"
274 : : );
|