19e229025SChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-or-later 29e229025SChristoph Hellwig /* 39e229025SChristoph Hellwig * Copyright (C) 1996, 1997, 1998, 1999, 2000, 49e229025SChristoph Hellwig * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson. 59e229025SChristoph Hellwig * 67c6e6b2bSChristoph Hellwig * Dispatch optimized XOR parity functions. 79e229025SChristoph Hellwig */ 89e229025SChristoph Hellwig 99e229025SChristoph Hellwig #include <linux/module.h> 109e229025SChristoph Hellwig #include <linux/gfp.h> 119e229025SChristoph Hellwig #include <linux/raid/xor.h> 129e229025SChristoph Hellwig #include <linux/jiffies.h> 139e229025SChristoph Hellwig #include <linux/preempt.h> 14*a21921ddSChristoph Hellwig #include <linux/static_call.h> 15e20043b4SChristoph Hellwig #include "xor_impl.h" 169e229025SChristoph Hellwig 17*a21921ddSChristoph Hellwig DEFINE_STATIC_CALL_NULL(xor_gen_impl, *xor_block_8regs.xor_gen); 189e229025SChristoph Hellwig 19e420f0a8SChristoph Hellwig /** 20e420f0a8SChristoph Hellwig * xor_gen - generate RAID-style XOR information 21e420f0a8SChristoph Hellwig * @dest: destination vector 22e420f0a8SChristoph Hellwig * @srcs: source vectors 23e420f0a8SChristoph Hellwig * @src_cnt: number of source vectors 24e420f0a8SChristoph Hellwig * @bytes: length in bytes of each vector 25e420f0a8SChristoph Hellwig * 26e420f0a8SChristoph Hellwig * Performs bit-wise XOR operation into @dest for each of the @src_cnt vectors 27e420f0a8SChristoph Hellwig * in @srcs for a length of @bytes bytes. @src_cnt must be non-zero, and the 28e420f0a8SChristoph Hellwig * memory pointed to by @dest and each member of @srcs must be at least 64-byte 29e420f0a8SChristoph Hellwig * aligned. @bytes must be non-zero and a multiple of 512. 30e420f0a8SChristoph Hellwig * 31e420f0a8SChristoph Hellwig * Note: for typical RAID uses, @dest either needs to be zeroed, or filled with 32e420f0a8SChristoph Hellwig * the first disk, which then needs to be removed from @srcs. 33e420f0a8SChristoph Hellwig */ 34e420f0a8SChristoph Hellwig void xor_gen(void *dest, void **srcs, unsigned int src_cnt, unsigned int bytes) 35e420f0a8SChristoph Hellwig { 3680dcf0a7SChristoph Hellwig WARN_ON_ONCE(!in_task() || irqs_disabled() || softirq_count()); 37e420f0a8SChristoph Hellwig WARN_ON_ONCE(bytes == 0); 38e420f0a8SChristoph Hellwig WARN_ON_ONCE(bytes & 511); 39e420f0a8SChristoph Hellwig 40*a21921ddSChristoph Hellwig static_call(xor_gen_impl)(dest, srcs, src_cnt, bytes); 41e420f0a8SChristoph Hellwig } 42e420f0a8SChristoph Hellwig EXPORT_SYMBOL(xor_gen); 43e420f0a8SChristoph Hellwig 449e229025SChristoph Hellwig /* Set of all registered templates. */ 459e229025SChristoph Hellwig static struct xor_block_template *__initdata template_list; 46*a21921ddSChristoph Hellwig static struct xor_block_template *forced_template; 479e229025SChristoph Hellwig 4835ebc4deSChristoph Hellwig /** 4935ebc4deSChristoph Hellwig * xor_register - register a XOR template 5035ebc4deSChristoph Hellwig * @tmpl: template to register 5135ebc4deSChristoph Hellwig * 5235ebc4deSChristoph Hellwig * Register a XOR implementation with the core. Registered implementations 5335ebc4deSChristoph Hellwig * will be measured by a trivial benchmark, and the fastest one is chosen 5435ebc4deSChristoph Hellwig * unless an implementation is forced using xor_force(). 5535ebc4deSChristoph Hellwig */ 5635ebc4deSChristoph Hellwig void __init xor_register(struct xor_block_template *tmpl) 579e229025SChristoph Hellwig { 589e229025SChristoph Hellwig tmpl->next = template_list; 599e229025SChristoph Hellwig template_list = tmpl; 609e229025SChristoph Hellwig } 619e229025SChristoph Hellwig 6235ebc4deSChristoph Hellwig /** 6335ebc4deSChristoph Hellwig * xor_force - force use of a XOR template 6435ebc4deSChristoph Hellwig * @tmpl: template to register 6535ebc4deSChristoph Hellwig * 6635ebc4deSChristoph Hellwig * Register a XOR implementation with the core and force using it. Forcing 6735ebc4deSChristoph Hellwig * an implementation will make the core ignore any template registered using 6835ebc4deSChristoph Hellwig * xor_register(), or any previous implementation forced using xor_force(). 6935ebc4deSChristoph Hellwig */ 7035ebc4deSChristoph Hellwig void __init xor_force(struct xor_block_template *tmpl) 7135ebc4deSChristoph Hellwig { 72*a21921ddSChristoph Hellwig forced_template = tmpl; 7335ebc4deSChristoph Hellwig } 7435ebc4deSChristoph Hellwig 759e229025SChristoph Hellwig #define BENCH_SIZE 4096 769e229025SChristoph Hellwig #define REPS 800U 779e229025SChristoph Hellwig 789e229025SChristoph Hellwig static void __init 799e229025SChristoph Hellwig do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) 809e229025SChristoph Hellwig { 819e229025SChristoph Hellwig int speed; 829e229025SChristoph Hellwig unsigned long reps; 839e229025SChristoph Hellwig ktime_t min, start, t0; 8480dcf0a7SChristoph Hellwig void *srcs[1] = { b2 }; 859e229025SChristoph Hellwig 869e229025SChristoph Hellwig preempt_disable(); 879e229025SChristoph Hellwig 889e229025SChristoph Hellwig reps = 0; 899e229025SChristoph Hellwig t0 = ktime_get(); 909e229025SChristoph Hellwig /* delay start until time has advanced */ 919e229025SChristoph Hellwig while ((start = ktime_get()) == t0) 929e229025SChristoph Hellwig cpu_relax(); 939e229025SChristoph Hellwig do { 949e229025SChristoph Hellwig mb(); /* prevent loop optimization */ 9580dcf0a7SChristoph Hellwig tmpl->xor_gen(b1, srcs, 1, BENCH_SIZE); 969e229025SChristoph Hellwig mb(); 979e229025SChristoph Hellwig } while (reps++ < REPS || (t0 = ktime_get()) == start); 989e229025SChristoph Hellwig min = ktime_sub(t0, start); 999e229025SChristoph Hellwig 1009e229025SChristoph Hellwig preempt_enable(); 1019e229025SChristoph Hellwig 1029e229025SChristoph Hellwig // bytes/ns == GB/s, multiply by 1000 to get MB/s [not MiB/s] 1039e229025SChristoph Hellwig speed = (1000 * reps * BENCH_SIZE) / (unsigned int)ktime_to_ns(min); 1049e229025SChristoph Hellwig tmpl->speed = speed; 1059e229025SChristoph Hellwig 1069e229025SChristoph Hellwig pr_info(" %-16s: %5d MB/sec\n", tmpl->name, speed); 1079e229025SChristoph Hellwig } 1089e229025SChristoph Hellwig 1090471415fSChristoph Hellwig static int __init calibrate_xor_blocks(void) 1109e229025SChristoph Hellwig { 1119e229025SChristoph Hellwig void *b1, *b2; 1129e229025SChristoph Hellwig struct xor_block_template *f, *fastest; 1139e229025SChristoph Hellwig 114*a21921ddSChristoph Hellwig if (forced_template) 1150471415fSChristoph Hellwig return 0; 1169e229025SChristoph Hellwig 1179e229025SChristoph Hellwig b1 = (void *) __get_free_pages(GFP_KERNEL, 2); 1189e229025SChristoph Hellwig if (!b1) { 1190471415fSChristoph Hellwig pr_warn("xor: Yikes! No memory available.\n"); 1209e229025SChristoph Hellwig return -ENOMEM; 1219e229025SChristoph Hellwig } 1229e229025SChristoph Hellwig b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE; 1239e229025SChristoph Hellwig 1240471415fSChristoph Hellwig pr_info("xor: measuring software checksum speed\n"); 1259e229025SChristoph Hellwig fastest = template_list; 1260471415fSChristoph Hellwig for (f = template_list; f; f = f->next) { 1270471415fSChristoph Hellwig do_xor_speed(f, b1, b2); 1289e229025SChristoph Hellwig if (f->speed > fastest->speed) 1299e229025SChristoph Hellwig fastest = f; 1300471415fSChristoph Hellwig } 131*a21921ddSChristoph Hellwig static_call_update(xor_gen_impl, fastest->xor_gen); 1329e229025SChristoph Hellwig pr_info("xor: using function: %s (%d MB/sec)\n", 1339e229025SChristoph Hellwig fastest->name, fastest->speed); 1349e229025SChristoph Hellwig 1359e229025SChristoph Hellwig free_pages((unsigned long)b1, 2); 1369e229025SChristoph Hellwig return 0; 1379e229025SChristoph Hellwig } 1389e229025SChristoph Hellwig 139e20043b4SChristoph Hellwig #ifdef CONFIG_XOR_BLOCKS_ARCH 140e20043b4SChristoph Hellwig #include "xor_arch.h" /* $SRCARCH/xor_arch.h */ 14135ebc4deSChristoph Hellwig #else 142e20043b4SChristoph Hellwig static void __init arch_xor_init(void) 143e20043b4SChristoph Hellwig { 14435ebc4deSChristoph Hellwig xor_register(&xor_block_8regs); 14535ebc4deSChristoph Hellwig xor_register(&xor_block_8regs_p); 14635ebc4deSChristoph Hellwig xor_register(&xor_block_32regs); 14735ebc4deSChristoph Hellwig xor_register(&xor_block_32regs_p); 148e20043b4SChristoph Hellwig } 149e20043b4SChristoph Hellwig #endif /* CONFIG_XOR_BLOCKS_ARCH */ 150e20043b4SChristoph Hellwig 151e20043b4SChristoph Hellwig static int __init xor_init(void) 152e20043b4SChristoph Hellwig { 153e20043b4SChristoph Hellwig arch_xor_init(); 15435ebc4deSChristoph Hellwig 1550471415fSChristoph Hellwig /* 1560471415fSChristoph Hellwig * If this arch/cpu has a short-circuited selection, don't loop through 1570471415fSChristoph Hellwig * all the possible functions, just use the best one. 1580471415fSChristoph Hellwig */ 159*a21921ddSChristoph Hellwig if (forced_template) { 1600471415fSChristoph Hellwig pr_info("xor: automatically using best checksumming function %-10s\n", 161*a21921ddSChristoph Hellwig forced_template->name); 162*a21921ddSChristoph Hellwig static_call_update(xor_gen_impl, forced_template->xor_gen); 1630471415fSChristoph Hellwig return 0; 1640471415fSChristoph Hellwig } 1650471415fSChristoph Hellwig 1660471415fSChristoph Hellwig #ifdef MODULE 1670471415fSChristoph Hellwig return calibrate_xor_blocks(); 1680471415fSChristoph Hellwig #else 1690471415fSChristoph Hellwig /* 1700471415fSChristoph Hellwig * Pick the first template as the temporary default until calibration 1710471415fSChristoph Hellwig * happens. 1720471415fSChristoph Hellwig */ 173*a21921ddSChristoph Hellwig static_call_update(xor_gen_impl, template_list->xor_gen); 1740471415fSChristoph Hellwig return 0; 1750471415fSChristoph Hellwig #endif 1760471415fSChristoph Hellwig } 1770471415fSChristoph Hellwig 1780471415fSChristoph Hellwig static __exit void xor_exit(void) 1790471415fSChristoph Hellwig { 1800471415fSChristoph Hellwig } 1819e229025SChristoph Hellwig 1829e229025SChristoph Hellwig MODULE_DESCRIPTION("RAID-5 checksumming functions"); 1839e229025SChristoph Hellwig MODULE_LICENSE("GPL"); 1849e229025SChristoph Hellwig 1850471415fSChristoph Hellwig /* 1860471415fSChristoph Hellwig * When built-in we must register the default template before md, but we don't 1870471415fSChristoph Hellwig * want calibration to run that early as that would delay the boot process. 1880471415fSChristoph Hellwig */ 1899e229025SChristoph Hellwig #ifndef MODULE 1900471415fSChristoph Hellwig __initcall(calibrate_xor_blocks); 1919e229025SChristoph Hellwig #endif 1920471415fSChristoph Hellwig core_initcall(xor_init); 1939e229025SChristoph Hellwig module_exit(xor_exit); 194