Commit 3499ba81 authored by David Woodhouse's avatar David Woodhouse Committed by Juergen Gross
Browse files

xen: Fix event channel callback via INTX/GSI



For a while, event channel notification via the PCI platform device
has been broken, because we attempt to communicate with xenstore before
we even have notifications working, with the xs_reset_watches() call
in xs_init().

We tend to get away with this on Xen versions below 4.0 because we avoid
calling xs_reset_watches() anyway, because xenstore might not cope with
reading a non-existent key. And newer Xen *does* have the vector
callback support, so we rarely fall back to INTX/GSI delivery.

To fix it, clean up a bit of the mess of xs_init() and xenbus_probe()
startup. Call xs_init() directly from xenbus_init() only in the !XS_HVM
case, deferring it to be called from xenbus_probe() in the XS_HVM case
instead.

Then fix up the invocation of xenbus_probe() to happen either from its
device_initcall if the callback is available early enough, or when the
callback is finally set up. This means that the hack of calling
xenbus_probe() from a workqueue after the first interrupt, or directly
from the PCI platform device setup, is no longer needed.

Signed-off-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
Link: https://lore.kernel.org/r/20210113132606.422794-2-dwmw2@infradead.org


Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
parent ef3a575b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -371,7 +371,7 @@ static int __init xen_guest_init(void)
	}
	gnttab_init();
	if (!xen_initial_domain())
		xenbus_probe(NULL);
		xenbus_probe();

	/*
	 * Making sure board specific code will not set up ops for
+0 −10
Original line number Diff line number Diff line
@@ -2010,16 +2010,6 @@ static struct irq_chip xen_percpu_chip __read_mostly = {
	.irq_ack		= ack_dynirq,
};

int xen_set_callback_via(uint64_t via)
{
	struct xen_hvm_param a;
	a.domid = DOMID_SELF;
	a.index = HVM_PARAM_CALLBACK_IRQ;
	a.value = via;
	return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
}
EXPORT_SYMBOL_GPL(xen_set_callback_via);

#ifdef CONFIG_XEN_PVHVM
/* Vector callbacks are better than PCI interrupts to receive event
 * channel notifications because we can receive vector callbacks on any
+0 −1
Original line number Diff line number Diff line
@@ -149,7 +149,6 @@ static int platform_pci_probe(struct pci_dev *pdev,
	ret = gnttab_init();
	if (ret)
		goto grant_out;
	xenbus_probe(NULL);
	return 0;
grant_out:
	gnttab_free_auto_xlat_frames();
+1 −0
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
		      const char *type,
		      const char *nodename);
int xenbus_probe_devices(struct xen_bus_type *bus);
void xenbus_probe(void);

void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);

+0 −8
Original line number Diff line number Diff line
@@ -57,16 +57,8 @@ DEFINE_MUTEX(xs_response_mutex);
static int xenbus_irq;
static struct task_struct *xenbus_task;

static DECLARE_WORK(probe_work, xenbus_probe);


static irqreturn_t wake_waiting(int irq, void *unused)
{
	if (unlikely(xenstored_ready == 0)) {
		xenstored_ready = 1;
		schedule_work(&probe_work);
	}

	wake_up(&xb_waitq);
	return IRQ_HANDLED;
}
Loading