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"); |
