scatterlist.h 4.5 KB

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