From: jbeulich@novell.com Subject: netback: use multicall for send multiple notifications Patch-mainline: obsolete This also yields a small fairness improvement since now notifications get sent in the order requests came in rather than in the inverse one. --- head-2011-02-08.orig/drivers/xen/core/evtchn.c 2011-02-16 08:29:29.000000000 +0100 +++ head-2011-02-08/drivers/xen/core/evtchn.c 2011-02-16 08:29:50.000000000 +0100 @@ -1473,6 +1473,27 @@ void notify_remote_via_irq(int irq) } EXPORT_SYMBOL_GPL(notify_remote_via_irq); +#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE) +int multi_notify_remote_via_irq(multicall_entry_t *mcl, int irq) +{ + const struct irq_cfg *cfg = irq_cfg(irq); + int evtchn; + + if (WARN_ON_ONCE(!cfg)) + return -EINVAL; + BUG_ON(type_from_irq_cfg(cfg) == IRQT_VIRQ); + BUG_IF_IPI(cfg); + + evtchn = evtchn_from_irq_cfg(cfg); + if (!VALID_EVTCHN(evtchn)) + return -EINVAL; + + multi_notify_remote_via_evtchn(mcl, evtchn); + return 0; +} +EXPORT_SYMBOL_GPL(multi_notify_remote_via_irq); +#endif + int irq_to_evtchn_port(int irq) { const struct irq_cfg *cfg = irq_cfg(irq); --- head-2011-02-08.orig/drivers/xen/netback/netback.c 2011-01-03 13:30:08.000000000 +0100 +++ head-2011-02-08/drivers/xen/netback/netback.c 2011-01-03 13:30:15.000000000 +0100 @@ -767,10 +767,20 @@ static void net_rx_action(unsigned long npo.meta_cons += nr_frags + 1; } - while (notify_nr != 0) { - irq = notify_list[--notify_nr]; + if (notify_nr == 1) { + irq = *notify_list; __clear_bit(irq, rx_notify); notify_remote_via_irq(irq + DYNIRQ_BASE); + } else { + for (count = ret = 0; ret < notify_nr; ++ret) { + irq = notify_list[ret]; + __clear_bit(irq, rx_notify); + if (!multi_notify_remote_via_irq(rx_mcl + count, + irq + DYNIRQ_BASE)) + ++count; + } + if (HYPERVISOR_multicall(rx_mcl, count)) + BUG(); } /* More work to do? */ --- head-2011-02-08.orig/include/xen/evtchn.h 2010-11-23 16:18:23.000000000 +0100 +++ head-2011-02-08/include/xen/evtchn.h 2010-11-23 16:20:08.000000000 +0100 @@ -193,6 +193,18 @@ static inline void notify_remote_via_evt VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send)); } +static inline void +multi_notify_remote_via_evtchn(multicall_entry_t *mcl, int port) +{ + struct evtchn_send *send = (void *)(mcl->args + 2); + + BUILD_BUG_ON(sizeof(*send) > sizeof(mcl->args) - 2 * sizeof(*mcl->args)); + send->port = port; + mcl->op = __HYPERVISOR_event_channel_op; + mcl->args[0] = EVTCHNOP_send; + mcl->args[1] = (unsigned long)send; +} + static inline int close_evtchn(int port) { struct evtchn_close close = { .port = port }; @@ -207,6 +219,7 @@ int xen_test_irq_pending(int irq); * by bind_*_to_irqhandler(). */ void notify_remote_via_irq(int irq); +int multi_notify_remote_via_irq(multicall_entry_t *, int irq); int irq_to_evtchn_port(int irq); #if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)