tx.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /* Copyright (C) 2024 Intel Corporation */
  3. #ifndef __LIBETH_TX_H
  4. #define __LIBETH_TX_H
  5. #include <linux/skbuff.h>
  6. #include <net/libeth/types.h>
  7. /* Tx buffer completion */
  8. /**
  9. * enum libeth_sqe_type - type of &libeth_sqe to act on Tx completion
  10. * @LIBETH_SQE_EMPTY: unused/empty, no action required
  11. * @LIBETH_SQE_CTX: context descriptor with empty SQE, no action required
  12. * @LIBETH_SQE_SLAB: kmalloc-allocated buffer, unmap and kfree()
  13. * @LIBETH_SQE_FRAG: mapped skb frag, only unmap DMA
  14. * @LIBETH_SQE_SKB: &sk_buff, unmap and napi_consume_skb(), update stats
  15. */
  16. enum libeth_sqe_type {
  17. LIBETH_SQE_EMPTY = 0U,
  18. LIBETH_SQE_CTX,
  19. LIBETH_SQE_SLAB,
  20. LIBETH_SQE_FRAG,
  21. LIBETH_SQE_SKB,
  22. };
  23. /**
  24. * struct libeth_sqe - represents a Send Queue Element / Tx buffer
  25. * @type: type of the buffer, see the enum above
  26. * @rs_idx: index of the last buffer from the batch this one was sent in
  27. * @raw: slab buffer to free via kfree()
  28. * @skb: &sk_buff to consume
  29. * @dma: DMA address to unmap
  30. * @len: length of the mapped region to unmap
  31. * @nr_frags: number of frags in the frame this buffer belongs to
  32. * @packets: number of physical packets sent for this frame
  33. * @bytes: number of physical bytes sent for this frame
  34. * @priv: driver-private scratchpad
  35. */
  36. struct libeth_sqe {
  37. enum libeth_sqe_type type:32;
  38. u32 rs_idx;
  39. union {
  40. void *raw;
  41. struct sk_buff *skb;
  42. };
  43. DEFINE_DMA_UNMAP_ADDR(dma);
  44. DEFINE_DMA_UNMAP_LEN(len);
  45. u32 nr_frags;
  46. u32 packets;
  47. u32 bytes;
  48. unsigned long priv;
  49. } __aligned_largest;
  50. /**
  51. * LIBETH_SQE_CHECK_PRIV - check the driver's private SQE data
  52. * @p: type or name of the object the driver wants to fit into &libeth_sqe
  53. *
  54. * Make sure the driver's private data fits into libeth_sqe::priv. To be used
  55. * right after its declaration.
  56. */
  57. #define LIBETH_SQE_CHECK_PRIV(p) \
  58. static_assert(sizeof(p) <= sizeof_field(struct libeth_sqe, priv))
  59. /**
  60. * struct libeth_cq_pp - completion queue poll params
  61. * @dev: &device to perform DMA unmapping
  62. * @ss: onstack NAPI stats to fill
  63. * @napi: whether it's called from the NAPI context
  64. *
  65. * libeth uses this structure to access objects needed for performing full
  66. * Tx complete operation without passing lots of arguments and change the
  67. * prototypes each time a new one is added.
  68. */
  69. struct libeth_cq_pp {
  70. struct device *dev;
  71. struct libeth_sq_napi_stats *ss;
  72. bool napi;
  73. };
  74. /**
  75. * libeth_tx_complete - perform Tx completion for one SQE
  76. * @sqe: SQE to complete
  77. * @cp: poll params
  78. *
  79. * Do Tx complete for all the types of buffers, incl. freeing, unmapping,
  80. * updating the stats etc.
  81. */
  82. static inline void libeth_tx_complete(struct libeth_sqe *sqe,
  83. const struct libeth_cq_pp *cp)
  84. {
  85. switch (sqe->type) {
  86. case LIBETH_SQE_EMPTY:
  87. return;
  88. case LIBETH_SQE_SKB:
  89. case LIBETH_SQE_FRAG:
  90. case LIBETH_SQE_SLAB:
  91. dma_unmap_page(cp->dev, dma_unmap_addr(sqe, dma),
  92. dma_unmap_len(sqe, len), DMA_TO_DEVICE);
  93. break;
  94. default:
  95. break;
  96. }
  97. switch (sqe->type) {
  98. case LIBETH_SQE_SKB:
  99. cp->ss->packets += sqe->packets;
  100. cp->ss->bytes += sqe->bytes;
  101. napi_consume_skb(sqe->skb, cp->napi);
  102. break;
  103. case LIBETH_SQE_SLAB:
  104. kfree(sqe->raw);
  105. break;
  106. default:
  107. break;
  108. }
  109. sqe->type = LIBETH_SQE_EMPTY;
  110. }
  111. #endif /* __LIBETH_TX_H */