aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/xor.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2007-07-09 14:56:42 -0400
committerDan Williams <dan.j.williams@intel.com>2007-07-13 11:06:14 -0400
commit685784aaf3cd0e3ff5e36c7ecf6f441cdbf57f73 (patch)
tree10f99829f7d877b87614fe69be77e363c026a8d7 /crypto/xor.c
parentd379b01e9087a582d58f4b678208a4f8d8376fe7 (diff)
xor: make 'xor_blocks' a library routine for use with async_tx
The async_tx api tries to use a dma engine for an operation, but will fall back to an optimized software routine otherwise. Xor support is implemented using the raid5 xor routines. For organizational purposes this routine is moved to a common area. The following fixes are also made: * rename xor_block => xor_blocks, suggested by Adrian Bunk * ensure that xor.o initializes before md.o in the built-in case * checkpatch.pl fixes * mark calibrate_xor_blocks __init, Adrian Bunk Cc: Adrian Bunk <bunk@stusta.de> Cc: NeilBrown <neilb@suse.de> Cc: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'crypto/xor.c')
-rw-r--r--crypto/xor.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/crypto/xor.c b/crypto/xor.c
new file mode 100644
index 000000000000..8281ac5e68a8
--- /dev/null
+++ b/crypto/xor.c
@@ -0,0 +1,156 @@
1/*
2 * xor.c : Multiple Devices driver for Linux
3 *
4 * Copyright (C) 1996, 1997, 1998, 1999, 2000,
5 * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson.
6 *
7 * Dispatch optimized RAID-5 checksumming functions.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * You should have received a copy of the GNU General Public License
15 * (for example /usr/src/linux/COPYING); if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19#define BH_TRACE 0
20#include <linux/module.h>
21#include <linux/raid/md.h>
22#include <linux/raid/xor.h>
23#include <asm/xor.h>
24
25/* The xor routines to use. */
26static struct xor_block_template *active_template;
27
28void
29xor_blocks(unsigned int count, unsigned int bytes, void **ptr)
30{
31 unsigned long *p0, *p1, *p2, *p3, *p4;
32
33 p0 = (unsigned long *) ptr[0];
34 p1 = (unsigned long *) ptr[1];
35 if (count == 2) {
36 active_template->do_2(bytes, p0, p1);
37 return;
38 }
39
40 p2 = (unsigned long *) ptr[2];
41 if (count == 3) {
42 active_template->do_3(bytes, p0, p1, p2);
43 return;
44 }
45
46 p3 = (unsigned long *) ptr[3];
47 if (count == 4) {
48 active_template->do_4(bytes, p0, p1, p2, p3);
49 return;
50 }
51
52 p4 = (unsigned long *) ptr[4];
53 active_template->do_5(bytes, p0, p1, p2, p3, p4);
54}
55EXPORT_SYMBOL(xor_blocks);
56
57/* Set of all registered templates. */
58static struct xor_block_template *template_list;
59
60#define BENCH_SIZE (PAGE_SIZE)
61
62static void
63do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
64{
65 int speed;
66 unsigned long now;
67 int i, count, max;
68
69 tmpl->next = template_list;
70 template_list = tmpl;
71
72 /*
73 * Count the number of XORs done during a whole jiffy, and use
74 * this to calculate the speed of checksumming. We use a 2-page
75 * allocation to have guaranteed color L1-cache layout.
76 */
77 max = 0;
78 for (i = 0; i < 5; i++) {
79 now = jiffies;
80 count = 0;
81 while (jiffies == now) {
82 mb(); /* prevent loop optimzation */
83 tmpl->do_2(BENCH_SIZE, b1, b2);
84 mb();
85 count++;
86 mb();
87 }
88 if (count > max)
89 max = count;
90 }
91
92 speed = max * (HZ * BENCH_SIZE / 1024);
93 tmpl->speed = speed;
94
95 printk(KERN_INFO " %-10s: %5d.%03d MB/sec\n", tmpl->name,
96 speed / 1000, speed % 1000);
97}
98
99static int __init
100calibrate_xor_blocks(void)
101{
102 void *b1, *b2;
103 struct xor_block_template *f, *fastest;
104
105 b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
106 if (!b1) {
107 printk(KERN_WARNING "xor: Yikes! No memory available.\n");
108 return -ENOMEM;
109 }
110 b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
111
112 /*
113 * If this arch/cpu has a short-circuited selection, don't loop through
114 * all the possible functions, just test the best one
115 */
116
117 fastest = NULL;
118
119#ifdef XOR_SELECT_TEMPLATE
120 fastest = XOR_SELECT_TEMPLATE(fastest);
121#endif
122
123#define xor_speed(templ) do_xor_speed((templ), b1, b2)
124
125 if (fastest) {
126 printk(KERN_INFO "xor: automatically using best "
127 "checksumming function: %s\n",
128 fastest->name);
129 xor_speed(fastest);
130 } else {
131 printk(KERN_INFO "xor: measuring checksumming speed\n");
132 XOR_TRY_TEMPLATES;
133 fastest = template_list;
134 for (f = fastest; f; f = f->next)
135 if (f->speed > fastest->speed)
136 fastest = f;
137 }
138
139 printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
140 fastest->name, fastest->speed / 1000, fastest->speed % 1000);
141
142#undef xor_speed
143
144 free_pages((unsigned long)b1, 2);
145
146 active_template = fastest;
147 return 0;
148}
149
150static __exit void xor_exit(void) { }
151
152MODULE_LICENSE("GPL");
153
154/* when built-in xor.o must initialize before drivers/md/md.o */
155core_initcall(calibrate_xor_blocks);
156module_exit(xor_exit);