root/lib/raid6/recov_s390xc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xor_block
  2. raid6_2data_recov_s390xc
  3. raid6_datap_recov_s390xc

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * RAID-6 data recovery in dual failure mode based on the XC instruction.
   4  *
   5  * Copyright IBM Corp. 2016
   6  * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
   7  */
   8 
   9 #include <linux/export.h>
  10 #include <linux/raid/pq.h>
  11 
  12 static inline void xor_block(u8 *p1, u8 *p2)
  13 {
  14         typedef struct { u8 _[256]; } addrtype;
  15 
  16         asm volatile(
  17                 "       xc      0(256,%[p1]),0(%[p2])\n"
  18                 : "+m" (*(addrtype *) p1) : "m" (*(addrtype *) p2),
  19                   [p1] "a" (p1), [p2] "a" (p2) : "cc");
  20 }
  21 
  22 /* Recover two failed data blocks. */
  23 static void raid6_2data_recov_s390xc(int disks, size_t bytes, int faila,
  24                 int failb, void **ptrs)
  25 {
  26         u8 *p, *q, *dp, *dq;
  27         const u8 *pbmul;        /* P multiplier table for B data */
  28         const u8 *qmul;         /* Q multiplier table (for both) */
  29         int i;
  30 
  31         p = (u8 *)ptrs[disks-2];
  32         q = (u8 *)ptrs[disks-1];
  33 
  34         /* Compute syndrome with zero for the missing data pages
  35            Use the dead data pages as temporary storage for
  36            delta p and delta q */
  37         dp = (u8 *)ptrs[faila];
  38         ptrs[faila] = (void *)raid6_empty_zero_page;
  39         ptrs[disks-2] = dp;
  40         dq = (u8 *)ptrs[failb];
  41         ptrs[failb] = (void *)raid6_empty_zero_page;
  42         ptrs[disks-1] = dq;
  43 
  44         raid6_call.gen_syndrome(disks, bytes, ptrs);
  45 
  46         /* Restore pointer table */
  47         ptrs[faila]   = dp;
  48         ptrs[failb]   = dq;
  49         ptrs[disks-2] = p;
  50         ptrs[disks-1] = q;
  51 
  52         /* Now, pick the proper data tables */
  53         pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
  54         qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
  55 
  56         /* Now do it... */
  57         while (bytes) {
  58                 xor_block(dp, p);
  59                 xor_block(dq, q);
  60                 for (i = 0; i < 256; i++)
  61                         dq[i] = pbmul[dp[i]] ^ qmul[dq[i]];
  62                 xor_block(dp, dq);
  63                 p += 256;
  64                 q += 256;
  65                 dp += 256;
  66                 dq += 256;
  67                 bytes -= 256;
  68         }
  69 }
  70 
  71 /* Recover failure of one data block plus the P block */
  72 static void raid6_datap_recov_s390xc(int disks, size_t bytes, int faila,
  73                 void **ptrs)
  74 {
  75         u8 *p, *q, *dq;
  76         const u8 *qmul;         /* Q multiplier table */
  77         int i;
  78 
  79         p = (u8 *)ptrs[disks-2];
  80         q = (u8 *)ptrs[disks-1];
  81 
  82         /* Compute syndrome with zero for the missing data page
  83            Use the dead data page as temporary storage for delta q */
  84         dq = (u8 *)ptrs[faila];
  85         ptrs[faila] = (void *)raid6_empty_zero_page;
  86         ptrs[disks-1] = dq;
  87 
  88         raid6_call.gen_syndrome(disks, bytes, ptrs);
  89 
  90         /* Restore pointer table */
  91         ptrs[faila]   = dq;
  92         ptrs[disks-1] = q;
  93 
  94         /* Now, pick the proper data tables */
  95         qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
  96 
  97         /* Now do it... */
  98         while (bytes) {
  99                 xor_block(dq, q);
 100                 for (i = 0; i < 256; i++)
 101                         dq[i] = qmul[dq[i]];
 102                 xor_block(p, dq);
 103                 p += 256;
 104                 q += 256;
 105                 dq += 256;
 106                 bytes -= 256;
 107         }
 108 }
 109 
 110 
 111 const struct raid6_recov_calls raid6_recov_s390xc = {
 112         .data2 = raid6_2data_recov_s390xc,
 113         .datap = raid6_datap_recov_s390xc,
 114         .valid = NULL,
 115         .name = "s390xc",
 116         .priority = 1,
 117 };

/* [<][>][^][v][top][bottom][index][help] */