Commit 7476bd79fc019dd9a8361de6696627a4eae3ef05

Authored by Dan Williams
1 parent 3bbdd49872

async_pq: convert to dmaengine_unmap_data

Use the generic unmap object to unmap dma buffers.

Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
[bzolnier: keep temporary dma_dest array in do_async_gen_syndrome()]
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

Showing 2 changed files with 69 additions and 53 deletions Side-by-side Diff

crypto/async_tx/async_pq.c
... ... @@ -46,50 +46,26 @@
46 46 * do_async_gen_syndrome - asynchronously calculate P and/or Q
47 47 */
48 48 static __async_inline struct dma_async_tx_descriptor *
49   -do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks,
50   - const unsigned char *scfs, unsigned int offset, int disks,
51   - size_t len, dma_addr_t *dma_src,
  49 +do_async_gen_syndrome(struct dma_chan *chan,
  50 + const unsigned char *scfs, int disks,
  51 + struct dmaengine_unmap_data *unmap,
  52 + enum dma_ctrl_flags dma_flags,
52 53 struct async_submit_ctl *submit)
53 54 {
54 55 struct dma_async_tx_descriptor *tx = NULL;
55 56 struct dma_device *dma = chan->device;
56   - enum dma_ctrl_flags dma_flags = 0;
57 57 enum async_tx_flags flags_orig = submit->flags;
58 58 dma_async_tx_callback cb_fn_orig = submit->cb_fn;
59 59 dma_async_tx_callback cb_param_orig = submit->cb_param;
60 60 int src_cnt = disks - 2;
61   - unsigned char coefs[src_cnt];
62 61 unsigned short pq_src_cnt;
63 62 dma_addr_t dma_dest[2];
64 63 int src_off = 0;
65   - int idx;
66   - int i;
67 64  
68   - /* DMAs use destinations as sources, so use BIDIRECTIONAL mapping */
69   - if (P(blocks, disks))
70   - dma_dest[0] = dma_map_page(dma->dev, P(blocks, disks), offset,
71   - len, DMA_BIDIRECTIONAL);
72   - else
73   - dma_flags |= DMA_PREP_PQ_DISABLE_P;
74   - if (Q(blocks, disks))
75   - dma_dest[1] = dma_map_page(dma->dev, Q(blocks, disks), offset,
76   - len, DMA_BIDIRECTIONAL);
77   - else
78   - dma_flags |= DMA_PREP_PQ_DISABLE_Q;
  65 + dma_flags |= DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP;
  66 + if (submit->flags & ASYNC_TX_FENCE)
  67 + dma_flags |= DMA_PREP_FENCE;
79 68  
80   - /* convert source addresses being careful to collapse 'empty'
81   - * sources and update the coefficients accordingly
82   - */
83   - for (i = 0, idx = 0; i < src_cnt; i++) {
84   - if (blocks[i] == NULL)
85   - continue;
86   - dma_src[idx] = dma_map_page(dma->dev, blocks[i], offset, len,
87   - DMA_TO_DEVICE);
88   - coefs[idx] = scfs[i];
89   - idx++;
90   - }
91   - src_cnt = idx;
92   -
93 69 while (src_cnt > 0) {
94 70 submit->flags = flags_orig;
95 71 pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags));
96 72  
97 73  
98 74  
99 75  
100 76  
101 77  
... ... @@ -100,28 +76,25 @@
100 76 if (src_cnt > pq_src_cnt) {
101 77 submit->flags &= ~ASYNC_TX_ACK;
102 78 submit->flags |= ASYNC_TX_FENCE;
103   - dma_flags |= DMA_COMPL_SKIP_DEST_UNMAP;
104 79 submit->cb_fn = NULL;
105 80 submit->cb_param = NULL;
106 81 } else {
107   - dma_flags &= ~DMA_COMPL_SKIP_DEST_UNMAP;
108 82 submit->cb_fn = cb_fn_orig;
109 83 submit->cb_param = cb_param_orig;
110 84 if (cb_fn_orig)
111 85 dma_flags |= DMA_PREP_INTERRUPT;
112 86 }
113   - if (submit->flags & ASYNC_TX_FENCE)
114   - dma_flags |= DMA_PREP_FENCE;
115 87  
116   - /* Since we have clobbered the src_list we are committed
117   - * to doing this asynchronously. Drivers force forward
118   - * progress in case they can not provide a descriptor
  88 + /* Drivers force forward progress in case they can not provide
  89 + * a descriptor
119 90 */
120 91 for (;;) {
  92 + dma_dest[0] = unmap->addr[disks - 2];
  93 + dma_dest[1] = unmap->addr[disks - 1];
121 94 tx = dma->device_prep_dma_pq(chan, dma_dest,
122   - &dma_src[src_off],
  95 + &unmap->addr[src_off],
123 96 pq_src_cnt,
124   - &coefs[src_off], len,
  97 + &scfs[src_off], unmap->len,
125 98 dma_flags);
126 99 if (likely(tx))
127 100 break;
... ... @@ -129,6 +102,7 @@
129 102 dma_async_issue_pending(chan);
130 103 }
131 104  
  105 + dma_set_unmap(tx, unmap);
