Commit 6b476e11 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-4.2-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen bug fixes from David Vrabel:

 - revert a fix from 4.2-rc5 that was causing lots of WARNING spam.

 - fix a memory leak affecting backends in HVM guests.

 - fix PV domU hang with certain configurations.

* tag 'for-linus-4.2-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/xenbus: Don't leak memory when unmapping the ring on HVM backend
  Revert "xen/events/fifo: Handle linked events when closing a port"
  x86/xen: build "Xen PV" APIC driver for domU as well
parents ed596cde c22fe519
...@@ -13,13 +13,13 @@ CFLAGS_mmu.o := $(nostackp) ...@@ -13,13 +13,13 @@ CFLAGS_mmu.o := $(nostackp)
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \ obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
time.o xen-asm.o xen-asm_$(BITS).o \ time.o xen-asm.o xen-asm_$(BITS).o \
grant-table.o suspend.o platform-pci-unplug.o \ grant-table.o suspend.o platform-pci-unplug.o \
p2m.o p2m.o apic.o
obj-$(CONFIG_EVENT_TRACING) += trace.o obj-$(CONFIG_EVENT_TRACING) += trace.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
obj-$(CONFIG_XEN_DOM0) += apic.o vga.o obj-$(CONFIG_XEN_DOM0) += vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
obj-$(CONFIG_XEN_EFI) += efi.o obj-$(CONFIG_XEN_EFI) += efi.o
...@@ -101,17 +101,15 @@ struct dom0_vga_console_info; ...@@ -101,17 +101,15 @@ struct dom0_vga_console_info;
#ifdef CONFIG_XEN_DOM0 #ifdef CONFIG_XEN_DOM0
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
void __init xen_init_apic(void);
#else #else
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
size_t size) size_t size)
{ {
} }
static inline void __init xen_init_apic(void)
{
}
#endif #endif
void __init xen_init_apic(void);
#ifdef CONFIG_XEN_EFI #ifdef CONFIG_XEN_EFI
extern void xen_efi_init(void); extern void xen_efi_init(void);
#else #else
......
...@@ -452,12 +452,10 @@ static void xen_free_irq(unsigned irq) ...@@ -452,12 +452,10 @@ static void xen_free_irq(unsigned irq)
irq_free_desc(irq); irq_free_desc(irq);
} }
static void xen_evtchn_close(unsigned int port, unsigned int cpu) static void xen_evtchn_close(unsigned int port)
{ {
struct evtchn_close close; struct evtchn_close close;
xen_evtchn_op_close(port, cpu);
close.port = port; close.port = port;
if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
BUG(); BUG();
...@@ -546,7 +544,7 @@ static unsigned int __startup_pirq(unsigned int irq) ...@@ -546,7 +544,7 @@ static unsigned int __startup_pirq(unsigned int irq)
err: err:
pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc); pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc);
xen_evtchn_close(evtchn, NR_CPUS); xen_evtchn_close(evtchn);
return 0; return 0;
} }
...@@ -567,7 +565,7 @@ static void shutdown_pirq(struct irq_data *data) ...@@ -567,7 +565,7 @@ static void shutdown_pirq(struct irq_data *data)
return; return;
mask_evtchn(evtchn); mask_evtchn(evtchn);
xen_evtchn_close(evtchn, cpu_from_evtchn(evtchn)); xen_evtchn_close(evtchn);
xen_irq_info_cleanup(info); xen_irq_info_cleanup(info);
} }
...@@ -611,7 +609,7 @@ static void __unbind_from_irq(unsigned int irq) ...@@ -611,7 +609,7 @@ static void __unbind_from_irq(unsigned int irq)
if (VALID_EVTCHN(evtchn)) { if (VALID_EVTCHN(evtchn)) {
unsigned int cpu = cpu_from_irq(irq); unsigned int cpu = cpu_from_irq(irq);
xen_evtchn_close(evtchn, cpu); xen_evtchn_close(evtchn);
switch (type_from_irq(irq)) { switch (type_from_irq(irq)) {
case IRQT_VIRQ: case IRQT_VIRQ:
......
...@@ -255,12 +255,6 @@ static void evtchn_fifo_unmask(unsigned port) ...@@ -255,12 +255,6 @@ static void evtchn_fifo_unmask(unsigned port)
} }
} }
static bool evtchn_fifo_is_linked(unsigned port)
{
event_word_t *word = event_word_from_port(port);
return sync_test_bit(EVTCHN_FIFO_BIT(LINKED, word), BM(word));
}
static uint32_t clear_linked(volatile event_word_t *word) static uint32_t clear_linked(volatile event_word_t *word)
{ {
event_word_t new, old, w; event_word_t new, old, w;
...@@ -287,8 +281,7 @@ static void handle_irq_for_port(unsigned port) ...@@ -287,8 +281,7 @@ static void handle_irq_for_port(unsigned port)
static void consume_one_event(unsigned cpu, static void consume_one_event(unsigned cpu,
struct evtchn_fifo_control_block *control_block, struct evtchn_fifo_control_block *control_block,
unsigned priority, unsigned long *ready, unsigned priority, unsigned long *ready)
bool drop)
{ {
struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
uint32_t head; uint32_t head;
...@@ -320,15 +313,13 @@ static void consume_one_event(unsigned cpu, ...@@ -320,15 +313,13 @@ static void consume_one_event(unsigned cpu,
if (head == 0) if (head == 0)
clear_bit(priority, ready); clear_bit(priority, ready);
if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) { if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
if (likely(!drop)) handle_irq_for_port(port);
handle_irq_for_port(port);
}
q->head[priority] = head; q->head[priority] = head;
} }
static void __evtchn_fifo_handle_events(unsigned cpu, bool drop) static void evtchn_fifo_handle_events(unsigned cpu)
{ {
struct evtchn_fifo_control_block *control_block; struct evtchn_fifo_control_block *control_block;
unsigned long ready; unsigned long ready;
...@@ -340,16 +331,11 @@ static void __evtchn_fifo_handle_events(unsigned cpu, bool drop) ...@@ -340,16 +331,11 @@ static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
while (ready) { while (ready) {
q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES); q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
consume_one_event(cpu, control_block, q, &ready, drop); consume_one_event(cpu, control_block, q, &ready);
ready |= xchg(&control_block->ready, 0); ready |= xchg(&control_block->ready, 0);
} }
} }
static void evtchn_fifo_handle_events(unsigned cpu)
{
__evtchn_fifo_handle_events(cpu, false);
}
static void evtchn_fifo_resume(void) static void evtchn_fifo_resume(void)
{ {
unsigned cpu; unsigned cpu;
...@@ -385,26 +371,6 @@ static void evtchn_fifo_resume(void) ...@@ -385,26 +371,6 @@ static void evtchn_fifo_resume(void)
event_array_pages = 0; event_array_pages = 0;
} }
static void evtchn_fifo_close(unsigned port, unsigned int cpu)
{
if (cpu == NR_CPUS)
return;
get_online_cpus();
if (cpu_online(cpu)) {
if (WARN_ON(irqs_disabled()))
goto out;
while (evtchn_fifo_is_linked(port))
cpu_relax();
} else {
__evtchn_fifo_handle_events(cpu, true);
}
out:
put_online_cpus();
}
static const struct evtchn_ops evtchn_ops_fifo = { static const struct evtchn_ops evtchn_ops_fifo = {
.max_channels = evtchn_fifo_max_channels, .max_channels = evtchn_fifo_max_channels,
.nr_channels = evtchn_fifo_nr_channels, .nr_channels = evtchn_fifo_nr_channels,
...@@ -418,7 +384,6 @@ static const struct evtchn_ops evtchn_ops_fifo = { ...@@ -418,7 +384,6 @@ static const struct evtchn_ops evtchn_ops_fifo = {
.unmask = evtchn_fifo_unmask, .unmask = evtchn_fifo_unmask,
.handle_events = evtchn_fifo_handle_events, .handle_events = evtchn_fifo_handle_events,
.resume = evtchn_fifo_resume, .resume = evtchn_fifo_resume,
.close = evtchn_fifo_close,
}; };
static int evtchn_fifo_alloc_control_block(unsigned cpu) static int evtchn_fifo_alloc_control_block(unsigned cpu)
......
...@@ -68,7 +68,6 @@ struct evtchn_ops { ...@@ -68,7 +68,6 @@ struct evtchn_ops {
bool (*test_and_set_mask)(unsigned port); bool (*test_and_set_mask)(unsigned port);
void (*mask)(unsigned port); void (*mask)(unsigned port);
void (*unmask)(unsigned port); void (*unmask)(unsigned port);
void (*close)(unsigned port, unsigned cpu);
void (*handle_events)(unsigned cpu); void (*handle_events)(unsigned cpu);
void (*resume)(void); void (*resume)(void);
...@@ -146,12 +145,6 @@ static inline void xen_evtchn_resume(void) ...@@ -146,12 +145,6 @@ static inline void xen_evtchn_resume(void)
evtchn_ops->resume(); evtchn_ops->resume();
} }
static inline void xen_evtchn_op_close(unsigned port, unsigned cpu)
{
if (evtchn_ops->close)
return evtchn_ops->close(port, cpu);
}
void xen_evtchn_2l_init(void); void xen_evtchn_2l_init(void);
int xen_evtchn_fifo_init(void); int xen_evtchn_fifo_init(void);
......
...@@ -814,8 +814,10 @@ static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr) ...@@ -814,8 +814,10 @@ static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr)
rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles, rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
addrs); addrs);
if (!rv) if (!rv) {
vunmap(vaddr); vunmap(vaddr);
free_xenballooned_pages(node->nr_handles, node->hvm.pages);
}
else else
WARN(1, "Leaking %p, size %u page(s)\n", vaddr, WARN(1, "Leaking %p, size %u page(s)\n", vaddr,
node->nr_handles); node->nr_handles);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment