diff options
Diffstat (limited to 'crypto/async_tx/async_tx.c')
-rw-r--r-- | crypto/async_tx/async_tx.c | 87 |
1 files changed, 42 insertions, 45 deletions
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index 06eb6cc09fef..f9cdf04fe7c0 100644 --- a/crypto/async_tx/async_tx.c +++ b/crypto/async_tx/async_tx.c | |||
@@ -42,16 +42,21 @@ static void __exit async_tx_exit(void) | |||
42 | async_dmaengine_put(); | 42 | async_dmaengine_put(); |
43 | } | 43 | } |
44 | 44 | ||
45 | module_init(async_tx_init); | ||
46 | module_exit(async_tx_exit); | ||
47 | |||
45 | /** | 48 | /** |
46 | * __async_tx_find_channel - find a channel to carry out the operation or let | 49 | * __async_tx_find_channel - find a channel to carry out the operation or let |
47 | * the transaction execute synchronously | 50 | * the transaction execute synchronously |
48 | * @depend_tx: transaction dependency | 51 | * @submit: transaction dependency and submission modifiers |
49 | * @tx_type: transaction type | 52 | * @tx_type: transaction type |
50 | */ | 53 | */ |
51 | struct dma_chan * | 54 | struct dma_chan * |
52 | __async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx, | 55 | __async_tx_find_channel(struct async_submit_ctl *submit, |
53 | enum dma_transaction_type tx_type) | 56 | enum dma_transaction_type tx_type) |
54 | { | 57 | { |
58 | struct dma_async_tx_descriptor *depend_tx = submit->depend_tx; | ||
59 | |||
55 | /* see if we can keep the chain on one channel */ | 60 | /* see if we can keep the chain on one channel */ |
56 | if (depend_tx && | 61 | if (depend_tx && |
57 | dma_has_cap(tx_type, depend_tx->chan->device->cap_mask)) | 62 | dma_has_cap(tx_type, depend_tx->chan->device->cap_mask)) |
@@ -59,17 +64,6 @@ __async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx, | |||
59 | return async_dma_find_channel(tx_type); | 64 | return async_dma_find_channel(tx_type); |
60 | } | 65 | } |
61 | EXPORT_SYMBOL_GPL(__async_tx_find_channel); | 66 | EXPORT_SYMBOL_GPL(__async_tx_find_channel); |
62 | #else | ||
63 | static int __init async_tx_init(void) | ||
64 | { | ||
65 | printk(KERN_INFO "async_tx: api initialized (sync-only)\n"); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void __exit async_tx_exit(void) | ||
70 | { | ||
71 | do { } while (0); | ||
72 | } | ||
73 | #endif | 67 | #endif |
74 | 68 | ||
75 | 69 | ||
@@ -83,10 +77,14 @@ static void | |||
83 | async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx, | 77 | async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx, |
84 | struct dma_async_tx_descriptor *tx) | 78 | struct dma_async_tx_descriptor *tx) |
85 | { | 79 | { |
86 | struct dma_chan *chan; | 80 | struct dma_chan *chan = depend_tx->chan; |
87 | struct dma_device *device; | 81 | struct dma_device *device = chan->device; |
88 | struct dma_async_tx_descriptor *intr_tx = (void *) ~0; | 82 | struct dma_async_tx_descriptor *intr_tx = (void *) ~0; |
89 | 83 | ||
84 | #ifdef CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH | ||
85 | BUG(); | ||
86 | #endif | ||
87 | |||
90 | /* first check to see if we can still append to depend_tx */ | 88 | /* first check to see if we can still append to depend_tx */ |
91 | spin_lock_bh(&depend_tx->lock); | 89 | spin_lock_bh(&depend_tx->lock); |
92 | if (depend_tx->parent && depend_tx->chan == tx->chan) { | 90 | if (depend_tx->parent && depend_tx->chan == tx->chan) { |
@@ -96,11 +94,11 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx, | |||
96 | } | 94 | } |
97 | spin_unlock_bh(&depend_tx->lock); | 95 | spin_unlock_bh(&depend_tx->lock); |
98 | 96 | ||
99 | if (!intr_tx) | 97 | /* attached dependency, flush the parent channel */ |
98 | if (!intr_tx) { | ||
99 | device->device_issue_pending(chan); | ||
100 | return; | 100 | return; |
101 | 101 | } | |
102 | chan = depend_tx->chan; | ||
103 | device = chan->device; | ||
104 | 102 | ||
105 | /* see if we can schedule an interrupt | 103 | /* see if we can schedule an interrupt |
106 | * otherwise poll for completion | 104 | * otherwise poll for completion |
@@ -134,6 +132,7 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx, | |||
134 | intr_tx->tx_submit(intr_tx); | 132 | intr_tx->tx_submit(intr_tx); |
135 | async_tx_ack(intr_tx); | 133 | async_tx_ack(intr_tx); |
136 | } | 134 | } |
135 | device->device_issue_pending(chan); | ||
137 | } else { | 136 | } else { |
138 | if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR) | 137 | if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR) |
139 | panic("%s: DMA_ERROR waiting for depend_tx\n", | 138 | panic("%s: DMA_ERROR waiting for depend_tx\n", |
@@ -144,13 +143,14 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx, | |||
144 | 143 | ||
145 | 144 | ||
146 | /** | 145 | /** |
147 | * submit_disposition - while holding depend_tx->lock we must avoid submitting | 146 | * submit_disposition - flags for routing an incoming operation |
148 | * new operations to prevent a circular locking dependency with | ||
149 | * drivers that already hold a channel lock when calling | ||
150 | * async_tx_run_dependencies. | ||
151 | * @ASYNC_TX_SUBMITTED: we were able to append the new operation under the lock | 147 | * @ASYNC_TX_SUBMITTED: we were able to append the new operation under the lock |
152 | * @ASYNC_TX_CHANNEL_SWITCH: when the lock is dropped schedule a channel switch | 148 | * @ASYNC_TX_CHANNEL_SWITCH: when the lock is dropped schedule a channel switch |
153 | * @ASYNC_TX_DIRECT_SUBMIT: when the lock is dropped submit directly | 149 | * @ASYNC_TX_DIRECT_SUBMIT: when the lock is dropped submit directly |
150 | * | ||
151 | * while holding depend_tx->lock we must avoid submitting new operations | ||
152 | * to prevent a circular locking dependency with drivers that already | ||
153 | * hold a channel lock when calling async_tx_run_dependencies. | ||
154 | */ | 154 | */ |
155 | enum submit_disposition { | 155 | enum submit_disposition { |
156 | ASYNC_TX_SUBMITTED, | 156 | ASYNC_TX_SUBMITTED, |
@@ -160,11 +160,12 @@ enum submit_disposition { | |||
160 | 160 | ||
161 | void | 161 | void |
162 | async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx, | 162 | async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx, |
163 | enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx, | 163 | struct async_submit_ctl *submit) |
164 | dma_async_tx_callback cb_fn, void *cb_param) | ||
165 | { | 164 | { |
166 | tx->callback = cb_fn; | 165 | struct dma_async_tx_descriptor *depend_tx = submit->depend_tx; |
167 | tx->callback_param = cb_param; | 166 | |
167 | tx->callback = submit->cb_fn; | ||
168 | tx->callback_param = submit->cb_param; | ||
168 | 169 | ||
169 | if (depend_tx) { | 170 | if (depend_tx) { |
170 | enum submit_disposition s; | 171 | enum submit_disposition s; |
@@ -220,30 +221,29 @@ async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx, | |||
220 | tx->tx_submit(tx); | 221 | tx->tx_submit(tx); |
221 | } | 222 | } |
222 | 223 | ||
223 | if (flags & ASYNC_TX_ACK) | 224 | if (submit->flags & ASYNC_TX_ACK) |
224 | async_tx_ack(tx); | 225 | async_tx_ack(tx); |
225 | 226 | ||
226 | if (depend_tx && (flags & ASYNC_TX_DEP_ACK)) | 227 | if (depend_tx) |
227 | async_tx_ack(depend_tx); | 228 | async_tx_ack(depend_tx); |
228 | } | 229 | } |
229 | EXPORT_SYMBOL_GPL(async_tx_submit); | 230 | EXPORT_SYMBOL_GPL(async_tx_submit); |
230 | 231 | ||
231 | /** | 232 | /** |
232 | * async_trigger_callback - schedules the callback function to be run after | 233 | * async_trigger_callback - schedules the callback function to be run |
233 | * any dependent operations have been completed. | 234 | * @submit: submission and completion parameters |
234 | * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK | 235 | * |
235 | * @depend_tx: 'callback' requires the completion of this transaction | 236 | * honored flags: ASYNC_TX_ACK |
236 | * @cb_fn: function to call after depend_tx completes | 237 | * |
237 | * @cb_param: parameter to pass to the callback routine | 238 | * The callback is run after any dependent operations have completed. |
238 | */ | 239 | */ |
239 | struct dma_async_tx_descriptor * | 240 | struct dma_async_tx_descriptor * |
240 | async_trigger_callback(enum async_tx_flags flags, | 241 | async_trigger_callback(struct async_submit_ctl *submit) |
241 | struct dma_async_tx_descriptor *depend_tx, | ||
242 | dma_async_tx_callback cb_fn, void *cb_param) | ||
243 | { | 242 | { |
244 | struct dma_chan *chan; | 243 | struct dma_chan *chan; |
245 | struct dma_device *device; | 244 | struct dma_device *device; |
246 | struct dma_async_tx_descriptor *tx; | 245 | struct dma_async_tx_descriptor *tx; |
246 | struct dma_async_tx_descriptor *depend_tx = submit->depend_tx; | ||
247 | 247 | ||
248 | if (depend_tx) { | 248 | if (depend_tx) { |
249 | chan = depend_tx->chan; | 249 | chan = depend_tx->chan; |
@@ -262,14 +262,14 @@ async_trigger_callback(enum async_tx_flags flags, | |||
262 | if (tx) { | 262 | if (tx) { |
263 | pr_debug("%s: (async)\n", __func__); | 263 | pr_debug("%s: (async)\n", __func__); |
264 | 264 | ||
265 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); | 265 | async_tx_submit(chan, tx, submit); |
266 | } else { | 266 | } else { |
267 | pr_debug("%s: (sync)\n", __func__); | 267 | pr_debug("%s: (sync)\n", __func__); |
268 | 268 | ||
269 | /* wait for any prerequisite operations */ | 269 | /* wait for any prerequisite operations */ |
270 | async_tx_quiesce(&depend_tx); | 270 | async_tx_quiesce(&submit->depend_tx); |
271 | 271 | ||
272 | async_tx_sync_epilog(cb_fn, cb_param); | 272 | async_tx_sync_epilog(submit); |
273 | } | 273 | } |
274 | 274 | ||
275 | return tx; | 275 | return tx; |
@@ -295,9 +295,6 @@ void async_tx_quiesce(struct dma_async_tx_descriptor **tx) | |||
295 | } | 295 | } |
296 | EXPORT_SYMBOL_GPL(async_tx_quiesce); | 296 | EXPORT_SYMBOL_GPL(async_tx_quiesce); |
297 | 297 | ||
298 | module_init(async_tx_init); | ||
299 | module_exit(async_tx_exit); | ||
300 | |||
301 | MODULE_AUTHOR("Intel Corporation"); | 298 | MODULE_AUTHOR("Intel Corporation"); |
302 | MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API"); | 299 | MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API"); |
303 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |