Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f99a2f0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'stable/bug-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/event: validate irq before get evtchn by irq
  xen/fb: fix potential memory leak
  xen/fb: fix xenfb suspend/resume race.
  xen: disable ACPI NUMA for PV guests
  xen/irq: Cleanup the find_unbound_irq
parents 8c8ae4e8 110e7c7e
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -1174,6 +1174,15 @@ asmlinkage void __init xen_start_kernel(void)


	xen_smp_init();
	xen_smp_init();


#ifdef CONFIG_ACPI_NUMA
	/*
	 * The pages we from Xen are not related to machine pages, so
	 * any NUMA information the kernel tries to get from ACPI will
	 * be meaningless.  Prevent it from trying.
	 */
	acpi_numa = -1;
#endif

	pgd = (pgd_t *)xen_start_info->pt_base;
	pgd = (pgd_t *)xen_start_info->pt_base;


	if (!xen_initial_domain())
	if (!xen_initial_domain())
+11 −8
Original line number Original line Diff line number Diff line
@@ -562,26 +562,24 @@ static void xenfb_init_shared_page(struct xenfb_info *info,
static int xenfb_connect_backend(struct xenbus_device *dev,
static int xenfb_connect_backend(struct xenbus_device *dev,
				 struct xenfb_info *info)
				 struct xenfb_info *info)
{
{
	int ret, evtchn;
	int ret, evtchn, irq;
	struct xenbus_transaction xbt;
	struct xenbus_transaction xbt;


	ret = xenbus_alloc_evtchn(dev, &evtchn);
	ret = xenbus_alloc_evtchn(dev, &evtchn);
	if (ret)
	if (ret)
		return ret;
		return ret;
	ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
	irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
					0, dev->devicetype, info);
					0, dev->devicetype, info);
	if (ret < 0) {
	if (irq < 0) {
		xenbus_free_evtchn(dev, evtchn);
		xenbus_free_evtchn(dev, evtchn);
		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
		return ret;
		return irq;
	}
	}
	info->irq = ret;

 again:
 again:
	ret = xenbus_transaction_start(&xbt);
	ret = xenbus_transaction_start(&xbt);
	if (ret) {
	if (ret) {
		xenbus_dev_fatal(dev, ret, "starting transaction");
		xenbus_dev_fatal(dev, ret, "starting transaction");
		return ret;
		goto unbind_irq;
	}
	}
	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
			    virt_to_mfn(info->page));
			    virt_to_mfn(info->page));
@@ -603,20 +601,25 @@ static int xenfb_connect_backend(struct xenbus_device *dev,
		if (ret == -EAGAIN)
		if (ret == -EAGAIN)
			goto again;
			goto again;
		xenbus_dev_fatal(dev, ret, "completing transaction");
		xenbus_dev_fatal(dev, ret, "completing transaction");
		return ret;
		goto unbind_irq;
	}
	}


	xenbus_switch_state(dev, XenbusStateInitialised);
	xenbus_switch_state(dev, XenbusStateInitialised);
	info->irq = irq;
	return 0;
	return 0;


 error_xenbus:
 error_xenbus:
	xenbus_transaction_end(xbt, 1);
	xenbus_transaction_end(xbt, 1);
	xenbus_dev_fatal(dev, ret, "writing xenstore");
	xenbus_dev_fatal(dev, ret, "writing xenstore");
 unbind_irq:
	unbind_from_irqhandler(irq, info);
	return ret;
	return ret;
}
}


static void xenfb_disconnect_backend(struct xenfb_info *info)
static void xenfb_disconnect_backend(struct xenfb_info *info)
{
{
	/* Prevent xenfb refresh */
	info->update_wanted = 0;
	if (info->irq >= 0)
	if (info->irq >= 0)
		unbind_from_irqhandler(info->irq, info);
		unbind_from_irqhandler(info->irq, info);
	info->irq = -1;
	info->irq = -1;
+15 −6
Original line number Original line Diff line number Diff line
@@ -170,6 +170,9 @@ static struct irq_info *info_for_irq(unsigned irq)


static unsigned int evtchn_from_irq(unsigned irq)
static unsigned int evtchn_from_irq(unsigned irq)
{
{
	if (unlikely(WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq)))
		return 0;

	return info_for_irq(irq)->evtchn;
	return info_for_irq(irq)->evtchn;
}
}


@@ -405,15 +408,21 @@ static int find_unbound_irq(void)
{
{
	struct irq_data *data;
	struct irq_data *data;
	int irq, res;
	int irq, res;
	int start = get_nr_hw_irqs();
	int bottom = get_nr_hw_irqs();
	int top = nr_irqs-1;


	if (start == nr_irqs)
	if (bottom == nr_irqs)
		goto no_irqs;
		goto no_irqs;


	/* nr_irqs is a magic value. Must not use it.*/
	/* This loop starts from the top of IRQ space and goes down.
	for (irq = nr_irqs-1; irq > start; irq--) {
	 * We need this b/c if we have a PCI device in a Xen PV guest
	 * we do not have an IO-APIC (though the backend might have them)
	 * mapped in. To not have a collision of physical IRQs with the Xen
	 * event channels start at the top of the IRQ space for virtual IRQs.
	 */
	for (irq = top; irq > bottom; irq--) {
		data = irq_get_irq_data(irq);
		data = irq_get_irq_data(irq);
		/* only 0->15 have init'd desc; handle irq > 16 */
		/* only 15->0 have init'd desc; handle irq > 16 */
		if (!data)
		if (!data)
			break;
			break;
		if (data->chip == &no_irq_chip)
		if (data->chip == &no_irq_chip)
@@ -424,7 +433,7 @@ static int find_unbound_irq(void)
			return irq;
			return irq;
	}
	}


	if (irq == start)
	if (irq == bottom)
		goto no_irqs;
		goto no_irqs;


	res = irq_alloc_desc_at(irq, -1);
	res = irq_alloc_desc_at(irq, -1);