iowait.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #ifndef _HFI1_IOWAIT_H
  2. #define _HFI1_IOWAIT_H
  3. /*
  4. * Copyright(c) 2015, 2016 Intel Corporation.
  5. *
  6. * This file is provided under a dual BSD/GPLv2 license. When using or
  7. * redistributing this file, you may do so under either license.
  8. *
  9. * GPL LICENSE SUMMARY
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of version 2 of the GNU General Public License as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful, but
  16. * WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * General Public License for more details.
  19. *
  20. * BSD LICENSE
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. *
  26. * - Redistributions of source code must retain the above copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * - Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in
  30. * the documentation and/or other materials provided with the
  31. * distribution.
  32. * - Neither the name of Intel Corporation nor the names of its
  33. * contributors may be used to endorse or promote products derived
  34. * from this software without specific prior written permission.
  35. *
  36. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  37. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  38. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  39. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  40. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  43. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  44. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  45. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  46. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  47. *
  48. */
  49. #include <linux/list.h>
  50. #include <linux/workqueue.h>
  51. #include <linux/sched.h>
  52. #include "sdma_txreq.h"
  53. /*
  54. * typedef (*restart_t)() - restart callback
  55. * @work: pointer to work structure
  56. */
  57. typedef void (*restart_t)(struct work_struct *work);
  58. struct sdma_txreq;
  59. struct sdma_engine;
  60. /**
  61. * struct iowait - linkage for delayed progress/waiting
  62. * @list: used to add/insert into QP/PQ wait lists
  63. * @lock: uses to record the list head lock
  64. * @tx_head: overflow list of sdma_txreq's
  65. * @sleep: no space callback
  66. * @wakeup: space callback wakeup
  67. * @sdma_drained: sdma count drained
  68. * @iowork: workqueue overhead
  69. * @wait_dma: wait for sdma_busy == 0
  70. * @wait_pio: wait for pio_busy == 0
  71. * @sdma_busy: # of packets in flight
  72. * @count: total number of descriptors in tx_head'ed list
  73. * @tx_limit: limit for overflow queuing
  74. * @tx_count: number of tx entry's in tx_head'ed list
  75. *
  76. * This is to be embedded in user's state structure
  77. * (QP or PQ).
  78. *
  79. * The sleep and wakeup members are a
  80. * bit misnamed. They do not strictly
  81. * speaking sleep or wake up, but they
  82. * are callbacks for the ULP to implement
  83. * what ever queuing/dequeuing of
  84. * the embedded iowait and its containing struct
  85. * when a resource shortage like SDMA ring space is seen.
  86. *
  87. * Both potentially have locks help
  88. * so sleeping is not allowed.
  89. *
  90. * The wait_dma member along with the iow
  91. *
  92. * The lock field is used by waiters to record
  93. * the seqlock_t that guards the list head.
  94. * Waiters explicity know that, but the destroy
  95. * code that unwaits QPs does not.
  96. */
  97. struct iowait {
  98. struct list_head list;
  99. struct list_head tx_head;
  100. int (*sleep)(
  101. struct sdma_engine *sde,
  102. struct iowait *wait,
  103. struct sdma_txreq *tx,
  104. unsigned seq);
  105. void (*wakeup)(struct iowait *wait, int reason);
  106. void (*sdma_drained)(struct iowait *wait);
  107. seqlock_t *lock;
  108. struct work_struct iowork;
  109. wait_queue_head_t wait_dma;
  110. wait_queue_head_t wait_pio;
  111. atomic_t sdma_busy;
  112. atomic_t pio_busy;
  113. u32 count;
  114. u32 tx_limit;
  115. u32 tx_count;
  116. };
  117. #define SDMA_AVAIL_REASON 0
  118. /**
  119. * iowait_init() - initialize wait structure
  120. * @wait: wait struct to initialize
  121. * @tx_limit: limit for overflow queuing
  122. * @func: restart function for workqueue
  123. * @sleep: sleep function for no space
  124. * @resume: wakeup function for no space
  125. *
  126. * This function initializes the iowait
  127. * structure embedded in the QP or PQ.
  128. *
  129. */
  130. static inline void iowait_init(
  131. struct iowait *wait,
  132. u32 tx_limit,
  133. void (*func)(struct work_struct *work),
  134. int (*sleep)(
  135. struct sdma_engine *sde,
  136. struct iowait *wait,
  137. struct sdma_txreq *tx,
  138. unsigned seq),
  139. void (*wakeup)(struct iowait *wait, int reason),
  140. void (*sdma_drained)(struct iowait *wait))
  141. {
  142. wait->count = 0;
  143. wait->lock = NULL;
  144. INIT_LIST_HEAD(&wait->list);
  145. INIT_LIST_HEAD(&wait->tx_head);
  146. INIT_WORK(&wait->iowork, func);
  147. init_waitqueue_head(&wait->wait_dma);
  148. init_waitqueue_head(&wait->wait_pio);
  149. atomic_set(&wait->sdma_busy, 0);
  150. atomic_set(&wait->pio_busy, 0);
  151. wait->tx_limit = tx_limit;
  152. wait->sleep = sleep;
  153. wait->wakeup = wakeup;
  154. wait->sdma_drained = sdma_drained;
  155. }
  156. /**
  157. * iowait_schedule() - initialize wait structure
  158. * @wait: wait struct to schedule
  159. * @wq: workqueue for schedule
  160. * @cpu: cpu
  161. */
  162. static inline void iowait_schedule(
  163. struct iowait *wait,
  164. struct workqueue_struct *wq,
  165. int cpu)
  166. {
  167. queue_work_on(cpu, wq, &wait->iowork);
  168. }
  169. /**
  170. * iowait_sdma_drain() - wait for DMAs to drain
  171. *
  172. * @wait: iowait structure
  173. *
  174. * This will delay until the iowait sdmas have
  175. * completed.
  176. */
  177. static inline void iowait_sdma_drain(struct iowait *wait)
  178. {
  179. wait_event(wait->wait_dma, !atomic_read(&wait->sdma_busy));
  180. }
  181. /**
  182. * iowait_sdma_pending() - return sdma pending count
  183. *
  184. * @wait: iowait structure
  185. *
  186. */
  187. static inline int iowait_sdma_pending(struct iowait *wait)
  188. {
  189. return atomic_read(&wait->sdma_busy);
  190. }
  191. /**
  192. * iowait_sdma_inc - note sdma io pending
  193. * @wait: iowait structure
  194. */
  195. static inline void iowait_sdma_inc(struct iowait *wait)
  196. {
  197. atomic_inc(&wait->sdma_busy);
  198. }
  199. /**
  200. * iowait_sdma_add - add count to pending
  201. * @wait: iowait structure
  202. */
  203. static inline void iowait_sdma_add(struct iowait *wait, int count)
  204. {
  205. atomic_add(count, &wait->sdma_busy);
  206. }
  207. /**
  208. * iowait_sdma_dec - note sdma complete
  209. * @wait: iowait structure
  210. */
  211. static inline int iowait_sdma_dec(struct iowait *wait)
  212. {
  213. return atomic_dec_and_test(&wait->sdma_busy);
  214. }
  215. /**
  216. * iowait_pio_drain() - wait for pios to drain
  217. *
  218. * @wait: iowait structure
  219. *
  220. * This will delay until the iowait pios have
  221. * completed.
  222. */
  223. static inline void iowait_pio_drain(struct iowait *wait)
  224. {
  225. wait_event_timeout(wait->wait_pio,
  226. !atomic_read(&wait->pio_busy),
  227. HZ);
  228. }
  229. /**
  230. * iowait_pio_pending() - return pio pending count
  231. *
  232. * @wait: iowait structure
  233. *
  234. */
  235. static inline int iowait_pio_pending(struct iowait *wait)
  236. {
  237. return atomic_read(&wait->pio_busy);
  238. }
  239. /**
  240. * iowait_pio_inc - note pio pending
  241. * @wait: iowait structure
  242. */
  243. static inline void iowait_pio_inc(struct iowait *wait)
  244. {
  245. atomic_inc(&wait->pio_busy);
  246. }
  247. /**
  248. * iowait_sdma_dec - note pio complete
  249. * @wait: iowait structure
  250. */
  251. static inline int iowait_pio_dec(struct iowait *wait)
  252. {
  253. return atomic_dec_and_test(&wait->pio_busy);
  254. }
  255. /**
  256. * iowait_drain_wakeup() - trigger iowait_drain() waiter
  257. *
  258. * @wait: iowait structure
  259. *
  260. * This will trigger any waiters.
  261. */
  262. static inline void iowait_drain_wakeup(struct iowait *wait)
  263. {
  264. wake_up(&wait->wait_dma);
  265. wake_up(&wait->wait_pio);
  266. if (wait->sdma_drained)
  267. wait->sdma_drained(wait);
  268. }
  269. /**
  270. * iowait_get_txhead() - get packet off of iowait list
  271. *
  272. * @wait wait struture
  273. */
  274. static inline struct sdma_txreq *iowait_get_txhead(struct iowait *wait)
  275. {
  276. struct sdma_txreq *tx = NULL;
  277. if (!list_empty(&wait->tx_head)) {
  278. tx = list_first_entry(
  279. &wait->tx_head,
  280. struct sdma_txreq,
  281. list);
  282. list_del_init(&tx->list);
  283. }
  284. return tx;
  285. }
  286. #endif