132 106 async_tx_submit(chan, tx, submit);
133 107 submit->depend_tx = tx;
134 108  
... ... @@ -188,10 +162,6 @@
188 162 * set to NULL those buffers will be replaced with the raid6_zero_page
189 163 * in the synchronous path and omitted in the hardware-asynchronous
190 164 * path.
191   - *
192   - * 'blocks' note: if submit->scribble is NULL then the contents of
193   - * 'blocks' may be overwritten to perform address conversions
194   - * (dma_map_page() or page_address()).
195 165 */
196 166 struct dma_async_tx_descriptor *
197 167 async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
198 168  
199 169  
200 170  
201 171  
202 172  
... ... @@ -202,25 +172,68 @@
202 172 &P(blocks, disks), 2,
203 173 blocks, src_cnt, len);
204 174 struct dma_device *device = chan ? chan->device : NULL;
205   - dma_addr_t *dma_src = NULL;
  175 + struct dmaengine_unmap_data *unmap = NULL;
206 176  
207 177 BUG_ON(disks > 255 || !(P(blocks, disks) || Q(blocks, disks)));
208 178  
209   - if (submit->scribble)
210   - dma_src = submit->scribble;
211   - else if (sizeof(dma_addr_t) <= sizeof(struct page *))
212   - dma_src = (dma_addr_t *) blocks;
  179 + if (device)
  180 + unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO);
213 181  
214   - if (dma_src && device &&
  182 + if (unmap &&
215 183 (src_cnt <= dma_maxpq(device, 0) ||
216 184 dma_maxpq(device, DMA_PREP_CONTINUE) > 0) &&
217 185 is_dma_pq_aligned(device, offset, 0, len)) {
  186 + struct dma_async_tx_descriptor *tx;
  187 + enum dma_ctrl_flags dma_flags = 0;
  188 + unsigned char coefs[src_cnt];
  189 + int i, j;
  190 +
218 191 /* run the p+q asynchronously */
219 192 pr_debug("%s: (async) disks: %d len: %zu\n",
220 193 __func__, disks, len);
221   - return do_async_gen_syndrome(chan, blocks, raid6_gfexp, offset,
222   - disks, len, dma_src, submit);
  194 +
  195 + /* convert source addresses being careful to collapse 'empty'
  196 + * sources and update the coefficients accordingly
  197 + */
  198 + unmap->len = len;
  199 + for (i = 0, j = 0; i < src_cnt; i++) {
  200 + if (blocks[i] == NULL)
  201 + continue;
  202 + unmap->addr[j] = dma_map_page(device->dev, blocks[i], offset,
  203 + len, DMA_TO_DEVICE);
  204 + coefs[j] = raid6_gfexp[i];
  205 + unmap->to_cnt++;
  206 + j++;
  207 + }
  208 +
  209 + /*
  210 + * DMAs use destinations as sources,
  211 + * so use BIDIRECTIONAL mapping
  212 + */
  213 + unmap->bidi_cnt++;
  214 + if (P(blocks, disks))
  215 + unmap->addr[j++] = dma_map_page(device->dev, P(blocks, disks),
  216 + offset, len, DMA_BIDIRECTIONAL);
  217 + else {
  218 + unmap->addr[j++] = 0;
  219 + dma_flags |= DMA_PREP_PQ_DISABLE_P;
  220 + }
  221 +
  222 + unmap->bidi_cnt++;
  223 + if (Q(blocks, disks))
  224 + unmap->addr[j++] = dma_map_page(device->dev, Q(blocks, disks),
  225 + offset, len, DMA_BIDIRECTIONAL);
  226 + else {
  227 + unmap->addr[j++] = 0;
  228 + dma_flags |= DMA_PREP_PQ_DISABLE_Q;
  229 + }
  230 +
  231 + tx = do_async_gen_syndrome(chan, coefs, j, unmap, dma_flags, submit);
  232 + dmaengine_unmap_put(unmap);
  233 + return tx;
223 234 }
  235 +
  236 + dmaengine_unmap_put(unmap);
224 237  
225 238 /* run the pq synchronously */
226 239 pr_debug("%s: (sync) disks: %d len: %zu\n", __func__, disks, len);
drivers/dma/dmaengine.c
... ... @@ -953,9 +953,12 @@
953 953 dma_unmap_page(dev, unmap->addr[i], unmap->len,
954 954 DMA_FROM_DEVICE);
955 955 cnt += unmap->bidi_cnt;
956   - for (; i < cnt; i++)
  956 + for (; i < cnt; i++) {
  957 + if (unmap->addr[i] == 0)
  958 + continue;
957 959 dma_unmap_page(dev, unmap->addr[i], unmap->len,
958 960 DMA_BIDIRECTIONAL);
  961 + }
959 962 mempool_free(unmap, __get_unmap_pool(cnt)->pool);
960 963 }
961 964