sg_sw_sec4.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * CAAM/SEC 4.x functions for using scatterlists in caam driver
  3. *
  4. * Copyright 2008-2011 Freescale Semiconductor, Inc.
  5. *
  6. */
  7. struct sec4_sg_entry;
  8. /*
  9. * convert single dma address to h/w link table format
  10. */
  11. static inline void dma_to_sec4_sg_one(struct sec4_sg_entry *sec4_sg_ptr,
  12. dma_addr_t dma, u32 len, u32 offset)
  13. {
  14. sec4_sg_ptr->ptr = dma;
  15. sec4_sg_ptr->len = len;
  16. sec4_sg_ptr->buf_pool_id = 0;
  17. sec4_sg_ptr->offset = offset;
  18. #ifdef DEBUG
  19. print_hex_dump(KERN_ERR, "sec4_sg_ptr@: ",
  20. DUMP_PREFIX_ADDRESS, 16, 4, sec4_sg_ptr,
  21. sizeof(struct sec4_sg_entry), 1);
  22. #endif
  23. }
  24. /*
  25. * convert scatterlist to h/w link table format
  26. * but does not have final bit; instead, returns last entry
  27. */
  28. static inline struct sec4_sg_entry *
  29. sg_to_sec4_sg(struct scatterlist *sg, int sg_count,
  30. struct sec4_sg_entry *sec4_sg_ptr, u32 offset)
  31. {
  32. while (sg_count) {
  33. dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg),
  34. sg_dma_len(sg), offset);
  35. sec4_sg_ptr++;
  36. sg = sg_next(sg);
  37. sg_count--;
  38. }
  39. return sec4_sg_ptr - 1;
  40. }
  41. /*
  42. * convert scatterlist to h/w link table format
  43. * scatterlist must have been previously dma mapped
  44. */
  45. static inline void sg_to_sec4_sg_last(struct scatterlist *sg, int sg_count,
  46. struct sec4_sg_entry *sec4_sg_ptr,
  47. u32 offset)
  48. {
  49. sec4_sg_ptr = sg_to_sec4_sg(sg, sg_count, sec4_sg_ptr, offset);
  50. sec4_sg_ptr->len |= SEC4_SG_LEN_FIN;
  51. }
  52. static inline struct sec4_sg_entry *sg_to_sec4_sg_len(
  53. struct scatterlist *sg, unsigned int total,
  54. struct sec4_sg_entry *sec4_sg_ptr)
  55. {
  56. do {
  57. unsigned int len = min(sg_dma_len(sg), total);
  58. dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), len, 0);
  59. sec4_sg_ptr++;
  60. sg = sg_next(sg);
  61. total -= len;
  62. } while (total);
  63. return sec4_sg_ptr - 1;
  64. }
  65. /* count number of elements in scatterlist */
  66. static inline int __sg_count(struct scatterlist *sg_list, int nbytes,
  67. bool *chained)
  68. {
  69. struct scatterlist *sg = sg_list;
  70. int sg_nents = 0;
  71. while (nbytes > 0) {
  72. sg_nents++;
  73. nbytes -= sg->length;
  74. if (!sg_is_last(sg) && (sg + 1)->length == 0)
  75. *chained = true;
  76. sg = sg_next(sg);
  77. }
  78. return sg_nents;
  79. }
  80. /* derive number of elements in scatterlist, but return 0 for 1 */
  81. static inline int sg_count(struct scatterlist *sg_list, int nbytes,
  82. bool *chained)
  83. {
  84. int sg_nents = __sg_count(sg_list, nbytes, chained);
  85. if (likely(sg_nents == 1))
  86. return 0;
  87. return sg_nents;
  88. }
  89. static inline void dma_unmap_sg_chained(
  90. struct device *dev, struct scatterlist *sg, unsigned int nents,
  91. enum dma_data_direction dir, bool chained)
  92. {
  93. if (unlikely(chained)) {
  94. int i;
  95. struct scatterlist *tsg = sg;
  96. /*
  97. * Use a local copy of the sg pointer to avoid moving the
  98. * head of the list pointed to by sg as we walk the list.
  99. */
  100. for (i = 0; i < nents; i++) {
  101. dma_unmap_sg(dev, tsg, 1, dir);
  102. tsg = sg_next(tsg);
  103. }
  104. } else if (nents) {
  105. dma_unmap_sg(dev, sg, nents, dir);
  106. }
  107. }
  108. static inline int dma_map_sg_chained(
  109. struct device *dev, struct scatterlist *sg, unsigned int nents,
  110. enum dma_data_direction dir, bool chained)
  111. {
  112. if (unlikely(chained)) {
  113. int i;
  114. struct scatterlist *tsg = sg;
  115. /*
  116. * Use a local copy of the sg pointer to avoid moving the
  117. * head of the list pointed to by sg as we walk the list.
  118. */
  119. for (i = 0; i < nents; i++) {
  120. if (!dma_map_sg(dev, tsg, 1, dir)) {
  121. dma_unmap_sg_chained(dev, sg, i, dir,
  122. chained);
  123. nents = 0;
  124. break;
  125. }
  126. tsg = sg_next(tsg);
  127. }
  128. } else
  129. nents = dma_map_sg(dev, sg, nents, dir);
  130. return nents;
  131. }