diff options
Diffstat (limited to 'arch/x86/xen/multicalls.c')
-rw-r--r-- | arch/x86/xen/multicalls.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c index 5791eb2e3750..9efd1c6c9776 100644 --- a/arch/x86/xen/multicalls.c +++ b/arch/x86/xen/multicalls.c | |||
@@ -29,14 +29,14 @@ | |||
29 | #define MC_DEBUG 1 | 29 | #define MC_DEBUG 1 |
30 | 30 | ||
31 | #define MC_BATCH 32 | 31 | #define MC_BATCH 32 |
32 | #define MC_ARGS (MC_BATCH * 16 / sizeof(u64)) | 32 | #define MC_ARGS (MC_BATCH * 16) |
33 | 33 | ||
34 | struct mc_buffer { | 34 | struct mc_buffer { |
35 | struct multicall_entry entries[MC_BATCH]; | 35 | struct multicall_entry entries[MC_BATCH]; |
36 | #if MC_DEBUG | 36 | #if MC_DEBUG |
37 | struct multicall_entry debug[MC_BATCH]; | 37 | struct multicall_entry debug[MC_BATCH]; |
38 | #endif | 38 | #endif |
39 | u64 args[MC_ARGS]; | 39 | unsigned char args[MC_ARGS]; |
40 | struct callback { | 40 | struct callback { |
41 | void (*fn)(void *); | 41 | void (*fn)(void *); |
42 | void *data; | 42 | void *data; |
@@ -76,6 +76,7 @@ void xen_mc_flush(void) | |||
76 | if (ret) { | 76 | if (ret) { |
77 | printk(KERN_ERR "%d multicall(s) failed: cpu %d\n", | 77 | printk(KERN_ERR "%d multicall(s) failed: cpu %d\n", |
78 | ret, smp_processor_id()); | 78 | ret, smp_processor_id()); |
79 | dump_stack(); | ||
79 | for (i = 0; i < b->mcidx; i++) { | 80 | for (i = 0; i < b->mcidx; i++) { |
80 | printk(" call %2d/%d: op=%lu arg=[%lx] result=%ld\n", | 81 | printk(" call %2d/%d: op=%lu arg=[%lx] result=%ld\n", |
81 | i+1, b->mcidx, | 82 | i+1, b->mcidx, |
@@ -107,20 +108,48 @@ struct multicall_space __xen_mc_entry(size_t args) | |||
107 | { | 108 | { |
108 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); | 109 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); |
109 | struct multicall_space ret; | 110 | struct multicall_space ret; |
110 | unsigned argspace = (args + sizeof(u64) - 1) / sizeof(u64); | 111 | unsigned argidx = roundup(b->argidx, sizeof(u64)); |
111 | 112 | ||
112 | BUG_ON(preemptible()); | 113 | BUG_ON(preemptible()); |
113 | BUG_ON(argspace > MC_ARGS); | 114 | BUG_ON(b->argidx > MC_ARGS); |
114 | 115 | ||
115 | if (b->mcidx == MC_BATCH || | 116 | if (b->mcidx == MC_BATCH || |
116 | (b->argidx + argspace) > MC_ARGS) | 117 | (argidx + args) > MC_ARGS) { |
117 | xen_mc_flush(); | 118 | xen_mc_flush(); |
119 | argidx = roundup(b->argidx, sizeof(u64)); | ||
120 | } | ||
118 | 121 | ||
119 | ret.mc = &b->entries[b->mcidx]; | 122 | ret.mc = &b->entries[b->mcidx]; |
120 | b->mcidx++; | 123 | b->mcidx++; |
124 | ret.args = &b->args[argidx]; | ||
125 | b->argidx = argidx + args; | ||
126 | |||
127 | BUG_ON(b->argidx > MC_ARGS); | ||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | struct multicall_space xen_mc_extend_args(unsigned long op, size_t size) | ||
132 | { | ||
133 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); | ||
134 | struct multicall_space ret = { NULL, NULL }; | ||
135 | |||
136 | BUG_ON(preemptible()); | ||
137 | BUG_ON(b->argidx > MC_ARGS); | ||
138 | |||
139 | if (b->mcidx == 0) | ||
140 | return ret; | ||
141 | |||
142 | if (b->entries[b->mcidx - 1].op != op) | ||
143 | return ret; | ||
144 | |||
145 | if ((b->argidx + size) > MC_ARGS) | ||
146 | return ret; | ||
147 | |||
148 | ret.mc = &b->entries[b->mcidx - 1]; | ||
121 | ret.args = &b->args[b->argidx]; | 149 | ret.args = &b->args[b->argidx]; |
122 | b->argidx += argspace; | 150 | b->argidx += size; |
123 | 151 | ||
152 | BUG_ON(b->argidx > MC_ARGS); | ||
124 | return ret; | 153 | return ret; |
125 | } | 154 | } |
126 | 155 | ||