fdma_api.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. #ifndef _FDMA_API_H_
  3. #define _FDMA_API_H_
  4. #include <linux/bits.h>
  5. #include <linux/etherdevice.h>
  6. #include <linux/types.h>
  7. /* This provides a common set of functions and data structures for interacting
  8. * with the Frame DMA engine on multiple Microchip switchcores.
  9. *
  10. * Frame DMA DCB format:
  11. *
  12. * +---------------------------+
  13. * | Next Ptr |
  14. * +---------------------------+
  15. * | Reserved | Info |
  16. * +---------------------------+
  17. * | Data0 Ptr |
  18. * +---------------------------+
  19. * | Reserved | Status0 |
  20. * +---------------------------+
  21. * | Data1 Ptr |
  22. * +---------------------------+
  23. * | Reserved | Status1 |
  24. * +---------------------------+
  25. * | Data2 Ptr |
  26. * +---------------------------+
  27. * | Reserved | Status2 |
  28. * |-------------|-------------|
  29. * | |
  30. * | |
  31. * | |
  32. * | |
  33. * | |
  34. * |---------------------------|
  35. * | Data14 Ptr |
  36. * +-------------|-------------+
  37. * | Reserved | Status14 |
  38. * +-------------|-------------+
  39. *
  40. * The data pointers points to the actual frame data to be received or sent. The
  41. * addresses of the data pointers can, as of writing, be either a: DMA address,
  42. * physical address or mapped address.
  43. *
  44. */
  45. #define FDMA_DCB_INFO_DATAL(x) ((x) & GENMASK(15, 0))
  46. #define FDMA_DCB_INFO_TOKEN BIT(17)
  47. #define FDMA_DCB_INFO_INTR BIT(18)
  48. #define FDMA_DCB_INFO_SW(x) (((x) << 24) & GENMASK(31, 24))
  49. #define FDMA_DCB_STATUS_BLOCKL(x) ((x) & GENMASK(15, 0))
  50. #define FDMA_DCB_STATUS_SOF BIT(16)
  51. #define FDMA_DCB_STATUS_EOF BIT(17)
  52. #define FDMA_DCB_STATUS_INTR BIT(18)
  53. #define FDMA_DCB_STATUS_DONE BIT(19)
  54. #define FDMA_DCB_STATUS_BLOCKO(x) (((x) << 20) & GENMASK(31, 20))
  55. #define FDMA_DCB_INVALID_DATA 0x1
  56. #define FDMA_DB_MAX 15 /* Max number of DB's on Sparx5 */
  57. struct fdma;
  58. struct fdma_db {
  59. u64 dataptr;
  60. u64 status;
  61. };
  62. struct fdma_dcb {
  63. u64 nextptr;
  64. u64 info;
  65. struct fdma_db db[FDMA_DB_MAX];
  66. };
  67. struct fdma_ops {
  68. /* User-provided callback to set the dataptr */
  69. int (*dataptr_cb)(struct fdma *fdma, int dcb_idx, int db_idx, u64 *ptr);
  70. /* User-provided callback to set the nextptr */
  71. int (*nextptr_cb)(struct fdma *fdma, int dcb_idx, u64 *ptr);
  72. };
  73. struct fdma {
  74. void *priv;
  75. /* Virtual addresses */
  76. struct fdma_dcb *dcbs;
  77. struct fdma_dcb *last_dcb;
  78. /* DMA address */
  79. dma_addr_t dma;
  80. /* Size of DCB + DB memory */
  81. int size;
  82. /* Indexes used to access the next-to-be-used DCB or DB */
  83. int db_index;
  84. int dcb_index;
  85. /* Number of DCB's and DB's */
  86. u32 n_dcbs;
  87. u32 n_dbs;
  88. /* Size of DB's */
  89. u32 db_size;
  90. /* Channel id this FDMA object operates on */
  91. u32 channel_id;
  92. struct fdma_ops ops;
  93. };
  94. /* Advance the DCB index and wrap if required. */
  95. static inline void fdma_dcb_advance(struct fdma *fdma)
  96. {
  97. fdma->dcb_index++;
  98. if (fdma->dcb_index >= fdma->n_dcbs)
  99. fdma->dcb_index = 0;
  100. }
  101. /* Advance the DB index. */
  102. static inline void fdma_db_advance(struct fdma *fdma)
  103. {
  104. fdma->db_index++;
  105. }
  106. /* Reset the db index to zero. */
  107. static inline void fdma_db_reset(struct fdma *fdma)
  108. {
  109. fdma->db_index = 0;
  110. }
  111. /* Check if a DCB can be reused in case of multiple DB's per DCB. */
  112. static inline bool fdma_dcb_is_reusable(struct fdma *fdma)
  113. {
  114. return fdma->db_index != fdma->n_dbs;
  115. }
  116. /* Check if the FDMA has marked this DB as done. */
  117. static inline bool fdma_db_is_done(struct fdma_db *db)
  118. {
  119. return db->status & FDMA_DCB_STATUS_DONE;
  120. }
  121. /* Get the length of a DB. */
  122. static inline int fdma_db_len_get(struct fdma_db *db)
  123. {
  124. return FDMA_DCB_STATUS_BLOCKL(db->status);
  125. }
  126. /* Set the length of a DB. */
  127. static inline void fdma_dcb_len_set(struct fdma_dcb *dcb, u32 len)
  128. {
  129. dcb->info = FDMA_DCB_INFO_DATAL(len);
  130. }
  131. /* Get a DB by index. */
  132. static inline struct fdma_db *fdma_db_get(struct fdma *fdma, int dcb_idx,
  133. int db_idx)
  134. {
  135. return &fdma->dcbs[dcb_idx].db[db_idx];
  136. }
  137. /* Get the next DB. */
  138. static inline struct fdma_db *fdma_db_next_get(struct fdma *fdma)
  139. {
  140. return fdma_db_get(fdma, fdma->dcb_index, fdma->db_index);
  141. }
  142. /* Get a DCB by index. */
  143. static inline struct fdma_dcb *fdma_dcb_get(struct fdma *fdma, int dcb_idx)
  144. {
  145. return &fdma->dcbs[dcb_idx];
  146. }
  147. /* Get the next DCB. */
  148. static inline struct fdma_dcb *fdma_dcb_next_get(struct fdma *fdma)
  149. {
  150. return fdma_dcb_get(fdma, fdma->dcb_index);
  151. }
  152. /* Check if the FDMA has frames ready for extraction. */
  153. static inline bool fdma_has_frames(struct fdma *fdma)
  154. {
  155. return fdma_db_is_done(fdma_db_next_get(fdma));
  156. }
  157. /* Get a nextptr by index */
  158. static inline int fdma_nextptr_cb(struct fdma *fdma, int dcb_idx, u64 *nextptr)
  159. {
  160. *nextptr = fdma->dma + (sizeof(struct fdma_dcb) * dcb_idx);
  161. return 0;
  162. }
  163. /* Get the DMA address of a dataptr, by index. This function is only applicable
  164. * if the dataptr addresses and DCB's are in contiguous memory and the driver
  165. * supports XDP.
  166. */
  167. static inline u64 fdma_dataptr_get_contiguous(struct fdma *fdma, int dcb_idx,
  168. int db_idx)
  169. {
  170. return fdma->dma + (sizeof(struct fdma_dcb) * fdma->n_dcbs) +
  171. (dcb_idx * fdma->n_dbs + db_idx) * fdma->db_size +
  172. XDP_PACKET_HEADROOM;
  173. }
  174. /* Get the virtual address of a dataptr, by index. This function is only
  175. * applicable if the dataptr addresses and DCB's are in contiguous memory and
  176. * the driver supports XDP.
  177. */
  178. static inline void *fdma_dataptr_virt_get_contiguous(struct fdma *fdma,
  179. int dcb_idx, int db_idx)
  180. {
  181. return (u8 *)fdma->dcbs + (sizeof(struct fdma_dcb) * fdma->n_dcbs) +
  182. (dcb_idx * fdma->n_dbs + db_idx) * fdma->db_size +
  183. XDP_PACKET_HEADROOM;
  184. }
  185. /* Check if this DCB is the last used DCB. */
  186. static inline bool fdma_is_last(struct fdma *fdma, struct fdma_dcb *dcb)
  187. {
  188. return dcb == fdma->last_dcb;
  189. }
  190. int fdma_dcbs_init(struct fdma *fdma, u64 info, u64 status);
  191. int fdma_db_add(struct fdma *fdma, int dcb_idx, int db_idx, u64 status);
  192. int fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status);
  193. int __fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status,
  194. int (*dcb_cb)(struct fdma *fdma, int dcb_idx, u64 *nextptr),
  195. int (*db_cb)(struct fdma *fdma, int dcb_idx, int db_idx,
  196. u64 *dataptr));
  197. int fdma_alloc_coherent(struct device *dev, struct fdma *fdma);
  198. int fdma_alloc_phys(struct fdma *fdma);
  199. void fdma_free_coherent(struct device *dev, struct fdma *fdma);
  200. void fdma_free_phys(struct fdma *fdma);
  201. u32 fdma_get_size(struct fdma *fdma);
  202. u32 fdma_get_size_contiguous(struct fdma *fdma);
  203. #endif