async_tx.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * core routines for the asynchronous memory transfer/transform api
  3. *
  4. * Copyright © 2006, Intel Corporation.
  5. *
  6. * Dan Williams <dan.j.williams@intel.com>
  7. *
  8. * with architecture considerations by:
  9. * Neil Brown <neilb@suse.de>
  10. * Jeff Garzik <jeff@garzik.org>
  11. *
  12. * This program is free software; you can redistribute it and/or modify it
  13. * under the terms and conditions of the GNU General Public License,
  14. * version 2, as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope it will be useful, but WITHOUT
  17. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  18. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  19. * more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along with
  22. * this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  24. *
  25. */
  26. #include <linux/kernel.h>
  27. #include <linux/async_tx.h>
  28. #ifdef CONFIG_DMA_ENGINE
  29. static enum dma_state_client
  30. dma_channel_add_remove(struct dma_client *client,
  31. struct dma_chan *chan, enum dma_state state);
  32. static struct dma_client async_tx_dma = {
  33. .event_callback = dma_channel_add_remove,
  34. /* .cap_mask == 0 defaults to all channels */
  35. };
  36. /**
  37. * dma_cap_mask_all - enable iteration over all operation types
  38. */
  39. static dma_cap_mask_t dma_cap_mask_all;
  40. /**
  41. * chan_ref_percpu - tracks channel allocations per core/opertion
  42. */
  43. struct chan_ref_percpu {
  44. struct dma_chan_ref *ref;
  45. };
  46. static int channel_table_initialized;
  47. static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
  48. /**
  49. * async_tx_lock - protect modification of async_tx_master_list and serialize
  50. * rebalance operations
  51. */
  52. static spinlock_t async_tx_lock;
  53. static struct list_head
  54. async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
  55. /* async_tx_issue_pending_all - start all transactions on all channels */
  56. void async_tx_issue_pending_all(void)
  57. {
  58. struct dma_chan_ref *ref;
  59. rcu_read_lock();
  60. list_for_each_entry_rcu(ref, &async_tx_master_list, node)
  61. ref->chan->device->device_issue_pending(ref->chan);
  62. rcu_read_unlock();
  63. }
  64. EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
  65. /* dma_wait_for_async_tx - spin wait for a transcation to complete
  66. * @tx: transaction to wait on
  67. */
  68. enum dma_status
  69. dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
  70. {
  71. enum dma_status status;
  72. struct dma_async_tx_descriptor *iter;
  73. if (!tx)
  74. return DMA_SUCCESS;
  75. /* poll through the dependency chain, return when tx is complete */
  76. do {
  77. iter = tx;
  78. while (iter->cookie == -EBUSY)
  79. iter = iter->parent;
  80. status = dma_sync_wait(iter->chan, iter->cookie);
  81. } while (status == DMA_IN_PROGRESS || (iter != tx));
  82. return status;
  83. }
  84. EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
  85. /* async_tx_run_dependencies - helper routine for dma drivers to process
  86. * (start) dependent operations on their target channel
  87. * @tx: transaction with dependencies
  88. */
  89. void
  90. async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
  91. {
  92. struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
  93. struct dma_device *dev;
  94. struct dma_chan *chan;
  95. list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
  96. depend_node) {
  97. chan = dep_tx->chan;
  98. dev = chan->device;
  99. /* we can't depend on ourselves */
  100. BUG_ON(chan == tx->chan);
  101. list_del(&dep_tx->depend_node);
  102. tx->tx_submit(dep_tx);
  103. /* we need to poke the engine as client code does not
  104. * know about dependency submission events
  105. */
  106. dev->device_issue_pending(chan);
  107. }
  108. }
  109. EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
  110. static void
  111. free_dma_chan_ref(struct rcu_head *rcu)
  112. {
  113. struct dma_chan_ref *ref;
  114. ref = container_of(rcu, struct dma_chan_ref, rcu);
  115. kfree(ref);
  116. }
  117. static void
  118. init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
  119. {
  120. INIT_LIST_HEAD(&ref->node);
  121. INIT_RCU_HEAD(&ref->rcu);
  122. ref->chan = chan;
  123. atomic_set(&ref->count, 0);
  124. }
  125. /**
  126. * get_chan_ref_by_cap - returns the nth channel of the given capability
  127. * defaults to returning the channel with the desired capability and the
  128. * lowest reference count if the index can not be satisfied
  129. * @cap: capability to match
  130. * @index: nth channel desired, passing -1 has the effect of forcing the
  131. * default return value
  132. */
  133. static struct dma_chan_ref *
  134. get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
  135. {
  136. struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
  137. rcu_read_lock();
  138. list_for_each_entry_rcu(ref, &async_tx_master_list, node)
  139. if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
  140. if (!min_ref)
  141. min_ref = ref;
  142. else if (atomic_read(&ref->count) <
  143. atomic_read(&min_ref->count))
  144. min_ref = ref;
  145. if (index-- == 0) {
  146. ret_ref = ref;
  147. break;
  148. }
  149. }
  150. rcu_read_unlock();
  151. if (!ret_ref)
  152. ret_ref = min_ref;
  153. if (ret_ref)
  154. atomic_inc(&ret_ref->count);
  155. return ret_ref;
  156. }
  157. /**
  158. * async_tx_rebalance - redistribute the available channels, optimize
  159. * for cpu isolation in the SMP case, and opertaion isolation in the
  160. * uniprocessor case
  161. */
  162. static void async_tx_rebalance(void)
  163. {
  164. int cpu, cap, cpu_idx = 0;
  165. unsigned long flags;
  166. if (!channel_table_initialized)
  167. return;
  168. spin_lock_irqsave(&async_tx_lock, flags);
  169. /* undo the last distribution */
  170. for_each_dma_cap_mask(cap, dma_cap_mask_all)
  171. for_each_possible_cpu(cpu) {
  172. struct dma_chan_ref *ref =
  173. per_cpu_ptr(channel_table[cap], cpu)->ref;
  174. if (ref) {
  175. atomic_set(&ref->count, 0);
  176. per_cpu_ptr(channel_table[cap], cpu)->ref =
  177. NULL;
  178. }
  179. }
  180. for_each_dma_cap_mask(cap, dma_cap_mask_all)
  181. for_each_online_cpu(cpu) {
  182. struct dma_chan_ref *new;
  183. if (NR_CPUS > 1)
  184. new = get_chan_ref_by_cap(cap, cpu_idx++);
  185. else
  186. new = get_chan_ref_by_cap(cap, -1);
  187. per_cpu_ptr(channel_table[cap], cpu)->ref = new;
  188. }
  189. spin_unlock_irqrestore(&async_tx_lock, flags);
  190. }
  191. static enum dma_state_client
  192. dma_channel_add_remove(struct dma_client *client,
  193. struct dma_chan *chan, enum dma_state state)
  194. {
  195. unsigned long found, flags;
  196. struct dma_chan_ref *master_ref, *ref;
  197. enum dma_state_client ack = DMA_DUP; /* default: take no action */
  198. switch (state) {
  199. case DMA_RESOURCE_AVAILABLE:
  200. found = 0;
  201. rcu_read_lock();
  202. list_for_each_entry_rcu(ref, &async_tx_master_list, node)
  203. if (ref->chan == chan) {
  204. found = 1;
  205. break;
  206. }
  207. rcu_read_unlock();
  208. pr_debug("async_tx: dma resource available [%s]\n",
  209. found ? "old" : "new");
  210. if (!found)
  211. ack = DMA_ACK;
  212. else
  213. break;
  214. /* add the channel to the generic management list */
  215. master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
  216. if (master_ref) {
  217. /* keep a reference until async_tx is unloaded */
  218. dma_chan_get(chan);
  219. init_dma_chan_ref(master_ref, chan);
  220. spin_lock_irqsave(&async_tx_lock, flags);
  221. list_add_tail_rcu(&master_ref->node,
  222. &async_tx_master_list);
  223. spin_unlock_irqrestore(&async_tx_lock,
  224. flags);
  225. } else {
  226. printk(KERN_WARNING "async_tx: unable to create"
  227. " new master entry in response to"
  228. " a DMA_RESOURCE_ADDED event"
  229. " (-ENOMEM)\n");
  230. return 0;
  231. }
  232. async_tx_rebalance();
  233. break;
  234. case DMA_RESOURCE_REMOVED:
  235. found = 0;
  236. spin_lock_irqsave(&async_tx_lock, flags);
  237. list_for_each_entry_rcu(ref, &async_tx_master_list, node)
  238. if (ref->chan == chan) {
  239. /* permit backing devices to go away */
  240. dma_chan_put(ref->chan);
  241. list_del_rcu(&ref->node);
  242. call_rcu(&ref->rcu, free_dma_chan_ref);
  243. found = 1;
  244. break;
  245. }
  246. spin_unlock_irqrestore(&async_tx_lock, flags);
  247. pr_debug("async_tx: dma resource removed [%s]\n",
  248. found ? "ours" : "not ours");
  249. if (found)
  250. ack = DMA_ACK;
  251. else
  252. break;
  253. async_tx_rebalance();
  254. break;
  255. case DMA_RESOURCE_SUSPEND:
  256. case DMA_RESOURCE_RESUME:
  257. printk(KERN_WARNING "async_tx: does not support dma channel"
  258. " suspend/resume\n");
  259. break;
  260. default:
  261. BUG();
  262. }
  263. return ack;
  264. }
  265. static int __init
  266. async_tx_init(void)
  267. {
  268. enum dma_transaction_type cap;
  269. spin_lock_init(&async_tx_lock);
  270. bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
  271. /* an interrupt will never be an explicit operation type.
  272. * clearing this bit prevents allocation to a slot in 'channel_table'
  273. */
  274. clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
  275. for_each_dma_cap_mask(cap, dma_cap_mask_all) {
  276. channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
  277. if (!channel_table[cap])
  278. goto err;
  279. }
  280. channel_table_initialized = 1;
  281. dma_async_client_register(&async_tx_dma);
  282. dma_async_client_chan_request(&async_tx_dma);
  283. printk(KERN_INFO "async_tx: api initialized (async)\n");
  284. return 0;
  285. err:
  286. printk(KERN_ERR "async_tx: initialization failure\n");
  287. while (--cap >= 0)
  288. free_percpu(channel_table[cap]);
  289. return 1;
  290. }
  291. static void __exit async_tx_exit(void)
  292. {
  293. enum dma_transaction_type cap;
  294. channel_table_initialized = 0;
  295. for_each_dma_cap_mask(cap, dma_cap_mask_all)
  296. if (channel_table[cap])
  297. free_percpu(channel_table[cap]);
  298. dma_async_client_unregister(&async_tx_dma);
  299. }
  300. /**
  301. * async_tx_find_channel - find a channel to carry out the operation or let
  302. * the transaction execute synchronously
  303. * @depend_tx: transaction dependency
  304. * @tx_type: transaction type
  305. */
  306. struct dma_chan *
  307. async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
  308. enum dma_transaction_type tx_type)
  309. {
  310. /* see if we can keep the chain on one channel */
  311. if (depend_tx &&
  312. dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
  313. return depend_tx->chan;
  314. else if (likely(channel_table_initialized)) {
  315. struct dma_chan_ref *ref;
  316. int cpu = get_cpu();
  317. ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
  318. put_cpu();
  319. return ref ? ref->chan : NULL;
  320. } else
  321. return NULL;
  322. }
  323. EXPORT_SYMBOL_GPL(async_tx_find_channel);
  324. #else
  325. static int __init async_tx_init(void)
  326. {
  327. printk(KERN_INFO "async_tx: api initialized (sync-only)\n");
  328. return 0;
  329. }
  330. static void __exit async_tx_exit(void)
  331. {
  332. do { } while (0);
  333. }
  334. #endif
  335. void
  336. async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
  337. enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
  338. dma_async_tx_callback cb_fn, void *cb_param)
  339. {
  340. tx->callback = cb_fn;
  341. tx->callback_param = cb_param;
  342. /* set this new tx to run after depend_tx if:
  343. * 1/ a dependency exists (depend_tx is !NULL)
  344. * 2/ the tx can not be submitted to the current channel
  345. */
  346. if (depend_tx && depend_tx->chan != chan) {
  347. /* if ack is already set then we cannot be sure
  348. * we are referring to the correct operation
  349. */
  350. BUG_ON(depend_tx->ack);
  351. tx->parent = depend_tx;
  352. spin_lock_bh(&depend_tx->lock);
  353. list_add_tail(&tx->depend_node, &depend_tx->depend_list);
  354. if (depend_tx->cookie == 0) {
  355. struct dma_chan *dep_chan = depend_tx->chan;
  356. struct dma_device *dep_dev = dep_chan->device;
  357. dep_dev->device_dependency_added(dep_chan);
  358. }
  359. spin_unlock_bh(&depend_tx->lock);
  360. /* schedule an interrupt to trigger the channel switch */
  361. async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
  362. } else {
  363. tx->parent = NULL;
  364. tx->tx_submit(tx);
  365. }
  366. if (flags & ASYNC_TX_ACK)
  367. async_tx_ack(tx);
  368. if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
  369. async_tx_ack(depend_tx);
  370. }
  371. EXPORT_SYMBOL_GPL(async_tx_submit);
  372. /**
  373. * async_trigger_callback - schedules the callback function to be run after
  374. * any dependent operations have been completed.
  375. * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
  376. * @depend_tx: 'callback' requires the completion of this transaction
  377. * @cb_fn: function to call after depend_tx completes
  378. * @cb_param: parameter to pass to the callback routine
  379. */
  380. struct dma_async_tx_descriptor *
  381. async_trigger_callback(enum async_tx_flags flags,
  382. struct dma_async_tx_descriptor *depend_tx,
  383. dma_async_tx_callback cb_fn, void *cb_param)
  384. {
  385. struct dma_chan *chan;
  386. struct dma_device *device;
  387. struct dma_async_tx_descriptor *tx;
  388. if (depend_tx) {
  389. chan = depend_tx->chan;
  390. device = chan->device;
  391. /* see if we can schedule an interrupt
  392. * otherwise poll for completion
  393. */
  394. if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
  395. device = NULL;
  396. tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
  397. } else
  398. tx = NULL;
  399. if (tx) {
  400. pr_debug("%s: (async)\n", __FUNCTION__);
  401. async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
  402. } else {
  403. pr_debug("%s: (sync)\n", __FUNCTION__);
  404. /* wait for any prerequisite operations */
  405. if (depend_tx) {
  406. /* if ack is already set then we cannot be sure
  407. * we are referring to the correct operation
  408. */
  409. BUG_ON(depend_tx->ack);
  410. if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
  411. panic("%s: DMA_ERROR waiting for depend_tx\n",
  412. __FUNCTION__);
  413. }
  414. async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
  415. }
  416. return tx;
  417. }
  418. EXPORT_SYMBOL_GPL(async_trigger_callback);
  419. module_init(async_tx_init);
  420. module_exit(async_tx_exit);
  421. MODULE_AUTHOR("Intel Corporation");
  422. MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
  423. MODULE_LICENSE("GPL");