#define MC_DEBUG 1
#define MC_BATCH 32
-#define MC_ARGS (MC_BATCH * 16 / sizeof(u64))
+#define MC_ARGS (MC_BATCH * 16)
struct mc_buffer {
struct multicall_entry entries[MC_BATCH];
#if MC_DEBUG
struct multicall_entry debug[MC_BATCH];
#endif
- u64 args[MC_ARGS];
+ unsigned char args[MC_ARGS];
struct callback {
void (*fn)(void *);
void *data;
if (ret) {
printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
ret, smp_processor_id());
- for(i = 0; i < b->mcidx; i++) {
+ for (i = 0; i < b->mcidx; i++) {
printk(" call %2d/%d: op=%lu arg=[%lx] result=%ld\n",
i+1, b->mcidx,
b->debug[i].op,
local_irq_restore(flags);
- for(i = 0; i < b->cbidx; i++) {
+ for (i = 0; i < b->cbidx; i++) {
struct callback *cb = &b->callbacks[i];
(*cb->fn)(cb->data);
{
struct mc_buffer *b = &__get_cpu_var(mc_buffer);
struct multicall_space ret;
- unsigned argspace = (args + sizeof(u64) - 1) / sizeof(u64);
+ unsigned argidx = roundup(b->argidx, sizeof(u64));
BUG_ON(preemptible());
- BUG_ON(argspace > MC_ARGS);
+ BUG_ON(b->argidx > MC_ARGS);
if (b->mcidx == MC_BATCH ||
- (b->argidx + argspace) > MC_ARGS)
+ (argidx + args) > MC_ARGS) {
xen_mc_flush();
+ argidx = roundup(b->argidx, sizeof(u64));
+ }
ret.mc = &b->entries[b->mcidx];
b->mcidx++;
+ ret.args = &b->args[argidx];
+ b->argidx = argidx + args;
+
+ BUG_ON(b->argidx > MC_ARGS);
+ return ret;
+}
+
+struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
+{
+ struct mc_buffer *b = &__get_cpu_var(mc_buffer);
+ struct multicall_space ret = { NULL, NULL };
+
+ BUG_ON(preemptible());
+ BUG_ON(b->argidx > MC_ARGS);
+
+ if (b->mcidx == 0)
+ return ret;
+
+ if (b->entries[b->mcidx - 1].op != op)
+ return ret;
+
+ if ((b->argidx + size) > MC_ARGS)
+ return ret;
+
+ ret.mc = &b->entries[b->mcidx - 1];
ret.args = &b->args[b->argidx];
- b->argidx += argspace;
+ b->argidx += size;
+ BUG_ON(b->argidx > MC_ARGS);
return ret;
}