diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/async_tx/async_memcpy.c | 27 | ||||
-rw-r--r-- | crypto/async_tx/async_memset.c | 20 | ||||
-rw-r--r-- | crypto/async_tx/async_xor.c | 94 |
3 files changed, 83 insertions, 58 deletions
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c index e8c8956ef1dd..faca0bc52068 100644 --- a/crypto/async_tx/async_memcpy.c +++ b/crypto/async_tx/async_memcpy.c | |||
@@ -48,26 +48,25 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, | |||
48 | { | 48 | { |
49 | struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY); | 49 | struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY); |
50 | struct dma_device *device = chan ? chan->device : NULL; | 50 | struct dma_device *device = chan ? chan->device : NULL; |
51 | int int_en = cb_fn ? 1 : 0; | 51 | struct dma_async_tx_descriptor *tx = NULL; |
52 | struct dma_async_tx_descriptor *tx = device ? | ||
53 | device->device_prep_dma_memcpy(chan, len, | ||
54 | int_en) : NULL; | ||
55 | 52 | ||
56 | if (tx) { /* run the memcpy asynchronously */ | 53 | if (device) { |
57 | dma_addr_t addr; | 54 | dma_addr_t dma_dest, dma_src; |
58 | 55 | ||
59 | pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len); | 56 | dma_dest = dma_map_page(device->dev, dest, dest_offset, len, |
57 | DMA_FROM_DEVICE); | ||
60 | 58 | ||
61 | addr = dma_map_page(device->dev, dest, dest_offset, len, | 59 | dma_src = dma_map_page(device->dev, src, src_offset, len, |
62 | DMA_FROM_DEVICE); | 60 | DMA_TO_DEVICE); |
63 | tx->tx_set_dest(addr, tx, 0); | ||
64 | 61 | ||
65 | addr = dma_map_page(device->dev, src, src_offset, len, | 62 | tx = device->device_prep_dma_memcpy(chan, dma_dest, dma_src, |
66 | DMA_TO_DEVICE); | 63 | len, cb_fn != NULL); |
67 | tx->tx_set_src(addr, tx, 0); | 64 | } |
68 | 65 | ||
66 | if (tx) { | ||
67 | pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len); | ||
69 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); | 68 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); |
70 | } else { /* run the memcpy synchronously */ | 69 | } else { |
71 | void *dest_buf, *src_buf; | 70 | void *dest_buf, *src_buf; |
72 | pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len); | 71 | pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len); |
73 | 72 | ||
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c index 760972803958..0c94851cfd37 100644 --- a/crypto/async_tx/async_memset.c +++ b/crypto/async_tx/async_memset.c | |||
@@ -48,20 +48,20 @@ async_memset(struct page *dest, int val, unsigned int offset, | |||
48 | { | 48 | { |
49 | struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET); | 49 | struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET); |
50 | struct dma_device *device = chan ? chan->device : NULL; | 50 | struct dma_device *device = chan ? chan->device : NULL; |
51 | int int_en = cb_fn ? 1 : 0; | 51 | struct dma_async_tx_descriptor *tx = NULL; |
52 | struct dma_async_tx_descriptor *tx = device ? | ||
53 | device->device_prep_dma_memset(chan, val, len, | ||
54 | int_en) : NULL; | ||
55 | 52 | ||
56 | if (tx) { /* run the memset asynchronously */ | 53 | if (device) { |
57 | dma_addr_t dma_addr; | 54 | dma_addr_t dma_dest; |
58 | 55 | ||
59 | pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len); | 56 | dma_dest = dma_map_page(device->dev, dest, offset, len, |
60 | |||
61 | dma_addr = dma_map_page(device->dev, dest, offset, len, | ||
62 | DMA_FROM_DEVICE); | 57 | DMA_FROM_DEVICE); |
63 | tx->tx_set_dest(dma_addr, tx, 0); | ||
64 | 58 | ||
59 | tx = device->device_prep_dma_memset(chan, dma_dest, val, len, | ||
60 | cb_fn != NULL); | ||
61 | } | ||
62 | |||
63 | if (tx) { | ||
64 | pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len); | ||
65 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); | 65 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); |
66 | } else { /* run the memset synchronously */ | 66 | } else { /* run the memset synchronously */ |
67 | void *dest_buf; | 67 | void *dest_buf; |
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c index cb41e6bbbc4d..12cba1a4205b 100644 --- a/crypto/async_tx/async_xor.c +++ b/crypto/async_tx/async_xor.c | |||
@@ -34,29 +34,46 @@ | |||
34 | * This routine is marked __always_inline so it can be compiled away | 34 | * This routine is marked __always_inline so it can be compiled away |
35 | * when CONFIG_DMA_ENGINE=n | 35 | * when CONFIG_DMA_ENGINE=n |
36 | */ | 36 | */ |
37 | static __always_inline void | 37 | static __always_inline struct dma_async_tx_descriptor * |
38 | do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device, | 38 | do_async_xor(struct dma_device *device, |
39 | struct dma_chan *chan, struct page *dest, struct page **src_list, | 39 | struct dma_chan *chan, struct page *dest, struct page **src_list, |
40 | unsigned int offset, unsigned int src_cnt, size_t len, | 40 | unsigned int offset, unsigned int src_cnt, size_t len, |
41 | enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx, | 41 | enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx, |
42 | dma_async_tx_callback cb_fn, void *cb_param) | 42 | dma_async_tx_callback cb_fn, void *cb_param) |
43 | { | 43 | { |
44 | dma_addr_t dma_addr; | 44 | dma_addr_t dma_dest; |
45 | dma_addr_t *dma_src = (dma_addr_t *) src_list; | ||
46 | struct dma_async_tx_descriptor *tx; | ||
45 | int i; | 47 | int i; |
46 | 48 | ||
47 | pr_debug("%s: len: %zu\n", __FUNCTION__, len); | 49 | pr_debug("%s: len: %zu\n", __FUNCTION__, len); |
48 | 50 | ||
49 | dma_addr = dma_map_page(device->dev, dest, offset, len, | 51 | dma_dest = dma_map_page(device->dev, dest, offset, len, |
50 | DMA_FROM_DEVICE); | 52 | DMA_FROM_DEVICE); |
51 | tx->tx_set_dest(dma_addr, tx, 0); | ||
52 | 53 | ||
53 | for (i = 0; i < src_cnt; i++) { | 54 | for (i = 0; i < src_cnt; i++) |
54 | dma_addr = dma_map_page(device->dev, src_list[i], | 55 | dma_src[i] = dma_map_page(device->dev, src_list[i], offset, |
55 | offset, len, DMA_TO_DEVICE); | 56 | len, DMA_TO_DEVICE); |
56 | tx->tx_set_src(dma_addr, tx, i); | 57 | |
58 | /* Since we have clobbered the src_list we are committed | ||
59 | * to doing this asynchronously. Drivers force forward progress | ||
60 | * in case they can not provide a descriptor | ||
61 | */ | ||
62 | tx = device->device_prep_dma_xor(chan, dma_dest, dma_src, src_cnt, len, | ||
63 | cb_fn != NULL); | ||
64 | if (!tx) { | ||
65 | if (depend_tx) | ||
66 | dma_wait_for_async_tx(depend_tx); | ||
67 | |||
68 | while (!tx) | ||
69 | tx = device->device_prep_dma_xor(chan, dma_dest, | ||
70 | dma_src, src_cnt, len, | ||
71 | cb_fn != NULL); | ||
57 | } | 72 | } |
58 | 73 | ||
59 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); | 74 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); |
75 | |||
76 | return tx; | ||
60 | } | 77 | } |
61 | 78 | ||
62 | static void | 79 | static void |
@@ -118,7 +135,7 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset, | |||
118 | void *_cb_param; | 135 | void *_cb_param; |
119 | unsigned long local_flags; | 136 | unsigned long local_flags; |
120 | int xor_src_cnt; | 137 | int xor_src_cnt; |
121 | int i = 0, src_off = 0, int_en; | 138 | int i = 0, src_off = 0; |
122 | 139 | ||
123 | BUG_ON(src_cnt <= 1); | 140 | BUG_ON(src_cnt <= 1); |
124 | 141 | ||
@@ -138,20 +155,11 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset, | |||
138 | _cb_param = cb_param; | 155 | _cb_param = cb_param; |
139 | } | 156 | } |
140 | 157 | ||
141 | int_en = _cb_fn ? 1 : 0; | 158 | tx = do_async_xor(device, chan, dest, |
142 | 159 | &src_list[src_off], offset, | |
143 | tx = device->device_prep_dma_xor( | 160 | xor_src_cnt, len, local_flags, |
144 | chan, xor_src_cnt, len, int_en); | 161 | depend_tx, _cb_fn, _cb_param); |
145 | |||
146 | if (tx) { | ||
147 | do_async_xor(tx, device, chan, dest, | ||
148 | &src_list[src_off], offset, xor_src_cnt, len, | ||
149 | local_flags, depend_tx, _cb_fn, | ||
150 | _cb_param); | ||
151 | } else /* fall through */ | ||
152 | goto xor_sync; | ||
153 | } else { /* run the xor synchronously */ | 162 | } else { /* run the xor synchronously */ |
154 | xor_sync: | ||
155 | /* in the sync case the dest is an implied source | 163 | /* in the sync case the dest is an implied source |
156 | * (assumes the dest is at the src_off index) | 164 | * (assumes the dest is at the src_off index) |
157 | */ | 165 | */ |
@@ -254,23 +262,31 @@ async_xor_zero_sum(struct page *dest, struct page **src_list, | |||
254 | { | 262 | { |
255 | struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM); | 263 | struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM); |
256 | struct dma_device *device = chan ? chan->device : NULL; | 264 | struct dma_device *device = chan ? chan->device : NULL; |
257 | int int_en = cb_fn ? 1 : 0; | 265 | struct dma_async_tx_descriptor *tx = NULL; |
258 | struct dma_async_tx_descriptor *tx = device ? | ||
259 | device->device_prep_dma_zero_sum(chan, src_cnt, len, result, | ||
260 | int_en) : NULL; | ||
261 | int i; | ||
262 | 266 | ||
263 | BUG_ON(src_cnt <= 1); | 267 | BUG_ON(src_cnt <= 1); |
264 | 268 | ||
265 | if (tx) { | 269 | if (device) { |
266 | dma_addr_t dma_addr; | 270 | dma_addr_t *dma_src = (dma_addr_t *) src_list; |
271 | int i; | ||
267 | 272 | ||
268 | pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len); | 273 | pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len); |
269 | 274 | ||
270 | for (i = 0; i < src_cnt; i++) { | 275 | for (i = 0; i < src_cnt; i++) |
271 | dma_addr = dma_map_page(device->dev, src_list[i], | 276 | dma_src[i] = dma_map_page(device->dev, src_list[i], |
272 | offset, len, DMA_TO_DEVICE); | 277 | offset, len, DMA_TO_DEVICE); |
273 | tx->tx_set_src(dma_addr, tx, i); | 278 | |
279 | tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt, | ||
280 | len, result, | ||
281 | cb_fn != NULL); | ||
282 | if (!tx) { | ||
283 | if (depend_tx) | ||
284 | dma_wait_for_async_tx(depend_tx); | ||
285 | |||
286 | while (!tx) | ||
287 | tx = device->device_prep_dma_zero_sum(chan, | ||
288 | dma_src, src_cnt, len, result, | ||
289 | cb_fn != NULL); | ||
274 | } | 290 | } |
275 | 291 | ||
276 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); | 292 | async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param); |
@@ -305,6 +321,16 @@ EXPORT_SYMBOL_GPL(async_xor_zero_sum); | |||
305 | 321 | ||
306 | static int __init async_xor_init(void) | 322 | static int __init async_xor_init(void) |
307 | { | 323 | { |
324 | #ifdef CONFIG_DMA_ENGINE | ||
325 | /* To conserve stack space the input src_list (array of page pointers) | ||
326 | * is reused to hold the array of dma addresses passed to the driver. | ||
327 | * This conversion is only possible when dma_addr_t is less than the | ||
328 | * the size of a pointer. HIGHMEM64G is known to violate this | ||
329 | * assumption. | ||
330 | */ | ||
331 | BUILD_BUG_ON(sizeof(dma_addr_t) > sizeof(struct page *)); | ||
332 | #endif | ||
333 | |||
308 | return 0; | 334 | return 0; |
309 | } | 335 | } |
310 | 336 | ||