idals.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * File...........: linux/include/asm-s390x/idals.h
  3. * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  4. * Martin Schwidefsky <schwidefsky@de.ibm.com>
  5. * Bugreports.to..: <Linux390@de.ibm.com>
  6. * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
  7. * History of changes
  8. * 07/24/00 new file
  9. * 05/04/02 code restructuring.
  10. */
  11. #ifndef _S390_IDALS_H
  12. #define _S390_IDALS_H
  13. #include <linux/errno.h>
  14. #include <linux/err.h>
  15. #include <linux/types.h>
  16. #include <linux/slab.h>
  17. #include <asm/cio.h>
  18. #include <asm/uaccess.h>
  19. #ifdef __s390x__
  20. #define IDA_SIZE_LOG 12 /* 11 for 2k , 12 for 4k */
  21. #else
  22. #define IDA_SIZE_LOG 11 /* 11 for 2k , 12 for 4k */
  23. #endif
  24. #define IDA_BLOCK_SIZE (1L<<IDA_SIZE_LOG)
  25. /*
  26. * Test if an address/length pair needs an idal list.
  27. */
  28. static inline int
  29. idal_is_needed(void *vaddr, unsigned int length)
  30. {
  31. #ifdef __s390x__
  32. return ((__pa(vaddr) + length - 1) >> 31) != 0;
  33. #else
  34. return 0;
  35. #endif
  36. }
  37. /*
  38. * Return the number of idal words needed for an address/length pair.
  39. */
  40. static inline unsigned int idal_nr_words(void *vaddr, unsigned int length)
  41. {
  42. return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
  43. (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
  44. }
  45. /*
  46. * Create the list of idal words for an address/length pair.
  47. */
  48. static inline unsigned long *idal_create_words(unsigned long *idaws,
  49. void *vaddr, unsigned int length)
  50. {
  51. unsigned long paddr;
  52. unsigned int cidaw;
  53. paddr = __pa(vaddr);
  54. cidaw = ((paddr & (IDA_BLOCK_SIZE-1)) + length +
  55. (IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
  56. *idaws++ = paddr;
  57. paddr &= -IDA_BLOCK_SIZE;
  58. while (--cidaw > 0) {
  59. paddr += IDA_BLOCK_SIZE;
  60. *idaws++ = paddr;
  61. }
  62. return idaws;
  63. }
  64. /*
  65. * Sets the address of the data in CCW.
  66. * If necessary it allocates an IDAL and sets the appropriate flags.
  67. */
  68. static inline int
  69. set_normalized_cda(struct ccw1 * ccw, void *vaddr)
  70. {
  71. #ifdef __s390x__
  72. unsigned int nridaws;
  73. unsigned long *idal;
  74. if (ccw->flags & CCW_FLAG_IDA)
  75. return -EINVAL;
  76. nridaws = idal_nr_words(vaddr, ccw->count);
  77. if (nridaws > 0) {
  78. idal = kmalloc(nridaws * sizeof(unsigned long),
  79. GFP_ATOMIC | GFP_DMA );
  80. if (idal == NULL)
  81. return -ENOMEM;
  82. idal_create_words(idal, vaddr, ccw->count);
  83. ccw->flags |= CCW_FLAG_IDA;
  84. vaddr = idal;
  85. }
  86. #endif
  87. ccw->cda = (__u32)(unsigned long) vaddr;
  88. return 0;
  89. }
  90. /*
  91. * Releases any allocated IDAL related to the CCW.
  92. */
  93. static inline void
  94. clear_normalized_cda(struct ccw1 * ccw)
  95. {
  96. #ifdef __s390x__
  97. if (ccw->flags & CCW_FLAG_IDA) {
  98. kfree((void *)(unsigned long) ccw->cda);
  99. ccw->flags &= ~CCW_FLAG_IDA;
  100. }
  101. #endif
  102. ccw->cda = 0;
  103. }
  104. /*
  105. * Idal buffer extension
  106. */
  107. struct idal_buffer {
  108. size_t size;
  109. size_t page_order;
  110. void *data[0];
  111. };
  112. /*
  113. * Allocate an idal buffer
  114. */
  115. static inline struct idal_buffer *
  116. idal_buffer_alloc(size_t size, int page_order)
  117. {
  118. struct idal_buffer *ib;
  119. int nr_chunks, nr_ptrs, i;
  120. nr_ptrs = (size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_LOG;
  121. nr_chunks = (4096 << page_order) >> IDA_SIZE_LOG;
  122. ib = kmalloc(sizeof(struct idal_buffer) + nr_ptrs*sizeof(void *),
  123. GFP_DMA | GFP_KERNEL);
  124. if (ib == NULL)
  125. return ERR_PTR(-ENOMEM);
  126. ib->size = size;
  127. ib->page_order = page_order;
  128. for (i = 0; i < nr_ptrs; i++) {
  129. if ((i & (nr_chunks - 1)) != 0) {
  130. ib->data[i] = ib->data[i-1] + IDA_BLOCK_SIZE;
  131. continue;
  132. }
  133. ib->data[i] = (void *)
  134. __get_free_pages(GFP_KERNEL, page_order);
  135. if (ib->data[i] != NULL)
  136. continue;
  137. // Not enough memory
  138. while (i >= nr_chunks) {
  139. i -= nr_chunks;
  140. free_pages((unsigned long) ib->data[i],
  141. ib->page_order);
  142. }
  143. kfree(ib);
  144. return ERR_PTR(-ENOMEM);
  145. }
  146. return ib;
  147. }
  148. /*
  149. * Free an idal buffer.
  150. */
  151. static inline void
  152. idal_buffer_free(struct idal_buffer *ib)
  153. {
  154. int nr_chunks, nr_ptrs, i;
  155. nr_ptrs = (ib->size + IDA_BLOCK_SIZE - 1) >> IDA_SIZE_LOG;
  156. nr_chunks = (4096 << ib->page_order) >> IDA_SIZE_LOG;
  157. for (i = 0; i < nr_ptrs; i += nr_chunks)
  158. free_pages((unsigned long) ib->data[i], ib->page_order);
  159. kfree(ib);
  160. }
  161. /*
  162. * Test if a idal list is really needed.
  163. */
  164. static inline int
  165. __idal_buffer_is_needed(struct idal_buffer *ib)
  166. {
  167. #ifdef __s390x__
  168. return ib->size > (4096ul << ib->page_order) ||
  169. idal_is_needed(ib->data[0], ib->size);
  170. #else
  171. return ib->size > (4096ul << ib->page_order);
  172. #endif
  173. }
  174. /*
  175. * Set channel data address to idal buffer.
  176. */
  177. static inline void
  178. idal_buffer_set_cda(struct idal_buffer *ib, struct ccw1 *ccw)
  179. {
  180. if (__idal_buffer_is_needed(ib)) {
  181. // setup idals;
  182. ccw->cda = (u32)(addr_t) ib->data;
  183. ccw->flags |= CCW_FLAG_IDA;
  184. } else
  185. // we do not need idals - use direct addressing
  186. ccw->cda = (u32)(addr_t) ib->data[0];
  187. ccw->count = ib->size;
  188. }
  189. /*
  190. * Copy count bytes from an idal buffer to user memory
  191. */
  192. static inline size_t
  193. idal_buffer_to_user(struct idal_buffer *ib, void __user *to, size_t count)
  194. {
  195. size_t left;
  196. int i;
  197. BUG_ON(count > ib->size);
  198. for (i = 0; count > IDA_BLOCK_SIZE; i++) {
  199. left = copy_to_user(to, ib->data[i], IDA_BLOCK_SIZE);
  200. if (left)
  201. return left + count - IDA_BLOCK_SIZE;
  202. to = (void __user *) to + IDA_BLOCK_SIZE;
  203. count -= IDA_BLOCK_SIZE;
  204. }
  205. return copy_to_user(to, ib->data[i], count);
  206. }
  207. /*
  208. * Copy count bytes from user memory to an idal buffer
  209. */
  210. static inline size_t
  211. idal_buffer_from_user(struct idal_buffer *ib, const void __user *from, size_t count)
  212. {
  213. size_t left;
  214. int i;
  215. BUG_ON(count > ib->size);
  216. for (i = 0; count > IDA_BLOCK_SIZE; i++) {
  217. left = copy_from_user(ib->data[i], from, IDA_BLOCK_SIZE);
  218. if (left)
  219. return left + count - IDA_BLOCK_SIZE;
  220. from = (void __user *) from + IDA_BLOCK_SIZE;
  221. count -= IDA_BLOCK_SIZE;
  222. }
  223. return copy_from_user(ib->data[i], from, count);
  224. }
  225. #endif