From: David Vrabel <david.vrabel@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>,
Boris Ostrovsky <boris.ostrovsky@oracle.com>,
Sander Eikelenboom <linux@eikelenboom.it>,
David Vrabel <david.vrabel@citrix.com>
Subject: [PATCHv1] xen/events/fifo: Handle linked events when closing a PIRQ port
Date: Mon, 10 Aug 2015 15:24:38 +0100 [thread overview]
Message-ID: <1439216678-12407-1-git-send-email-david.vrabel@citrix.com> (raw)
Commit fcdf31a7c162de0c93a2bee51df4688ab0a348f8 (xen/events/fifo:
Handle linked events when closing a port) did not handle closing a
port bound to a PIRQ because these are closed from shutdown_pirq()
which is called with interrupts disabled.
Defer the close to a work queue where we can safely spin waiting for
the LINKED bit to clear. For simplicity, the close is always deferred
even if it is not required (i.e., we're already in process context).
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
---
Cc: Sander Eikelenboom <linux@eikelenboom.it>
---
drivers/xen/events/events_2l.c | 10 +++++++
drivers/xen/events/events_base.c | 13 +--------
drivers/xen/events/events_fifo.c | 52 +++++++++++++++++++++++++++---------
drivers/xen/events/events_internal.h | 5 ++--
4 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c
index 7dd4631..82c90de 100644
--- a/drivers/xen/events/events_2l.c
+++ b/drivers/xen/events/events_2l.c
@@ -354,6 +354,15 @@ static void evtchn_2l_resume(void)
EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
}
+static void evtchn_2l_close(unsigned int port, unsigned int cpu)
+{
+ struct evtchn_close close;
+
+ close.port = port;
+ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+ BUG();
+}
+
static const struct evtchn_ops evtchn_ops_2l = {
.max_channels = evtchn_2l_max_channels,
.nr_channels = evtchn_2l_max_channels,
@@ -366,6 +375,7 @@ static const struct evtchn_ops evtchn_ops_2l = {
.unmask = evtchn_2l_unmask,
.handle_events = evtchn_2l_handle_events,
.resume = evtchn_2l_resume,
+ .close = evtchn_2l_close,
};
void __init xen_evtchn_2l_init(void)
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 1495ecc..e3f0049 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -452,17 +452,6 @@ static void xen_free_irq(unsigned irq)
irq_free_desc(irq);
}
-static void xen_evtchn_close(unsigned int port, unsigned int cpu)
-{
- struct evtchn_close close;
-
- xen_evtchn_op_close(port, cpu);
-
- close.port = port;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
- BUG();
-}
-
static void pirq_query_unmask(int irq)
{
struct physdev_irq_status_query irq_status;
@@ -546,7 +535,7 @@ out:
err:
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, 0);
return 0;
}
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 6df8aac..149e1e9 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -40,6 +40,7 @@
#include <linux/smp.h>
#include <linux/percpu.h>
#include <linux/cpu.h>
+#include <linux/slab.h>
#include <asm/sync_bitops.h>
#include <asm/xen/hypercall.h>
@@ -385,24 +386,51 @@ static void evtchn_fifo_resume(void)
event_array_pages = 0;
}
+struct close_work {
+ struct work_struct work;
+ unsigned int port;
+};
+
+static void evtchn_fifo_close_work(struct work_struct *work)
+{
+ struct close_work *cw = container_of(work, struct close_work, work);
+ struct evtchn_close close;
+
+ while (evtchn_fifo_is_linked(cw->port))
+ cpu_relax();
+
+ close.port = cw->port;
+ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+ BUG();
+
+ kfree(cw);
+}
+
static void evtchn_fifo_close(unsigned port, unsigned int cpu)
{
- if (cpu == NR_CPUS)
- return;
+ struct close_work *cw;
- get_online_cpus();
- if (cpu_online(cpu)) {
- if (WARN_ON(irqs_disabled()))
- goto out;
+ /*
+ * A port cannot be closed until the LINKED bit is clear.
+ *
+ * Reusing an already linked event may: a) cause the new event
+ * to be raised on the wrong VCPU; or b) cause the event to be
+ * lost (if the old VCPU is offline).
+ *
+ * If the VCPU is offline, its queues must be drained before
+ * spinning for LINKED to be clear.
+ */
- while (evtchn_fifo_is_linked(port))
- cpu_relax();
- } else {
+ if (!cpu_online(cpu))
__evtchn_fifo_handle_events(cpu, true);
- }
-out:
- put_online_cpus();
+ cw = kzalloc(sizeof(*cw), GFP_ATOMIC);
+ if (!cw)
+ return;
+ INIT_WORK(&cw->work, evtchn_fifo_close_work);
+ cw->port = port;
+
+ schedule_work_on(cpu, &cw->work);
}
static const struct evtchn_ops evtchn_ops_fifo = {
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h
index d18e123..017cc22 100644
--- a/drivers/xen/events/events_internal.h
+++ b/drivers/xen/events/events_internal.h
@@ -146,10 +146,9 @@ static inline void xen_evtchn_resume(void)
evtchn_ops->resume();
}
-static inline void xen_evtchn_op_close(unsigned port, unsigned cpu)
+static inline void xen_evtchn_close(unsigned port, unsigned cpu)
{
- if (evtchn_ops->close)
- return evtchn_ops->close(port, cpu);
+ evtchn_ops->close(port, cpu);
}
void xen_evtchn_2l_init(void);
--
2.1.4
next reply other threads:[~2015-08-10 14:25 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-10 14:24 David Vrabel [this message]
2015-08-10 16:09 ` [PATCHv1] xen/events/fifo: Handle linked events when closing a PIRQ port Boris Ostrovsky
2015-08-10 16:47 ` linux
2015-08-10 17:16 ` David Vrabel
2015-09-16 15:26 ` Boris Ostrovsky
2015-09-16 15:34 ` David Vrabel
2015-09-16 17:34 ` Boris Ostrovsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1439216678-12407-1-git-send-email-david.vrabel@citrix.com \
--to=david.vrabel@citrix.com \
--cc=boris.ostrovsky@oracle.com \
--cc=linux@eikelenboom.it \
--cc=ross.lagerwall@citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).