hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/crypto/async_tx/async_raid6_recov.c
....@@ -1,24 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Asynchronous RAID-6 recovery calculations ASYNC_TX API.
34 * Copyright(c) 2009 Intel Corporation
45 *
56 * based on raid6recov.c:
67 * Copyright 2002 H. Peter Anvin
7
- *
8
- * This program is free software; you can redistribute it and/or modify it
9
- * under the terms of the GNU General Public License as published by the Free
10
- * Software Foundation; either version 2 of the License, or (at your option)
11
- * any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful, but WITHOUT
14
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16
- * more details.
17
- *
18
- * You should have received a copy of the GNU General Public License along with
19
- * this program; if not, write to the Free Software Foundation, Inc., 51
20
- * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21
- *
228 */
239 #include <linux/kernel.h>
2410 #include <linux/interrupt.h>
....@@ -29,8 +15,9 @@
2915 #include <linux/dmaengine.h>
3016
3117 static struct dma_async_tx_descriptor *
32
-async_sum_product(struct page *dest, struct page **srcs, unsigned char *coef,
33
- size_t len, struct async_submit_ctl *submit)
18
+async_sum_product(struct page *dest, unsigned int d_off,
19
+ struct page **srcs, unsigned int *src_offs, unsigned char *coef,
20
+ size_t len, struct async_submit_ctl *submit)
3421 {
3522 struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,
3623 &dest, 1, srcs, 2, len);
....@@ -51,11 +38,14 @@
5138
5239 if (submit->flags & ASYNC_TX_FENCE)
5340 dma_flags |= DMA_PREP_FENCE;
54
- unmap->addr[0] = dma_map_page(dev, srcs[0], 0, len, DMA_TO_DEVICE);
55
- unmap->addr[1] = dma_map_page(dev, srcs[1], 0, len, DMA_TO_DEVICE);
41
+ unmap->addr[0] = dma_map_page(dev, srcs[0], src_offs[0],
42
+ len, DMA_TO_DEVICE);
43
+ unmap->addr[1] = dma_map_page(dev, srcs[1], src_offs[1],
44
+ len, DMA_TO_DEVICE);
5645 unmap->to_cnt = 2;
5746
58
- unmap->addr[2] = dma_map_page(dev, dest, 0, len, DMA_BIDIRECTIONAL);
47
+ unmap->addr[2] = dma_map_page(dev, dest, d_off,
48
+ len, DMA_BIDIRECTIONAL);
5949 unmap->bidi_cnt = 1;
6050 /* engine only looks at Q, but expects it to follow P */
6151 pq[1] = unmap->addr[2];
....@@ -80,9 +70,9 @@
8070 async_tx_quiesce(&submit->depend_tx);
8171 amul = raid6_gfmul[coef[0]];
8272 bmul = raid6_gfmul[coef[1]];
83
- a = page_address(srcs[0]);
84
- b = page_address(srcs[1]);
85
- c = page_address(dest);
73
+ a = page_address(srcs[0]) + src_offs[0];
74
+ b = page_address(srcs[1]) + src_offs[1];
75
+ c = page_address(dest) + d_off;
8676
8777 while (len--) {
8878 ax = amul[*a++];
....@@ -94,8 +84,9 @@
9484 }
9585
9686 static struct dma_async_tx_descriptor *
97
-async_mult(struct page *dest, struct page *src, u8 coef, size_t len,
98
- struct async_submit_ctl *submit)
87
+async_mult(struct page *dest, unsigned int d_off, struct page *src,
88
+ unsigned int s_off, u8 coef, size_t len,
89
+ struct async_submit_ctl *submit)
9990 {
10091 struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,
10192 &dest, 1, &src, 1, len);
....@@ -115,9 +106,11 @@
115106
116107 if (submit->flags & ASYNC_TX_FENCE)
117108 dma_flags |= DMA_PREP_FENCE;
118
- unmap->addr[0] = dma_map_page(dev, src, 0, len, DMA_TO_DEVICE);
109
+ unmap->addr[0] = dma_map_page(dev, src, s_off,
110
+ len, DMA_TO_DEVICE);
119111 unmap->to_cnt++;
120
- unmap->addr[1] = dma_map_page(dev, dest, 0, len, DMA_BIDIRECTIONAL);
112
+ unmap->addr[1] = dma_map_page(dev, dest, d_off,
113
+ len, DMA_BIDIRECTIONAL);
121114 dma_dest[1] = unmap->addr[1];
122115 unmap->bidi_cnt++;
123116 unmap->len = len;
....@@ -147,8 +140,8 @@
147140 */
148141 async_tx_quiesce(&submit->depend_tx);
149142 qmul = raid6_gfmul[coef];
150
- d = page_address(dest);
151
- s = page_address(src);
143
+ d = page_address(dest) + d_off;
144
+ s = page_address(src) + s_off;
152145
153146 while (len--)
154147 *d++ = qmul[*s++];
....@@ -158,11 +151,14 @@
158151
159152 static struct dma_async_tx_descriptor *
160153 __2data_recov_4(int disks, size_t bytes, int faila, int failb,
161
- struct page **blocks, struct async_submit_ctl *submit)
154
+ struct page **blocks, unsigned int *offs,
155
+ struct async_submit_ctl *submit)
162156 {
163157 struct dma_async_tx_descriptor *tx = NULL;
164158 struct page *p, *q, *a, *b;
159
+ unsigned int p_off, q_off, a_off, b_off;
165160 struct page *srcs[2];
161
+ unsigned int src_offs[2];
166162 unsigned char coef[2];
167163 enum async_tx_flags flags = submit->flags;
168164 dma_async_tx_callback cb_fn = submit->cb_fn;
....@@ -170,26 +166,34 @@
170166 void *scribble = submit->scribble;
171167
172168 p = blocks[disks-2];
169
+ p_off = offs[disks-2];
173170 q = blocks[disks-1];
171
+ q_off = offs[disks-1];
174172
175173 a = blocks[faila];
174
+ a_off = offs[faila];
176175 b = blocks[failb];
176
+ b_off = offs[failb];
177177
178178 /* in the 4 disk case P + Pxy == P and Q + Qxy == Q */
179179 /* Dx = A*(P+Pxy) + B*(Q+Qxy) */
180180 srcs[0] = p;
181
+ src_offs[0] = p_off;
181182 srcs[1] = q;
183
+ src_offs[1] = q_off;
182184 coef[0] = raid6_gfexi[failb-faila];
183185 coef[1] = raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]];
184186 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
185
- tx = async_sum_product(b, srcs, coef, bytes, submit);
187
+ tx = async_sum_product(b, b_off, srcs, src_offs, coef, bytes, submit);
186188
187189 /* Dy = P+Pxy+Dx */
188190 srcs[0] = p;
191
+ src_offs[0] = p_off;
189192 srcs[1] = b;
193
+ src_offs[1] = b_off;
190194 init_async_submit(submit, flags | ASYNC_TX_XOR_ZERO_DST, tx, cb_fn,
191195 cb_param, scribble);
192
- tx = async_xor(a, srcs, 0, 2, bytes, submit);
196
+ tx = async_xor_offs(a, a_off, srcs, src_offs, 2, bytes, submit);
193197
194198 return tx;
195199
....@@ -197,11 +201,14 @@
197201
198202 static struct dma_async_tx_descriptor *
199203 __2data_recov_5(int disks, size_t bytes, int faila, int failb,
200
- struct page **blocks, struct async_submit_ctl *submit)
204
+ struct page **blocks, unsigned int *offs,
205
+ struct async_submit_ctl *submit)
201206 {
202207 struct dma_async_tx_descriptor *tx = NULL;
203208 struct page *p, *q, *g, *dp, *dq;
209
+ unsigned int p_off, q_off, g_off, dp_off, dq_off;
204210 struct page *srcs[2];
211
+ unsigned int src_offs[2];
205212 unsigned char coef[2];
206213 enum async_tx_flags flags = submit->flags;
207214 dma_async_tx_callback cb_fn = submit->cb_fn;
....@@ -222,60 +229,77 @@
222229 BUG_ON(good_srcs > 1);
223230
224231 p = blocks[disks-2];
232
+ p_off = offs[disks-2];
225233 q = blocks[disks-1];
234
+ q_off = offs[disks-1];
226235 g = blocks[good];
236
+ g_off = offs[good];
227237
228238 /* Compute syndrome with zero for the missing data pages
229239 * Use the dead data pages as temporary storage for delta p and
230240 * delta q
231241 */
232242 dp = blocks[faila];
243
+ dp_off = offs[faila];
233244 dq = blocks[failb];
245
+ dq_off = offs[failb];
234246
235247 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
236
- tx = async_memcpy(dp, g, 0, 0, bytes, submit);
248
+ tx = async_memcpy(dp, g, dp_off, g_off, bytes, submit);
237249 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
238
- tx = async_mult(dq, g, raid6_gfexp[good], bytes, submit);
250
+ tx = async_mult(dq, dq_off, g, g_off,
251
+ raid6_gfexp[good], bytes, submit);
239252
240253 /* compute P + Pxy */
241254 srcs[0] = dp;
255
+ src_offs[0] = dp_off;
242256 srcs[1] = p;
257
+ src_offs[1] = p_off;
243258 init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,
244259 NULL, NULL, scribble);
245
- tx = async_xor(dp, srcs, 0, 2, bytes, submit);
260
+ tx = async_xor_offs(dp, dp_off, srcs, src_offs, 2, bytes, submit);
246261
247262 /* compute Q + Qxy */
248263 srcs[0] = dq;
264
+ src_offs[0] = dq_off;
249265 srcs[1] = q;
266
+ src_offs[1] = q_off;
250267 init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,
251268 NULL, NULL, scribble);
252
- tx = async_xor(dq, srcs, 0, 2, bytes, submit);
269
+ tx = async_xor_offs(dq, dq_off, srcs, src_offs, 2, bytes, submit);
253270
254271 /* Dx = A*(P+Pxy) + B*(Q+Qxy) */
255272 srcs[0] = dp;
273
+ src_offs[0] = dp_off;
256274 srcs[1] = dq;
275
+ src_offs[1] = dq_off;
257276 coef[0] = raid6_gfexi[failb-faila];
258277 coef[1] = raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]];
259278 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
260
- tx = async_sum_product(dq, srcs, coef, bytes, submit);
279
+ tx = async_sum_product(dq, dq_off, srcs, src_offs, coef, bytes, submit);
261280
262281 /* Dy = P+Pxy+Dx */
263282 srcs[0] = dp;
283
+ src_offs[0] = dp_off;
264284 srcs[1] = dq;
285
+ src_offs[1] = dq_off;
265286 init_async_submit(submit, flags | ASYNC_TX_XOR_DROP_DST, tx, cb_fn,
266287 cb_param, scribble);
267
- tx = async_xor(dp, srcs, 0, 2, bytes, submit);
288
+ tx = async_xor_offs(dp, dp_off, srcs, src_offs, 2, bytes, submit);
268289
269290 return tx;
270291 }
271292
272293 static struct dma_async_tx_descriptor *
273294 __2data_recov_n(int disks, size_t bytes, int faila, int failb,
274
- struct page **blocks, struct async_submit_ctl *submit)
295
+ struct page **blocks, unsigned int *offs,
296
+ struct async_submit_ctl *submit)
275297 {
276298 struct dma_async_tx_descriptor *tx = NULL;
277299 struct page *p, *q, *dp, *dq;
300
+ unsigned int p_off, q_off, dp_off, dq_off;
278301 struct page *srcs[2];
302
+ unsigned int src_offs[2];
279303 unsigned char coef[2];
280304 enum async_tx_flags flags = submit->flags;
281305 dma_async_tx_callback cb_fn = submit->cb_fn;
....@@ -283,56 +307,74 @@
283307 void *scribble = submit->scribble;
284308
285309 p = blocks[disks-2];
310
+ p_off = offs[disks-2];
286311 q = blocks[disks-1];
312
+ q_off = offs[disks-1];
287313
288314 /* Compute syndrome with zero for the missing data pages
289315 * Use the dead data pages as temporary storage for
290316 * delta p and delta q
291317 */
292318 dp = blocks[faila];
319
+ dp_off = offs[faila];
293320 blocks[faila] = NULL;
294321 blocks[disks-2] = dp;
322
+ offs[disks-2] = dp_off;
295323 dq = blocks[failb];
324
+ dq_off = offs[failb];
296325 blocks[failb] = NULL;
297326 blocks[disks-1] = dq;
327
+ offs[disks-1] = dq_off;
298328
299329 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
300
- tx = async_gen_syndrome(blocks, 0, disks, bytes, submit);
330
+ tx = async_gen_syndrome(blocks, offs, disks, bytes, submit);
301331
302332 /* Restore pointer table */
303333 blocks[faila] = dp;
334
+ offs[faila] = dp_off;
304335 blocks[failb] = dq;
336
+ offs[failb] = dq_off;
305337 blocks[disks-2] = p;
338
+ offs[disks-2] = p_off;
306339 blocks[disks-1] = q;
340
+ offs[disks-1] = q_off;
307341
308342 /* compute P + Pxy */
309343 srcs[0] = dp;
344
+ src_offs[0] = dp_off;
310345 srcs[1] = p;
346
+ src_offs[1] = p_off;
311347 init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,
312348 NULL, NULL, scribble);
313
- tx = async_xor(dp, srcs, 0, 2, bytes, submit);
349
+ tx = async_xor_offs(dp, dp_off, srcs, src_offs, 2, bytes, submit);
314350
315351 /* compute Q + Qxy */
316352 srcs[0] = dq;
353
+ src_offs[0] = dq_off;
317354 srcs[1] = q;
355
+ src_offs[1] = q_off;
318356 init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,
319357 NULL, NULL, scribble);
320
- tx = async_xor(dq, srcs, 0, 2, bytes, submit);
358
+ tx = async_xor_offs(dq, dq_off, srcs, src_offs, 2, bytes, submit);
321359
322360 /* Dx = A*(P+Pxy) + B*(Q+Qxy) */
323361 srcs[0] = dp;
362
+ src_offs[0] = dp_off;
324363 srcs[1] = dq;
364
+ src_offs[1] = dq_off;
325365 coef[0] = raid6_gfexi[failb-faila];
326366 coef[1] = raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]];
327367 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
328
- tx = async_sum_product(dq, srcs, coef, bytes, submit);
368
+ tx = async_sum_product(dq, dq_off, srcs, src_offs, coef, bytes, submit);
329369
330370 /* Dy = P+Pxy+Dx */
331371 srcs[0] = dp;
372
+ src_offs[0] = dp_off;
332373 srcs[1] = dq;
374
+ src_offs[1] = dq_off;
333375 init_async_submit(submit, flags | ASYNC_TX_XOR_DROP_DST, tx, cb_fn,
334376 cb_param, scribble);
335
- tx = async_xor(dp, srcs, 0, 2, bytes, submit);
377
+ tx = async_xor_offs(dp, dp_off, srcs, src_offs, 2, bytes, submit);
336378
337379 return tx;
338380 }
....@@ -344,11 +386,13 @@
344386 * @faila: first failed drive index
345387 * @failb: second failed drive index
346388 * @blocks: array of source pointers where the last two entries are p and q
389
+ * @offs: array of offset for pages in blocks
347390 * @submit: submission/completion modifiers
348391 */
349392 struct dma_async_tx_descriptor *
350393 async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
351
- struct page **blocks, struct async_submit_ctl *submit)
394
+ struct page **blocks, unsigned int *offs,
395
+ struct async_submit_ctl *submit)
352396 {
353397 void *scribble = submit->scribble;
354398 int non_zero_srcs, i;
....@@ -372,7 +416,7 @@
372416 if (blocks[i] == NULL)
373417 ptrs[i] = (void *) raid6_empty_zero_page;
374418 else
375
- ptrs[i] = page_address(blocks[i]);
419
+ ptrs[i] = page_address(blocks[i]) + offs[i];
376420
377421 raid6_2data_recov(disks, bytes, faila, failb, ptrs);
378422
....@@ -397,16 +441,19 @@
397441 * explicitly handle the special case of a 4 disk array with
398442 * both data disks missing.
399443 */
400
- return __2data_recov_4(disks, bytes, faila, failb, blocks, submit);
444
+ return __2data_recov_4(disks, bytes, faila, failb,
445
+ blocks, offs, submit);
401446 case 3:
402447 /* dma devices do not uniformly understand a single
403448 * source pq operation (in contrast to the synchronous
404449 * case), so explicitly handle the special case of a 5 disk
405450 * array with 2 of 3 data disks missing.
406451 */
407
- return __2data_recov_5(disks, bytes, faila, failb, blocks, submit);
452
+ return __2data_recov_5(disks, bytes, faila, failb,
453
+ blocks, offs, submit);
408454 default:
409
- return __2data_recov_n(disks, bytes, faila, failb, blocks, submit);
455
+ return __2data_recov_n(disks, bytes, faila, failb,
456
+ blocks, offs, submit);
410457 }
411458 }
412459 EXPORT_SYMBOL_GPL(async_raid6_2data_recov);
....@@ -417,14 +464,17 @@
417464 * @bytes: block size
418465 * @faila: failed drive index
419466 * @blocks: array of source pointers where the last two entries are p and q
467
+ * @offs: array of offset for pages in blocks
420468 * @submit: submission/completion modifiers
421469 */
422470 struct dma_async_tx_descriptor *
423471 async_raid6_datap_recov(int disks, size_t bytes, int faila,
424
- struct page **blocks, struct async_submit_ctl *submit)
472
+ struct page **blocks, unsigned int *offs,
473
+ struct async_submit_ctl *submit)
425474 {
426475 struct dma_async_tx_descriptor *tx = NULL;
427476 struct page *p, *q, *dq;
477
+ unsigned int p_off, q_off, dq_off;
428478 u8 coef;
429479 enum async_tx_flags flags = submit->flags;
430480 dma_async_tx_callback cb_fn = submit->cb_fn;
....@@ -432,6 +482,7 @@
432482 void *scribble = submit->scribble;
433483 int good_srcs, good, i;
434484 struct page *srcs[2];
485
+ unsigned int src_offs[2];
435486
436487 pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
437488
....@@ -448,7 +499,7 @@
448499 if (blocks[i] == NULL)
449500 ptrs[i] = (void*)raid6_empty_zero_page;
450501 else
451
- ptrs[i] = page_address(blocks[i]);
502
+ ptrs[i] = page_address(blocks[i]) + offs[i];
452503
453504 raid6_datap_recov(disks, bytes, faila, ptrs);
454505
....@@ -472,55 +523,67 @@
472523 BUG_ON(good_srcs == 0);
473524
474525 p = blocks[disks-2];
526
+ p_off = offs[disks-2];
475527 q = blocks[disks-1];
528
+ q_off = offs[disks-1];
476529
477530 /* Compute syndrome with zero for the missing data page
478531 * Use the dead data page as temporary storage for delta q
479532 */
480533 dq = blocks[faila];
534
+ dq_off = offs[faila];
481535 blocks[faila] = NULL;
482536 blocks[disks-1] = dq;
537
+ offs[disks-1] = dq_off;
483538
484539 /* in the 4-disk case we only need to perform a single source
485540 * multiplication with the one good data block.
486541 */
487542 if (good_srcs == 1) {
488543 struct page *g = blocks[good];
544
+ unsigned int g_off = offs[good];
489545
490546 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,
491547 scribble);
492
- tx = async_memcpy(p, g, 0, 0, bytes, submit);
548
+ tx = async_memcpy(p, g, p_off, g_off, bytes, submit);
493549
494550 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,
495551 scribble);
496
- tx = async_mult(dq, g, raid6_gfexp[good], bytes, submit);
552
+ tx = async_mult(dq, dq_off, g, g_off,
553
+ raid6_gfexp[good], bytes, submit);
497554 } else {
498555 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL,
499556 scribble);
500
- tx = async_gen_syndrome(blocks, 0, disks, bytes, submit);
557
+ tx = async_gen_syndrome(blocks, offs, disks, bytes, submit);
501558 }
502559
503560 /* Restore pointer table */
504561 blocks[faila] = dq;
562
+ offs[faila] = dq_off;
505563 blocks[disks-1] = q;
564
+ offs[disks-1] = q_off;
506565
507566 /* calculate g^{-faila} */
508567 coef = raid6_gfinv[raid6_gfexp[faila]];
509568
510569 srcs[0] = dq;
570
+ src_offs[0] = dq_off;
511571 srcs[1] = q;
572
+ src_offs[1] = q_off;
512573 init_async_submit(submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,
513574 NULL, NULL, scribble);
514
- tx = async_xor(dq, srcs, 0, 2, bytes, submit);
575
+ tx = async_xor_offs(dq, dq_off, srcs, src_offs, 2, bytes, submit);
515576
516577 init_async_submit(submit, ASYNC_TX_FENCE, tx, NULL, NULL, scribble);
517
- tx = async_mult(dq, dq, coef, bytes, submit);
578
+ tx = async_mult(dq, dq_off, dq, dq_off, coef, bytes, submit);
518579
519580 srcs[0] = p;
581
+ src_offs[0] = p_off;
520582 srcs[1] = dq;
583
+ src_offs[1] = dq_off;
521584 init_async_submit(submit, flags | ASYNC_TX_XOR_DROP_DST, tx, cb_fn,
522585 cb_param, scribble);
523
- tx = async_xor(p, srcs, 0, 2, bytes, submit);
586
+ tx = async_xor_offs(p, p_off, srcs, src_offs, 2, bytes, submit);
524587
525588 return tx;
526589 }