History

net/fungible: Add service module for Fungible drivers

Fungible cards have a number of different PCI functions and thus different drivers, all of which use a common method to initialize and interact with the device. This commit adds a library module that collects these common mechanisms. They mainly deal with device initialization, setting up and destroying queues, and operating an admin queue. A subset of the FW interface is also included here.

Dimitris Michailidis committed 4 years ago

Commit e1ffcc61 parent e8eb9e36 files · +2976 −0Browse files

Unified · Split

6 files
  1. drivers/net/ethernet/fungible/funcore/Makefile +5 −0
  2. drivers/net/ethernet/fungible/funcore/fun_dev.c +843 −0
  3. drivers/net/ethernet/fungible/funcore/fun_dev.h +150 −0
  4. drivers/net/ethernet/fungible/funcore/fun_hci.h +1202 −0
  5. drivers/net/ethernet/fungible/funcore/fun_queue.c +601 −0
  6. drivers/net/ethernet/fungible/funcore/fun_queue.h +175 −0
drivers/net/ethernet/fungible/funcore/Makefile+5−0
@@ -0,0 +1,5 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2
3obj-$(CONFIG_FUN_CORE) += funcore.o
4
5funcore-y := fun_dev.o fun_queue.o
drivers/net/ethernet/fungible/funcore/fun_dev.c+843−0
@@ -0,0 +1,843 @@
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2
3#include <linux/aer.h>
4#include <linux/bitmap.h>
5#include <linux/delay.h>
6#include <linux/interrupt.h>
7#include <linux/io.h>
8#include <linux/io-64-nonatomic-lo-hi.h>
9#include <linux/mm.h>
10#include <linux/module.h>
11#include <linux/nvme.h>
12#include <linux/pci.h>
13#include <linux/wait.h>
14#include <linux/sched/signal.h>
15
16#include "fun_queue.h"
17#include "fun_dev.h"
18
19#define FUN_ADMIN_CMD_TO_MS 3000
20
21enum {
22 AQA_ASQS_SHIFT = 0,
23 AQA_ACQS_SHIFT = 16,
24 AQA_MIN_QUEUE_SIZE = 2,
25 AQA_MAX_QUEUE_SIZE = 4096
26};
27
28/* context for admin commands */
29struct fun_cmd_ctx {
30 fun_admin_callback_t cb; /* callback to invoke on completion */
31 void *cb_data; /* user data provided to callback */
32 int cpu; /* CPU where the cmd's tag was allocated */
33};
34
35/* Context for synchronous admin commands. */
36struct fun_sync_cmd_ctx {
37 struct completion compl;
38 u8 *rsp_buf; /* caller provided response buffer */
39 unsigned int rsp_len; /* response buffer size */
40 u8 rsp_status; /* command response status */
41};
42
43/* Wait for the CSTS.RDY bit to match @enabled. */
44static int fun_wait_ready(struct fun_dev *fdev, bool enabled)
45{
46 unsigned int cap_to = NVME_CAP_TIMEOUT(fdev->cap_reg);
47 u32 bit = enabled ? NVME_CSTS_RDY : 0;
48 unsigned long deadline;
49
50 deadline = ((cap_to + 1) * HZ / 2) + jiffies; /* CAP.TO is in 500ms */
51
52 for (;;) {
53 u32 csts = readl(fdev->bar + NVME_REG_CSTS);
54
55 if (csts == ~0) {
56 dev_err(fdev->dev, "CSTS register read %#x\n", csts);
57 return -EIO;
58 }
59
60 if ((csts & NVME_CSTS_RDY) == bit)
61 return 0;
62
63 if (time_is_before_jiffies(deadline))
64 break;
65
66 msleep(100);
67 }
68
69 dev_err(fdev->dev,
70 "Timed out waiting for device to indicate RDY %u; aborting %s\n",
71 enabled, enabled ? "initialization" : "reset");
72 return -ETIMEDOUT;
73}
74
75/* Check CSTS and return an error if it is unreadable or has unexpected
76 * RDY value.
77 */
78static int fun_check_csts_rdy(struct fun_dev *fdev, unsigned int expected_rdy)
79{
80 u32 csts = readl(fdev->bar + NVME_REG_CSTS);
81 u32 actual_rdy = csts & NVME_CSTS_RDY;
82
83 if (csts == ~0) {
84 dev_err(fdev->dev, "CSTS register read %#x\n", csts);
85 return -EIO;
86 }
87 if (actual_rdy != expected_rdy) {
88 dev_err(fdev->dev, "Unexpected CSTS RDY %u\n", actual_rdy);
89 return -EINVAL;
90 }
91 return 0;
92}
93
94/* Check that CSTS RDY has the expected value. Then write a new value to the CC
95 * register and wait for CSTS RDY to match the new CC ENABLE state.
96 */
97static int fun_update_cc_enable(struct fun_dev *fdev, unsigned int initial_rdy)
98{
99 int rc = fun_check_csts_rdy(fdev, initial_rdy);
100
101 if (rc)
102 return rc;
103 writel(fdev->cc_reg, fdev->bar + NVME_REG_CC);
104 return fun_wait_ready(fdev, !!(fdev->cc_reg & NVME_CC_ENABLE));
105}
106
107static int fun_disable_ctrl(struct fun_dev *fdev)
108{
109 fdev->cc_reg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
110 return fun_update_cc_enable(fdev, 1);
111}
112
113static int fun_enable_ctrl(struct fun_dev *fdev, u32 admin_cqesz_log2,
114 u32 admin_sqesz_log2)
115{
116 fdev->cc_reg = (admin_cqesz_log2 << NVME_CC_IOCQES_SHIFT) |
117 (admin_sqesz_log2 << NVME_CC_IOSQES_SHIFT) |
118 ((PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT) |
119 NVME_CC_ENABLE;
120
121 return fun_update_cc_enable(fdev, 0);
122}
123
124static int fun_map_bars(struct fun_dev *fdev, const char *name)
125{
126 struct pci_dev *pdev = to_pci_dev(fdev->dev);
127 int err;
128
129 err = pci_request_mem_regions(pdev, name);
130 if (err) {
131 dev_err(&pdev->dev,
132 "Couldn't get PCI memory resources, err %d\n", err);
133 return err;
134 }
135
136 fdev->bar = pci_ioremap_bar(pdev, 0);
137 if (!fdev->bar) {
138 dev_err(&pdev->dev, "Couldn't map BAR 0\n");
139 pci_release_mem_regions(pdev);
140 return -ENOMEM;
141 }
142
143 return 0;
144}
145
146static void fun_unmap_bars(struct fun_dev *fdev)
147{
148 struct pci_dev *pdev = to_pci_dev(fdev->dev);
149
150 if (fdev->bar) {
151 iounmap(fdev->bar);
152 fdev->bar = NULL;
153 pci_release_mem_regions(pdev);
154 }
155}
156
157static int fun_set_dma_masks(struct device *dev)
158{
159 int err;
160
161 err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
162 if (err)
163 dev_err(dev, "DMA mask configuration failed, err %d\n", err);
164 return err;
165}
166
167static irqreturn_t fun_admin_irq(int irq, void *data)
168{
169 struct fun_queue *funq = data;
170
171 return fun_process_cq(funq, 0) ? IRQ_HANDLED : IRQ_NONE;
172}
173
174static void fun_complete_admin_cmd(struct fun_queue *funq, void *data,
175 void *entry, const struct fun_cqe_info *info)
176{
177 const struct fun_admin_rsp_common *rsp_common = entry;
178 struct fun_dev *fdev = funq->fdev;
179 struct fun_cmd_ctx *cmd_ctx;
180 int cpu;
181 u16 cid;
182
183 if (info->sqhd == cpu_to_be16(0xffff)) {
184 dev_dbg(fdev->dev, "adminq event");
185 if (fdev->adminq_cb)
186 fdev->adminq_cb(fdev, entry);
187 return;
188 }
189
190 cid = be16_to_cpu(rsp_common->cid);
191 dev_dbg(fdev->dev, "admin CQE cid %u, op %u, ret %u\n", cid,
192 rsp_common->op, rsp_common->ret);
193
194 cmd_ctx = &fdev->cmd_ctx[cid];
195 if (cmd_ctx->cpu < 0) {
196 dev_err(fdev->dev,
197 "admin CQE with CID=%u, op=%u does not match a pending command\n",
198 cid, rsp_common->op);
199 return;
200 }
201
202 if (cmd_ctx->cb)
203 cmd_ctx->cb(fdev, entry, xchg(&cmd_ctx->cb_data, NULL));
204
205 cpu = cmd_ctx->cpu;
206 cmd_ctx->cpu = -1;
207 sbitmap_queue_clear(&fdev->admin_sbq, cid, cpu);
208}
209
210static int fun_init_cmd_ctx(struct fun_dev *fdev, unsigned int ntags)
211{
212 unsigned int i;
213
214 fdev->cmd_ctx = kvcalloc(ntags, sizeof(*fdev->cmd_ctx), GFP_KERNEL);
215 if (!fdev->cmd_ctx)
216 return -ENOMEM;
217
218 for (i = 0; i < ntags; i++)
219 fdev->cmd_ctx[i].cpu = -1;
220
221 return 0;
222}
223
224/* Allocate and enable an admin queue and assign it the first IRQ vector. */
225static int fun_enable_admin_queue(struct fun_dev *fdev,
226 const struct fun_dev_params *areq)
227{
228 struct fun_queue_alloc_req qreq = {
229 .cqe_size_log2 = areq->cqe_size_log2,
230 .sqe_size_log2 = areq->sqe_size_log2,
231 .cq_depth = areq->cq_depth,
232 .sq_depth = areq->sq_depth,
233 .rq_depth = areq->rq_depth,
234 };
235 unsigned int ntags = areq->sq_depth - 1;
236 struct fun_queue *funq;
237 int rc;
238
239 if (fdev->admin_q)
240 return -EEXIST;
241
242 if (areq->sq_depth < AQA_MIN_QUEUE_SIZE ||
243 areq->sq_depth > AQA_MAX_QUEUE_SIZE ||
244 areq->cq_depth < AQA_MIN_QUEUE_SIZE ||
245 areq->cq_depth > AQA_MAX_QUEUE_SIZE)
246 return -EINVAL;
247
248 fdev->admin_q = fun_alloc_queue(fdev, 0, &qreq);
249 if (!fdev->admin_q)
250 return -ENOMEM;
251
252 rc = fun_init_cmd_ctx(fdev, ntags);
253 if (rc)
254 goto free_q;
255
256 rc = sbitmap_queue_init_node(&fdev->admin_sbq, ntags, -1, false,
257 GFP_KERNEL, dev_to_node(fdev->dev));
258 if (rc)
259 goto free_cmd_ctx;
260
261 funq = fdev->admin_q;
262 funq->cq_vector = 0;
263 rc = fun_request_irq(funq, dev_name(fdev->dev), fun_admin_irq, funq);
264 if (rc)
265 goto free_sbq;
266
267 fun_set_cq_callback(funq, fun_complete_admin_cmd, NULL);
268 fdev->adminq_cb = areq->event_cb;
269
270 writel((funq->sq_depth - 1) << AQA_ASQS_SHIFT |
271 (funq->cq_depth - 1) << AQA_ACQS_SHIFT,
272 fdev->bar + NVME_REG_AQA);
273
274 writeq(funq->sq_dma_addr, fdev->bar + NVME_REG_ASQ);
275 writeq(funq->cq_dma_addr, fdev->bar + NVME_REG_ACQ);
276
277 rc = fun_enable_ctrl(fdev, areq->cqe_size_log2, areq->sqe_size_log2);
278 if (rc)
279 goto free_irq;
280
281 if (areq->rq_depth) {
282 rc = fun_create_rq(funq);
283 if (rc)
284 goto disable_ctrl;
285
286 funq_rq_post(funq);
287 }
288
289 return 0;
290
291disable_ctrl:
292 fun_disable_ctrl(fdev);
293free_irq:
294 fun_free_irq(funq);
295free_sbq:
296 sbitmap_queue_free(&fdev->admin_sbq);
297free_cmd_ctx:
298 kvfree(fdev->cmd_ctx);
299 fdev->cmd_ctx = NULL;
300free_q:
301 fun_free_queue(fdev->admin_q);
302 fdev->admin_q = NULL;
303 return rc;
304}
305
306static void fun_disable_admin_queue(struct fun_dev *fdev)
307{
308 struct fun_queue *admq = fdev->admin_q;
309
310 if (!admq)
311 return;
312
313 fun_disable_ctrl(fdev);
314
315 fun_free_irq(admq);
316 __fun_process_cq(admq, 0);
317
318 sbitmap_queue_free(&fdev->admin_sbq);
319
320 kvfree(fdev->cmd_ctx);
321 fdev->cmd_ctx = NULL;
322
323 fun_free_queue(admq);
324 fdev->admin_q = NULL;
325}
326
327/* Return %true if the admin queue has stopped servicing commands as can be
328 * detected through registers. This isn't exhaustive and may provide false
329 * negatives.
330 */
331static bool fun_adminq_stopped(struct fun_dev *fdev)
332{
333 u32 csts = readl(fdev->bar + NVME_REG_CSTS);
334
335 return (csts & (NVME_CSTS_CFS | NVME_CSTS_RDY)) != NVME_CSTS_RDY;
336}
337
338static int fun_wait_for_tag(struct fun_dev *fdev, int *cpup)
339{
340 struct sbitmap_queue *sbq = &fdev->admin_sbq;
341 struct sbq_wait_state *ws = &sbq->ws[0];
342 DEFINE_SBQ_WAIT(wait);
343 int tag;
344
345 for (;;) {
346 sbitmap_prepare_to_wait(sbq, ws, &wait, TASK_UNINTERRUPTIBLE);
347 if (fdev->suppress_cmds) {
348 tag = -ESHUTDOWN;
349 break;
350 }
351 tag = sbitmap_queue_get(sbq, cpup);
352 if (tag >= 0)
353 break;
354 schedule();
355 }
356
357 sbitmap_finish_wait(sbq, ws, &wait);
358 return tag;
359}
360
361/* Submit an asynchronous admin command. Caller is responsible for implementing
362 * any waiting or timeout. Upon command completion the callback @cb is called.
363 */
364int fun_submit_admin_cmd(struct fun_dev *fdev, struct fun_admin_req_common *cmd,
365 fun_admin_callback_t cb, void *cb_data, bool wait_ok)
366{
367 struct fun_queue *funq = fdev->admin_q;
368 unsigned int cmdsize = cmd->len8 * 8;
369 struct fun_cmd_ctx *cmd_ctx;
370 int tag, cpu, rc = 0;
371
372 if (WARN_ON(cmdsize > (1 << funq->sqe_size_log2)))
373 return -EMSGSIZE;
374
375 tag = sbitmap_queue_get(&fdev->admin_sbq, &cpu);
376 if (tag < 0) {
377 if (!wait_ok)
378 return -EAGAIN;
379 tag = fun_wait_for_tag(fdev, &cpu);
380 if (tag < 0)
381 return tag;
382 }
383
384 cmd->cid = cpu_to_be16(tag);
385
386 cmd_ctx = &fdev->cmd_ctx[tag];
387 cmd_ctx->cb = cb;
388 cmd_ctx->cb_data = cb_data;
389
390 spin_lock(&funq->sq_lock);
391
392 if (unlikely(fdev->suppress_cmds)) {
393 rc = -ESHUTDOWN;
394 sbitmap_queue_clear(&fdev->admin_sbq, tag, cpu);
395 } else {
396 cmd_ctx->cpu = cpu;
397 memcpy(fun_sqe_at(funq, funq->sq_tail), cmd, cmdsize);
398
399 dev_dbg(fdev->dev, "admin cmd @ %u: %8ph\n", funq->sq_tail,
400 cmd);
401
402 if (++funq->sq_tail == funq->sq_depth)
403 funq->sq_tail = 0;
404 writel(funq->sq_tail, funq->sq_db);
405 }
406 spin_unlock(&funq->sq_lock);
407 return rc;
408}
409
410/* Abandon a pending admin command by clearing the issuer's callback data.
411 * Failure indicates that the command either has already completed or its
412 * completion is racing with this call.
413 */
414static bool fun_abandon_admin_cmd(struct fun_dev *fd,
415 const struct fun_admin_req_common *cmd,
416 void *cb_data)
417{
418 u16 cid = be16_to_cpu(cmd->cid);
419 struct fun_cmd_ctx *cmd_ctx = &fd->cmd_ctx[cid];
420
421 return cmpxchg(&cmd_ctx->cb_data, cb_data, NULL) == cb_data;
422}
423
424/* Stop submission of new admin commands and wake up any processes waiting for
425 * tags. Already submitted commands are left to complete or time out.
426 */
427static void fun_admin_stop(struct fun_dev *fdev)
428{
429 spin_lock(&fdev->admin_q->sq_lock);
430 fdev->suppress_cmds = true;
431 spin_unlock(&fdev->admin_q->sq_lock);
432 sbitmap_queue_wake_all(&fdev->admin_sbq);
433}
434
435/* The callback for synchronous execution of admin commands. It copies the
436 * command response to the caller's buffer and signals completion.
437 */
438static void fun_admin_cmd_sync_cb(struct fun_dev *fd, void *rsp, void *cb_data)
439{
440 const struct fun_admin_rsp_common *rsp_common = rsp;
441 struct fun_sync_cmd_ctx *ctx = cb_data;
442
443 if (!ctx)
444 return; /* command issuer timed out and left */
445 if (ctx->rsp_buf) {
446 unsigned int rsp_len = rsp_common->len8 * 8;
447
448 if (unlikely(rsp_len > ctx->rsp_len)) {
449 dev_err(fd->dev,
450 "response for op %u is %uB > response buffer %uB\n",
451 rsp_common->op, rsp_len, ctx->rsp_len);
452 rsp_len = ctx->rsp_len;
453 }
454 memcpy(ctx->rsp_buf, rsp, rsp_len);
455 }
456 ctx->rsp_status = rsp_common->ret;
457 complete(&ctx->compl);
458}
459
460/* Submit a synchronous admin command. */
461int fun_submit_admin_sync_cmd(struct fun_dev *fdev,
462 struct fun_admin_req_common *cmd, void *rsp,
463 size_t rspsize, unsigned int timeout)
464{
465 struct fun_sync_cmd_ctx ctx = {
466 .compl = COMPLETION_INITIALIZER_ONSTACK(ctx.compl),
467 .rsp_buf = rsp,
468 .rsp_len = rspsize,
469 };
470 unsigned int cmdlen = cmd->len8 * 8;
471 unsigned long jiffies_left;
472 int ret;
473
474 ret = fun_submit_admin_cmd(fdev, cmd, fun_admin_cmd_sync_cb, &ctx,
475 true);
476 if (ret)
477 return ret;
478
479 if (!timeout)
480 timeout = FUN_ADMIN_CMD_TO_MS;
481
482 jiffies_left = wait_for_completion_timeout(&ctx.compl,
483 msecs_to_jiffies(timeout));
484 if (!jiffies_left) {
485 /* The command timed out. Attempt to cancel it so we can return.
486 * But if the command is in the process of completing we'll
487 * wait for it.
488 */
489 if (fun_abandon_admin_cmd(fdev, cmd, &ctx)) {
490 dev_err(fdev->dev, "admin command timed out: %*ph\n",
491 cmdlen, cmd);
492 fun_admin_stop(fdev);
493 /* see if the timeout was due to a queue failure */
494 if (fun_adminq_stopped(fdev))
495 dev_err(fdev->dev,
496 "device does not accept admin commands\n");
497
498 return -ETIMEDOUT;
499 }
500 wait_for_completion(&ctx.compl);
501 }
502
503 if (ctx.rsp_status) {
504 dev_err(fdev->dev, "admin command failed, err %d: %*ph\n",
505 ctx.rsp_status, cmdlen, cmd);
506 }
507
508 return -ctx.rsp_status;
509}
510EXPORT_SYMBOL_GPL(fun_submit_admin_sync_cmd);
511
512/* Return the number of device resources of the requested type. */
513int fun_get_res_count(struct fun_dev *fdev, enum fun_admin_op res)
514{
515 union {
516 struct fun_admin_res_count_req req;
517 struct fun_admin_res_count_rsp rsp;
518 } cmd;
519 int rc;
520
521 cmd.req.common = FUN_ADMIN_REQ_COMMON_INIT2(res, sizeof(cmd.req));
522 cmd.req.count = FUN_ADMIN_SIMPLE_SUBOP_INIT(FUN_ADMIN_SUBOP_RES_COUNT,
523 0, 0);
524
525 rc = fun_submit_admin_sync_cmd(fdev, &cmd.req.common, &cmd.rsp,
526 sizeof(cmd), 0);
527 return rc ? rc : be32_to_cpu(cmd.rsp.count.data);
528}
529EXPORT_SYMBOL_GPL(fun_get_res_count);
530
531/* Request that the instance of resource @res with the given id be deleted. */
532int fun_res_destroy(struct fun_dev *fdev, enum fun_admin_op res,
533 unsigned int flags, u32 id)
534{
535 struct fun_admin_generic_destroy_req req = {
536 .common = FUN_ADMIN_REQ_COMMON_INIT2(res, sizeof(req)),
537 .destroy = FUN_ADMIN_SIMPLE_SUBOP_INIT(FUN_ADMIN_SUBOP_DESTROY,
538 flags, id)
539 };
540
541 return fun_submit_admin_sync_cmd(fdev, &req.common, NULL, 0, 0);
542}
543EXPORT_SYMBOL_GPL(fun_res_destroy);
544
545/* Bind two entities of the given types and IDs. */
546int fun_bind(struct fun_dev *fdev, enum fun_admin_bind_type type0,
547 unsigned int id0, enum fun_admin_bind_type type1,
548 unsigned int id1)
549{
550 struct {
551 struct fun_admin_bind_req req;
552 struct fun_admin_bind_entry entry[2];
553 } cmd = {
554 .req.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_BIND,
555 sizeof(cmd)),
556 .entry[0] = FUN_ADMIN_BIND_ENTRY_INIT(type0, id0),
557 .entry[1] = FUN_ADMIN_BIND_ENTRY_INIT(type1, id1),
558 };
559
560 return fun_submit_admin_sync_cmd(fdev, &cmd.req.common, NULL, 0, 0);
561}
562EXPORT_SYMBOL_GPL(fun_bind);
563
564static int fun_get_dev_limits(struct fun_dev *fdev)
565{
566 struct pci_dev *pdev = to_pci_dev(fdev->dev);
567 unsigned int cq_count, sq_count, num_dbs;
568 int rc;
569
570 rc = fun_get_res_count(fdev, FUN_ADMIN_OP_EPCQ);
571 if (rc < 0)
572 return rc;
573 cq_count = rc;
574
575 rc = fun_get_res_count(fdev, FUN_ADMIN_OP_EPSQ);
576 if (rc < 0)
577 return rc;
578 sq_count = rc;
579
580 /* The admin queue consumes 1 CQ and at least 1 SQ. To be usable the
581 * device must provide additional queues.
582 */
583 if (cq_count < 2 || sq_count < 2 + !!fdev->admin_q->rq_depth)
584 return -EINVAL;
585
586 /* Calculate the max QID based on SQ/CQ/doorbell counts.
587 * SQ/CQ doorbells alternate.
588 */
589 num_dbs = (pci_resource_len(pdev, 0) - NVME_REG_DBS) /
590 (fdev->db_stride * 4);
591 fdev->max_qid = min3(cq_count, sq_count, num_dbs / 2) - 1;
592 fdev->kern_end_qid = fdev->max_qid + 1;
593 return 0;
594}
595
596/* Allocate all MSI-X vectors available on a function and at least @min_vecs. */
597static int fun_alloc_irqs(struct pci_dev *pdev, unsigned int min_vecs)
598{
599 int vecs, num_msix = pci_msix_vec_count(pdev);
600
601 if (num_msix < 0)
602 return num_msix;
603 if (min_vecs > num_msix)
604 return -ERANGE;
605
606 vecs = pci_alloc_irq_vectors(pdev, min_vecs, num_msix, PCI_IRQ_MSIX);
607 if (vecs > 0) {
608 dev_info(&pdev->dev,
609 "Allocated %d IRQ vectors of %d requested\n",
610 vecs, num_msix);
611 } else {
612 dev_err(&pdev->dev,
613 "Unable to allocate at least %u IRQ vectors\n",
614 min_vecs);
615 }
616 return vecs;
617}
618
619/* Allocate and initialize the IRQ manager state. */
620static int fun_alloc_irq_mgr(struct fun_dev *fdev)
621{
622 fdev->irq_map = bitmap_zalloc(fdev->num_irqs, GFP_KERNEL);
623 if (!fdev->irq_map)
624 return -ENOMEM;
625
626 spin_lock_init(&fdev->irqmgr_lock);
627 /* mark IRQ 0 allocated, it is used by the admin queue */
628 __set_bit(0, fdev->irq_map);
629 fdev->irqs_avail = fdev->num_irqs - 1;
630 return 0;
631}
632
633/* Reserve @nirqs of the currently available IRQs and return their indices. */
634int fun_reserve_irqs(struct fun_dev *fdev, unsigned int nirqs, u16 *irq_indices)
635{
636 unsigned int b, n = 0;
637 int err = -ENOSPC;
638
639 if (!nirqs)
640 return 0;
641
642 spin_lock(&fdev->irqmgr_lock);
643 if (nirqs > fdev->irqs_avail)
644 goto unlock;
645
646 for_each_clear_bit(b, fdev->irq_map, fdev->num_irqs) {
647 __set_bit(b, fdev->irq_map);
648 irq_indices[n++] = b;
649 if (n >= nirqs)
650 break;
651 }
652
653 WARN_ON(n < nirqs);
654 fdev->irqs_avail -= n;
655 err = n;
656unlock:
657 spin_unlock(&fdev->irqmgr_lock);
658 return err;
659}
660EXPORT_SYMBOL(fun_reserve_irqs);
661
662/* Release @nirqs previously allocated IRQS with the supplied indices. */
663void fun_release_irqs(struct fun_dev *fdev, unsigned int nirqs,
664 u16 *irq_indices)
665{
666 unsigned int i;
667
668 spin_lock(&fdev->irqmgr_lock);
669 for (i = 0; i < nirqs; i++)
670 __clear_bit(irq_indices[i], fdev->irq_map);
671 fdev->irqs_avail += nirqs;
672 spin_unlock(&fdev->irqmgr_lock);
673}
674EXPORT_SYMBOL(fun_release_irqs);
675
676static void fun_serv_handler(struct work_struct *work)
677{
678 struct fun_dev *fd = container_of(work, struct fun_dev, service_task);
679
680 if (test_bit(FUN_SERV_DISABLED, &fd->service_flags))
681 return;
682 if (fd->serv_cb)
683 fd->serv_cb(fd);
684}
685
686void fun_serv_stop(struct fun_dev *fd)
687{
688 set_bit(FUN_SERV_DISABLED, &fd->service_flags);
689 cancel_work_sync(&fd->service_task);
690}
691EXPORT_SYMBOL_GPL(fun_serv_stop);
692
693void fun_serv_restart(struct fun_dev *fd)
694{
695 clear_bit(FUN_SERV_DISABLED, &fd->service_flags);
696 if (fd->service_flags)
697 schedule_work(&fd->service_task);
698}
699EXPORT_SYMBOL_GPL(fun_serv_restart);
700
701void fun_serv_sched(struct fun_dev *fd)
702{
703 if (!test_bit(FUN_SERV_DISABLED, &fd->service_flags))
704 schedule_work(&fd->service_task);
705}
706EXPORT_SYMBOL_GPL(fun_serv_sched);
707
708/* Check and try to get the device into a proper state for initialization,
709 * i.e., CSTS.RDY = CC.EN = 0.
710 */
711static int sanitize_dev(struct fun_dev *fdev)
712{
713 int rc;
714
715 fdev->cap_reg = readq(fdev->bar + NVME_REG_CAP);
716 fdev->cc_reg = readl(fdev->bar + NVME_REG_CC);
717
718 /* First get RDY to agree with the current EN. Give RDY the opportunity
719 * to complete a potential recent EN change.
720 */
721 rc = fun_wait_ready(fdev, fdev->cc_reg & NVME_CC_ENABLE);
722 if (rc)
723 return rc;
724
725 /* Next, reset the device if EN is currently 1. */
726 if (fdev->cc_reg & NVME_CC_ENABLE)
727 rc = fun_disable_ctrl(fdev);
728
729 return rc;
730}
731
732/* Undo the device initialization of fun_dev_enable(). */
733void fun_dev_disable(struct fun_dev *fdev)
734{
735 struct pci_dev *pdev = to_pci_dev(fdev->dev);
736
737 pci_set_drvdata(pdev, NULL);
738
739 if (fdev->fw_handle != FUN_HCI_ID_INVALID) {
740 fun_res_destroy(fdev, FUN_ADMIN_OP_SWUPGRADE, 0,
741 fdev->fw_handle);
742 fdev->fw_handle = FUN_HCI_ID_INVALID;
743 }
744
745 fun_disable_admin_queue(fdev);
746
747 bitmap_free(fdev->irq_map);
748 pci_free_irq_vectors(pdev);
749
750 pci_clear_master(pdev);
751 pci_disable_pcie_error_reporting(pdev);
752 pci_disable_device(pdev);
753
754 fun_unmap_bars(fdev);
755}
756EXPORT_SYMBOL(fun_dev_disable);
757
758/* Perform basic initialization of a device, including
759 * - PCI config space setup and BAR0 mapping
760 * - interrupt management initialization
761 * - 1 admin queue setup
762 * - determination of some device limits, such as number of queues.
763 */
764int fun_dev_enable(struct fun_dev *fdev, struct pci_dev *pdev,
765 const struct fun_dev_params *areq, const char *name)
766{
767 int rc;
768
769 fdev->dev = &pdev->dev;
770 rc = fun_map_bars(fdev, name);
771 if (rc)
772 return rc;
773
774 rc = fun_set_dma_masks(fdev->dev);
775 if (rc)
776 goto unmap;
777
778 rc = pci_enable_device_mem(pdev);
779 if (rc) {
780 dev_err(&pdev->dev, "Couldn't enable device, err %d\n", rc);
781 goto unmap;
782 }
783
784 pci_enable_pcie_error_reporting(pdev);
785
786 rc = sanitize_dev(fdev);
787 if (rc)
788 goto disable_dev;
789
790 fdev->fw_handle = FUN_HCI_ID_INVALID;
791 fdev->q_depth = NVME_CAP_MQES(fdev->cap_reg) + 1;
792 fdev->db_stride = 1 << NVME_CAP_STRIDE(fdev->cap_reg);
793 fdev->dbs = fdev->bar + NVME_REG_DBS;
794
795 INIT_WORK(&fdev->service_task, fun_serv_handler);
796 fdev->service_flags = FUN_SERV_DISABLED;
797 fdev->serv_cb = areq->serv_cb;
798
799 rc = fun_alloc_irqs(pdev, areq->min_msix + 1); /* +1 for admin CQ */
800 if (rc < 0)
801 goto disable_dev;
802 fdev->num_irqs = rc;
803
804 rc = fun_alloc_irq_mgr(fdev);
805 if (rc)
806 goto free_irqs;
807
808 pci_set_master(pdev);
809 rc = fun_enable_admin_queue(fdev, areq);
810 if (rc)
811 goto free_irq_mgr;
812
813 rc = fun_get_dev_limits(fdev);
814 if (rc < 0)
815 goto disable_admin;
816
817 pci_save_state(pdev);
818 pci_set_drvdata(pdev, fdev);
819 pcie_print_link_status(pdev);
820 dev_dbg(fdev->dev, "q_depth %u, db_stride %u, max qid %d kern_end_qid %d\n",
821 fdev->q_depth, fdev->db_stride, fdev->max_qid,
822 fdev->kern_end_qid);
823 return 0;
824
825disable_admin:
826 fun_disable_admin_queue(fdev);
827free_irq_mgr:
828 pci_clear_master(pdev);
829 bitmap_free(fdev->irq_map);
830free_irqs:
831 pci_free_irq_vectors(pdev);
832disable_dev:
833 pci_disable_pcie_error_reporting(pdev);
834 pci_disable_device(pdev);
835unmap:
836 fun_unmap_bars(fdev);
837 return rc;
838}
839EXPORT_SYMBOL(fun_dev_enable);
840
841MODULE_AUTHOR("Dimitris Michailidis <dmichail@fungible.com>");
842MODULE_DESCRIPTION("Core services driver for Fungible devices");
843MODULE_LICENSE("Dual BSD/GPL");
drivers/net/ethernet/fungible/funcore/fun_dev.h+150−0
@@ -0,0 +1,150 @@
1/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2
3#ifndef _FUNDEV_H
4#define _FUNDEV_H
5
6#include <linux/sbitmap.h>
7#include <linux/spinlock_types.h>
8#include <linux/workqueue.h>
9#include "fun_hci.h"
10
11struct pci_dev;
12struct fun_dev;
13struct fun_queue;
14struct fun_cmd_ctx;
15struct fun_queue_alloc_req;
16
17/* doorbell fields */
18enum {
19 FUN_DB_QIDX_S = 0,
20 FUN_DB_INTCOAL_ENTRIES_S = 16,
21 FUN_DB_INTCOAL_ENTRIES_M = 0x7f,
22 FUN_DB_INTCOAL_USEC_S = 23,
23 FUN_DB_INTCOAL_USEC_M = 0x7f,
24 FUN_DB_IRQ_S = 30,
25 FUN_DB_IRQ_F = 1 << FUN_DB_IRQ_S,
26 FUN_DB_IRQ_ARM_S = 31,
27 FUN_DB_IRQ_ARM_F = 1U << FUN_DB_IRQ_ARM_S
28};
29
30/* Callback for asynchronous admin commands.
31 * Invoked on reception of command response.
32 */
33typedef void (*fun_admin_callback_t)(struct fun_dev *fdev, void *rsp,
34 void *cb_data);
35
36/* Callback for events/notifications received by an admin queue. */
37typedef void (*fun_admin_event_cb)(struct fun_dev *fdev, void *cqe);
38
39/* Callback for pending work handled by the service task. */
40typedef void (*fun_serv_cb)(struct fun_dev *fd);
41
42/* service task flags */
43enum {
44 FUN_SERV_DISABLED, /* service task is disabled */
45 FUN_SERV_FIRST_AVAIL
46};
47
48/* Driver state associated with a PCI function. */
49struct fun_dev {
50 struct device *dev;
51
52 void __iomem *bar; /* start of BAR0 mapping */
53 u32 __iomem *dbs; /* start of doorbells in BAR0 mapping */
54
55 /* admin queue */
56 struct fun_queue *admin_q;
57 struct sbitmap_queue admin_sbq;
58 struct fun_cmd_ctx *cmd_ctx;
59 fun_admin_event_cb adminq_cb;
60 bool suppress_cmds; /* if set don't write commands to SQ */
61
62 /* address increment between consecutive doorbells, in 4B units */
63 unsigned int db_stride;
64
65 /* SW versions of device registers */
66 u32 cc_reg; /* CC register */
67 u64 cap_reg; /* CAPability register */
68
69 unsigned int q_depth; /* max queue depth supported by device */
70 unsigned int max_qid; /* = #queues - 1, separately for SQs and CQs */
71 unsigned int kern_end_qid; /* last qid in the kernel range + 1 */
72
73 unsigned int fw_handle;
74
75 /* IRQ manager */
76 unsigned int num_irqs;
77 unsigned int irqs_avail;
78 spinlock_t irqmgr_lock;
79 unsigned long *irq_map;
80
81 /* The service task handles work that needs a process context */
82 struct work_struct service_task;
83 unsigned long service_flags;
84 fun_serv_cb serv_cb;
85};
86
87struct fun_dev_params {
88 u8 cqe_size_log2; /* admin q CQE size */
89 u8 sqe_size_log2; /* admin q SQE size */
90
91 /* admin q depths */
92 u16 cq_depth;
93 u16 sq_depth;
94 u16 rq_depth;
95
96 u16 min_msix; /* min vectors needed by requesting driver */
97
98 fun_admin_event_cb event_cb;
99 fun_serv_cb serv_cb;
100};
101
102/* Return the BAR address of a doorbell. */
103static inline u32 __iomem *fun_db_addr(const struct fun_dev *fdev,
104 unsigned int db_index)
105{
106 return &fdev->dbs[db_index * fdev->db_stride];
107}
108
109/* Return the BAR address of an SQ doorbell. SQ and CQ DBs alternate,
110 * SQs have even DB indices.
111 */
112static inline u32 __iomem *fun_sq_db_addr(const struct fun_dev *fdev,
113 unsigned int sqid)
114{
115 return fun_db_addr(fdev, sqid * 2);
116}
117
118static inline u32 __iomem *fun_cq_db_addr(const struct fun_dev *fdev,
119 unsigned int cqid)
120{
121 return fun_db_addr(fdev, cqid * 2 + 1);
122}
123
124int fun_get_res_count(struct fun_dev *fdev, enum fun_admin_op res);
125int fun_res_destroy(struct fun_dev *fdev, enum fun_admin_op res,
126 unsigned int flags, u32 id);
127int fun_bind(struct fun_dev *fdev, enum fun_admin_bind_type type0,
128 unsigned int id0, enum fun_admin_bind_type type1,
129 unsigned int id1);
130
131int fun_submit_admin_cmd(struct fun_dev *fdev, struct fun_admin_req_common *cmd,
132 fun_admin_callback_t cb, void *cb_data, bool wait_ok);
133int fun_submit_admin_sync_cmd(struct fun_dev *fdev,
134 struct fun_admin_req_common *cmd, void *rsp,
135 size_t rspsize, unsigned int timeout);
136
137int fun_dev_enable(struct fun_dev *fdev, struct pci_dev *pdev,
138 const struct fun_dev_params *areq, const char *name);
139void fun_dev_disable(struct fun_dev *fdev);
140
141int fun_reserve_irqs(struct fun_dev *fdev, unsigned int nirqs,
142 u16 *irq_indices);
143void fun_release_irqs(struct fun_dev *fdev, unsigned int nirqs,
144 u16 *irq_indices);
145
146void fun_serv_stop(struct fun_dev *fd);
147void fun_serv_restart(struct fun_dev *fd);
148void fun_serv_sched(struct fun_dev *fd);
149
150#endif /* _FUNDEV_H */
drivers/net/ethernet/fungible/funcore/fun_hci.h+1202−0
@@ -0,0 +1,1202 @@
1/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2
3#ifndef __FUN_HCI_H
4#define __FUN_HCI_H
5
6enum {
7 FUN_HCI_ID_INVALID = 0xffffffff,
8};
9
10enum fun_admin_op {
11 FUN_ADMIN_OP_BIND = 0x1,
12 FUN_ADMIN_OP_EPCQ = 0x11,
13 FUN_ADMIN_OP_EPSQ = 0x12,
14 FUN_ADMIN_OP_PORT = 0x13,
15 FUN_ADMIN_OP_ETH = 0x14,
16 FUN_ADMIN_OP_VI = 0x15,
17 FUN_ADMIN_OP_SWUPGRADE = 0x1f,
18 FUN_ADMIN_OP_RSS = 0x21,
19 FUN_ADMIN_OP_ADI = 0x25,
20 FUN_ADMIN_OP_KTLS = 0x26,
21};
22
23enum {
24 FUN_REQ_COMMON_FLAG_RSP = 0x1,
25 FUN_REQ_COMMON_FLAG_HEAD_WB = 0x2,
26 FUN_REQ_COMMON_FLAG_INT = 0x4,
27 FUN_REQ_COMMON_FLAG_CQE_IN_RQBUF = 0x8,
28};
29
30struct fun_admin_req_common {
31 __u8 op;
32 __u8 len8;
33 __be16 flags;
34 __u8 suboff8;
35 __u8 rsvd0;
36 __be16 cid;
37};
38
39#define FUN_ADMIN_REQ_COMMON_INIT(_op, _len8, _flags, _suboff8, _cid) \
40 (struct fun_admin_req_common) { \
41 .op = (_op), .len8 = (_len8), .flags = cpu_to_be16(_flags), \
42 .suboff8 = (_suboff8), .cid = cpu_to_be16(_cid), \
43 }
44
45#define FUN_ADMIN_REQ_COMMON_INIT2(_op, _len) \
46 (struct fun_admin_req_common) { \
47 .op = (_op), .len8 = (_len) / 8, \
48 }
49
50struct fun_admin_rsp_common {
51 __u8 op;
52 __u8 len8;
53 __be16 flags;
54 __u8 suboff8;
55 __u8 ret;
56 __be16 cid;
57};
58
59struct fun_admin_write48_req {
60 __be64 key_to_data;
61};
62
63#define FUN_ADMIN_WRITE48_REQ_KEY_S 56U
64#define FUN_ADMIN_WRITE48_REQ_KEY_M 0xff
65#define FUN_ADMIN_WRITE48_REQ_KEY_P_NOSWAP(x) \
66 (((__u64)x) << FUN_ADMIN_WRITE48_REQ_KEY_S)
67
68#define FUN_ADMIN_WRITE48_REQ_DATA_S 0U
69#define FUN_ADMIN_WRITE48_REQ_DATA_M 0xffffffffffff
70#define FUN_ADMIN_WRITE48_REQ_DATA_P_NOSWAP(x) \
71 (((__u64)x) << FUN_ADMIN_WRITE48_REQ_DATA_S)
72
73#define FUN_ADMIN_WRITE48_REQ_INIT(key, data) \
74 (struct fun_admin_write48_req) { \
75 .key_to_data = cpu_to_be64( \
76 FUN_ADMIN_WRITE48_REQ_KEY_P_NOSWAP(key) | \
77 FUN_ADMIN_WRITE48_REQ_DATA_P_NOSWAP(data)), \
78 }
79
80struct fun_admin_write48_rsp {
81 __be64 key_to_data;
82};
83
84struct fun_admin_read48_req {
85 __be64 key_pack;
86};
87
88#define FUN_ADMIN_READ48_REQ_KEY_S 56U
89#define FUN_ADMIN_READ48_REQ_KEY_M 0xff
90#define FUN_ADMIN_READ48_REQ_KEY_P_NOSWAP(x) \
91 (((__u64)x) << FUN_ADMIN_READ48_REQ_KEY_S)
92
93#define FUN_ADMIN_READ48_REQ_INIT(key) \
94 (struct fun_admin_read48_req) { \
95 .key_pack = \
96 cpu_to_be64(FUN_ADMIN_READ48_REQ_KEY_P_NOSWAP(key)), \
97 }
98
99struct fun_admin_read48_rsp {
100 __be64 key_to_data;
101};
102
103#define FUN_ADMIN_READ48_RSP_KEY_S 56U
104#define FUN_ADMIN_READ48_RSP_KEY_M 0xff
105#define FUN_ADMIN_READ48_RSP_KEY_G(x) \
106 ((be64_to_cpu(x) >> FUN_ADMIN_READ48_RSP_KEY_S) & \
107 FUN_ADMIN_READ48_RSP_KEY_M)
108
109#define FUN_ADMIN_READ48_RSP_RET_S 48U
110#define FUN_ADMIN_READ48_RSP_RET_M 0xff
111#define FUN_ADMIN_READ48_RSP_RET_G(x) \
112 ((be64_to_cpu(x) >> FUN_ADMIN_READ48_RSP_RET_S) & \
113 FUN_ADMIN_READ48_RSP_RET_M)
114
115#define FUN_ADMIN_READ48_RSP_DATA_S 0U
116#define FUN_ADMIN_READ48_RSP_DATA_M 0xffffffffffff
117#define FUN_ADMIN_READ48_RSP_DATA_G(x) \
118 ((be64_to_cpu(x) >> FUN_ADMIN_READ48_RSP_DATA_S) & \
119 FUN_ADMIN_READ48_RSP_DATA_M)
120
121enum fun_admin_bind_type {
122 FUN_ADMIN_BIND_TYPE_EPCQ = 0x1,
123 FUN_ADMIN_BIND_TYPE_EPSQ = 0x2,
124 FUN_ADMIN_BIND_TYPE_PORT = 0x3,
125 FUN_ADMIN_BIND_TYPE_RSS = 0x4,
126 FUN_ADMIN_BIND_TYPE_VI = 0x5,
127 FUN_ADMIN_BIND_TYPE_ETH = 0x6,
128};
129
130struct fun_admin_bind_entry {
131 __u8 type;
132 __u8 rsvd0[3];
133 __be32 id;
134};
135
136#define FUN_ADMIN_BIND_ENTRY_INIT(_type, _id) \
137 (struct fun_admin_bind_entry) { \
138 .type = (_type), .id = cpu_to_be32(_id), \
139 }
140
141struct fun_admin_bind_req {
142 struct fun_admin_req_common common;
143 struct fun_admin_bind_entry entry[];
144};
145
146struct fun_admin_bind_rsp {
147 struct fun_admin_rsp_common bind_rsp_common;
148};
149
150struct fun_admin_simple_subop {
151 __u8 subop;
152 __u8 rsvd0;
153 __be16 flags;
154 __be32 data;
155};
156
157#define FUN_ADMIN_SIMPLE_SUBOP_INIT(_subop, _flags, _data) \
158 (struct fun_admin_simple_subop) { \
159 .subop = (_subop), .flags = cpu_to_be16(_flags), \
160 .data = cpu_to_be32(_data), \
161 }
162
163enum fun_admin_subop {
164 FUN_ADMIN_SUBOP_CREATE = 0x10,
165 FUN_ADMIN_SUBOP_DESTROY = 0x11,
166 FUN_ADMIN_SUBOP_MODIFY = 0x12,
167 FUN_ADMIN_SUBOP_RES_COUNT = 0x14,
168 FUN_ADMIN_SUBOP_READ = 0x15,
169 FUN_ADMIN_SUBOP_WRITE = 0x16,
170 FUN_ADMIN_SUBOP_NOTIFY = 0x17,
171};
172
173enum {
174 FUN_ADMIN_RES_CREATE_FLAG_ALLOCATOR = 0x1,
175};
176
177struct fun_admin_generic_destroy_req {
178 struct fun_admin_req_common common;
179 struct fun_admin_simple_subop destroy;
180};
181
182struct fun_admin_generic_create_rsp {
183 struct fun_admin_rsp_common common;
184
185 __u8 subop;
186 __u8 rsvd0;
187 __be16 flags;
188 __be32 id;
189};
190
191struct fun_admin_res_count_req {
192 struct fun_admin_req_common common;
193 struct fun_admin_simple_subop count;
194};
195
196struct fun_admin_res_count_rsp {
197 struct fun_admin_rsp_common common;
198 struct fun_admin_simple_subop count;
199};
200
201enum {
202 FUN_ADMIN_EPCQ_CREATE_FLAG_INT_EPCQ = 0x2,
203 FUN_ADMIN_EPCQ_CREATE_FLAG_ENTRY_WR_TPH = 0x4,
204 FUN_ADMIN_EPCQ_CREATE_FLAG_SL_WR_TPH = 0x8,
205 FUN_ADMIN_EPCQ_CREATE_FLAG_RQ = 0x80,
206 FUN_ADMIN_EPCQ_CREATE_FLAG_INT_IQ = 0x100,
207 FUN_ADMIN_EPCQ_CREATE_FLAG_INT_NOARM = 0x200,
208 FUN_ADMIN_EPCQ_CREATE_FLAG_DROP_ON_OVERFLOW = 0x400,
209};
210
211struct fun_admin_epcq_req {
212 struct fun_admin_req_common common;
213 union epcq_req_subop {
214 struct fun_admin_epcq_create_req {
215 __u8 subop;
216 __u8 rsvd0;
217 __be16 flags;
218 __be32 id;
219
220 __be32 epsqid;
221 __u8 rsvd1;
222 __u8 entry_size_log2;
223 __be16 nentries;
224
225 __be64 address;
226
227 __be16 tailroom; /* per packet tailroom in bytes */
228 __u8 headroom; /* per packet headroom in 2B units */
229 __u8 intcoal_kbytes;
230 __u8 intcoal_holdoff_nentries;
231 __u8 intcoal_holdoff_usecs;
232 __be16 intid;
233
234 __be32 scan_start_id;
235 __be32 scan_end_id;
236
237 __be16 tph_cpuid;
238 __u8 rsvd3[6];
239 } create;
240
241 struct fun_admin_epcq_modify_req {
242 __u8 subop;
243 __u8 rsvd0;
244 __be16 flags;
245 __be32 id;
246
247 __be16 headroom; /* headroom in bytes */
248 __u8 rsvd1[6];
249 } modify;
250 } u;
251};
252
253#define FUN_ADMIN_EPCQ_CREATE_REQ_INIT( \
254 _subop, _flags, _id, _epsqid, _entry_size_log2, _nentries, _address, \
255 _tailroom, _headroom, _intcoal_kbytes, _intcoal_holdoff_nentries, \
256 _intcoal_holdoff_usecs, _intid, _scan_start_id, _scan_end_id, \
257 _tph_cpuid) \
258 (struct fun_admin_epcq_create_req) { \
259 .subop = (_subop), .flags = cpu_to_be16(_flags), \
260 .id = cpu_to_be32(_id), .epsqid = cpu_to_be32(_epsqid), \
261 .entry_size_log2 = _entry_size_log2, \
262 .nentries = cpu_to_be16(_nentries), \
263 .address = cpu_to_be64(_address), \
264 .tailroom = cpu_to_be16(_tailroom), .headroom = _headroom, \
265 .intcoal_kbytes = _intcoal_kbytes, \
266 .intcoal_holdoff_nentries = _intcoal_holdoff_nentries, \
267 .intcoal_holdoff_usecs = _intcoal_holdoff_usecs, \
268 .intid = cpu_to_be16(_intid), \
269 .scan_start_id = cpu_to_be32(_scan_start_id), \
270 .scan_end_id = cpu_to_be32(_scan_end_id), \
271 .tph_cpuid = cpu_to_be16(_tph_cpuid), \
272 }
273
274#define FUN_ADMIN_EPCQ_MODIFY_REQ_INIT(_subop, _flags, _id, _headroom) \
275 (struct fun_admin_epcq_modify_req) { \
276 .subop = (_subop), .flags = cpu_to_be16(_flags), \
277 .id = cpu_to_be32(_id), .headroom = cpu_to_be16(_headroom), \
278 }
279
280enum {
281 FUN_ADMIN_EPSQ_CREATE_FLAG_INT_EPSQ = 0x2,
282 FUN_ADMIN_EPSQ_CREATE_FLAG_ENTRY_RD_TPH = 0x4,
283 FUN_ADMIN_EPSQ_CREATE_FLAG_GL_RD_TPH = 0x8,
284 FUN_ADMIN_EPSQ_CREATE_FLAG_HEAD_WB_ADDRESS = 0x10,
285 FUN_ADMIN_EPSQ_CREATE_FLAG_HEAD_WB_ADDRESS_TPH = 0x20,
286 FUN_ADMIN_EPSQ_CREATE_FLAG_HEAD_WB_EPCQ = 0x40,
287 FUN_ADMIN_EPSQ_CREATE_FLAG_RQ = 0x80,
288 FUN_ADMIN_EPSQ_CREATE_FLAG_INT_IQ = 0x100,
289 FUN_ADMIN_EPSQ_CREATE_FLAG_NO_CMPL = 0x200,
290};
291
292struct fun_admin_epsq_req {
293 struct fun_admin_req_common common;
294
295 union epsq_req_subop {
296 struct fun_admin_epsq_create_req {
297 __u8 subop;
298 __u8 rsvd0;
299 __be16 flags;
300 __be32 id;
301
302 __be32 epcqid;
303 __u8 rsvd1;
304 __u8 entry_size_log2;
305 __be16 nentries;
306
307 __be64 address; /* DMA address of epsq */
308
309 __u8 rsvd2[3];
310 __u8 intcoal_kbytes;
311 __u8 intcoal_holdoff_nentries;
312 __u8 intcoal_holdoff_usecs;
313 __be16 intid;
314
315 __be32 scan_start_id;
316 __be32 scan_end_id;
317
318 __u8 rsvd3[4];
319 __be16 tph_cpuid;
320 __u8 buf_size_log2; /* log2 of RQ buffer size */
321 __u8 head_wb_size_log2; /* log2 of head write back size */
322
323 __be64 head_wb_address; /* DMA address for head writeback */
324 } create;
325 } u;
326};
327
328#define FUN_ADMIN_EPSQ_CREATE_REQ_INIT( \
329 _subop, _flags, _id, _epcqid, _entry_size_log2, _nentries, _address, \
330 _intcoal_kbytes, _intcoal_holdoff_nentries, _intcoal_holdoff_usecs, \
331 _intid, _scan_start_id, _scan_end_id, _tph_cpuid, _buf_size_log2, \
332 _head_wb_size_log2, _head_wb_address) \
333 (struct fun_admin_epsq_create_req) { \
334 .subop = (_subop), .flags = cpu_to_be16(_flags), \
335 .id = cpu_to_be32(_id), .epcqid = cpu_to_be32(_epcqid), \
336 .entry_size_log2 = _entry_size_log2, \
337 .nentries = cpu_to_be16(_nentries), \
338 .address = cpu_to_be64(_address), \
339 .intcoal_kbytes = _intcoal_kbytes, \
340 .intcoal_holdoff_nentries = _intcoal_holdoff_nentries, \
341 .intcoal_holdoff_usecs = _intcoal_holdoff_usecs, \
342 .intid = cpu_to_be16(_intid), \
343 .scan_start_id = cpu_to_be32(_scan_start_id), \
344 .scan_end_id = cpu_to_be32(_scan_end_id), \
345 .tph_cpuid = cpu_to_be16(_tph_cpuid), \
346 .buf_size_log2 = _buf_size_log2, \
347 .head_wb_size_log2 = _head_wb_size_log2, \
348 .head_wb_address = cpu_to_be64(_head_wb_address), \
349 }
350
351enum {
352 FUN_PORT_CAP_OFFLOADS = 0x1,
353 FUN_PORT_CAP_STATS = 0x2,
354 FUN_PORT_CAP_LOOPBACK = 0x4,
355 FUN_PORT_CAP_VPORT = 0x8,
356 FUN_PORT_CAP_TX_PAUSE = 0x10,
357 FUN_PORT_CAP_RX_PAUSE = 0x20,
358 FUN_PORT_CAP_AUTONEG = 0x40,
359 FUN_PORT_CAP_RSS = 0x80,
360 FUN_PORT_CAP_VLAN_OFFLOADS = 0x100,
361 FUN_PORT_CAP_ENCAP_OFFLOADS = 0x200,
362 FUN_PORT_CAP_1000_X = 0x1000,
363 FUN_PORT_CAP_10G_R = 0x2000,
364 FUN_PORT_CAP_40G_R4 = 0x4000,
365 FUN_PORT_CAP_25G_R = 0x8000,
366 FUN_PORT_CAP_50G_R2 = 0x10000,
367 FUN_PORT_CAP_50G_R = 0x20000,
368 FUN_PORT_CAP_100G_R4 = 0x40000,
369 FUN_PORT_CAP_100G_R2 = 0x80000,
370 FUN_PORT_CAP_200G_R4 = 0x100000,
371 FUN_PORT_CAP_FEC_NONE = 0x10000000,
372 FUN_PORT_CAP_FEC_FC = 0x20000000,
373 FUN_PORT_CAP_FEC_RS = 0x40000000,
374};
375
376enum fun_port_brkout_mode {
377 FUN_PORT_BRKMODE_NA = 0x0,
378 FUN_PORT_BRKMODE_NONE = 0x1,
379 FUN_PORT_BRKMODE_2X = 0x2,
380 FUN_PORT_BRKMODE_4X = 0x3,
381};
382
383enum {
384 FUN_PORT_SPEED_AUTO = 0x0,
385 FUN_PORT_SPEED_10M = 0x1,
386 FUN_PORT_SPEED_100M = 0x2,
387 FUN_PORT_SPEED_1G = 0x4,
388 FUN_PORT_SPEED_10G = 0x8,
389 FUN_PORT_SPEED_25G = 0x10,
390 FUN_PORT_SPEED_40G = 0x20,
391 FUN_PORT_SPEED_50G = 0x40,
392 FUN_PORT_SPEED_100G = 0x80,
393 FUN_PORT_SPEED_200G = 0x100,
394};
395
396enum fun_port_duplex_mode {
397 FUN_PORT_FULL_DUPLEX = 0x0,
398 FUN_PORT_HALF_DUPLEX = 0x1,
399};
400
401enum {
402 FUN_PORT_FEC_NA = 0x0,
403 FUN_PORT_FEC_OFF = 0x1,
404 FUN_PORT_FEC_RS = 0x2,
405 FUN_PORT_FEC_FC = 0x4,
406 FUN_PORT_FEC_AUTO = 0x8,
407};
408
409enum fun_port_link_status {
410 FUN_PORT_LINK_UP = 0x0,
411 FUN_PORT_LINK_UP_WITH_ERR = 0x1,
412 FUN_PORT_LINK_DOWN = 0x2,
413};
414
415enum fun_port_led_type {
416 FUN_PORT_LED_OFF = 0x0,
417 FUN_PORT_LED_AMBER = 0x1,
418 FUN_PORT_LED_GREEN = 0x2,
419 FUN_PORT_LED_BEACON_ON = 0x3,
420 FUN_PORT_LED_BEACON_OFF = 0x4,
421};
422
423enum {
424 FUN_PORT_FLAG_MAC_DOWN = 0x1,
425 FUN_PORT_FLAG_MAC_UP = 0x2,
426 FUN_PORT_FLAG_NH_DOWN = 0x4,
427 FUN_PORT_FLAG_NH_UP = 0x8,
428};
429
430enum {
431 FUN_PORT_FLAG_ENABLE_NOTIFY = 0x1,
432};
433
434enum fun_port_lane_attr {
435 FUN_PORT_LANE_1 = 0x1,
436 FUN_PORT_LANE_2 = 0x2,
437 FUN_PORT_LANE_4 = 0x4,
438 FUN_PORT_LANE_SPEED_10G = 0x100,
439 FUN_PORT_LANE_SPEED_25G = 0x200,
440 FUN_PORT_LANE_SPEED_50G = 0x400,
441 FUN_PORT_LANE_SPLIT = 0x8000,
442};
443
444enum fun_admin_port_subop {
445 FUN_ADMIN_PORT_SUBOP_INETADDR_EVENT = 0x24,
446};
447
448enum fun_admin_port_key {
449 FUN_ADMIN_PORT_KEY_ILLEGAL = 0x0,
450 FUN_ADMIN_PORT_KEY_MTU = 0x1,
451 FUN_ADMIN_PORT_KEY_FEC = 0x2,
452 FUN_ADMIN_PORT_KEY_SPEED = 0x3,
453 FUN_ADMIN_PORT_KEY_DEBOUNCE = 0x4,
454 FUN_ADMIN_PORT_KEY_DUPLEX = 0x5,
455 FUN_ADMIN_PORT_KEY_MACADDR = 0x6,
456 FUN_ADMIN_PORT_KEY_LINKMODE = 0x7,
457 FUN_ADMIN_PORT_KEY_BREAKOUT = 0x8,
458 FUN_ADMIN_PORT_KEY_ENABLE = 0x9,
459 FUN_ADMIN_PORT_KEY_DISABLE = 0xa,
460 FUN_ADMIN_PORT_KEY_ERR_DISABLE = 0xb,
461 FUN_ADMIN_PORT_KEY_CAPABILITIES = 0xc,
462 FUN_ADMIN_PORT_KEY_LP_CAPABILITIES = 0xd,
463 FUN_ADMIN_PORT_KEY_STATS_DMA_LOW = 0xe,
464 FUN_ADMIN_PORT_KEY_STATS_DMA_HIGH = 0xf,
465 FUN_ADMIN_PORT_KEY_LANE_ATTRS = 0x10,
466 FUN_ADMIN_PORT_KEY_LED = 0x11,
467 FUN_ADMIN_PORT_KEY_ADVERT = 0x12,
468};
469
470struct fun_subop_imm {
471 __u8 subop; /* see fun_data_subop enum */
472 __u8 flags;
473 __u8 nsgl;
474 __u8 rsvd0;
475 __be32 len;
476
477 __u8 data[];
478};
479
480enum fun_subop_sgl_flags {
481 FUN_SUBOP_SGL_USE_OFF8 = 0x1,
482 FUN_SUBOP_FLAG_FREE_BUF = 0x2,
483 FUN_SUBOP_FLAG_IS_REFBUF = 0x4,
484 FUN_SUBOP_SGL_FLAG_LOCAL = 0x8,
485};
486
487enum fun_data_op {
488 FUN_DATAOP_INVALID = 0x0,
489 FUN_DATAOP_SL = 0x1, /* scatter */
490 FUN_DATAOP_GL = 0x2, /* gather */
491 FUN_DATAOP_SGL = 0x3, /* scatter-gather */
492 FUN_DATAOP_IMM = 0x4, /* immediate data */
493 FUN_DATAOP_RQBUF = 0x8, /* rq buffer */
494};
495
496struct fun_dataop_gl {
497 __u8 subop;
498 __u8 flags;
499 __be16 sgl_off;
500 __be32 sgl_len;
501
502 __be64 sgl_data;
503};
504
505static inline void fun_dataop_gl_init(struct fun_dataop_gl *s, u8 flags,
506 u16 sgl_off, u32 sgl_len, u64 sgl_data)
507{
508 s->subop = FUN_DATAOP_GL;
509 s->flags = flags;
510 s->sgl_off = cpu_to_be16(sgl_off);
511 s->sgl_len = cpu_to_be32(sgl_len);
512 s->sgl_data = cpu_to_be64(sgl_data);
513}
514
515struct fun_dataop_imm {
516 __u8 subop;
517 __u8 flags;
518 __be16 rsvd0;
519 __be32 sgl_len;
520};
521
522struct fun_subop_sgl {
523 __u8 subop;
524 __u8 flags;
525 __u8 nsgl;
526 __u8 rsvd0;
527 __be32 sgl_len;
528
529 __be64 sgl_data;
530};
531
532#define FUN_SUBOP_SGL_INIT(_subop, _flags, _nsgl, _sgl_len, _sgl_data) \
533 (struct fun_subop_sgl) { \
534 .subop = (_subop), .flags = (_flags), .nsgl = (_nsgl), \
535 .sgl_len = cpu_to_be32(_sgl_len), \
536 .sgl_data = cpu_to_be64(_sgl_data), \
537 }
538
539struct fun_dataop_rqbuf {
540 __u8 subop;
541 __u8 rsvd0;
542 __be16 cid;
543 __be32 bufoff;
544};
545
546struct fun_dataop_hdr {
547 __u8 nsgl;
548 __u8 flags;
549 __u8 ngather;
550 __u8 nscatter;
551 __be32 total_len;
552
553 struct fun_dataop_imm imm[];
554};
555
556#define FUN_DATAOP_HDR_INIT(_nsgl, _flags, _ngather, _nscatter, _total_len) \
557 (struct fun_dataop_hdr) { \
558 .nsgl = _nsgl, .flags = _flags, .ngather = _ngather, \
559 .nscatter = _nscatter, .total_len = cpu_to_be32(_total_len), \
560 }
561
562enum fun_port_inetaddr_event_type {
563 FUN_PORT_INETADDR_ADD = 0x1,
564 FUN_PORT_INETADDR_DEL = 0x2,
565};
566
567enum fun_port_inetaddr_addr_family {
568 FUN_PORT_INETADDR_IPV4 = 0x1,
569 FUN_PORT_INETADDR_IPV6 = 0x2,
570};
571
572struct fun_admin_port_req {
573 struct fun_admin_req_common common;
574
575 union port_req_subop {
576 struct fun_admin_port_create_req {
577 __u8 subop;
578 __u8 rsvd0;
579 __be16 flags;
580 __be32 id;
581 } create;
582 struct fun_admin_port_write_req {
583 __u8 subop;
584 __u8 rsvd0;
585 __be16 flags;
586 __be32 id; /* portid */
587
588 struct fun_admin_write48_req write48[];
589 } write;
590 struct fun_admin_port_read_req {
591 __u8 subop;
592 __u8 rsvd0;
593 __be16 flags;
594 __be32 id; /* portid */
595
596 struct fun_admin_read48_req read48[];
597 } read;
598 struct fun_admin_port_inetaddr_event_req {
599 __u8 subop;
600 __u8 rsvd0;
601 __u8 event_type;
602 __u8 addr_family;
603 __be32 id;
604
605 __u8 addr[];
606 } inetaddr_event;
607 } u;
608};
609
610#define FUN_ADMIN_PORT_CREATE_REQ_INIT(_subop, _flags, _id) \
611 (struct fun_admin_port_create_req) { \
612 .subop = (_subop), .flags = cpu_to_be16(_flags), \
613 .id = cpu_to_be32(_id), \
614 }
615
616#define FUN_ADMIN_PORT_WRITE_REQ_INIT(_subop, _flags, _id) \
617 (struct fun_admin_port_write_req) { \
618 .subop = (_subop), .flags = cpu_to_be16(_flags), \
619 .id = cpu_to_be32(_id), \
620 }
621
622#define FUN_ADMIN_PORT_READ_REQ_INIT(_subop, _flags, _id) \
623 (struct fun_admin_port_read_req) { \
624 .subop = (_subop), .flags = cpu_to_be16(_flags), \
625 .id = cpu_to_be32(_id), \
626 }
627
628struct fun_admin_port_rsp {
629 struct fun_admin_rsp_common common;
630
631 union port_rsp_subop {
632 struct fun_admin_port_create_rsp {
633 __u8 subop;
634 __u8 rsvd0[3];
635 __be32 id;
636
637 __be16 lport;
638 __u8 rsvd1[6];
639 } create;
640 struct fun_admin_port_write_rsp {
641 __u8 subop;
642 __u8 rsvd0[3];
643 __be32 id; /* portid */
644
645 struct fun_admin_write48_rsp write48[];
646 } write;
647 struct fun_admin_port_read_rsp {
648 __u8 subop;
649 __u8 rsvd0[3];
650 __be32 id; /* portid */
651
652 struct fun_admin_read48_rsp read48[];
653 } read;
654 struct fun_admin_port_inetaddr_event_rsp {
655 __u8 subop;
656 __u8 rsvd0[3];
657 __be32 id; /* portid */
658 } inetaddr_event;
659 } u;
660};
661
662enum fun_xcvr_type {
663 FUN_XCVR_BASET = 0x0,
664 FUN_XCVR_CU = 0x1,
665 FUN_XCVR_SMF = 0x2,
666 FUN_XCVR_MMF = 0x3,
667 FUN_XCVR_AOC = 0x4,
668 FUN_XCVR_SFPP = 0x10, /* SFP+ or later */
669 FUN_XCVR_QSFPP = 0x11, /* QSFP+ or later */
670 FUN_XCVR_QSFPDD = 0x12, /* QSFP-DD */
671};
672
673struct fun_admin_port_notif {
674 struct fun_admin_rsp_common common;
675
676 __u8 subop;
677 __u8 rsvd0;
678 __be16 id;
679 __be32 speed; /* in 10 Mbps units */
680
681 __u8 link_state;
682 __u8 missed_events;
683 __u8 link_down_reason;
684 __u8 xcvr_type;
685 __u8 flow_ctrl;
686 __u8 fec;
687 __u8 active_lanes;
688 __u8 rsvd1;
689
690 __be64 advertising;
691
692 __be64 lp_advertising;
693};
694
695enum fun_eth_rss_const {
696 FUN_ETH_RSS_MAX_KEY_SIZE = 0x28,
697 FUN_ETH_RSS_MAX_INDIR_ENT = 0x40,
698};
699
700enum fun_eth_hash_alg {
701 FUN_ETH_RSS_ALG_INVALID = 0x0,
702 FUN_ETH_RSS_ALG_TOEPLITZ = 0x1,
703 FUN_ETH_RSS_ALG_CRC32 = 0x2,
704};
705
706struct fun_admin_rss_req {
707 struct fun_admin_req_common common;
708
709 union rss_req_subop {
710 struct fun_admin_rss_create_req {
711 __u8 subop;
712 __u8 rsvd0;
713 __be16 flags;
714 __be32 id;
715
716 __be32 rsvd1;
717 __be32 viid; /* VI flow id */
718
719 __be64 metadata[1];
720
721 __u8 alg;
722 __u8 keylen;
723 __u8 indir_nent;
724 __u8 rsvd2;
725 __be16 key_off;
726 __be16 indir_off;
727
728 struct fun_dataop_hdr dataop;
729 } create;
730 } u;
731};
732
733#define FUN_ADMIN_RSS_CREATE_REQ_INIT(_subop, _flags, _id, _viid, _alg, \
734 _keylen, _indir_nent, _key_off, \
735 _indir_off) \
736 (struct fun_admin_rss_create_req) { \
737 .subop = (_subop), .flags = cpu_to_be16(_flags), \
738 .id = cpu_to_be32(_id), .viid = cpu_to_be32(_viid), \
739 .alg = _alg, .keylen = _keylen, .indir_nent = _indir_nent, \
740 .key_off = cpu_to_be16(_key_off), \
741 .indir_off = cpu_to_be16(_indir_off), \
742 }
743
744struct fun_admin_vi_req {
745 struct fun_admin_req_common common;
746
747 union vi_req_subop {
748 struct fun_admin_vi_create_req {
749 __u8 subop;
750 __u8 rsvd0;
751 __be16 flags;
752 __be32 id;
753
754 __be32 rsvd1;
755 __be32 portid; /* port flow id */
756 } create;
757 } u;
758};
759
760#define FUN_ADMIN_VI_CREATE_REQ_INIT(_subop, _flags, _id, _portid) \
761 (struct fun_admin_vi_create_req) { \
762 .subop = (_subop), .flags = cpu_to_be16(_flags), \
763 .id = cpu_to_be32(_id), .portid = cpu_to_be32(_portid), \
764 }
765
766struct fun_admin_eth_req {
767 struct fun_admin_req_common common;
768
769 union eth_req_subop {
770 struct fun_admin_eth_create_req {
771 __u8 subop;
772 __u8 rsvd0;
773 __be16 flags;
774 __be32 id;
775
776 __be32 rsvd1;
777 __be32 portid; /* port flow id */
778 } create;
779 } u;
780};
781
782#define FUN_ADMIN_ETH_CREATE_REQ_INIT(_subop, _flags, _id, _portid) \
783 (struct fun_admin_eth_create_req) { \
784 .subop = (_subop), .flags = cpu_to_be16(_flags), \
785 .id = cpu_to_be32(_id), .portid = cpu_to_be32(_portid), \
786 }
787
788enum {
789 FUN_ADMIN_SWU_UPGRADE_FLAG_INIT = 0x10,
790 FUN_ADMIN_SWU_UPGRADE_FLAG_COMPLETE = 0x20,
791 FUN_ADMIN_SWU_UPGRADE_FLAG_DOWNGRADE = 0x40,
792 FUN_ADMIN_SWU_UPGRADE_FLAG_ACTIVE_IMAGE = 0x80,
793 FUN_ADMIN_SWU_UPGRADE_FLAG_ASYNC = 0x1,
794};
795
796enum fun_admin_swu_subop {
797 FUN_ADMIN_SWU_SUBOP_GET_VERSION = 0x20,
798 FUN_ADMIN_SWU_SUBOP_UPGRADE = 0x21,
799 FUN_ADMIN_SWU_SUBOP_UPGRADE_DATA = 0x22,
800 FUN_ADMIN_SWU_SUBOP_GET_ALL_VERSIONS = 0x23,
801};
802
803struct fun_admin_swu_req {
804 struct fun_admin_req_common common;
805
806 union swu_req_subop {
807 struct fun_admin_swu_create_req {
808 __u8 subop;
809 __u8 rsvd0;
810 __be16 flags;
811 __be32 id;
812 } create;
813 struct fun_admin_swu_upgrade_req {
814 __u8 subop;
815 __u8 rsvd0;
816 __be16 flags;
817 __be32 id;
818
819 __be32 fourcc;
820 __be32 rsvd1;
821
822 __be64 image_size; /* upgrade image length */
823 } upgrade;
824 struct fun_admin_swu_upgrade_data_req {
825 __u8 subop;
826 __u8 rsvd0;
827 __be16 flags;
828 __be32 id;
829
830 __be32 offset; /* offset of data in this command */
831 __be32 size; /* total size of data in this command */
832 } upgrade_data;
833 } u;
834
835 struct fun_subop_sgl sgl[]; /* in, out buffers through sgl */
836};
837
838#define FUN_ADMIN_SWU_CREATE_REQ_INIT(_subop, _flags, _id) \
839 (struct fun_admin_swu_create_req) { \
840 .subop = (_subop), .flags = cpu_to_be16(_flags), \
841 .id = cpu_to_be32(_id), \
842 }
843
844#define FUN_ADMIN_SWU_UPGRADE_REQ_INIT(_subop, _flags, _id, _fourcc, \
845 _image_size) \
846 (struct fun_admin_swu_upgrade_req) { \
847 .subop = (_subop), .flags = cpu_to_be16(_flags), \
848 .id = cpu_to_be32(_id), .fourcc = cpu_to_be32(_fourcc), \
849 .image_size = cpu_to_be64(_image_size), \
850 }
851
852#define FUN_ADMIN_SWU_UPGRADE_DATA_REQ_INIT(_subop, _flags, _id, _offset, \
853 _size) \
854 (struct fun_admin_swu_upgrade_data_req) { \
855 .subop = (_subop), .flags = cpu_to_be16(_flags), \
856 .id = cpu_to_be32(_id), .offset = cpu_to_be32(_offset), \
857 .size = cpu_to_be32(_size), \
858 }
859
860struct fun_admin_swu_rsp {
861 struct fun_admin_rsp_common common;
862
863 union swu_rsp_subop {
864 struct fun_admin_swu_create_rsp {
865 __u8 subop;
866 __u8 rsvd0;
867 __be16 flags;
868 __be32 id;
869 } create;
870 struct fun_admin_swu_upgrade_rsp {
871 __u8 subop;
872 __u8 rsvd0[3];
873 __be32 id;
874
875 __be32 fourcc;
876 __be32 status;
877
878 __be32 progress;
879 __be32 unused;
880 } upgrade;
881 struct fun_admin_swu_upgrade_data_rsp {
882 __u8 subop;
883 __u8 rsvd0;
884 __be16 flags;
885 __be32 id;
886
887 __be32 offset;
888 __be32 size;
889 } upgrade_data;
890 } u;
891};
892
893enum fun_ktls_version {
894 FUN_KTLS_TLSV2 = 0x20,
895 FUN_KTLS_TLSV3 = 0x30,
896};
897
898enum fun_ktls_cipher {
899 FUN_KTLS_CIPHER_AES_GCM_128 = 0x33,
900 FUN_KTLS_CIPHER_AES_GCM_256 = 0x34,
901 FUN_KTLS_CIPHER_AES_CCM_128 = 0x35,
902 FUN_KTLS_CIPHER_CHACHA20_POLY1305 = 0x36,
903};
904
905enum fun_ktls_modify_flags {
906 FUN_KTLS_MODIFY_REMOVE = 0x1,
907};
908
909struct fun_admin_ktls_create_req {
910 struct fun_admin_req_common common;
911
912 __u8 subop;
913 __u8 rsvd0;
914 __be16 flags;
915 __be32 id;
916};
917
918#define FUN_ADMIN_KTLS_CREATE_REQ_INIT(_subop, _flags, _id) \
919 (struct fun_admin_ktls_create_req) { \
920 .subop = (_subop), .flags = cpu_to_be16(_flags), \
921 .id = cpu_to_be32(_id), \
922 }
923
924struct fun_admin_ktls_create_rsp {
925 struct fun_admin_rsp_common common;
926
927 __u8 subop;
928 __u8 rsvd0[3];
929 __be32 id;
930};
931
932struct fun_admin_ktls_modify_req {
933 struct fun_admin_req_common common;
934
935 __u8 subop;
936 __u8 rsvd0;
937 __be16 flags;
938 __be32 id;
939
940 __be64 tlsid;
941
942 __be32 tcp_seq;
943 __u8 version;
944 __u8 cipher;
945 __u8 rsvd1[2];
946
947 __u8 record_seq[8];
948
949 __u8 key[32];
950
951 __u8 iv[16];
952
953 __u8 salt[8];
954};
955
956#define FUN_ADMIN_KTLS_MODIFY_REQ_INIT(_subop, _flags, _id, _tlsid, _tcp_seq, \
957 _version, _cipher) \
958 (struct fun_admin_ktls_modify_req) { \
959 .subop = (_subop), .flags = cpu_to_be16(_flags), \
960 .id = cpu_to_be32(_id), .tlsid = cpu_to_be64(_tlsid), \
961 .tcp_seq = cpu_to_be32(_tcp_seq), .version = _version, \
962 .cipher = _cipher, \
963 }
964
965struct fun_admin_ktls_modify_rsp {
966 struct fun_admin_rsp_common common;
967
968 __u8 subop;
969 __u8 rsvd0[3];
970 __be32 id;
971
972 __be64 tlsid;
973};
974
975struct fun_req_common {
976 __u8 op;
977 __u8 len8;
978 __be16 flags;
979 __u8 suboff8;
980 __u8 rsvd0;
981 __be16 cid;
982};
983
984struct fun_rsp_common {
985 __u8 op;
986 __u8 len8;
987 __be16 flags;
988 __u8 suboff8;
989 __u8 ret;
990 __be16 cid;
991};
992
993struct fun_cqe_info {
994 __be16 sqhd;
995 __be16 sqid;
996 __be16 cid;
997 __be16 sf_p;
998};
999
1000enum fun_eprq_def {
1001 FUN_EPRQ_PKT_ALIGN = 0x80,
1002};
1003
1004struct fun_eprq_rqbuf {
1005 __be64 bufaddr;
1006};
1007
1008#define FUN_EPRQ_RQBUF_INIT(_bufaddr) \
1009 (struct fun_eprq_rqbuf) { \
1010 .bufaddr = cpu_to_be64(_bufaddr), \
1011 }
1012
1013enum fun_eth_op {
1014 FUN_ETH_OP_TX = 0x1,
1015 FUN_ETH_OP_RX = 0x2,
1016};
1017
1018enum {
1019 FUN_ETH_OFFLOAD_EN = 0x8000,
1020 FUN_ETH_OUTER_EN = 0x4000,
1021 FUN_ETH_INNER_LSO = 0x2000,
1022 FUN_ETH_INNER_TSO = 0x1000,
1023 FUN_ETH_OUTER_IPV6 = 0x800,
1024 FUN_ETH_OUTER_UDP = 0x400,
1025 FUN_ETH_INNER_IPV6 = 0x200,
1026 FUN_ETH_INNER_UDP = 0x100,
1027 FUN_ETH_UPDATE_OUTER_L3_LEN = 0x80,
1028 FUN_ETH_UPDATE_OUTER_L3_CKSUM = 0x40,
1029 FUN_ETH_UPDATE_OUTER_L4_LEN = 0x20,
1030 FUN_ETH_UPDATE_OUTER_L4_CKSUM = 0x10,
1031 FUN_ETH_UPDATE_INNER_L3_LEN = 0x8,
1032 FUN_ETH_UPDATE_INNER_L3_CKSUM = 0x4,
1033 FUN_ETH_UPDATE_INNER_L4_LEN = 0x2,
1034 FUN_ETH_UPDATE_INNER_L4_CKSUM = 0x1,
1035};
1036
1037struct fun_eth_offload {
1038 __be16 flags; /* combination of above flags */
1039 __be16 mss; /* TSO max seg size */
1040 __be16 tcp_doff_flags; /* TCP data offset + flags 16b word */
1041 __be16 vlan;
1042
1043 __be16 inner_l3_off; /* Inner L3 header offset */
1044 __be16 inner_l4_off; /* Inner L4 header offset */
1045 __be16 outer_l3_off; /* Outer L3 header offset */
1046 __be16 outer_l4_off; /* Outer L4 header offset */
1047};
1048
1049static inline void fun_eth_offload_init(struct fun_eth_offload *s, u16 flags,
1050 u16 mss, __be16 tcp_doff_flags,
1051 __be16 vlan, u16 inner_l3_off,
1052 u16 inner_l4_off, u16 outer_l3_off,
1053 u16 outer_l4_off)
1054{
1055 s->flags = cpu_to_be16(flags);
1056 s->mss = cpu_to_be16(mss);
1057 s->tcp_doff_flags = tcp_doff_flags;
1058 s->vlan = vlan;
1059 s->inner_l3_off = cpu_to_be16(inner_l3_off);
1060 s->inner_l4_off = cpu_to_be16(inner_l4_off);
1061 s->outer_l3_off = cpu_to_be16(outer_l3_off);
1062 s->outer_l4_off = cpu_to_be16(outer_l4_off);
1063}
1064
1065struct fun_eth_tls {
1066 __be64 tlsid;
1067};
1068
1069enum {
1070 FUN_ETH_TX_TLS = 0x8000,
1071};
1072
1073struct fun_eth_tx_req {
1074 __u8 op;
1075 __u8 len8;
1076 __be16 flags;
1077 __u8 suboff8;
1078 __u8 repr_idn;
1079 __be16 encap_proto;
1080
1081 struct fun_eth_offload offload;
1082
1083 struct fun_dataop_hdr dataop;
1084};
1085
1086struct fun_eth_rx_cv {
1087 __be16 il4_prot_to_l2_type;
1088};
1089
1090#define FUN_ETH_RX_CV_IL4_PROT_S 13U
1091#define FUN_ETH_RX_CV_IL4_PROT_M 0x3
1092
1093#define FUN_ETH_RX_CV_IL3_PROT_S 11U
1094#define FUN_ETH_RX_CV_IL3_PROT_M 0x3
1095
1096#define FUN_ETH_RX_CV_OL4_PROT_S 8U
1097#define FUN_ETH_RX_CV_OL4_PROT_M 0x7
1098
1099#define FUN_ETH_RX_CV_ENCAP_TYPE_S 6U
1100#define FUN_ETH_RX_CV_ENCAP_TYPE_M 0x3
1101
1102#define FUN_ETH_RX_CV_OL3_PROT_S 4U
1103#define FUN_ETH_RX_CV_OL3_PROT_M 0x3
1104
1105#define FUN_ETH_RX_CV_VLAN_TYPE_S 3U
1106#define FUN_ETH_RX_CV_VLAN_TYPE_M 0x1
1107
1108#define FUN_ETH_RX_CV_L2_TYPE_S 2U
1109#define FUN_ETH_RX_CV_L2_TYPE_M 0x1
1110
1111enum fun_rx_cv {
1112 FUN_RX_CV_NONE = 0x0,
1113 FUN_RX_CV_IP = 0x2,
1114 FUN_RX_CV_IP6 = 0x3,
1115 FUN_RX_CV_TCP = 0x2,
1116 FUN_RX_CV_UDP = 0x3,
1117 FUN_RX_CV_VXLAN = 0x2,
1118 FUN_RX_CV_MPLS = 0x3,
1119};
1120
1121struct fun_eth_cqe {
1122 __u8 op;
1123 __u8 len8;
1124 __u8 nsgl;
1125 __u8 repr_idn;
1126 __be32 pkt_len;
1127
1128 __be64 timestamp;
1129
1130 __be16 pkt_cv;
1131 __be16 rsvd0;
1132 __be32 hash;
1133
1134 __be16 encap_proto;
1135 __be16 vlan;
1136 __be32 rsvd1;
1137
1138 __be32 buf_offset;
1139 __be16 headroom;
1140 __be16 csum;
1141};
1142
1143enum fun_admin_adi_attr {
1144 FUN_ADMIN_ADI_ATTR_MACADDR = 0x1,
1145 FUN_ADMIN_ADI_ATTR_VLAN = 0x2,
1146 FUN_ADMIN_ADI_ATTR_RATE = 0x3,
1147};
1148
1149struct fun_adi_param {
1150 union adi_param {
1151 struct fun_adi_mac {
1152 __be64 addr;
1153 } mac;
1154 struct fun_adi_vlan {
1155 __be32 rsvd;
1156 __be16 eth_type;
1157 __be16 tci;
1158 } vlan;
1159 struct fun_adi_rate {
1160 __be32 rsvd;
1161 __be32 tx_mbps;
1162 } rate;
1163 } u;
1164};
1165
1166#define FUN_ADI_MAC_INIT(_addr) \
1167 (struct fun_adi_mac) { \
1168 .addr = cpu_to_be64(_addr), \
1169 }
1170
1171#define FUN_ADI_VLAN_INIT(_eth_type, _tci) \
1172 (struct fun_adi_vlan) { \
1173 .eth_type = cpu_to_be16(_eth_type), .tci = cpu_to_be16(_tci), \
1174 }
1175
1176#define FUN_ADI_RATE_INIT(_tx_mbps) \
1177 (struct fun_adi_rate) { \
1178 .tx_mbps = cpu_to_be32(_tx_mbps), \
1179 }
1180
1181struct fun_admin_adi_req {
1182 struct fun_admin_req_common common;
1183
1184 union adi_req_subop {
1185 struct fun_admin_adi_write_req {
1186 __u8 subop;
1187 __u8 attribute;
1188 __be16 rsvd;
1189 __be32 id;
1190
1191 struct fun_adi_param param;
1192 } write;
1193 } u;
1194};
1195
1196#define FUN_ADMIN_ADI_WRITE_REQ_INIT(_subop, _attribute, _id) \
1197 (struct fun_admin_adi_write_req) { \
1198 .subop = (_subop), .attribute = (_attribute), \
1199 .id = cpu_to_be32(_id), \
1200 }
1201
1202#endif /* __FUN_HCI_H */
drivers/net/ethernet/fungible/funcore/fun_queue.c+601−0
@@ -0,0 +1,601 @@
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2
3#include <linux/dma-mapping.h>
4#include <linux/interrupt.h>
5#include <linux/log2.h>
6#include <linux/mm.h>
7#include <linux/netdevice.h>
8#include <linux/pci.h>
9#include <linux/slab.h>
10
11#include "fun_dev.h"
12#include "fun_queue.h"
13
14/* Allocate memory for a queue. This includes the memory for the HW descriptor
15 * ring, an optional 64b HW write-back area, and an optional SW state ring.
16 * Returns the virtual and DMA addresses of the HW ring, the VA of the SW ring,
17 * and the VA of the write-back area.
18 */
19void *fun_alloc_ring_mem(struct device *dma_dev, size_t depth,
20 size_t hw_desc_sz, size_t sw_desc_sz, bool wb,
21 int numa_node, dma_addr_t *dma_addr, void **sw_va,
22 volatile __be64 **wb_va)
23{
24 int dev_node = dev_to_node(dma_dev);
25 size_t dma_sz;
26 void *va;
27
28 if (numa_node == NUMA_NO_NODE)
29 numa_node = dev_node;
30
31 /* Place optional write-back area at end of descriptor ring. */
32 dma_sz = hw_desc_sz * depth;
33 if (wb)
34 dma_sz += sizeof(u64);
35
36 set_dev_node(dma_dev, numa_node);
37 va = dma_alloc_coherent(dma_dev, dma_sz, dma_addr, GFP_KERNEL);
38 set_dev_node(dma_dev, dev_node);
39 if (!va)
40 return NULL;
41
42 if (sw_desc_sz) {
43 *sw_va = kvzalloc_node(sw_desc_sz * depth, GFP_KERNEL,
44 numa_node);
45 if (!*sw_va) {
46 dma_free_coherent(dma_dev, dma_sz, va, *dma_addr);
47 return NULL;
48 }
49 }
50
51 if (wb)
52 *wb_va = va + dma_sz - sizeof(u64);
53 return va;
54}
55EXPORT_SYMBOL_GPL(fun_alloc_ring_mem);
56
57void fun_free_ring_mem(struct device *dma_dev, size_t depth, size_t hw_desc_sz,
58 bool wb, void *hw_va, dma_addr_t dma_addr, void *sw_va)
59{
60 if (hw_va) {
61 size_t sz = depth * hw_desc_sz;
62
63 if (wb)
64 sz += sizeof(u64);
65 dma_free_coherent(dma_dev, sz, hw_va, dma_addr);
66 }
67 kvfree(sw_va);
68}
69EXPORT_SYMBOL_GPL(fun_free_ring_mem);
70
71/* Prepare and issue an admin command to create an SQ on the device with the
72 * provided parameters. If the queue ID is auto-allocated by the device it is
73 * returned in *sqidp.
74 */
75int fun_sq_create(struct fun_dev *fdev, u16 flags, u32 sqid, u32 cqid,
76 u8 sqe_size_log2, u32 sq_depth, dma_addr_t dma_addr,
77 u8 coal_nentries, u8 coal_usec, u32 irq_num,
78 u32 scan_start_id, u32 scan_end_id,
79 u32 rq_buf_size_log2, u32 *sqidp, u32 __iomem **dbp)
80{
81 union {
82 struct fun_admin_epsq_req req;
83 struct fun_admin_generic_create_rsp rsp;
84 } cmd;
85 dma_addr_t wb_addr;
86 u32 hw_qid;
87 int rc;
88
89 if (sq_depth > fdev->q_depth)
90 return -EINVAL;
91 if (flags & FUN_ADMIN_EPSQ_CREATE_FLAG_RQ)
92 sqe_size_log2 = ilog2(sizeof(struct fun_eprq_rqbuf));
93
94 wb_addr = dma_addr + (sq_depth << sqe_size_log2);
95
96 cmd.req.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_EPSQ,
97 sizeof(cmd.req));
98 cmd.req.u.create =
99 FUN_ADMIN_EPSQ_CREATE_REQ_INIT(FUN_ADMIN_SUBOP_CREATE, flags,
100 sqid, cqid, sqe_size_log2,
101 sq_depth - 1, dma_addr, 0,
102 coal_nentries, coal_usec,
103 irq_num, scan_start_id,
104 scan_end_id, 0,
105 rq_buf_size_log2,
106 ilog2(sizeof(u64)), wb_addr);
107
108 rc = fun_submit_admin_sync_cmd(fdev, &cmd.req.common,
109 &cmd.rsp, sizeof(cmd.rsp), 0);
110 if (rc)
111 return rc;
112
113 hw_qid = be32_to_cpu(cmd.rsp.id);
114 *dbp = fun_sq_db_addr(fdev, hw_qid);
115 if (flags & FUN_ADMIN_RES_CREATE_FLAG_ALLOCATOR)
116 *sqidp = hw_qid;
117 return rc;
118}
119EXPORT_SYMBOL_GPL(fun_sq_create);
120
121/* Prepare and issue an admin command to create a CQ on the device with the
122 * provided parameters. If the queue ID is auto-allocated by the device it is
123 * returned in *cqidp.
124 */
125int fun_cq_create(struct fun_dev *fdev, u16 flags, u32 cqid, u32 rqid,
126 u8 cqe_size_log2, u32 cq_depth, dma_addr_t dma_addr,
127 u16 headroom, u16 tailroom, u8 coal_nentries, u8 coal_usec,
128 u32 irq_num, u32 scan_start_id, u32 scan_end_id, u32 *cqidp,
129 u32 __iomem **dbp)
130{
131 union {
132 struct fun_admin_epcq_req req;
133 struct fun_admin_generic_create_rsp rsp;
134 } cmd;
135 u32 hw_qid;
136 int rc;
137
138 if (cq_depth > fdev->q_depth)
139 return -EINVAL;
140
141 cmd.req.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_EPCQ,
142 sizeof(cmd.req));
143 cmd.req.u.create =
144 FUN_ADMIN_EPCQ_CREATE_REQ_INIT(FUN_ADMIN_SUBOP_CREATE, flags,
145 cqid, rqid, cqe_size_log2,
146 cq_depth - 1, dma_addr, tailroom,
147 headroom / 2, 0, coal_nentries,
148 coal_usec, irq_num,
149 scan_start_id, scan_end_id, 0);
150
151 rc = fun_submit_admin_sync_cmd(fdev, &cmd.req.common,
152 &cmd.rsp, sizeof(cmd.rsp), 0);
153 if (rc)
154 return rc;
155
156 hw_qid = be32_to_cpu(cmd.rsp.id);
157 *dbp = fun_cq_db_addr(fdev, hw_qid);
158 if (flags & FUN_ADMIN_RES_CREATE_FLAG_ALLOCATOR)
159 *cqidp = hw_qid;
160 return rc;
161}
162EXPORT_SYMBOL_GPL(fun_cq_create);
163
164static bool fun_sq_is_head_wb(const struct fun_queue *funq)
165{
166 return funq->sq_flags & FUN_ADMIN_EPSQ_CREATE_FLAG_HEAD_WB_ADDRESS;
167}
168
169static void fun_clean_rq(struct fun_queue *funq)
170{
171 struct fun_dev *fdev = funq->fdev;
172 struct fun_rq_info *rqinfo;
173 unsigned int i;
174
175 for (i = 0; i < funq->rq_depth; i++) {
176 rqinfo = &funq->rq_info[i];
177 if (rqinfo->page) {
178 dma_unmap_page(fdev->dev, rqinfo->dma, PAGE_SIZE,
179 DMA_FROM_DEVICE);
180 put_page(rqinfo->page);
181 rqinfo->page = NULL;
182 }
183 }
184}
185
186static int fun_fill_rq(struct fun_queue *funq)
187{
188 struct device *dev = funq->fdev->dev;
189 int i, node = dev_to_node(dev);
190 struct fun_rq_info *rqinfo;
191
192 for (i = 0; i < funq->rq_depth; i++) {
193 rqinfo = &funq->rq_info[i];
194 rqinfo->page = alloc_pages_node(node, GFP_KERNEL, 0);
195 if (unlikely(!rqinfo->page))
196 return -ENOMEM;
197
198 rqinfo->dma = dma_map_page(dev, rqinfo->page, 0,
199 PAGE_SIZE, DMA_FROM_DEVICE);
200 if (unlikely(dma_mapping_error(dev, rqinfo->dma))) {
201 put_page(rqinfo->page);
202 rqinfo->page = NULL;
203 return -ENOMEM;
204 }
205
206 funq->rqes[i] = FUN_EPRQ_RQBUF_INIT(rqinfo->dma);
207 }
208
209 funq->rq_tail = funq->rq_depth - 1;
210 return 0;
211}
212
213static void fun_rq_update_pos(struct fun_queue *funq, int buf_offset)
214{
215 if (buf_offset <= funq->rq_buf_offset) {
216 struct fun_rq_info *rqinfo = &funq->rq_info[funq->rq_buf_idx];
217 struct device *dev = funq->fdev->dev;
218
219 dma_sync_single_for_device(dev, rqinfo->dma, PAGE_SIZE,
220 DMA_FROM_DEVICE);
221 funq->num_rqe_to_fill++;
222 if (++funq->rq_buf_idx == funq->rq_depth)
223 funq->rq_buf_idx = 0;
224 }
225 funq->rq_buf_offset = buf_offset;
226}
227
228/* Given a command response with data scattered across >= 1 RQ buffers return
229 * a pointer to a contiguous buffer containing all the data. If the data is in
230 * one RQ buffer the start address within that buffer is returned, otherwise a
231 * new buffer is allocated and the data is gathered into it.
232 */
233static void *fun_data_from_rq(struct fun_queue *funq,
234 const struct fun_rsp_common *rsp, bool *need_free)
235{
236 u32 bufoff, total_len, remaining, fragsize, dataoff;
237 struct device *dma_dev = funq->fdev->dev;
238 const struct fun_dataop_rqbuf *databuf;
239 const struct fun_dataop_hdr *dataop;
240 const struct fun_rq_info *rqinfo;
241 void *data;
242
243 dataop = (void *)rsp + rsp->suboff8 * 8;
244 total_len = be32_to_cpu(dataop->total_len);
245
246 if (likely(dataop->nsgl == 1)) {
247 databuf = (struct fun_dataop_rqbuf *)dataop->imm;
248 bufoff = be32_to_cpu(databuf->bufoff);
249 fun_rq_update_pos(funq, bufoff);
250 rqinfo = &funq->rq_info[funq->rq_buf_idx];
251 dma_sync_single_for_cpu(dma_dev, rqinfo->dma + bufoff,
252 total_len, DMA_FROM_DEVICE);
253 *need_free = false;
254 return page_address(rqinfo->page) + bufoff;
255 }
256
257 /* For scattered completions gather the fragments into one buffer. */
258
259 data = kmalloc(total_len, GFP_ATOMIC);
260 /* NULL is OK here. In case of failure we still need to consume the data
261 * for proper buffer accounting but indicate an error in the response.
262 */
263 if (likely(data))
264 *need_free = true;
265
266 dataoff = 0;
267 for (remaining = total_len; remaining; remaining -= fragsize) {
268 fun_rq_update_pos(funq, 0);
269 fragsize = min_t(unsigned int, PAGE_SIZE, remaining);
270 if (data) {
271 rqinfo = &funq->rq_info[funq->rq_buf_idx];
272 dma_sync_single_for_cpu(dma_dev, rqinfo->dma, fragsize,
273 DMA_FROM_DEVICE);
274 memcpy(data + dataoff, page_address(rqinfo->page),
275 fragsize);
276 dataoff += fragsize;
277 }
278 }
279 return data;
280}
281
282unsigned int __fun_process_cq(struct fun_queue *funq, unsigned int max)
283{
284 const struct fun_cqe_info *info;
285 struct fun_rsp_common *rsp;
286 unsigned int new_cqes;
287 u16 sf_p, flags;
288 bool need_free;
289 void *cqe;
290
291 if (!max)
292 max = funq->cq_depth - 1;
293
294 for (new_cqes = 0; new_cqes < max; new_cqes++) {
295 cqe = funq->cqes + (funq->cq_head << funq->cqe_size_log2);
296 info = funq_cqe_info(funq, cqe);
297 sf_p = be16_to_cpu(info->sf_p);
298
299 if ((sf_p & 1) != funq->cq_phase)
300 break;
301
302 /* ensure the phase tag is read before other CQE fields */
303 dma_rmb();
304
305 if (++funq->cq_head == funq->cq_depth) {
306 funq->cq_head = 0;
307 funq->cq_phase = !funq->cq_phase;
308 }
309
310 rsp = cqe;
311 flags = be16_to_cpu(rsp->flags);
312
313 need_free = false;
314 if (unlikely(flags & FUN_REQ_COMMON_FLAG_CQE_IN_RQBUF)) {
315 rsp = fun_data_from_rq(funq, rsp, &need_free);
316 if (!rsp) {
317 rsp = cqe;
318 rsp->len8 = 1;
319 if (rsp->ret == 0)
320 rsp->ret = ENOMEM;
321 }
322 }
323
324 if (funq->cq_cb)
325 funq->cq_cb(funq, funq->cb_data, rsp, info);
326 if (need_free)
327 kfree(rsp);
328 }
329
330 dev_dbg(funq->fdev->dev, "CQ %u, new CQEs %u/%u, head %u, phase %u\n",
331 funq->cqid, new_cqes, max, funq->cq_head, funq->cq_phase);
332 return new_cqes;
333}
334
335unsigned int fun_process_cq(struct fun_queue *funq, unsigned int max)
336{
337 unsigned int processed;
338 u32 db;
339
340 processed = __fun_process_cq(funq, max);
341
342 if (funq->num_rqe_to_fill) {
343 funq->rq_tail = (funq->rq_tail + funq->num_rqe_to_fill) %
344 funq->rq_depth;
345 funq->num_rqe_to_fill = 0;
346 writel(funq->rq_tail, funq->rq_db);
347 }
348
349 db = funq->cq_head | FUN_DB_IRQ_ARM_F;
350 writel(db, funq->cq_db);
351 return processed;
352}
353
354static int fun_alloc_sqes(struct fun_queue *funq)
355{
356 funq->sq_cmds = fun_alloc_ring_mem(funq->fdev->dev, funq->sq_depth,
357 1 << funq->sqe_size_log2, 0,
358 fun_sq_is_head_wb(funq),
359 NUMA_NO_NODE, &funq->sq_dma_addr,
360 NULL, &funq->sq_head);
361 return funq->sq_cmds ? 0 : -ENOMEM;
362}
363
364static int fun_alloc_cqes(struct fun_queue *funq)
365{
366 funq->cqes = fun_alloc_ring_mem(funq->fdev->dev, funq->cq_depth,
367 1 << funq->cqe_size_log2, 0, false,
368 NUMA_NO_NODE, &funq->cq_dma_addr, NULL,
369 NULL);
370 return funq->cqes ? 0 : -ENOMEM;
371}
372
373static int fun_alloc_rqes(struct fun_queue *funq)
374{
375 funq->rqes = fun_alloc_ring_mem(funq->fdev->dev, funq->rq_depth,
376 sizeof(*funq->rqes),
377 sizeof(*funq->rq_info), false,
378 NUMA_NO_NODE, &funq->rq_dma_addr,
379 (void **)&funq->rq_info, NULL);
380 return funq->rqes ? 0 : -ENOMEM;
381}
382
383/* Free a queue's structures. */
384void fun_free_queue(struct fun_queue *funq)
385{
386 struct device *dev = funq->fdev->dev;
387
388 fun_free_ring_mem(dev, funq->cq_depth, 1 << funq->cqe_size_log2, false,
389 funq->cqes, funq->cq_dma_addr, NULL);
390 fun_free_ring_mem(dev, funq->sq_depth, 1 << funq->sqe_size_log2,
391 fun_sq_is_head_wb(funq), funq->sq_cmds,
392 funq->sq_dma_addr, NULL);
393
394 if (funq->rqes) {
395 fun_clean_rq(funq);
396 fun_free_ring_mem(dev, funq->rq_depth, sizeof(*funq->rqes),
397 false, funq->rqes, funq->rq_dma_addr,
398 funq->rq_info);
399 }
400
401 kfree(funq);
402}
403
404/* Allocate and initialize a funq's structures. */
405struct fun_queue *fun_alloc_queue(struct fun_dev *fdev, int qid,
406 const struct fun_queue_alloc_req *req)
407{
408 struct fun_queue *funq = kzalloc(sizeof(*funq), GFP_KERNEL);
409
410 if (!funq)
411 return NULL;
412
413 funq->fdev = fdev;
414 spin_lock_init(&funq->sq_lock);
415
416 funq->qid = qid;
417
418 /* Initial CQ/SQ/RQ ids */
419 if (req->rq_depth) {
420 funq->cqid = 2 * qid;
421 if (funq->qid) {
422 /* I/O Q: use rqid = cqid, sqid = +1 */
423 funq->rqid = funq->cqid;
424 funq->sqid = funq->rqid + 1;
425 } else {
426 /* Admin Q: sqid is always 0, use ID 1 for RQ */
427 funq->sqid = 0;
428 funq->rqid = 1;
429 }
430 } else {
431 funq->cqid = qid;
432 funq->sqid = qid;
433 }
434
435 funq->cq_flags = req->cq_flags;
436 funq->sq_flags = req->sq_flags;
437
438 funq->cqe_size_log2 = req->cqe_size_log2;
439 funq->sqe_size_log2 = req->sqe_size_log2;
440
441 funq->cq_depth = req->cq_depth;
442 funq->sq_depth = req->sq_depth;
443
444 funq->cq_intcoal_nentries = req->cq_intcoal_nentries;
445 funq->cq_intcoal_usec = req->cq_intcoal_usec;
446
447 funq->sq_intcoal_nentries = req->sq_intcoal_nentries;
448 funq->sq_intcoal_usec = req->sq_intcoal_usec;
449
450 if (fun_alloc_cqes(funq))
451 goto free_funq;
452
453 funq->cq_phase = 1;
454
455 if (fun_alloc_sqes(funq))
456 goto free_funq;
457
458 if (req->rq_depth) {
459 funq->rq_flags = req->rq_flags | FUN_ADMIN_EPSQ_CREATE_FLAG_RQ;
460 funq->rq_depth = req->rq_depth;
461 funq->rq_buf_offset = -1;
462
463 if (fun_alloc_rqes(funq) || fun_fill_rq(funq))
464 goto free_funq;
465 }
466
467 funq->cq_vector = -1;
468 funq->cqe_info_offset = (1 << funq->cqe_size_log2) - sizeof(struct fun_cqe_info);
469
470 /* SQ/CQ 0 are implicitly created, assign their doorbells now.
471 * Other queues are assigned doorbells at their explicit creation.
472 */
473 if (funq->sqid == 0)
474 funq->sq_db = fun_sq_db_addr(fdev, 0);
475 if (funq->cqid == 0)
476 funq->cq_db = fun_cq_db_addr(fdev, 0);
477
478 return funq;
479
480free_funq:
481 fun_free_queue(funq);
482 return NULL;
483}
484
485/* Create a funq's CQ on the device. */
486static int fun_create_cq(struct fun_queue *funq)
487{
488 struct fun_dev *fdev = funq->fdev;
489 unsigned int rqid;
490 int rc;
491
492 rqid = funq->cq_flags & FUN_ADMIN_EPCQ_CREATE_FLAG_RQ ?
493 funq->rqid : FUN_HCI_ID_INVALID;
494 rc = fun_cq_create(fdev, funq->cq_flags, funq->cqid, rqid,
495 funq->cqe_size_log2, funq->cq_depth,
496 funq->cq_dma_addr, 0, 0, funq->cq_intcoal_nentries,
497 funq->cq_intcoal_usec, funq->cq_vector, 0, 0,
498 &funq->cqid, &funq->cq_db);
499 if (!rc)
500 dev_dbg(fdev->dev, "created CQ %u\n", funq->cqid);
501
502 return rc;
503}
504
505/* Create a funq's SQ on the device. */
506static int fun_create_sq(struct fun_queue *funq)
507{
508 struct fun_dev *fdev = funq->fdev;
509 int rc;
510
511 rc = fun_sq_create(fdev, funq->sq_flags, funq->sqid, funq->cqid,
512 funq->sqe_size_log2, funq->sq_depth,
513 funq->sq_dma_addr, funq->sq_intcoal_nentries,
514 funq->sq_intcoal_usec, funq->cq_vector, 0, 0,
515 0, &funq->sqid, &funq->sq_db);
516 if (!rc)
517 dev_dbg(fdev->dev, "created SQ %u\n", funq->sqid);
518
519 return rc;
520}
521
522/* Create a funq's RQ on the device. */
523int fun_create_rq(struct fun_queue *funq)
524{
525 struct fun_dev *fdev = funq->fdev;
526 int rc;
527
528 rc = fun_sq_create(fdev, funq->rq_flags, funq->rqid, funq->cqid, 0,
529 funq->rq_depth, funq->rq_dma_addr, 0, 0,
530 funq->cq_vector, 0, 0, PAGE_SHIFT, &funq->rqid,
531 &funq->rq_db);
532 if (!rc)
533 dev_dbg(fdev->dev, "created RQ %u\n", funq->rqid);
534
535 return rc;
536}
537
538static unsigned int funq_irq(struct fun_queue *funq)
539{
540 return pci_irq_vector(to_pci_dev(funq->fdev->dev), funq->cq_vector);
541}
542
543int fun_request_irq(struct fun_queue *funq, const char *devname,
544 irq_handler_t handler, void *data)
545{
546 int rc;
547
548 if (funq->cq_vector < 0)
549 return -EINVAL;
550
551 funq->irq_handler = handler;
552 funq->irq_data = data;
553
554 snprintf(funq->irqname, sizeof(funq->irqname),
555 funq->qid ? "%s-q[%d]" : "%s-adminq", devname, funq->qid);
556
557 rc = request_irq(funq_irq(funq), handler, 0, funq->irqname, data);
558 if (rc)
559 funq->irq_handler = NULL;
560
561 return rc;
562}
563
564/* Create all component queues of a funq on the device. */
565int fun_create_queue(struct fun_queue *funq)
566{
567 int rc;
568
569 rc = fun_create_cq(funq);
570 if (rc)
571 return rc;
572
573 if (funq->rq_depth) {
574 rc = fun_create_rq(funq);
575 if (rc)
576 goto release_cq;
577 }
578
579 rc = fun_create_sq(funq);
580 if (rc)
581 goto release_rq;
582
583 return 0;
584
585release_rq:
586 fun_destroy_sq(funq->fdev, funq->rqid);
587release_cq:
588 fun_destroy_cq(funq->fdev, funq->cqid);
589 return rc;
590}
591
592void fun_free_irq(struct fun_queue *funq)
593{
594 if (funq->irq_handler) {
595 unsigned int vector = funq_irq(funq);
596
597 free_irq(vector, funq->irq_data);
598 funq->irq_handler = NULL;
599 funq->irq_data = NULL;
600 }
601}
drivers/net/ethernet/fungible/funcore/fun_queue.h+175−0
@@ -0,0 +1,175 @@
1/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2
3#ifndef _FUN_QEUEUE_H
4#define _FUN_QEUEUE_H
5
6#include <linux/interrupt.h>
7#include <linux/io.h>
8
9struct device;
10struct fun_dev;
11struct fun_queue;
12struct fun_cqe_info;
13struct fun_rsp_common;
14
15typedef void (*cq_callback_t)(struct fun_queue *funq, void *data, void *msg,
16 const struct fun_cqe_info *info);
17
18struct fun_rq_info {
19 dma_addr_t dma;
20 struct page *page;
21};
22
23/* A queue group consisting of an SQ, a CQ, and an optional RQ. */
24struct fun_queue {
25 struct fun_dev *fdev;
26 spinlock_t sq_lock;
27
28 dma_addr_t cq_dma_addr;
29 dma_addr_t sq_dma_addr;
30 dma_addr_t rq_dma_addr;
31
32 u32 __iomem *cq_db;
33 u32 __iomem *sq_db;
34 u32 __iomem *rq_db;
35
36 void *cqes;
37 void *sq_cmds;
38 struct fun_eprq_rqbuf *rqes;
39 struct fun_rq_info *rq_info;
40
41 u32 cqid;
42 u32 sqid;
43 u32 rqid;
44
45 u32 cq_depth;
46 u32 sq_depth;
47 u32 rq_depth;
48
49 u16 cq_head;
50 u16 sq_tail;
51 u16 rq_tail;
52
53 u8 cqe_size_log2;
54 u8 sqe_size_log2;
55
56 u16 cqe_info_offset;
57
58 u16 rq_buf_idx;
59 int rq_buf_offset;
60 u16 num_rqe_to_fill;
61
62 u8 cq_intcoal_usec;
63 u8 cq_intcoal_nentries;
64 u8 sq_intcoal_usec;
65 u8 sq_intcoal_nentries;
66
67 u16 cq_flags;
68 u16 sq_flags;
69 u16 rq_flags;
70
71 /* SQ head writeback */
72 u16 sq_comp;
73
74 volatile __be64 *sq_head;
75
76 cq_callback_t cq_cb;
77 void *cb_data;
78
79 irq_handler_t irq_handler;
80 void *irq_data;
81 s16 cq_vector;
82 u8 cq_phase;
83
84 /* I/O q index */
85 u16 qid;
86
87 char irqname[24];
88};
89
90static inline void *fun_sqe_at(const struct fun_queue *funq, unsigned int pos)
91{
92 return funq->sq_cmds + (pos << funq->sqe_size_log2);
93}
94
95static inline void funq_sq_post_tail(struct fun_queue *funq, u16 tail)
96{
97 if (++tail == funq->sq_depth)
98 tail = 0;
99 funq->sq_tail = tail;
100 writel(tail, funq->sq_db);
101}
102
103static inline struct fun_cqe_info *funq_cqe_info(const struct fun_queue *funq,
104 void *cqe)
105{
106 return cqe + funq->cqe_info_offset;
107}
108
109static inline void funq_rq_post(struct fun_queue *funq)
110{
111 writel(funq->rq_tail, funq->rq_db);
112}
113
114struct fun_queue_alloc_req {
115 u8 cqe_size_log2;
116 u8 sqe_size_log2;
117
118 u16 cq_flags;
119 u16 sq_flags;
120 u16 rq_flags;
121
122 u32 cq_depth;
123 u32 sq_depth;
124 u32 rq_depth;
125
126 u8 cq_intcoal_usec;
127 u8 cq_intcoal_nentries;
128 u8 sq_intcoal_usec;
129 u8 sq_intcoal_nentries;
130};
131
132int fun_sq_create(struct fun_dev *fdev, u16 flags, u32 sqid, u32 cqid,
133 u8 sqe_size_log2, u32 sq_depth, dma_addr_t dma_addr,
134 u8 coal_nentries, u8 coal_usec, u32 irq_num,
135 u32 scan_start_id, u32 scan_end_id,
136 u32 rq_buf_size_log2, u32 *sqidp, u32 __iomem **dbp);
137int fun_cq_create(struct fun_dev *fdev, u16 flags, u32 cqid, u32 rqid,
138 u8 cqe_size_log2, u32 cq_depth, dma_addr_t dma_addr,
139 u16 headroom, u16 tailroom, u8 coal_nentries, u8 coal_usec,
140 u32 irq_num, u32 scan_start_id, u32 scan_end_id,
141 u32 *cqidp, u32 __iomem **dbp);
142void *fun_alloc_ring_mem(struct device *dma_dev, size_t depth,
143 size_t hw_desc_sz, size_t sw_desc_size, bool wb,
144 int numa_node, dma_addr_t *dma_addr, void **sw_va,
145 volatile __be64 **wb_va);
146void fun_free_ring_mem(struct device *dma_dev, size_t depth, size_t hw_desc_sz,
147 bool wb, void *hw_va, dma_addr_t dma_addr, void *sw_va);
148
149#define fun_destroy_sq(fdev, sqid) \
150 fun_res_destroy((fdev), FUN_ADMIN_OP_EPSQ, 0, (sqid))
151#define fun_destroy_cq(fdev, cqid) \
152 fun_res_destroy((fdev), FUN_ADMIN_OP_EPCQ, 0, (cqid))
153
154struct fun_queue *fun_alloc_queue(struct fun_dev *fdev, int qid,
155 const struct fun_queue_alloc_req *req);
156void fun_free_queue(struct fun_queue *funq);
157
158static inline void fun_set_cq_callback(struct fun_queue *funq, cq_callback_t cb,
159 void *cb_data)
160{
161 funq->cq_cb = cb;
162 funq->cb_data = cb_data;
163}
164
165int fun_create_rq(struct fun_queue *funq);
166int fun_create_queue(struct fun_queue *funq);
167
168void fun_free_irq(struct fun_queue *funq);
169int fun_request_irq(struct fun_queue *funq, const char *devname,
170 irq_handler_t handler, void *data);
171
172unsigned int __fun_process_cq(struct fun_queue *funq, unsigned int max);
173unsigned int fun_process_cq(struct fun_queue *funq, unsigned int max);
174
175#endif /* _FUN_QEUEUE_H */