.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
---|
2 | 2 | /* |
---|
3 | 3 | * Copyright 2014-2016 Freescale Semiconductor Inc. |
---|
4 | | - * Copyright 2016 NXP |
---|
| 4 | + * Copyright 2016-2019 NXP |
---|
5 | 5 | * |
---|
6 | 6 | */ |
---|
7 | 7 | #include <linux/types.h> |
---|
.. | .. |
---|
27 | 27 | /* protect notifications list */ |
---|
28 | 28 | spinlock_t lock_notifications; |
---|
29 | 29 | struct list_head notifications; |
---|
| 30 | + struct device *dev; |
---|
30 | 31 | }; |
---|
31 | 32 | |
---|
32 | 33 | struct dpaa2_io_store { |
---|
.. | .. |
---|
57 | 58 | * If cpu == -1, choose the current cpu, with no guarantees about |
---|
58 | 59 | * potentially being migrated away. |
---|
59 | 60 | */ |
---|
60 | | - if (unlikely(cpu < 0)) |
---|
61 | | - cpu = smp_processor_id(); |
---|
| 61 | + if (cpu < 0) |
---|
| 62 | + cpu = raw_smp_processor_id(); |
---|
62 | 63 | |
---|
63 | 64 | /* If a specific cpu was requested, pick it up immediately */ |
---|
64 | 65 | return dpio_by_cpu[cpu]; |
---|
.. | .. |
---|
66 | 67 | |
---|
67 | 68 | static inline struct dpaa2_io *service_select(struct dpaa2_io *d) |
---|
68 | 69 | { |
---|
| 70 | + if (d) |
---|
| 71 | + return d; |
---|
| 72 | + |
---|
| 73 | + d = service_select_by_cpu(d, -1); |
---|
69 | 74 | if (d) |
---|
70 | 75 | return d; |
---|
71 | 76 | |
---|
.. | .. |
---|
98 | 103 | /** |
---|
99 | 104 | * dpaa2_io_create() - create a dpaa2_io object. |
---|
100 | 105 | * @desc: the dpaa2_io descriptor |
---|
| 106 | + * @dev: the actual DPIO device |
---|
101 | 107 | * |
---|
102 | 108 | * Activates a "struct dpaa2_io" corresponding to the given config of an actual |
---|
103 | 109 | * DPIO object. |
---|
104 | 110 | * |
---|
105 | 111 | * Return a valid dpaa2_io object for success, or NULL for failure. |
---|
106 | 112 | */ |
---|
107 | | -struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) |
---|
| 113 | +struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc, |
---|
| 114 | + struct device *dev) |
---|
108 | 115 | { |
---|
109 | 116 | struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL); |
---|
110 | 117 | |
---|
.. | .. |
---|
146 | 153 | dpio_by_cpu[desc->cpu] = obj; |
---|
147 | 154 | spin_unlock(&dpio_list_lock); |
---|
148 | 155 | |
---|
| 156 | + obj->dev = dev; |
---|
| 157 | + |
---|
149 | 158 | return obj; |
---|
150 | 159 | } |
---|
151 | 160 | |
---|
.. | .. |
---|
160 | 169 | */ |
---|
161 | 170 | void dpaa2_io_down(struct dpaa2_io *d) |
---|
162 | 171 | { |
---|
| 172 | + spin_lock(&dpio_list_lock); |
---|
| 173 | + dpio_by_cpu[d->dpio_desc.cpu] = NULL; |
---|
| 174 | + list_del(&d->node); |
---|
| 175 | + spin_unlock(&dpio_list_lock); |
---|
| 176 | + |
---|
163 | 177 | kfree(d); |
---|
164 | 178 | } |
---|
165 | 179 | |
---|
.. | .. |
---|
210 | 224 | } |
---|
211 | 225 | |
---|
212 | 226 | /** |
---|
| 227 | + * dpaa2_io_get_cpu() - get the cpu associated with a given DPIO object |
---|
| 228 | + * |
---|
| 229 | + * @d: the given DPIO object. |
---|
| 230 | + * |
---|
| 231 | + * Return the cpu associated with the DPIO object |
---|
| 232 | + */ |
---|
| 233 | +int dpaa2_io_get_cpu(struct dpaa2_io *d) |
---|
| 234 | +{ |
---|
| 235 | + return d->dpio_desc.cpu; |
---|
| 236 | +} |
---|
| 237 | +EXPORT_SYMBOL(dpaa2_io_get_cpu); |
---|
| 238 | + |
---|
| 239 | +/** |
---|
213 | 240 | * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN |
---|
214 | 241 | * notifications on the given DPIO service. |
---|
215 | 242 | * @d: the given DPIO service. |
---|
216 | 243 | * @ctx: the notification context. |
---|
| 244 | + * @dev: the device that requests the register |
---|
217 | 245 | * |
---|
218 | 246 | * The caller should make the MC command to attach a DPAA2 object to |
---|
219 | 247 | * a DPIO after this function completes successfully. In that way: |
---|
.. | .. |
---|
228 | 256 | * Return 0 for success, or -ENODEV for failure. |
---|
229 | 257 | */ |
---|
230 | 258 | int dpaa2_io_service_register(struct dpaa2_io *d, |
---|
231 | | - struct dpaa2_io_notification_ctx *ctx) |
---|
| 259 | + struct dpaa2_io_notification_ctx *ctx, |
---|
| 260 | + struct device *dev) |
---|
232 | 261 | { |
---|
| 262 | + struct device_link *link; |
---|
233 | 263 | unsigned long irqflags; |
---|
234 | 264 | |
---|
235 | 265 | d = service_select_by_cpu(d, ctx->desired_cpu); |
---|
236 | 266 | if (!d) |
---|
237 | 267 | return -ENODEV; |
---|
| 268 | + |
---|
| 269 | + link = device_link_add(dev, d->dev, DL_FLAG_AUTOREMOVE_CONSUMER); |
---|
| 270 | + if (!link) |
---|
| 271 | + return -EINVAL; |
---|
238 | 272 | |
---|
239 | 273 | ctx->dpio_id = d->dpio_desc.dpio_id; |
---|
240 | 274 | ctx->qman64 = (u64)(uintptr_t)ctx; |
---|
.. | .. |
---|
256 | 290 | * dpaa2_io_service_deregister - The opposite of 'register'. |
---|
257 | 291 | * @service: the given DPIO service. |
---|
258 | 292 | * @ctx: the notification context. |
---|
| 293 | + * @dev: the device that requests to be deregistered |
---|
259 | 294 | * |
---|
260 | 295 | * This function should be called only after sending the MC command to |
---|
261 | 296 | * to detach the notification-producing device from the DPIO. |
---|
262 | 297 | */ |
---|
263 | 298 | void dpaa2_io_service_deregister(struct dpaa2_io *service, |
---|
264 | | - struct dpaa2_io_notification_ctx *ctx) |
---|
| 299 | + struct dpaa2_io_notification_ctx *ctx, |
---|
| 300 | + struct device *dev) |
---|
265 | 301 | { |
---|
266 | 302 | struct dpaa2_io *d = ctx->dpio_private; |
---|
267 | 303 | unsigned long irqflags; |
---|
.. | .. |
---|
272 | 308 | spin_lock_irqsave(&d->lock_notifications, irqflags); |
---|
273 | 309 | list_del(&ctx->node); |
---|
274 | 310 | spin_unlock_irqrestore(&d->lock_notifications, irqflags); |
---|
| 311 | + |
---|
275 | 312 | } |
---|
276 | 313 | EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); |
---|
277 | 314 | |
---|
.. | .. |
---|
310 | 347 | EXPORT_SYMBOL_GPL(dpaa2_io_service_rearm); |
---|
311 | 348 | |
---|
312 | 349 | /** |
---|
| 350 | + * dpaa2_io_service_pull_fq() - pull dequeue functions from a fq. |
---|
| 351 | + * @d: the given DPIO service. |
---|
| 352 | + * @fqid: the given frame queue id. |
---|
| 353 | + * @s: the dpaa2_io_store object for the result. |
---|
| 354 | + * |
---|
| 355 | + * Return 0 for success, or error code for failure. |
---|
| 356 | + */ |
---|
| 357 | +int dpaa2_io_service_pull_fq(struct dpaa2_io *d, u32 fqid, |
---|
| 358 | + struct dpaa2_io_store *s) |
---|
| 359 | +{ |
---|
| 360 | + struct qbman_pull_desc pd; |
---|
| 361 | + int err; |
---|
| 362 | + |
---|
| 363 | + qbman_pull_desc_clear(&pd); |
---|
| 364 | + qbman_pull_desc_set_storage(&pd, s->vaddr, s->paddr, 1); |
---|
| 365 | + qbman_pull_desc_set_numframes(&pd, (u8)s->max); |
---|
| 366 | + qbman_pull_desc_set_fq(&pd, fqid); |
---|
| 367 | + |
---|
| 368 | + d = service_select(d); |
---|
| 369 | + if (!d) |
---|
| 370 | + return -ENODEV; |
---|
| 371 | + s->swp = d->swp; |
---|
| 372 | + err = qbman_swp_pull(d->swp, &pd); |
---|
| 373 | + if (err) |
---|
| 374 | + s->swp = NULL; |
---|
| 375 | + |
---|
| 376 | + return err; |
---|
| 377 | +} |
---|
| 378 | +EXPORT_SYMBOL(dpaa2_io_service_pull_fq); |
---|
| 379 | + |
---|
| 380 | +/** |
---|
313 | 381 | * dpaa2_io_service_pull_channel() - pull dequeue functions from a channel. |
---|
314 | 382 | * @d: the given DPIO service. |
---|
315 | 383 | * @channelid: the given channel id. |
---|
.. | .. |
---|
340 | 408 | return err; |
---|
341 | 409 | } |
---|
342 | 410 | EXPORT_SYMBOL_GPL(dpaa2_io_service_pull_channel); |
---|
| 411 | + |
---|
| 412 | +/** |
---|
| 413 | + * dpaa2_io_service_enqueue_fq() - Enqueue a frame to a frame queue. |
---|
| 414 | + * @d: the given DPIO service. |
---|
| 415 | + * @fqid: the given frame queue id. |
---|
| 416 | + * @fd: the frame descriptor which is enqueued. |
---|
| 417 | + * |
---|
| 418 | + * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, |
---|
| 419 | + * or -ENODEV if there is no dpio service. |
---|
| 420 | + */ |
---|
| 421 | +int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, |
---|
| 422 | + u32 fqid, |
---|
| 423 | + const struct dpaa2_fd *fd) |
---|
| 424 | +{ |
---|
| 425 | + struct qbman_eq_desc ed; |
---|
| 426 | + |
---|
| 427 | + d = service_select(d); |
---|
| 428 | + if (!d) |
---|
| 429 | + return -ENODEV; |
---|
| 430 | + |
---|
| 431 | + qbman_eq_desc_clear(&ed); |
---|
| 432 | + qbman_eq_desc_set_no_orp(&ed, 0); |
---|
| 433 | + qbman_eq_desc_set_fq(&ed, fqid); |
---|
| 434 | + |
---|
| 435 | + return qbman_swp_enqueue(d->swp, &ed, fd); |
---|
| 436 | +} |
---|
| 437 | +EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq); |
---|
| 438 | + |
---|
| 439 | +/** |
---|
| 440 | + * dpaa2_io_service_enqueue_multiple_fq() - Enqueue multiple frames |
---|
| 441 | + * to a frame queue using one fqid. |
---|
| 442 | + * @d: the given DPIO service. |
---|
| 443 | + * @fqid: the given frame queue id. |
---|
| 444 | + * @fd: the frame descriptor which is enqueued. |
---|
| 445 | + * @nb: number of frames to be enqueud |
---|
| 446 | + * |
---|
| 447 | + * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, |
---|
| 448 | + * or -ENODEV if there is no dpio service. |
---|
| 449 | + */ |
---|
| 450 | +int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d, |
---|
| 451 | + u32 fqid, |
---|
| 452 | + const struct dpaa2_fd *fd, |
---|
| 453 | + int nb) |
---|
| 454 | +{ |
---|
| 455 | + struct qbman_eq_desc ed; |
---|
| 456 | + |
---|
| 457 | + d = service_select(d); |
---|
| 458 | + if (!d) |
---|
| 459 | + return -ENODEV; |
---|
| 460 | + |
---|
| 461 | + qbman_eq_desc_clear(&ed); |
---|
| 462 | + qbman_eq_desc_set_no_orp(&ed, 0); |
---|
| 463 | + qbman_eq_desc_set_fq(&ed, fqid); |
---|
| 464 | + |
---|
| 465 | + return qbman_swp_enqueue_multiple(d->swp, &ed, fd, 0, nb); |
---|
| 466 | +} |
---|
| 467 | +EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_fq); |
---|
| 468 | + |
---|
| 469 | +/** |
---|
| 470 | + * dpaa2_io_service_enqueue_multiple_desc_fq() - Enqueue multiple frames |
---|
| 471 | + * to different frame queue using a list of fqids. |
---|
| 472 | + * @d: the given DPIO service. |
---|
| 473 | + * @fqid: the given list of frame queue ids. |
---|
| 474 | + * @fd: the frame descriptor which is enqueued. |
---|
| 475 | + * @nb: number of frames to be enqueud |
---|
| 476 | + * |
---|
| 477 | + * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready, |
---|
| 478 | + * or -ENODEV if there is no dpio service. |
---|
| 479 | + */ |
---|
| 480 | +int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d, |
---|
| 481 | + u32 *fqid, |
---|
| 482 | + const struct dpaa2_fd *fd, |
---|
| 483 | + int nb) |
---|
| 484 | +{ |
---|
| 485 | + struct qbman_eq_desc *ed; |
---|
| 486 | + int i, ret; |
---|
| 487 | + |
---|
| 488 | + ed = kcalloc(sizeof(struct qbman_eq_desc), 32, GFP_KERNEL); |
---|
| 489 | + if (!ed) |
---|
| 490 | + return -ENOMEM; |
---|
| 491 | + |
---|
| 492 | + d = service_select(d); |
---|
| 493 | + if (!d) { |
---|
| 494 | + ret = -ENODEV; |
---|
| 495 | + goto out; |
---|
| 496 | + } |
---|
| 497 | + |
---|
| 498 | + for (i = 0; i < nb; i++) { |
---|
| 499 | + qbman_eq_desc_clear(&ed[i]); |
---|
| 500 | + qbman_eq_desc_set_no_orp(&ed[i], 0); |
---|
| 501 | + qbman_eq_desc_set_fq(&ed[i], fqid[i]); |
---|
| 502 | + } |
---|
| 503 | + |
---|
| 504 | + ret = qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb); |
---|
| 505 | +out: |
---|
| 506 | + kfree(ed); |
---|
| 507 | + return ret; |
---|
| 508 | +} |
---|
| 509 | +EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_desc_fq); |
---|
343 | 510 | |
---|
344 | 511 | /** |
---|
345 | 512 | * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD. |
---|
.. | .. |
---|
380 | 547 | * Return 0 for success, and negative error code for failure. |
---|
381 | 548 | */ |
---|
382 | 549 | int dpaa2_io_service_release(struct dpaa2_io *d, |
---|
383 | | - u32 bpid, |
---|
| 550 | + u16 bpid, |
---|
384 | 551 | const u64 *buffers, |
---|
385 | 552 | unsigned int num_buffers) |
---|
386 | 553 | { |
---|
.. | .. |
---|
409 | 576 | * Eg. if the buffer pool is empty, this will return zero. |
---|
410 | 577 | */ |
---|
411 | 578 | int dpaa2_io_service_acquire(struct dpaa2_io *d, |
---|
412 | | - u32 bpid, |
---|
| 579 | + u16 bpid, |
---|
413 | 580 | u64 *buffers, |
---|
414 | 581 | unsigned int num_buffers) |
---|
415 | 582 | { |
---|
.. | .. |
---|
435 | 602 | |
---|
436 | 603 | /** |
---|
437 | 604 | * dpaa2_io_store_create() - Create the dma memory storage for dequeue result. |
---|
438 | | - * @max_frames: the maximum number of dequeued result for frames, must be <= 16. |
---|
| 605 | + * @max_frames: the maximum number of dequeued result for frames, must be <= 32. |
---|
439 | 606 | * @dev: the device to allow mapping/unmapping the DMAable region. |
---|
440 | 607 | * |
---|
441 | 608 | * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)". |
---|
.. | .. |
---|
450 | 617 | struct dpaa2_io_store *ret; |
---|
451 | 618 | size_t size; |
---|
452 | 619 | |
---|
453 | | - if (!max_frames || (max_frames > 16)) |
---|
| 620 | + if (!max_frames || (max_frames > 32)) |
---|
454 | 621 | return NULL; |
---|
455 | 622 | |
---|
456 | 623 | ret = kmalloc(sizeof(*ret), GFP_KERNEL); |
---|
.. | .. |
---|
537 | 704 | if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME)) |
---|
538 | 705 | ret = NULL; |
---|
539 | 706 | } else { |
---|
| 707 | + prefetch(&s->vaddr[s->idx]); |
---|
540 | 708 | *is_last = 0; |
---|
541 | 709 | } |
---|
542 | 710 | |
---|
543 | 711 | return ret; |
---|
544 | 712 | } |
---|
545 | 713 | EXPORT_SYMBOL_GPL(dpaa2_io_store_next); |
---|
| 714 | + |
---|
| 715 | +/** |
---|
| 716 | + * dpaa2_io_query_fq_count() - Get the frame and byte count for a given fq. |
---|
| 717 | + * @d: the given DPIO object. |
---|
| 718 | + * @fqid: the id of frame queue to be queried. |
---|
| 719 | + * @fcnt: the queried frame count. |
---|
| 720 | + * @bcnt: the queried byte count. |
---|
| 721 | + * |
---|
| 722 | + * Knowing the FQ count at run-time can be useful in debugging situations. |
---|
| 723 | + * The instantaneous frame- and byte-count are hereby returned. |
---|
| 724 | + * |
---|
| 725 | + * Return 0 for a successful query, and negative error code if query fails. |
---|
| 726 | + */ |
---|
| 727 | +int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid, |
---|
| 728 | + u32 *fcnt, u32 *bcnt) |
---|
| 729 | +{ |
---|
| 730 | + struct qbman_fq_query_np_rslt state; |
---|
| 731 | + struct qbman_swp *swp; |
---|
| 732 | + unsigned long irqflags; |
---|
| 733 | + int ret; |
---|
| 734 | + |
---|
| 735 | + d = service_select(d); |
---|
| 736 | + if (!d) |
---|
| 737 | + return -ENODEV; |
---|
| 738 | + |
---|
| 739 | + swp = d->swp; |
---|
| 740 | + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); |
---|
| 741 | + ret = qbman_fq_query_state(swp, fqid, &state); |
---|
| 742 | + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); |
---|
| 743 | + if (ret) |
---|
| 744 | + return ret; |
---|
| 745 | + *fcnt = qbman_fq_state_frame_count(&state); |
---|
| 746 | + *bcnt = qbman_fq_state_byte_count(&state); |
---|
| 747 | + |
---|
| 748 | + return 0; |
---|
| 749 | +} |
---|
| 750 | +EXPORT_SYMBOL_GPL(dpaa2_io_query_fq_count); |
---|
| 751 | + |
---|
| 752 | +/** |
---|
| 753 | + * dpaa2_io_query_bp_count() - Query the number of buffers currently in a |
---|
| 754 | + * buffer pool. |
---|
| 755 | + * @d: the given DPIO object. |
---|
| 756 | + * @bpid: the index of buffer pool to be queried. |
---|
| 757 | + * @num: the queried number of buffers in the buffer pool. |
---|
| 758 | + * |
---|
| 759 | + * Return 0 for a successful query, and negative error code if query fails. |
---|
| 760 | + */ |
---|
| 761 | +int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid, u32 *num) |
---|
| 762 | +{ |
---|
| 763 | + struct qbman_bp_query_rslt state; |
---|
| 764 | + struct qbman_swp *swp; |
---|
| 765 | + unsigned long irqflags; |
---|
| 766 | + int ret; |
---|
| 767 | + |
---|
| 768 | + d = service_select(d); |
---|
| 769 | + if (!d) |
---|
| 770 | + return -ENODEV; |
---|
| 771 | + |
---|
| 772 | + swp = d->swp; |
---|
| 773 | + spin_lock_irqsave(&d->lock_mgmt_cmd, irqflags); |
---|
| 774 | + ret = qbman_bp_query(swp, bpid, &state); |
---|
| 775 | + spin_unlock_irqrestore(&d->lock_mgmt_cmd, irqflags); |
---|
| 776 | + if (ret) |
---|
| 777 | + return ret; |
---|
| 778 | + *num = qbman_bp_info_num_free_bufs(&state); |
---|
| 779 | + return 0; |
---|
| 780 | +} |
---|
| 781 | +EXPORT_SYMBOL_GPL(dpaa2_io_query_bp_count); |
---|