scatterlist.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef SCATTERLIST_H
  3. #define SCATTERLIST_H
  4. #include <linux/kernel.h>
  5. struct scatterlist {
  6. unsigned long page_link;
  7. unsigned int offset;
  8. unsigned int length;
  9. dma_addr_t dma_address;
  10. };
  11. /* Scatterlist helpers, stolen from linux/scatterlist.h */
  12. #define sg_is_chain(sg) ((sg)->page_link & 0x01)
  13. #define sg_is_last(sg) ((sg)->page_link & 0x02)
  14. #define sg_chain_ptr(sg) \
  15. ((struct scatterlist *) ((sg)->page_link & ~0x03))
  16. /**
  17. * sg_assign_page - Assign a given page to an SG entry
  18. * @sg: SG entry
  19. * @page: The page
  20. *
  21. * Description:
  22. * Assign page to sg entry. Also see sg_set_page(), the most commonly used
  23. * variant.
  24. *
  25. **/
  26. static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
  27. {
  28. unsigned long page_link = sg->page_link & 0x3;
  29. /*
  30. * In order for the low bit stealing approach to work, pages
  31. * must be aligned at a 32-bit boundary as a minimum.
  32. */
  33. BUG_ON((unsigned long) page & 0x03);
  34. #ifdef CONFIG_DEBUG_SG
  35. BUG_ON(sg->sg_magic != SG_MAGIC);
  36. BUG_ON(sg_is_chain(sg));
  37. #endif
  38. sg->page_link = page_link | (unsigned long) page;
  39. }
  40. /**
  41. * sg_set_page - Set sg entry to point at given page
  42. * @sg: SG entry
  43. * @page: The page
  44. * @len: Length of data
  45. * @offset: Offset into page
  46. *
  47. * Description:
  48. * Use this function to set an sg entry pointing at a page, never assign
  49. * the page directly. We encode sg table information in the lower bits
  50. * of the page pointer. See sg_page() for looking up the page belonging
  51. * to an sg entry.
  52. *
  53. **/
  54. static inline void sg_set_page(struct scatterlist *sg, struct page *page,
  55. unsigned int len, unsigned int offset)
  56. {
  57. sg_assign_page(sg, page);
  58. sg->offset = offset;
  59. sg->length = len;
  60. }
  61. static inline struct page *sg_page(struct scatterlist *sg)
  62. {
  63. #ifdef CONFIG_DEBUG_SG
  64. BUG_ON(sg->sg_magic != SG_MAGIC);
  65. BUG_ON(sg_is_chain(sg));
  66. #endif
  67. return (struct page *)((sg)->page_link & ~0x3);
  68. }
  69. /*
  70. * Loop over each sg element, following the pointer to a new list if necessary
  71. */
  72. #define for_each_sg(sglist, sg, nr, __i) \
  73. for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
  74. /**
  75. * sg_chain - Chain two sglists together
  76. * @prv: First scatterlist
  77. * @prv_nents: Number of entries in prv
  78. * @sgl: Second scatterlist
  79. *
  80. * Description:
  81. * Links @prv@ and @sgl@ together, to form a longer scatterlist.
  82. *
  83. **/
  84. static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
  85. struct scatterlist *sgl)
  86. {
  87. /*
  88. * offset and length are unused for chain entry. Clear them.
  89. */
  90. prv[prv_nents - 1].offset = 0;
  91. prv[prv_nents - 1].length = 0;
  92. /*
  93. * Set lowest bit to indicate a link pointer, and make sure to clear
  94. * the termination bit if it happens to be set.
  95. */
  96. prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
  97. }
  98. /**
  99. * sg_mark_end - Mark the end of the scatterlist
  100. * @sg: SG entryScatterlist
  101. *
  102. * Description:
  103. * Marks the passed in sg entry as the termination point for the sg
  104. * table. A call to sg_next() on this entry will return NULL.
  105. *
  106. **/
  107. static inline void sg_mark_end(struct scatterlist *sg)
  108. {
  109. #ifdef CONFIG_DEBUG_SG
  110. BUG_ON(sg->sg_magic != SG_MAGIC);
  111. #endif
  112. /*
  113. * Set termination bit, clear potential chain bit
  114. */
  115. sg->page_link |= 0x02;
  116. sg->page_link &= ~0x01;
  117. }
  118. /**
  119. * sg_unmark_end - Undo setting the end of the scatterlist
  120. * @sg: SG entryScatterlist
  121. *
  122. * Description:
  123. * Removes the termination marker from the given entry of the scatterlist.
  124. *
  125. **/
  126. static inline void sg_unmark_end(struct scatterlist *sg)
  127. {
  128. #ifdef CONFIG_DEBUG_SG
  129. BUG_ON(sg->sg_magic != SG_MAGIC);
  130. #endif
  131. sg->page_link &= ~0x02;
  132. }
  133. static inline struct scatterlist *sg_next(struct scatterlist *sg)
  134. {
  135. #ifdef CONFIG_DEBUG_SG
  136. BUG_ON(sg->sg_magic != SG_MAGIC);
  137. #endif
  138. if (sg_is_last(sg))
  139. return NULL;
  140. sg++;
  141. if (unlikely(sg_is_chain(sg)))
  142. sg = sg_chain_ptr(sg);
  143. return sg;
  144. }
  145. static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
  146. {
  147. memset(sgl, 0, sizeof(*sgl) * nents);
  148. #ifdef CONFIG_DEBUG_SG
  149. {
  150. unsigned int i;
  151. for (i = 0; i < nents; i++)
  152. sgl[i].sg_magic = SG_MAGIC;
  153. }
  154. #endif
  155. sg_mark_end(&sgl[nents - 1]);
  156. }
  157. static inline dma_addr_t sg_phys(struct scatterlist *sg)
  158. {
  159. return page_to_phys(sg_page(sg)) + sg->offset;
  160. }
  161. static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
  162. unsigned int buflen)
  163. {
  164. sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
  165. }
  166. static inline void sg_init_one(struct scatterlist *sg,
  167. const void *buf, unsigned int buflen)
  168. {
  169. sg_init_table(sg, 1);
  170. sg_set_buf(sg, buf, buflen);
  171. }
  172. #endif /* SCATTERLIST_H */