Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include <bus_pci_driver.h>
5 : : #include <rte_common.h>
6 : : #include <dev_driver.h>
7 : : #include <rte_eal.h>
8 : : #include <rte_lcore.h>
9 : : #include <rte_pci.h>
10 : : #include <rte_rawdev.h>
11 : : #include <rte_rawdev_pmd.h>
12 : :
13 : : #include <roc_api.h>
14 : :
15 : : #include "cnxk_bphy_irq.h"
16 : : #include "rte_pmd_bphy.h"
17 : :
18 : : static const struct rte_pci_id pci_bphy_map[] = {
19 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_BPHY)},
20 : : {
21 : : .vendor_id = 0,
22 : : },
23 : : };
24 : :
25 : : struct bphy_test {
26 : : int irq_num;
27 : : cnxk_bphy_intr_handler_t handler;
28 : : void *data;
29 : : int cpu;
30 : : bool handled_intr;
31 : : int handled_data;
32 : : int test_data;
33 : : };
34 : :
35 : : static struct bphy_test *test;
36 : :
37 : : static void
38 : 0 : bphy_test_handler_fn(int irq_num, void *isr_data)
39 : : {
40 : 0 : test[irq_num].handled_intr = true;
41 : 0 : test[irq_num].handled_data = *((int *)isr_data);
42 : 0 : }
43 : :
44 : : int
45 : 0 : rte_pmd_bphy_npa_pf_func_get_rmt(uint16_t *pf_func)
46 : : {
47 : 0 : *pf_func = roc_bphy_npa_pf_func_get();
48 : :
49 : 0 : return 0;
50 : : }
51 : :
52 : : int
53 : 0 : rte_pmd_bphy_sso_pf_func_get_rmt(uint16_t *pf_func)
54 : : {
55 : 0 : *pf_func = roc_bphy_sso_pf_func_get();
56 : :
57 : 0 : return 0;
58 : : }
59 : :
60 : : static int
61 : 0 : bphy_rawdev_selftest(uint16_t dev_id)
62 : : {
63 : : unsigned int i, queues, descs;
64 : : uint16_t pf_func;
65 : : uint64_t max_irq;
66 : : int ret;
67 : :
68 : 0 : queues = rte_rawdev_queue_count(dev_id);
69 [ # # ]: 0 : if (queues == 0)
70 : : return -ENODEV;
71 [ # # ]: 0 : if (queues != BPHY_QUEUE_CNT)
72 : : return -EINVAL;
73 : :
74 : 0 : ret = rte_rawdev_start(dev_id);
75 [ # # ]: 0 : if (ret)
76 : : return ret;
77 : :
78 : 0 : ret = rte_rawdev_queue_conf_get(dev_id, CNXK_BPHY_DEF_QUEUE, &descs,
79 : : sizeof(descs));
80 [ # # ]: 0 : if (ret)
81 : 0 : goto err_desc;
82 [ # # ]: 0 : if (descs != 1) {
83 : : ret = -ENODEV;
84 : 0 : CNXK_BPHY_LOG(ERR, "Wrong number of descs reported");
85 : 0 : goto err_desc;
86 : : }
87 : :
88 : : ret = rte_pmd_bphy_npa_pf_func_get(dev_id, &pf_func);
89 [ # # ]: 0 : if (ret || pf_func == 0)
90 : 0 : CNXK_BPHY_LOG(WARNING, "NPA pf_func is invalid");
91 : :
92 : : ret = rte_pmd_bphy_sso_pf_func_get(dev_id, &pf_func);
93 [ # # ]: 0 : if (ret || pf_func == 0)
94 : 0 : CNXK_BPHY_LOG(WARNING, "SSO pf_func is invalid");
95 : :
96 : : ret = rte_pmd_bphy_intr_init(dev_id);
97 : : if (ret) {
98 : 0 : CNXK_BPHY_LOG(ERR, "intr init failed");
99 : 0 : return ret;
100 : : }
101 : :
102 : 0 : max_irq = cnxk_bphy_irq_max_get(dev_id);
103 : :
104 : 0 : test = rte_zmalloc("BPHY", max_irq * sizeof(*test), 0);
105 [ # # ]: 0 : if (test == NULL) {
106 : 0 : CNXK_BPHY_LOG(ERR, "intr alloc failed");
107 : 0 : goto err_alloc;
108 : : }
109 : :
110 [ # # ]: 0 : for (i = 0; i < max_irq; i++) {
111 : 0 : test[i].test_data = i;
112 : 0 : test[i].irq_num = i;
113 : 0 : test[i].handler = bphy_test_handler_fn;
114 : 0 : test[i].data = &test[i].test_data;
115 : : }
116 : :
117 [ # # ]: 0 : for (i = 0; i < max_irq; i++) {
118 : 0 : ret = rte_pmd_bphy_intr_register(dev_id, test[i].irq_num,
119 : 0 : test[i].handler, test[i].data,
120 : : 0);
121 [ # # ]: 0 : if (ret == -ENOTSUP) {
122 : : /* In the test we iterate over all irq numbers
123 : : * so if some of them are not supported by given
124 : : * platform we treat respective results as valid
125 : : * ones. This way they have no impact on overall
126 : : * test results.
127 : : */
128 : 0 : test[i].handled_intr = true;
129 : 0 : test[i].handled_data = test[i].test_data;
130 : : ret = 0;
131 : 0 : continue;
132 : : }
133 : :
134 [ # # ]: 0 : if (ret) {
135 : 0 : CNXK_BPHY_LOG(ERR, "intr register failed at irq %d", i);
136 : 0 : goto err_register;
137 : : }
138 : : }
139 : :
140 [ # # ]: 0 : for (i = 0; i < max_irq; i++)
141 : 0 : roc_bphy_intr_handler(i);
142 : :
143 [ # # ]: 0 : for (i = 0; i < max_irq; i++) {
144 [ # # ]: 0 : if (!test[i].handled_intr) {
145 : 0 : CNXK_BPHY_LOG(ERR, "intr %u not handled", i);
146 : : ret = -1;
147 : 0 : break;
148 : : }
149 [ # # ]: 0 : if (test[i].handled_data != test[i].test_data) {
150 : 0 : CNXK_BPHY_LOG(ERR, "intr %u has wrong handler", i);
151 : : ret = -1;
152 : 0 : break;
153 : : }
154 : : }
155 : :
156 : 0 : err_register:
157 : : /*
158 : : * In case of registration failure the loop goes over all
159 : : * interrupts which is safe due to internal guards in
160 : : * rte_pmd_bphy_intr_unregister().
161 : : */
162 [ # # ]: 0 : for (i = 0; i < max_irq; i++)
163 : 0 : rte_pmd_bphy_intr_unregister(dev_id, i);
164 : :
165 : 0 : rte_free(test);
166 : 0 : err_alloc:
167 : : rte_pmd_bphy_intr_fini(dev_id);
168 : 0 : err_desc:
169 : 0 : rte_rawdev_stop(dev_id);
170 : :
171 : 0 : return ret;
172 : : }
173 : :
174 : : static void
175 : 0 : bphy_rawdev_get_name(char *name, struct rte_pci_device *pci_dev)
176 : : {
177 : 0 : snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "BPHY:%02x:%02x.%x",
178 : 0 : pci_dev->addr.bus, pci_dev->addr.devid,
179 : 0 : pci_dev->addr.function);
180 : 0 : }
181 : :
182 : : static int
183 : 0 : cnxk_bphy_irq_enqueue_bufs(struct rte_rawdev *dev,
184 : : struct rte_rawdev_buf **buffers, unsigned int count,
185 : : rte_rawdev_obj_t context)
186 : : {
187 : 0 : struct bphy_device *bphy_dev = (struct bphy_device *)dev->dev_private;
188 : 0 : struct cnxk_bphy_irq_msg *msg = buffers[0]->buf_addr;
189 : : struct bphy_irq_queue *qp = &bphy_dev->queues[0];
190 : 0 : unsigned int queue = (size_t)context;
191 : : struct cnxk_bphy_irq_info *info;
192 : : struct cnxk_bphy_mem *mem;
193 : : uint16_t *pf_func;
194 : : void *rsp = NULL;
195 : : int ret;
196 : :
197 [ # # ]: 0 : if (queue >= RTE_DIM(bphy_dev->queues))
198 : : return -EINVAL;
199 : :
200 [ # # ]: 0 : if (count == 0)
201 : : return 0;
202 : :
203 [ # # # # : 0 : switch (msg->type) {
# # # # ]
204 : 0 : case CNXK_BPHY_IRQ_MSG_TYPE_INIT:
205 : 0 : ret = cnxk_bphy_intr_init(dev->dev_id);
206 [ # # ]: 0 : if (ret)
207 : : return ret;
208 : : break;
209 : 0 : case CNXK_BPHY_IRQ_MSG_TYPE_FINI:
210 : 0 : cnxk_bphy_intr_fini(dev->dev_id);
211 : 0 : break;
212 : 0 : case CNXK_BPHY_IRQ_MSG_TYPE_REGISTER:
213 : 0 : info = (struct cnxk_bphy_irq_info *)msg->data;
214 : 0 : ret = cnxk_bphy_intr_register(dev->dev_id, info->irq_num,
215 : : info->handler, info->data,
216 : : info->cpu);
217 [ # # ]: 0 : if (ret)
218 : : return ret;
219 : : break;
220 : 0 : case CNXK_BPHY_IRQ_MSG_TYPE_UNREGISTER:
221 : 0 : info = (struct cnxk_bphy_irq_info *)msg->data;
222 : 0 : cnxk_bphy_intr_unregister(dev->dev_id, info->irq_num);
223 : 0 : break;
224 : 0 : case CNXK_BPHY_IRQ_MSG_TYPE_MEM_GET:
225 : 0 : mem = rte_zmalloc(NULL, sizeof(*mem), 0);
226 [ # # ]: 0 : if (!mem)
227 : : return -ENOMEM;
228 : :
229 : 0 : *mem = bphy_dev->mem;
230 : : rsp = mem;
231 : 0 : break;
232 : 0 : case CNXK_BPHY_MSG_TYPE_NPA_PF_FUNC:
233 : 0 : pf_func = rte_malloc(NULL, sizeof(*pf_func), 0);
234 [ # # ]: 0 : if (!pf_func)
235 : : return -ENOMEM;
236 : :
237 : 0 : *pf_func = roc_bphy_npa_pf_func_get();
238 : : rsp = pf_func;
239 : 0 : break;
240 : 0 : case CNXK_BPHY_MSG_TYPE_SSO_PF_FUNC:
241 : 0 : pf_func = rte_malloc(NULL, sizeof(*pf_func), 0);
242 [ # # ]: 0 : if (!pf_func)
243 : : return -ENOMEM;
244 : :
245 : 0 : *pf_func = roc_bphy_sso_pf_func_get();
246 : : rsp = pf_func;
247 : 0 : break;
248 : : default:
249 : : return -EINVAL;
250 : : }
251 : :
252 : : /* get rid of last response if any */
253 [ # # ]: 0 : if (qp->rsp) {
254 : 0 : CNXK_BPHY_LOG(WARNING, "Previous response got overwritten");
255 : 0 : rte_free(qp->rsp);
256 : : }
257 : 0 : qp->rsp = rsp;
258 : :
259 : 0 : return 1;
260 : : }
261 : :
262 : : static int
263 : 0 : cnxk_bphy_irq_dequeue_bufs(struct rte_rawdev *dev,
264 : : struct rte_rawdev_buf **buffers, unsigned int count,
265 : : rte_rawdev_obj_t context)
266 : : {
267 : 0 : struct bphy_device *bphy_dev = (struct bphy_device *)dev->dev_private;
268 : 0 : unsigned int queue = (size_t)context;
269 : : struct bphy_irq_queue *qp;
270 : :
271 [ # # ]: 0 : if (queue >= RTE_DIM(bphy_dev->queues))
272 : : return -EINVAL;
273 : :
274 [ # # ]: 0 : if (count == 0)
275 : : return 0;
276 : :
277 : : qp = &bphy_dev->queues[queue];
278 [ # # ]: 0 : if (qp->rsp) {
279 : 0 : buffers[0]->buf_addr = qp->rsp;
280 : 0 : qp->rsp = NULL;
281 : :
282 : 0 : return 1;
283 : : }
284 : :
285 : : return 0;
286 : : }
287 : :
288 : : static uint16_t
289 : 0 : cnxk_bphy_irq_queue_count(struct rte_rawdev *dev)
290 : : {
291 : : struct bphy_device *bphy_dev = (struct bphy_device *)dev->dev_private;
292 : :
293 : 0 : return RTE_DIM(bphy_dev->queues);
294 : : }
295 : :
296 : : static int
297 : 0 : cnxk_bphy_irq_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
298 : : rte_rawdev_obj_t queue_conf,
299 : : size_t queue_conf_size)
300 : : {
301 : : RTE_SET_USED(dev);
302 : : RTE_SET_USED(queue_id);
303 : :
304 [ # # ]: 0 : if (queue_conf_size != sizeof(unsigned int))
305 : : return -EINVAL;
306 : :
307 : 0 : *(unsigned int *)queue_conf = 1;
308 : :
309 : 0 : return 0;
310 : : }
311 : :
312 : : static const struct rte_rawdev_ops bphy_rawdev_ops = {
313 : : .queue_def_conf = cnxk_bphy_irq_queue_def_conf,
314 : : .enqueue_bufs = cnxk_bphy_irq_enqueue_bufs,
315 : : .dequeue_bufs = cnxk_bphy_irq_dequeue_bufs,
316 : : .queue_count = cnxk_bphy_irq_queue_count,
317 : : .dev_selftest = bphy_rawdev_selftest,
318 : : };
319 : :
320 : : static int
321 : 0 : bphy_rawdev_probe(struct rte_pci_driver *pci_drv,
322 : : struct rte_pci_device *pci_dev)
323 : : {
324 : : struct bphy_device *bphy_dev = NULL;
325 : : char name[RTE_RAWDEV_NAME_MAX_LEN];
326 : : struct rte_rawdev *bphy_rawdev;
327 : : int ret;
328 : :
329 : : RTE_SET_USED(pci_drv);
330 : :
331 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
332 : : return 0;
333 : :
334 [ # # ]: 0 : if (!pci_dev->mem_resource[0].addr) {
335 : 0 : CNXK_BPHY_LOG(ERR, "BARs have invalid values: BAR0 %p BAR2 %p",
336 : : pci_dev->mem_resource[0].addr, pci_dev->mem_resource[2].addr);
337 : 0 : return -ENODEV;
338 : : }
339 : :
340 : 0 : ret = roc_plt_init();
341 [ # # ]: 0 : if (ret)
342 : : return ret;
343 : :
344 : 0 : bphy_rawdev_get_name(name, pci_dev);
345 : 0 : bphy_rawdev = rte_rawdev_pmd_allocate(name, sizeof(*bphy_dev),
346 : 0 : rte_socket_id());
347 [ # # ]: 0 : if (bphy_rawdev == NULL) {
348 : 0 : CNXK_BPHY_LOG(ERR, "Failed to allocate rawdev");
349 : 0 : return -ENOMEM;
350 : : }
351 : :
352 : 0 : bphy_rawdev->dev_ops = &bphy_rawdev_ops;
353 : 0 : bphy_rawdev->device = &pci_dev->device;
354 : 0 : bphy_rawdev->driver_name = pci_dev->driver->driver.name;
355 : :
356 : 0 : bphy_dev = (struct bphy_device *)bphy_rawdev->dev_private;
357 : 0 : bphy_dev->mem.res0 = pci_dev->mem_resource[0];
358 : 0 : bphy_dev->mem.res2 = pci_dev->mem_resource[2];
359 : 0 : bphy_dev->bphy.pci_dev = pci_dev;
360 : :
361 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
362 : 0 : ret = roc_bphy_dev_init(&bphy_dev->bphy);
363 [ # # ]: 0 : if (ret) {
364 : 0 : rte_rawdev_pmd_release(bphy_rawdev);
365 : 0 : return ret;
366 : : }
367 : : }
368 : :
369 : : return 0;
370 : : }
371 : :
372 : : static int
373 : 0 : bphy_rawdev_remove(struct rte_pci_device *pci_dev)
374 : : {
375 : : char name[RTE_RAWDEV_NAME_MAX_LEN];
376 : : struct bphy_device *bphy_dev;
377 : : struct rte_rawdev *rawdev;
378 : :
379 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
380 : : return 0;
381 : :
382 [ # # ]: 0 : if (pci_dev == NULL) {
383 : 0 : CNXK_BPHY_LOG(ERR, "invalid pci_dev");
384 : 0 : return -EINVAL;
385 : : }
386 : :
387 : 0 : bphy_rawdev_get_name(name, pci_dev);
388 : 0 : rawdev = rte_rawdev_pmd_get_named_dev(name);
389 [ # # ]: 0 : if (rawdev == NULL) {
390 : 0 : CNXK_BPHY_LOG(ERR, "invalid device name (%s)", name);
391 : 0 : return -EINVAL;
392 : : }
393 : :
394 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
395 : 0 : bphy_dev = (struct bphy_device *)rawdev->dev_private;
396 : 0 : roc_bphy_dev_fini(&bphy_dev->bphy);
397 : : }
398 : :
399 : 0 : return rte_rawdev_pmd_release(rawdev);
400 : : }
401 : :
402 : : static struct rte_pci_driver cnxk_bphy_rawdev_pmd = {
403 : : .id_table = pci_bphy_map,
404 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
405 : : .probe = bphy_rawdev_probe,
406 : : .remove = bphy_rawdev_remove,
407 : : };
408 : :
409 : 252 : RTE_PMD_REGISTER_PCI(bphy_rawdev_pci_driver, cnxk_bphy_rawdev_pmd);
410 : : RTE_PMD_REGISTER_PCI_TABLE(bphy_rawdev_pci_driver, pci_bphy_map);
411 : : RTE_PMD_REGISTER_KMOD_DEP(bphy_rawdev_pci_driver, "vfio-pci");
412 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(cnxk_logtype_bphy, bphy, INFO);
|