/* Routine choices */
 struct raid6_calls {
        void (*gen_syndrome)(int, size_t, void **);
+       void (*xor_syndrome)(int, int, int, size_t, void **);
        int  (*valid)(void);    /* Returns 1 if this routine set is usable */
        const char *name;       /* Name of this routine set */
        int prefer;             /* Has special performance attribute */
 
 static inline const struct raid6_calls *raid6_choose_gen(
        void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks)
 {
-       unsigned long perf, bestperf, j0, j1;
+       unsigned long perf, bestgenperf, bestxorperf, j0, j1;
+       int start = (disks>>1)-1, stop = disks-3;       /* work on the second half of the disks */
        const struct raid6_calls *const *algo;
        const struct raid6_calls *best;
 
-       for (bestperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
+       for (bestgenperf = 0, bestxorperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
                if (!best || (*algo)->prefer >= best->prefer) {
                        if ((*algo)->valid && !(*algo)->valid())
                                continue;
                        }
                        preempt_enable();
 
-                       if (perf > bestperf) {
-                               bestperf = perf;
+                       if (perf > bestgenperf) {
+                               bestgenperf = perf;
                                best = *algo;
                        }
-                       pr_info("raid6: %-8s %5ld MB/s\n", (*algo)->name,
+                       pr_info("raid6: %-8s gen() %5ld MB/s\n", (*algo)->name,
                               (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
+
+                       if (!(*algo)->xor_syndrome)
+                               continue;
+
+                       perf = 0;
+
+                       preempt_disable();
+                       j0 = jiffies;
+                       while ((j1 = jiffies) == j0)
+                               cpu_relax();
+                       while (time_before(jiffies,
+                                           j1 + (1<<RAID6_TIME_JIFFIES_LG2))) {
+                               (*algo)->xor_syndrome(disks, start, stop,
+                                                     PAGE_SIZE, *dptrs);
+                               perf++;
+                       }
+                       preempt_enable();
+
+                       if (best == *algo)
+                               bestxorperf = perf;
+
+                       pr_info("raid6: %-8s xor() %5ld MB/s\n", (*algo)->name,
+                               (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1));
                }
        }
 
        if (best) {
-               pr_info("raid6: using algorithm %s (%ld MB/s)\n",
+               pr_info("raid6: using algorithm %s gen() %ld MB/s\n",
                       best->name,
-                      (bestperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
+                      (bestgenperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
+               if (best->xor_syndrome)
+                       pr_info("raid6: .... xor() %ld MB/s, rmw enabled\n",
+                              (bestxorperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1));
                raid6_call = *best;
        } else
                pr_err("raid6: Yikes!  No algorithm found!\n");
 
 
 const struct raid6_calls raid6_altivec$# = {
        raid6_altivec$#_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_altivec,
        "altivecx$#",
        0
 
 
 const struct raid6_calls raid6_avx2x1 = {
        raid6_avx21_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_avx2,
        "avx2x1",
        1                       /* Has cache hints */
 
 const struct raid6_calls raid6_avx2x2 = {
        raid6_avx22_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_avx2,
        "avx2x2",
        1                       /* Has cache hints */
 
 const struct raid6_calls raid6_avx2x4 = {
        raid6_avx24_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_avx2,
        "avx2x4",
        1                       /* Has cache hints */
 
 
 const struct raid6_calls raid6_intx$# = {
        raid6_int$#_gen_syndrome,
-       NULL,           /* always valid */
+       NULL,                   /* XOR not yet implemented */
+       NULL,                   /* always valid */
        "int" NSTRING "x$#",
        0
 };
 
 
 const struct raid6_calls raid6_mmxx1 = {
        raid6_mmx1_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_mmx,
        "mmxx1",
        0
 
 const struct raid6_calls raid6_mmxx2 = {
        raid6_mmx2_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_mmx,
        "mmxx2",
        0
 
        }                                                               \
        struct raid6_calls const raid6_neonx ## _n = {                  \
                raid6_neon ## _n ## _gen_syndrome,                      \
+               NULL,           /* XOR not yet implemented */           \
                raid6_have_neon,                                        \
                "neonx" #_n,                                            \
                0                                                       \
 
 
 const struct raid6_calls raid6_sse1x1 = {
        raid6_sse11_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse1_or_mmxext,
        "sse1x1",
        1                       /* Has cache hints */
 
 const struct raid6_calls raid6_sse1x2 = {
        raid6_sse12_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse1_or_mmxext,
        "sse1x2",
        1                       /* Has cache hints */
 
 
 const struct raid6_calls raid6_sse2x1 = {
        raid6_sse21_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse2,
        "sse2x1",
        1                       /* Has cache hints */
 
 const struct raid6_calls raid6_sse2x2 = {
        raid6_sse22_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse2,
        "sse2x2",
        1                       /* Has cache hints */
 
 const struct raid6_calls raid6_sse2x4 = {
        raid6_sse24_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse2,
        "sse2x4",
        1                       /* Has cache hints */
 
 
 const struct raid6_calls raid6_tilegx$# = {
        raid6_tilegx$#_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        NULL,
        "tilegx$#",
        0