All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] Xen PCI frontend driver (v0.5)
@ 2010-08-04 18:18 Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 01/20] xen: Don't disable the I/O space Konrad Rzeszutek Wilk
                   ` (20 more replies)
  0 siblings, 21 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:18 UTC (permalink / raw)
  To: linux-kernel, xen-devel; +Cc: alex.williamson

This patch set contains the groundwork and the driver itself for
Xen Paravirtualized (PV) domains to use PCI pass-through devices.

These patches utilize the Xen-SWIOTLB library
(http://lkml.org/lkml/2010/7/27/246) and I don't expect them to
get in the 2.6.36 merge window.

Some of these groundwork patches had been posted in the past, and
gotten some review (and some Acks). Since then work has been done to
expand them, fix bugs, squish them, etc, so that they are feature complete.
I was not sure if I should carry the Ack/Reviewed-by flags, so I've just
reset them to Cc.

Also some of the authors of these patches have moved on, and their e-mails
are bouncing. Any thoughts of what to do about that? I've squished some of
my patches in their work as I want to have the least amount of patches, and
I am de facto the maintainer at this point.

First of Xen PCI frontend driver can be used by PV guests on hardware
that with or without hardware IOMMU. Without an hardware IOMMU you have a
potential security hole wherein a guest domain can use the hardware to map
pages outside its memory range and slurp pages up. As such, this is more
restricted to a Privileged PV domain, aka - device driver domain
(similar to Qubes but a poor-man mechanism [1]).

I am not sure how many folks are actually interested in the internal workings
of the Xen PCI frontend, so I've skipped on that and concentrated on the
other patches (X86 related) which would be more interesting to folks I think.

The first four expose functionality for module drivers to be able to
enumerate and also have the appropriate flag set on PCI devices (_PAGE_IOMAP):

 [PATCH 04/20] x86/io_apic: add get_nr_irqs_gsi()
 [PATCH 12/20] x86/PCI: Clean up pci_cache_line_size
 [PATCH 13/20] x86/PCI: make sure _PAGE_IOMAP it set on pci mappings
 [PATCH 14/20] x86/PCI: Export pci_walk_bus function.

The MSI/MSI-X ones are a mechanism for the MSI/MSI-X framework 'arch_*'
to call into a function pointer structure and call from there the
appropriate sub-platform MSI implementation. On bare-metal this 
is still the old code, except that first part of the name has changed
from 'arch' to 'native':

 [PATCH 15/20] x86: Copy-n-paste arch_teardown_msi_irqs from msi.c to io_apic.c.
 [PATCH 16/20] x86: Introduce x86_msi_ops

And lastly, the Xen PCI stub driver. I've put it in the same location
where other sub-platform PCI drivers are (say, OLPC). It hooks up to the
PCI legacy IRQ setup ('pcibios_enable_irq'), and MSI/MSI-X
allocation/de-allocation (via the x86_msi_ops).

 [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem

The Xen PCI driver by itself is responsible for hooking up to the PCI
configuration read/write methods via the 'pci_scan_bus_parented' call.
In essence all pci_conf_read/write would be tunneled via
pcifront_bus_[read|write] methods:

 [PATCH 20/20] xen-pcifront: Xen PCI frontend driver.

The rest of the patches are related to the Xen framework and
tweaking it to properly work. Those patches have/are in Jeremy's
tree too since 2.6.31, but it made more sense to have them
logically separated in this patch-set since they are utilized by this
driver.

And here is the full list of patches and the diffstat:
Alex Nixon (3):
      xen: Don't disable the I/O space
      x86/PCI: Clean up pci_cache_line_size
      xen/x86/PCI: Add support for the Xen PCI subsystem

Gerd Hoffmann (2):
      xen: implement pirq type event channels
      xen: set pirq name to something useful.

Jeremy Fitzhardinge (5):
      xen: define BIOVEC_PHYS_MERGEABLE()
      x86/io_apic: add get_nr_irqs_gsi()
      xen: identity map gsi->irqs
      xen: statically initialize cpu_evtchn_mask_p
      x86/PCI: make sure _PAGE_IOMAP it set on pci mappings

Konrad Rzeszutek Wilk (5):
      xen: dynamically allocate irq & event structures
      xen: Find an unbound irq number in reverse order (high to low).
      xen: Provide a variant of xen_poll_irq with timeout.
      x86/PCI: Export pci_walk_bus function.
      x86: Copy-n-paste arch_teardown_msi_irqs from msi.c to io_apic.c.

Noboru Iwamatsu (1):
      xenbus: prevent warnings on unhandled enumeration values

Ryan Wilson (1):
      xen-pcifront: Xen PCI frontend driver.

Stefano Stabellini (1):
      x86: Introduce x86_msi_ops

Weidong Han (1):
      xen: fix shared irq device passthrough

Yosuke Iwamatsu (1):
      xenbus: Xen paravirtualised PCI hotplug support.

 arch/x86/Kconfig                   |    5 +
 arch/x86/include/asm/io.h          |   13 +
 arch/x86/include/asm/io_apic.h     |    1 +
 arch/x86/include/asm/pci.h         |   25 +-
 arch/x86/include/asm/pci_x86.h     |    1 +
 arch/x86/include/asm/x86_init.h    |    9 +
 arch/x86/include/asm/xen/pci.h     |   53 ++
 arch/x86/kernel/apic/io_apic.c     |   23 +-
 arch/x86/kernel/x86_init.c         |    6 +
 arch/x86/pci/Makefile              |    1 +
 arch/x86/pci/common.c              |   17 +-
 arch/x86/pci/i386.c                |    2 +
 arch/x86/pci/xen.c                 |  147 +++++
 arch/x86/xen/enlighten.c           |    3 +
 arch/x86/xen/setup.c               |    2 -
 drivers/block/xen-blkfront.c       |    2 +
 drivers/input/xen-kbdfront.c       |    2 +
 drivers/net/xen-netfront.c         |    2 +
 drivers/pci/Kconfig                |   16 +
 drivers/pci/Makefile               |    2 +
 drivers/pci/bus.c                  |    1 +
 drivers/pci/xen-pcifront.c         | 1157 ++++++++++++++++++++++++++++++++++++
 drivers/video/xen-fbfront.c        |    2 +
 drivers/xen/Makefile               |    2 +-
 drivers/xen/biomerge.c             |   13 +
 drivers/xen/events.c               |  338 ++++++++++-
 drivers/xen/xenbus/xenbus_client.c |    2 +
 include/xen/events.h               |   18 +
 include/xen/interface/io/pciif.h   |  122 ++++
 include/xen/interface/io/xenbus.h  |    8 +-
 30 files changed, 1964 insertions(+), 31 deletions(-)


P.S.
[1]. In case you prefer to look at git tree:
git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git devel/xen-pcifront-0.5

To get it working, you would need to checkout first:
git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb-2.6.git devel/linux-next
and then merge the above mentioned branch in it.

[2]: http://qubes-os.org/ which utilizes hardware IOMMU to run seperate domains wherein
each has specific access to hardware.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 01/20] xen: Don't disable the I/O space
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
@ 2010-08-04 18:18 ` Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE() Konrad Rzeszutek Wilk
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:18 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Alex Nixon, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk

From: Alex Nixon <alex.nixon@citrix.com>

If a guest domain wants to access PCI devices through the frontend
driver (coming later in the patch series), it will need access to the
I/O space.

[ Impact: Allow for domU IO access, preparing for pci passthrough ]

Signed-off-by: Alex Nixon <alex.nixon@citrix.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 arch/x86/xen/setup.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index ad0047f..2a709ef 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -188,7 +188,5 @@ void __init xen_arch_setup(void)
 
 	pm_idle = xen_idle;
 
-	paravirt_disable_iospace();
-
 	fiddle_vdso();
 }
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE()
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 01/20] xen: Don't disable the I/O space Konrad Rzeszutek Wilk
@ 2010-08-04 18:18 ` Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 03/20] xen: implement pirq type event channels Konrad Rzeszutek Wilk
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:18 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Jeremy Fitzhardinge,
	Konrad Rzeszutek Wilk

From: Jeremy Fitzhardinge <jeremy@goop.org>

Impact: allow Xen control of bio merging

When running in Xen domain with device access, we need to make sure
the block subsystem doesn't merge requests across pages which aren't
machine physically contiguous.  To do this, we define our own
BIOVEC_PHYS_MERGEABLE.  When CONFIG_XEN isn't enabled, or we're not
running in a Xen domain, this has identical behaviour to the normal
implementation.  When running under Xen, we also make sure the
underlying machine pages are the same or adjacent.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 arch/x86/include/asm/io.h |   13 +++++++++++++
 drivers/xen/Makefile      |    2 +-
 drivers/xen/biomerge.c    |   13 +++++++++++++
 3 files changed, 27 insertions(+), 1 deletions(-)
 create mode 100644 drivers/xen/biomerge.c

diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 30a3e97..0ad29d4 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -41,6 +41,8 @@
 #include <asm-generic/int-ll64.h>
 #include <asm/page.h>
 
+#include <xen/xen.h>
+
 #define build_mmio_read(name, size, type, reg, barrier) \
 static inline type name(const volatile void __iomem *addr) \
 { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
@@ -349,6 +351,17 @@ extern void __iomem *early_memremap(resource_size_t phys_addr,
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void fixup_early_ioremap(void);
 
+#ifdef CONFIG_XEN
+struct bio_vec;
+
+extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
+				      const struct bio_vec *vec2);
+
+#define BIOVEC_PHYS_MERGEABLE(vec1, vec2)				\
+	(__BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&				\
+	 (!xen_domain() || xen_biovec_phys_mergeable(vec1, vec2)))
+#endif	/* CONFIG_XEN */
+
 #define IO_SPACE_LIMIT 0xffff
 
 #endif /* _ASM_X86_IO_H */
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 7c28434..97dd5b5 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,4 +1,4 @@
-obj-y	+= grant-table.o features.o events.o manage.o
+obj-y	+= grant-table.o features.o events.o manage.o biomerge.o
 obj-y	+= xenbus/
 
 nostackp := $(call cc-option, -fno-stack-protector)
diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c
new file mode 100644
index 0000000..ba6eda4
--- /dev/null
+++ b/drivers/xen/biomerge.c
@@ -0,0 +1,13 @@
+#include <linux/bio.h>
+#include <linux/io.h>
+#include <xen/page.h>
+
+bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
+			       const struct bio_vec *vec2)
+{
+	unsigned long mfn1 = pfn_to_mfn(page_to_pfn(vec1->bv_page));
+	unsigned long mfn2 = pfn_to_mfn(page_to_pfn(vec2->bv_page));
+
+	return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&
+		((mfn1 == mfn2) || ((mfn1+1) == mfn2));
+}
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 03/20] xen: implement pirq type event channels
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 01/20] xen: Don't disable the I/O space Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE() Konrad Rzeszutek Wilk
@ 2010-08-04 18:18 ` Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 04/20] x86/io_apic: add get_nr_irqs_gsi() Konrad Rzeszutek Wilk
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:18 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Gerd Hoffmann, Jeremy Fitzhardinge,
	Konrad Rzeszutek Wilk

From: Gerd Hoffmann <kraxel@xeni.home.kraxel.org>

A privileged PV Xen domain can get direct access to hardware.  In
order for this to be useful, it must be able to get hardware
interrupts.

Being a PV Xen domain, all interrupts are delivered as event channels.
PIRQ event channels are bound to a pirq number and an interrupt
vector.  When a IO APIC raises a hardware interrupt on that vector, it
is delivered as an event channel, which we can deliver to the
appropriate device driver(s).

This patch simply implements the infrastructure for dealing with pirq
event channels.

[ Impact: integrate hardware interrupts into Xen's event scheme ]

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |  245 +++++++++++++++++++++++++++++++++++++++++++++++++-
 include/xen/events.h |   11 +++
 2 files changed, 253 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index db8f506..288077f 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -16,7 +16,7 @@
  *    (typically dom0).
  * 2. VIRQs, typically used for timers.  These are per-cpu events.
  * 3. IPIs.
- * 4. Hardware interrupts. Not supported at present.
+ * 4. PIRQs - Hardware interrupts.
  *
  * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
  */
@@ -41,6 +41,9 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/event_channel.h>
 
+/* Leave low irqs free for identity mapping */
+#define LEGACY_IRQS	16
+
 /*
  * This lock protects updates to the following mapping and reference-count
  * arrays. The lock does not need to be acquired to read the mapping tables.
@@ -84,10 +87,12 @@ struct irq_info
 		enum ipi_vector ipi;
 		struct {
 			unsigned short gsi;
-			unsigned short vector;
+			unsigned char vector;
+			unsigned char flags;
 		} pirq;
 	} u;
 };
+#define PIRQ_NEEDS_EOI	(1 << 0)
 
 static struct irq_info irq_info[NR_IRQS];
 
@@ -107,6 +112,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu)
 #define VALID_EVTCHN(chn)	((chn) != 0)
 
 static struct irq_chip xen_dynamic_chip;
+static struct irq_chip xen_pirq_chip;
 
 /* Constructor for packed IRQ information. */
 static struct irq_info mk_unbound_info(void)
@@ -219,6 +225,15 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
 	return ret;
 }
 
+static bool pirq_needs_eoi(unsigned irq)
+{
+	struct irq_info *info = info_for_irq(irq);
+
+	BUG_ON(info->type != IRQT_PIRQ);
+
+	return info->u.pirq.flags & PIRQ_NEEDS_EOI;
+}
+
 static inline unsigned long active_evtchns(unsigned int cpu,
 					   struct shared_info *sh,
 					   unsigned int idx)
@@ -335,7 +350,7 @@ static int find_unbound_irq(void)
 	int irq;
 	struct irq_desc *desc;
 
-	for (irq = 0; irq < nr_irqs; irq++)
+	for (irq = LEGACY_IRQS; irq < nr_irqs; irq++)
 		if (irq_info[irq].type == IRQT_UNBOUND)
 			break;
 
@@ -351,6 +366,210 @@ static int find_unbound_irq(void)
 	return irq;
 }
 
+static bool identity_mapped_irq(unsigned irq)
+{
+	/* only identity map legacy irqs */
+	return irq < LEGACY_IRQS;
+}
+
+static void pirq_unmask_notify(int irq)
+{
+	struct physdev_eoi eoi = { .irq = irq };
+
+	if (unlikely(pirq_needs_eoi(irq))) {
+		int rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
+		WARN_ON(rc);
+	}
+}
+
+static void pirq_query_unmask(int irq)
+{
+	struct physdev_irq_status_query irq_status;
+	struct irq_info *info = info_for_irq(irq);
+
+	BUG_ON(info->type != IRQT_PIRQ);
+
+	irq_status.irq = irq;
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
+		irq_status.flags = 0;
+
+	info->u.pirq.flags &= ~PIRQ_NEEDS_EOI;
+	if (irq_status.flags & XENIRQSTAT_needs_eoi)
+		info->u.pirq.flags |= PIRQ_NEEDS_EOI;
+}
+
+static bool probing_irq(int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	return desc && desc->action == NULL;
+}
+
+static unsigned int startup_pirq(unsigned int irq)
+{
+	struct evtchn_bind_pirq bind_pirq;
+	struct irq_info *info = info_for_irq(irq);
+	int evtchn = evtchn_from_irq(irq);
+
+	BUG_ON(info->type != IRQT_PIRQ);
+
+	if (VALID_EVTCHN(evtchn))
+		goto out;
+
+	bind_pirq.pirq = irq;
+	/* NB. We are happy to share unless we are probing. */
+	bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
+		if (!probing_irq(irq))
+			printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
+			       irq);
+		return 0;
+	}
+	evtchn = bind_pirq.port;
+
+	pirq_query_unmask(irq);
+
+	evtchn_to_irq[evtchn] = irq;
+	bind_evtchn_to_cpu(evtchn, 0);
+	info->evtchn = evtchn;
+
+ out:
+	unmask_evtchn(evtchn);
+	pirq_unmask_notify(irq);
+
+	return 0;
+}
+
+static void shutdown_pirq(unsigned int irq)
+{
+	struct evtchn_close close;
+	struct irq_info *info = info_for_irq(irq);
+	int evtchn = evtchn_from_irq(irq);
+
+	BUG_ON(info->type != IRQT_PIRQ);
+
+	if (!VALID_EVTCHN(evtchn))
+		return;
+
+	mask_evtchn(evtchn);
+
+	close.port = evtchn;
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+		BUG();
+
+	bind_evtchn_to_cpu(evtchn, 0);
+	evtchn_to_irq[evtchn] = -1;
+	info->evtchn = 0;
+}
+
+static void enable_pirq(unsigned int irq)
+{
+	startup_pirq(irq);
+}
+
+static void disable_pirq(unsigned int irq)
+{
+}
+
+static void ack_pirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	move_native_irq(irq);
+
+	if (VALID_EVTCHN(evtchn)) {
+		mask_evtchn(evtchn);
+		clear_evtchn(evtchn);
+	}
+}
+
+static void end_pirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (WARN_ON(!desc))
+		return;
+
+	if ((desc->status & (IRQ_DISABLED|IRQ_PENDING)) ==
+	    (IRQ_DISABLED|IRQ_PENDING)) {
+		shutdown_pirq(irq);
+	} else if (VALID_EVTCHN(evtchn)) {
+		unmask_evtchn(evtchn);
+		pirq_unmask_notify(irq);
+	}
+}
+
+static int find_irq_by_gsi(unsigned gsi)
+{
+	int irq;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		struct irq_info *info = info_for_irq(irq);
+
+		if (info == NULL || info->type != IRQT_PIRQ)
+			continue;
+
+		if (gsi_from_irq(irq) == gsi)
+			return irq;
+	}
+
+	return -1;
+}
+
+/*
+ * Allocate a physical irq, along with a vector.  We don't assign an
+ * event channel until the irq actually started up.  Return an
+ * existing irq if we've already got one for the gsi.
+ */
+int xen_allocate_pirq(unsigned gsi)
+{
+	int irq;
+	struct physdev_irq irq_op;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	irq = find_irq_by_gsi(gsi);
+	if (irq != -1) {
+		printk(KERN_INFO "xen_allocate_pirq: returning irq %d for gsi %u\n",
+		       irq, gsi);
+		goto out;	/* XXX need refcount? */
+	}
+
+	if (identity_mapped_irq(gsi)) {
+		irq = gsi;
+		dynamic_irq_init(irq);
+	} else
+		irq = find_unbound_irq();
+
+	set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
+				      handle_level_irq, "pirq");
+
+	irq_op.irq = irq;
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
+		dynamic_irq_cleanup(irq);
+		irq = -ENOSPC;
+		goto out;
+	}
+
+	irq_info[irq] = mk_pirq_info(0, gsi, irq_op.vector);
+
+out:
+	spin_unlock(&irq_mapping_update_lock);
+
+	return irq;
+}
+
+int xen_vector_from_irq(unsigned irq)
+{
+	return vector_from_irq(irq);
+}
+
+int xen_gsi_from_irq(unsigned irq)
+{
+	return gsi_from_irq(irq);
+}
+
 int bind_evtchn_to_irq(unsigned int evtchn)
 {
 	int irq;
@@ -933,6 +1152,26 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
 	.retrigger	= retrigger_dynirq,
 };
 
+static struct irq_chip xen_pirq_chip __read_mostly = {
+	.name		= "xen-pirq",
+
+	.startup	= startup_pirq,
+	.shutdown	= shutdown_pirq,
+
+	.enable		= enable_pirq,
+	.unmask		= enable_pirq,
+
+	.disable	= disable_pirq,
+	.mask		= disable_pirq,
+
+	.ack		= ack_pirq,
+	.end		= end_pirq,
+
+	.set_affinity	= set_affinity_irq,
+
+	.retrigger	= retrigger_dynirq,
+};
+
 void __init xen_init_IRQ(void)
 {
 	int i;
diff --git a/include/xen/events.h b/include/xen/events.h
index e68d59a..2303180 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -56,4 +56,15 @@ void xen_poll_irq(int irq);
 /* Determine the IRQ which is bound to an event channel */
 unsigned irq_from_evtchn(unsigned int evtchn);
 
+/* Allocate an irq for a physical interrupt, given a gsi.  "Legacy"
+   GSIs are identity mapped; others are dynamically allocated as
+   usual. */
+int xen_allocate_pirq(unsigned gsi);
+
+/* Return vector allocated to pirq */
+int xen_vector_from_irq(unsigned pirq);
+
+/* Return gsi allocated to pirq */
+int xen_gsi_from_irq(unsigned pirq);
+
 #endif	/* _XEN_EVENTS_H */
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 04/20] x86/io_apic: add get_nr_irqs_gsi()
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (2 preceding siblings ...)
  2010-08-04 18:18 ` [PATCH 03/20] xen: implement pirq type event channels Konrad Rzeszutek Wilk
@ 2010-08-04 18:18 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 05/20] xen: identity map gsi->irqs Konrad Rzeszutek Wilk
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:18 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk,
	Thomas Gleixner, x86, Jesse Barnes

From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

Impact: new interface to get max GSI

Add get_nr_irqs_gsi() to return nr_irqs_gsi.  Xen will use this to
determine how many irqs it needs to reserve for hardware irqs.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86@kernel.org
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/apic/io_apic.c |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9cb2edb..f27c681 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -169,6 +169,7 @@ extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
 
 extern void probe_nr_irqs_gsi(void);
+extern int get_nr_irqs_gsi(void);
 
 extern int setup_ioapic_entry(int apic, int irq,
 			      struct IO_APIC_route_entry *entry,
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e41ed24..8353c40 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3860,6 +3860,11 @@ void __init probe_nr_irqs_gsi(void)
 	printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
 }
 
+int get_nr_irqs_gsi(void)
+{
+	return nr_irqs_gsi;
+}
+
 #ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 05/20] xen: identity map gsi->irqs
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (3 preceding siblings ...)
  2010-08-04 18:18 ` [PATCH 04/20] x86/io_apic: add get_nr_irqs_gsi() Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19   ` Konrad Rzeszutek Wilk
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk

From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

Impact: preserve compat with native

Reserve the lower irq range for use for hardware interrupts so we
can identity-map them.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |   23 +++++++++++++++++------
 1 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 288077f..b6de004 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -32,6 +32,7 @@
 #include <asm/ptrace.h>
 #include <asm/irq.h>
 #include <asm/idle.h>
+#include <asm/io_apic.h>
 #include <asm/sync_bitops.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -41,9 +42,6 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/event_channel.h>
 
-/* Leave low irqs free for identity mapping */
-#define LEGACY_IRQS	16
-
 /*
  * This lock protects updates to the following mapping and reference-count
  * arrays. The lock does not need to be acquired to read the mapping tables.
@@ -345,12 +343,24 @@ static void unmask_evtchn(int port)
 	put_cpu();
 }
 
+static int get_nr_hw_irqs(void)
+{
+	int ret = 1;
+
+#ifdef CONFIG_X86_IO_APIC
+	ret = get_nr_irqs_gsi();
+#endif
+
+	return ret;
+}
+
 static int find_unbound_irq(void)
 {
 	int irq;
 	struct irq_desc *desc;
+	int start = get_nr_hw_irqs();
 
-	for (irq = LEGACY_IRQS; irq < nr_irqs; irq++)
+	for (irq = start; irq < nr_irqs; irq++)
 		if (irq_info[irq].type == IRQT_UNBOUND)
 			break;
 
@@ -368,8 +378,8 @@ static int find_unbound_irq(void)
 
 static bool identity_mapped_irq(unsigned irq)
 {
-	/* only identity map legacy irqs */
-	return irq < LEGACY_IRQS;
+	/* identity map all the hardware irqs */
+	return irq < get_nr_hw_irqs();
 }
 
 static void pirq_unmask_notify(int irq)
@@ -538,6 +548,7 @@ int xen_allocate_pirq(unsigned gsi)
 
 	if (identity_mapped_irq(gsi)) {
 		irq = gsi;
+		irq_to_desc_alloc_node(irq, 0);
 		dynamic_irq_init(irq);
 	} else
 		irq = find_unbound_irq();
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 06/20] xen: dynamically allocate irq & event structures
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
@ 2010-08-04 18:19   ` Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE() Konrad Rzeszutek Wilk
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Konrad Rzeszutek Wilk, Jeremy Fitzhardinge

Dynamically allocate the irq_info and evtchn_to_irq arrays, so that
1) the irq_info array scales to the actual number of possible irqs,
and 2) we don't needlessly increase the static size of the kernel
when we aren't running under Xen.

Derived on patch from Mike Travis <travis@sgi.com>.

[Impact: reduce memory usage ]
[v2: Conflict in drivers/xen/events.c: Replaced alloc_bootmen with kcalloc ]

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index b6de004..ac04ded 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -28,6 +28,7 @@
 #include <linux/string.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
+#include <linux/irqnr.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq.h>
@@ -92,11 +93,9 @@ struct irq_info
 };
 #define PIRQ_NEEDS_EOI	(1 << 0)
 
-static struct irq_info irq_info[NR_IRQS];
+static struct irq_info *irq_info;
 
-static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
-	[0 ... NR_EVENT_CHANNELS-1] = -1
-};
+static int *evtchn_to_irq;
 struct cpu_evtchn_s {
 	unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG];
 };
@@ -514,7 +513,7 @@ static int find_irq_by_gsi(unsigned gsi)
 {
 	int irq;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		struct irq_info *info = info_for_irq(irq);
 
 		if (info == NULL || info->type != IRQT_PIRQ)
@@ -1189,7 +1188,12 @@ void __init xen_init_IRQ(void)
 
 	cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
 				    GFP_KERNEL);
-	BUG_ON(cpu_evtchn_mask_p == NULL);
+	irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL);
+
+	evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
+				    GFP_KERNEL);
+	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+		evtchn_to_irq[i] = -1;
 
 	init_evtchn_cpu_bindings();
 
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 06/20] xen: dynamically allocate irq & event structures
@ 2010-08-04 18:19   ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk

Dynamically allocate the irq_info and evtchn_to_irq arrays, so that
1) the irq_info array scales to the actual number of possible irqs,
and 2) we don't needlessly increase the static size of the kernel
when we aren't running under Xen.

Derived on patch from Mike Travis <travis@sgi.com>.

[Impact: reduce memory usage ]
[v2: Conflict in drivers/xen/events.c: Replaced alloc_bootmen with kcalloc ]

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index b6de004..ac04ded 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -28,6 +28,7 @@
 #include <linux/string.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
+#include <linux/irqnr.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq.h>
@@ -92,11 +93,9 @@ struct irq_info
 };
 #define PIRQ_NEEDS_EOI	(1 << 0)
 
-static struct irq_info irq_info[NR_IRQS];
+static struct irq_info *irq_info;
 
-static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
-	[0 ... NR_EVENT_CHANNELS-1] = -1
-};
+static int *evtchn_to_irq;
 struct cpu_evtchn_s {
 	unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG];
 };
@@ -514,7 +513,7 @@ static int find_irq_by_gsi(unsigned gsi)
 {
 	int irq;
 
-	for (irq = 0; irq < NR_IRQS; irq++) {
+	for (irq = 0; irq < nr_irqs; irq++) {
 		struct irq_info *info = info_for_irq(irq);
 
 		if (info == NULL || info->type != IRQT_PIRQ)
@@ -1189,7 +1188,12 @@ void __init xen_init_IRQ(void)
 
 	cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
 				    GFP_KERNEL);
-	BUG_ON(cpu_evtchn_mask_p == NULL);
+	irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL);
+
+	evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
+				    GFP_KERNEL);
+	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+		evtchn_to_irq[i] = -1;
 
 	init_evtchn_cpu_bindings();
 
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 07/20] xen: set pirq name to something useful.
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
@ 2010-08-04 18:19   ` Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE() Konrad Rzeszutek Wilk
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Gerd Hoffmann, Jeremy Fitzhardinge,
	Konrad Rzeszutek Wilk

From: Gerd Hoffmann <kraxel@xeni.home.kraxel.org>

Impact: cleanup

Make pirq show useful information in /proc/interrupts

[v2: Removed the parts for arch/x86/xen/pci.c ]

Signed-off-by: Gerd Hoffmann <kraxel@xeni.home.kraxel.org>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |    4 ++--
 include/xen/events.h |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index ac04ded..64cde24 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -531,7 +531,7 @@ static int find_irq_by_gsi(unsigned gsi)
  * event channel until the irq actually started up.  Return an
  * existing irq if we've already got one for the gsi.
  */
-int xen_allocate_pirq(unsigned gsi)
+int xen_allocate_pirq(unsigned gsi, char *name)
 {
 	int irq;
 	struct physdev_irq irq_op;
@@ -553,7 +553,7 @@ int xen_allocate_pirq(unsigned gsi)
 		irq = find_unbound_irq();
 
 	set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
-				      handle_level_irq, "pirq");
+				      handle_level_irq, name);
 
 	irq_op.irq = irq;
 	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
diff --git a/include/xen/events.h b/include/xen/events.h
index 2303180..e8f5b81 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -59,7 +59,7 @@ unsigned irq_from_evtchn(unsigned int evtchn);
 /* Allocate an irq for a physical interrupt, given a gsi.  "Legacy"
    GSIs are identity mapped; others are dynamically allocated as
    usual. */
-int xen_allocate_pirq(unsigned gsi);
+int xen_allocate_pirq(unsigned gsi, char *name);
 
 /* Return vector allocated to pirq */
 int xen_vector_from_irq(unsigned pirq);
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 07/20] xen: set pirq name to something useful.
@ 2010-08-04 18:19   ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Gerd Hoffmann,
	Konrad Rzeszutek Wilk

From: Gerd Hoffmann <kraxel@xeni.home.kraxel.org>

Impact: cleanup

Make pirq show useful information in /proc/interrupts

[v2: Removed the parts for arch/x86/xen/pci.c ]

Signed-off-by: Gerd Hoffmann <kraxel@xeni.home.kraxel.org>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |    4 ++--
 include/xen/events.h |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index ac04ded..64cde24 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -531,7 +531,7 @@ static int find_irq_by_gsi(unsigned gsi)
  * event channel until the irq actually started up.  Return an
  * existing irq if we've already got one for the gsi.
  */
-int xen_allocate_pirq(unsigned gsi)
+int xen_allocate_pirq(unsigned gsi, char *name)
 {
 	int irq;
 	struct physdev_irq irq_op;
@@ -553,7 +553,7 @@ int xen_allocate_pirq(unsigned gsi)
 		irq = find_unbound_irq();
 
 	set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
-				      handle_level_irq, "pirq");
+				      handle_level_irq, name);
 
 	irq_op.irq = irq;
 	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
diff --git a/include/xen/events.h b/include/xen/events.h
index 2303180..e8f5b81 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -59,7 +59,7 @@ unsigned irq_from_evtchn(unsigned int evtchn);
 /* Allocate an irq for a physical interrupt, given a gsi.  "Legacy"
    GSIs are identity mapped; others are dynamically allocated as
    usual. */
-int xen_allocate_pirq(unsigned gsi);
+int xen_allocate_pirq(unsigned gsi, char *name);
 
 /* Return vector allocated to pirq */
 int xen_vector_from_irq(unsigned pirq);
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 08/20] xen: statically initialize cpu_evtchn_mask_p
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (6 preceding siblings ...)
  2010-08-04 18:19   ` Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 09/20] xen: Find an unbound irq number in reverse order (high to low) Konrad Rzeszutek Wilk
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk

From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

Sometimes cpu_evtchn_mask_p can get used early, before it has been
allocated.  Statically initialize it with an initdata version to catch
any early references.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 64cde24..35718db 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -99,7 +99,12 @@ static int *evtchn_to_irq;
 struct cpu_evtchn_s {
 	unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG];
 };
-static struct cpu_evtchn_s *cpu_evtchn_mask_p;
+
+static __initdata struct cpu_evtchn_s init_evtchn_mask = {
+	.bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul,
+};
+static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask;
+
 static inline unsigned long *cpu_evtchn_mask(int cpu)
 {
 	return cpu_evtchn_mask_p[cpu].bits;
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 09/20] xen: Find an unbound irq number in reverse order (high to low).
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (7 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 08/20] xen: statically initialize cpu_evtchn_mask_p Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19   ` Konrad Rzeszutek Wilk
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Konrad Rzeszutek Wilk, Jeremy Fitzhardinge

In earlier Xen Linux kernels, the IRQ mapping was a straight 1:1 and the
find_unbound_irq started looking around 256 for open IRQs and up. IRQs
from 0 to 255 were reserved for PCI devices.  Previous to this patch,
the 'find_unbound_irq'  started looking at get_nr_hw_irqs() number.
For privileged  domain where the ACPI information is available that
returns the upper-bound of what the GSIs. For non-privileged PV domains,
where ACPI is no-existent the get_nr_hw_irqs() reports the IRQ_LEGACY (16).
With PCI passthrough enabled, and with PCI cards that have IRQs pinned
to a higher number than 16 we collide with previously allocated IRQs.
Specifically the PCI IRQs collide with the IPI's for Xen functions
(as they are allocated earlier).
For example:

00:00.11 USB Controller: ATI Technologies Inc SB700 USB OHCI1 Controller (prog-if 10 [OHCI])
	...
	Interrupt: pin A routed to IRQ 18

[root@localhost ~]# cat /proc/interrupts | head
           CPU0       CPU1       CPU2
 16:      38186          0          0   xen-dyn-virq      timer0
 17:        149          0          0   xen-dyn-ipi       spinlock0
 18:        962          0          0   xen-dyn-ipi       resched0

and when the USB controller is loaded, the kernel reports:
IRQ handler type mismatch for IRQ 18
current handler: resched0

One way to fix this is to reverse the logic when looking for un-used
IRQ numbers and start with the highest available number. With that,
we would get:

           CPU0       CPU1       CPU2
... snip ..
292:         35          0          0   xen-dyn-ipi       callfunc0
293:       3992          0          0   xen-dyn-ipi       resched0
294:        224          0          0   xen-dyn-ipi       spinlock0
295:      57183          0          0   xen-dyn-virq      timer0
NMI:          0          0          0   Non-maskable interrupts
.. snip ..

And interrupts for PCI cards are now accessible.

This patch also includes the fix, found by Ian Campbell, titled
"xen: fix off-by-one error in find_unbound_irq."

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
 drivers/xen/events.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 35718db..cd633fa 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -364,12 +364,16 @@ static int find_unbound_irq(void)
 	struct irq_desc *desc;
 	int start = get_nr_hw_irqs();
 
-	for (irq = start; irq < nr_irqs; irq++)
+	if (start == nr_irqs)
+		goto no_irqs;
+
+	/* nr_irqs is a magic value. Must not use it.*/
+	for (irq = nr_irqs-1; irq > start; irq--)
 		if (irq_info[irq].type == IRQT_UNBOUND)
 			break;
 
-	if (irq == nr_irqs)
-		panic("No available IRQ to bind to: increase nr_irqs!\n");
+	if (irq == start)
+		goto no_irqs;
 
 	desc = irq_to_desc_alloc_node(irq, 0);
 	if (WARN_ON(desc == NULL))
@@ -378,6 +382,9 @@ static int find_unbound_irq(void)
 	dynamic_irq_init(irq);
 
 	return irq;
+
+no_irqs:
+	panic("No available IRQ to bind to: increase nr_irqs!\n");
 }
 
 static bool identity_mapped_irq(unsigned irq)
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 10/20] xen: Provide a variant of xen_poll_irq with timeout.
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
@ 2010-08-04 18:19   ` Konrad Rzeszutek Wilk
  2010-08-04 18:18 ` [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE() Konrad Rzeszutek Wilk
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Konrad Rzeszutek Wilk, Jeremy Fitzhardinge

The 'xen_poll_irq_timeout' provides a method to pass in
the poll timeout for IRQs if requested. We also export
this poll function and the xen_clear_irq_pending as Xen PCI fronted uses them.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
 drivers/xen/events.c |   17 ++++++++++++-----
 include/xen/events.h |    4 ++++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index cd633fa..9d85707 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1101,7 +1101,7 @@ void xen_clear_irq_pending(int irq)
 	if (VALID_EVTCHN(evtchn))
 		clear_evtchn(evtchn);
 }
-
+EXPORT_SYMBOL(xen_clear_irq_pending);
 void xen_set_irq_pending(int irq)
 {
 	int evtchn = evtchn_from_irq(irq);
@@ -1121,9 +1121,9 @@ bool xen_test_irq_pending(int irq)
 	return ret;
 }
 
-/* Poll waiting for an irq to become pending.  In the usual case, the
-   irq will be disabled so it won't deliver an interrupt. */
-void xen_poll_irq(int irq)
+/* Poll waiting for an irq to become pending with timeout.  In the usual case,
+ * the irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq_timeout(int irq, u64 timeout)
 {
 	evtchn_port_t evtchn = evtchn_from_irq(irq);
 
@@ -1131,13 +1131,20 @@ void xen_poll_irq(int irq)
 		struct sched_poll poll;
 
 		poll.nr_ports = 1;
-		poll.timeout = 0;
+		poll.timeout = timeout;
 		set_xen_guest_handle(poll.ports, &evtchn);
 
 		if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0)
 			BUG();
 	}
 }
+EXPORT_SYMBOL(xen_poll_irq_timeout);
+/* Poll waiting for an irq to become pending.  In the usual case, the
+   irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq)
+{
+	xen_poll_irq_timeout(irq, 0 /* no timeout */);
+}
 
 void xen_irq_resume(void)
 {
diff --git a/include/xen/events.h b/include/xen/events.h
index e8f5b81..91143b4 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -53,6 +53,10 @@ bool xen_test_irq_pending(int irq);
    irq will be disabled so it won't deliver an interrupt. */
 void xen_poll_irq(int irq);
 
+/* Poll waiting for an irq to become pending with a timeout.  In the usual case,
+ * the irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq_timeout(int irq, u64 timeout);
+
 /* Determine the IRQ which is bound to an event channel */
 unsigned irq_from_evtchn(unsigned int evtchn);
 
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 10/20] xen: Provide a variant of xen_poll_irq with timeout.
@ 2010-08-04 18:19   ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk

The 'xen_poll_irq_timeout' provides a method to pass in
the poll timeout for IRQs if requested. We also export
this poll function and the xen_clear_irq_pending as Xen PCI fronted uses them.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
 drivers/xen/events.c |   17 ++++++++++++-----
 include/xen/events.h |    4 ++++
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index cd633fa..9d85707 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1101,7 +1101,7 @@ void xen_clear_irq_pending(int irq)
 	if (VALID_EVTCHN(evtchn))
 		clear_evtchn(evtchn);
 }
-
+EXPORT_SYMBOL(xen_clear_irq_pending);
 void xen_set_irq_pending(int irq)
 {
 	int evtchn = evtchn_from_irq(irq);
@@ -1121,9 +1121,9 @@ bool xen_test_irq_pending(int irq)
 	return ret;
 }
 
-/* Poll waiting for an irq to become pending.  In the usual case, the
-   irq will be disabled so it won't deliver an interrupt. */
-void xen_poll_irq(int irq)
+/* Poll waiting for an irq to become pending with timeout.  In the usual case,
+ * the irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq_timeout(int irq, u64 timeout)
 {
 	evtchn_port_t evtchn = evtchn_from_irq(irq);
 
@@ -1131,13 +1131,20 @@ void xen_poll_irq(int irq)
 		struct sched_poll poll;
 
 		poll.nr_ports = 1;
-		poll.timeout = 0;
+		poll.timeout = timeout;
 		set_xen_guest_handle(poll.ports, &evtchn);
 
 		if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0)
 			BUG();
 	}
 }
+EXPORT_SYMBOL(xen_poll_irq_timeout);
+/* Poll waiting for an irq to become pending.  In the usual case, the
+   irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq)
+{
+	xen_poll_irq_timeout(irq, 0 /* no timeout */);
+}
 
 void xen_irq_resume(void)
 {
diff --git a/include/xen/events.h b/include/xen/events.h
index e8f5b81..91143b4 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -53,6 +53,10 @@ bool xen_test_irq_pending(int irq);
    irq will be disabled so it won't deliver an interrupt. */
 void xen_poll_irq(int irq);
 
+/* Poll waiting for an irq to become pending with a timeout.  In the usual case,
+ * the irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq_timeout(int irq, u64 timeout);
+
 /* Determine the IRQ which is bound to an event channel */
 unsigned irq_from_evtchn(unsigned int evtchn);
 
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 11/20] xen: fix shared irq device passthrough
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (9 preceding siblings ...)
  2010-08-04 18:19   ` Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 12/20] x86/PCI: Clean up pci_cache_line_size Konrad Rzeszutek Wilk
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Weidong Han, Jeremy Fitzhardinge, Konrad Rzeszutek Wilk

From: Weidong Han <weidong.han@intel.com>

In driver/xen/events.c, whether bind_pirq is shareable or not is
determined by desc->action is NULL or not. But in __setup_irq,
startup(irq) is invoked before desc->action is assigned with
new action. So desc->action in startup_irq is always NULL, and
bind_pirq is always not shareable. This results in pt_irq_create_bind
failure when passthrough a device which shares irq to other devices.

This patch doesn't use probing_irq to determine if pirq is shareable
or not, instead set shareable flag in irq_info according to trigger
mode in xen_allocate_pirq. Set level triggered interrupts shareable.
Thus use this flag to set bind_pirq flag accordingly.

[v2: arch/x86/xen/pci.c no more, so file skipped]

Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/xen/events.c |   11 ++++++++---
 include/xen/events.h |    2 +-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 9d85707..78c1525 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -92,6 +92,7 @@ struct irq_info
 	} u;
 };
 #define PIRQ_NEEDS_EOI	(1 << 0)
+#define PIRQ_SHAREABLE	(1 << 1)
 
 static struct irq_info *irq_info;
 
@@ -431,6 +432,7 @@ static unsigned int startup_pirq(unsigned int irq)
 	struct evtchn_bind_pirq bind_pirq;
 	struct irq_info *info = info_for_irq(irq);
 	int evtchn = evtchn_from_irq(irq);
+	int rc;
 
 	BUG_ON(info->type != IRQT_PIRQ);
 
@@ -439,8 +441,10 @@ static unsigned int startup_pirq(unsigned int irq)
 
 	bind_pirq.pirq = irq;
 	/* NB. We are happy to share unless we are probing. */
-	bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
-	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
+	bind_pirq.flags = info->u.pirq.flags & PIRQ_SHAREABLE ?
+					BIND_PIRQ__WILL_SHARE : 0;
+	rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq);
+	if (rc != 0) {
 		if (!probing_irq(irq))
 			printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
 			       irq);
@@ -543,7 +547,7 @@ static int find_irq_by_gsi(unsigned gsi)
  * event channel until the irq actually started up.  Return an
  * existing irq if we've already got one for the gsi.
  */
-int xen_allocate_pirq(unsigned gsi, char *name)
+int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
 {
 	int irq;
 	struct physdev_irq irq_op;
@@ -575,6 +579,7 @@ int xen_allocate_pirq(unsigned gsi, char *name)
 	}
 
 	irq_info[irq] = mk_pirq_info(0, gsi, irq_op.vector);
+	irq_info[irq].u.pirq.flags |= shareable ? PIRQ_SHAREABLE : 0;
 
 out:
 	spin_unlock(&irq_mapping_update_lock);
diff --git a/include/xen/events.h b/include/xen/events.h
index 91143b4..20e27c3 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -63,7 +63,7 @@ unsigned irq_from_evtchn(unsigned int evtchn);
 /* Allocate an irq for a physical interrupt, given a gsi.  "Legacy"
    GSIs are identity mapped; others are dynamically allocated as
    usual. */
-int xen_allocate_pirq(unsigned gsi, char *name);
+int xen_allocate_pirq(unsigned gsi, int shareable, char *name);
 
 /* Return vector allocated to pirq */
 int xen_vector_from_irq(unsigned pirq);
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 12/20] x86/PCI: Clean up pci_cache_line_size
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (10 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 11/20] xen: fix shared irq device passthrough Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 13/20] x86/PCI: make sure _PAGE_IOMAP it set on pci mappings Konrad Rzeszutek Wilk
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Alex Nixon, Jeremy Fitzhardinge,
	Konrad Rzeszutek Wilk, x86

From: Alex Nixon <alex.nixon@citrix.com>

Separate out x86 cache_line_size initialisation code into its own
function (so it can be shared by Xen later in this patch series)

[ Impact: cleanup ]

Signed-off-by: Alex Nixon <alex.nixon@citrix.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: "H. Peter Anvin" <hpa@zytor.com>
Reviewed-by: Matthew Wilcox <willy@linux.intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: x86@kernel.org
---
 arch/x86/include/asm/pci_x86.h |    1 +
 arch/x86/pci/common.c          |   17 ++++++++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index cd2a31d..69abe01 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -46,6 +46,7 @@ enum pci_bf_sort_state {
 extern unsigned int pcibios_max_latency;
 
 void pcibios_resource_survey(void);
+void pcibios_set_cache_line_size(void);
 
 /* pci-pc.c */
 
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 215a27a..d4214ac 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -404,16 +404,10 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
 
 	return bus;
 }
-
-int __init pcibios_init(void)
+void __init pcibios_set_cache_line_size(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 
-	if (!raw_pci_ops) {
-		printk(KERN_WARNING "PCI: System does not support PCI\n");
-		return 0;
-	}
-
 	/*
 	 * Set PCI cacheline size to that of the CPU if the CPU has reported it.
 	 * (For older CPUs that don't support cpuid, we se it to 32 bytes
@@ -428,7 +422,16 @@ int __init pcibios_init(void)
  		pci_dfl_cache_line_size = 32 >> 2;
 		printk(KERN_DEBUG "PCI: Unknown cacheline size. Setting to 32 bytes\n");
 	}
+}
+
+int __init pcibios_init(void)
+{
+	if (!raw_pci_ops) {
+		printk(KERN_WARNING "PCI: System does not support PCI\n");
+		return 0;
+	}
 
+	pcibios_set_cache_line_size();
 	pcibios_resource_survey();
 
 	if (pci_bf_sort >= pci_force_bf)
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 13/20] x86/PCI: make sure _PAGE_IOMAP it set on pci mappings
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (11 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 12/20] x86/PCI: Clean up pci_cache_line_size Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 14/20] x86/PCI: Export pci_walk_bus function Konrad Rzeszutek Wilk
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Jeremy Fitzhardinge, x86, Jesse Barnes

From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

When mapping pci space via /sys or /proc, make sure we're really
doing a hardware mapping by setting _PAGE_IOMAP.

[ Impact: bugfix; make PCI mappings map the right pages ]

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: "H. Peter Anvin" <hpa@zytor.com>
Reviewed-by: Matthew Wilcox <willy@linux.intel.com>
Cc: x86@kernel.org
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/x86/pci/i386.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 5525309..8379c2c 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -311,6 +311,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 		 */
 		prot |= _PAGE_CACHE_UC_MINUS;
 
+	prot |= _PAGE_IOMAP;	/* creating a mapping for IO */
+
 	vma->vm_page_prot = __pgprot(prot);
 
 	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 14/20] x86/PCI: Export pci_walk_bus function.
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (12 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 13/20] x86/PCI: make sure _PAGE_IOMAP it set on pci mappings Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 15/20] x86: Copy-n-paste arch_teardown_msi_irqs from msi.c to io_apic.c Konrad Rzeszutek Wilk
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Konrad Rzeszutek Wilk, Jeremy Fitzhardinge

In preperation of modularizing Xen-pcifront the pci_walk_bus
needs to be exported so that the xen-pcifront module can walk
call the pci subsystem to walk the PCI devices and claim them.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> [http://marc.info/?l=linux-pci&m=126149958010298&w=2]
---
 drivers/pci/bus.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 628ea20..dbe2861 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -297,6 +297,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
 	}
 	up_read(&pci_bus_sem);
 }
+EXPORT_SYMBOL_GPL(pci_walk_bus);
 
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 15/20] x86: Copy-n-paste arch_teardown_msi_irqs from msi.c to io_apic.c.
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (13 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 14/20] x86/PCI: Export pci_walk_bus function Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 16/20] x86: Introduce x86_msi_ops Konrad Rzeszutek Wilk
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Konrad Rzeszutek Wilk, Jeremy Fitzhardinge,
	Thomas Gleixner, H. Peter Anvin, x86, Jesse Barnes

In preparation for non-privileged domains to disable PCI devices'
MSI/MSIx, we need to augment arch_teardown_msi_irqs to make
a call to the privileged domain (patch to follow).

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/x86/include/asm/pci.h     |    1 +
 arch/x86/kernel/apic/io_apic.c |   14 ++++++++++++++
 2 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 404a880..bcf84e1 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -94,6 +94,7 @@ extern void pci_iommu_alloc(void);
 
 /* MSI arch hook */
 #define arch_setup_msi_irqs arch_setup_msi_irqs
+#define arch_teardown_msi_irqs arch_teardown_msi_irqs
 
 #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 8353c40..a8d069e 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3597,6 +3597,20 @@ void arch_teardown_msi_irq(unsigned int irq)
 	destroy_irq(irq);
 }
 
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		int i, nvec;
+		if (entry->irq == 0)
+			continue;
+		nvec = 1 << entry->msi_attrib.multiple;
+		for (i = 0; i < nvec; i++)
+			arch_teardown_msi_irq(entry->irq + i);
+	}
+}
+
 #if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
 #ifdef CONFIG_SMP
 static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 16/20] x86: Introduce x86_msi_ops
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (14 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 15/20] x86: Copy-n-paste arch_teardown_msi_irqs from msi.c to io_apic.c Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-31 18:31     ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem Konrad Rzeszutek Wilk
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Stefano Stabellini, Thomas Gleixner,
	H. Peter Anvin, x86, Jesse Barnes

From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Introduce an x86 specific indirect mechanism to setup MSIs.
The MSI setup functions become function pointers in an x86_msi_ops
struct, that defaults to the implementation in io_apic.c

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/x86/include/asm/pci.h      |   26 +++++++++++++++++++++++---
 arch/x86/include/asm/x86_init.h |    9 +++++++++
 arch/x86/kernel/apic/io_apic.c  |    8 ++++----
 arch/x86/kernel/x86_init.c      |    6 ++++++
 4 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index bcf84e1..861d0d0 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
+#include <asm/x86_init.h>
 
 #ifdef __KERNEL__
 
@@ -92,9 +93,28 @@ static inline void early_quirks(void) { }
 
 extern void pci_iommu_alloc(void);
 
-/* MSI arch hook */
-#define arch_setup_msi_irqs arch_setup_msi_irqs
-#define arch_teardown_msi_irqs arch_teardown_msi_irqs
+/* MSI arch specific hooks */
+static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	return x86_msi.setup_msi_irqs(dev, nvec, type);
+}
+
+static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
+{
+	x86_msi.teardown_msi_irqs(dev);
+}
+
+static inline void x86_teardown_msi_irq(unsigned int irq)
+{
+	x86_msi.teardown_msi_irq(irq);
+}
+
+#define arch_setup_msi_irqs x86_setup_msi_irqs
+#define arch_teardown_msi_irqs x86_teardown_msi_irqs
+#define arch_teardown_msi_irq x86_teardown_msi_irq
+int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+void native_teardown_msi_irq(unsigned int irq);
+void native_teardown_msi_irqs(struct pci_dev *dev);
 
 #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
 
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index baa579c..64642ad 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -154,9 +154,18 @@ struct x86_platform_ops {
 	int (*i8042_detect)(void);
 };
 
+struct pci_dev;
+
+struct x86_msi_ops {
+	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
+	void (*teardown_msi_irq)(unsigned int irq);
+	void (*teardown_msi_irqs)(struct pci_dev *dev);
+};
+
 extern struct x86_init_ops x86_init;
 extern struct x86_cpuinit_ops x86_cpuinit;
 extern struct x86_platform_ops x86_platform;
+extern struct x86_msi_ops x86_msi;
 
 extern void x86_init_noop(void);
 extern void x86_init_uint_noop(unsigned int unused);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index a8d069e..0b552ec 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3531,7 +3531,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 	return 0;
 }
 
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	unsigned int irq;
 	int ret, sub_handle;
@@ -3592,12 +3592,12 @@ error:
 	return ret;
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+void native_teardown_msi_irq(unsigned int irq)
 {
 	destroy_irq(irq);
 }
 
-void arch_teardown_msi_irqs(struct pci_dev *dev)
+void native_teardown_msi_irqs(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
 
@@ -3607,7 +3607,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
 			continue;
 		nvec = 1 << entry->msi_attrib.multiple;
 		for (i = 0; i < nvec; i++)
-			arch_teardown_msi_irq(entry->irq + i);
+			x86_msi.teardown_msi_irq(entry->irq + i);
 	}
 }
 
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index cd6da6b..91b5209 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 
 #include <asm/bios_ebda.h>
 #include <asm/paravirt.h>
@@ -99,3 +100,8 @@ struct x86_platform_ops x86_platform = {
 };
 
 EXPORT_SYMBOL_GPL(x86_platform);
+struct x86_msi_ops x86_msi = {
+	.setup_msi_irqs = native_setup_msi_irqs,
+	.teardown_msi_irq = native_teardown_msi_irq,
+	.teardown_msi_irqs = native_teardown_msi_irqs,
+};
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (15 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 16/20] x86: Introduce x86_msi_ops Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-13 23:28   ` Jesse Barnes
  2010-08-04 18:19 ` [PATCH 18/20] xenbus: Xen paravirtualised PCI hotplug support Konrad Rzeszutek Wilk
                   ` (3 subsequent siblings)
  20 siblings, 1 reply; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Alex Nixon, Jeremy Fitzhardinge, Ian Campbell,
	Konrad Rzeszutek Wilk, Stefano Stabellini, H. Peter Anvin,
	Matthew Wilcox, Qing He, Thomas Gleixner, x86, Jesse Barnes

From: Alex Nixon <alex.nixon@citrix.com>

The frontend stub lives in arch/x86/pci/xen.c, alongside other
sub-arch PCI init code (e.g. olpc.c).

It provides a mechanism for Xen PCI frontend to setup/destroy
legacy interrupts, MSI/MSI-X, and PCI configuration operations.

[ Impact: add core of Xen PCI support ]
[ v2: Removed the IOMMU code and only focusing on PCI. Dropping:
drivers/pci/Makefile, drivers/pci/xen-iommu.c, arch/x86/kernel/pci-dma.c
and arch/x86/include/asm/xen/iommu.h]
[ v3: removed usage of pci_scan_all_fns as that does not exist]
[ v4: introduced pci_xen value to fix compile warnings]
[ v5: squished fixes+features in one patch, changed Reviewed-by to Ccs]
Signed-off-by: Alex Nixon <alex.nixon@citrix.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Qing He <qing.he@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86@kernel.org
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 arch/x86/Kconfig               |    5 ++
 arch/x86/include/asm/xen/pci.h |   53 ++++++++++++++
 arch/x86/pci/Makefile          |    1 +
 arch/x86/pci/xen.c             |  147 ++++++++++++++++++++++++++++++++++++++++
 arch/x86/xen/enlighten.c       |    3 +
 drivers/xen/events.c           |   32 ++++++++-
 include/xen/events.h           |    3 +
 7 files changed, 242 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/include/asm/xen/pci.h
 create mode 100644 arch/x86/pci/xen.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index dcb0593..108b2ab 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1922,6 +1922,11 @@ config PCI_OLPC
 	def_bool y
 	depends on PCI && OLPC && (PCI_GOOLPC || PCI_GOANY)
 
+config PCI_XEN
+	def_bool n
+	depends on XEN
+	select SWIOTLB_XEN
+
 config PCI_DOMAINS
 	def_bool y
 	depends on PCI
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h
new file mode 100644
index 0000000..449c82f
--- /dev/null
+++ b/arch/x86/include/asm/xen/pci.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_X86_XEN_PCI_H
+#define _ASM_X86_XEN_PCI_H
+
+#if defined(CONFIG_PCI_XEN)
+extern int __init pci_xen_init(void);
+#define pci_xen 1
+#else
+#define pci_xen 0
+#define pci_xen_init (0)
+#endif
+
+#if defined(CONFIG_PCI_MSI)
+#if defined(CONFIG_PCI_XEN)
+/* The drivers/pci/xen-pcifront.c sets this structure to
+ * its own functions.
+ */
+struct xen_pci_frontend_ops {
+	int (*enable_msi)(struct pci_dev *dev, int **vectors);
+	void (*disable_msi)(struct pci_dev *dev);
+	int (*enable_msix)(struct pci_dev *dev, int **vectors, int nvec);
+	void (*disable_msix)(struct pci_dev *dev);
+};
+
+extern struct xen_pci_frontend_ops *xen_pci_frontend;
+
+static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev,
+					      int **vectors)
+{
+	if (xen_pci_frontend && xen_pci_frontend->enable_msi)
+		return xen_pci_frontend->enable_msi(dev, vectors);
+	return -ENODEV;
+}
+static inline void xen_pci_frontend_disable_msi(struct pci_dev *dev)
+{
+	if (xen_pci_frontend && xen_pci_frontend->disable_msi)
+			xen_pci_frontend->disable_msi(dev);
+}
+static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev,
+					       int **vectors, int nvec)
+{
+	if (xen_pci_frontend && xen_pci_frontend->enable_msix)
+		return xen_pci_frontend->enable_msix(dev, vectors, nvec);
+	return -ENODEV;
+}
+static inline void xen_pci_frontend_disable_msix(struct pci_dev *dev)
+{
+	if (xen_pci_frontend && xen_pci_frontend->disable_msix)
+			xen_pci_frontend->disable_msix(dev);
+}
+#endif /* CONFIG_PCI_XEN */
+#endif /* CONFIG_PCI_MSI */
+
+#endif	/* _ASM_X86_XEN_PCI_H */
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index a0207a7..effd96e 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
 obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig_$(BITS).o direct.o mmconfig-shared.o
 obj-$(CONFIG_PCI_DIRECT)	+= direct.o
 obj-$(CONFIG_PCI_OLPC)		+= olpc.o
+obj-$(CONFIG_PCI_XEN)		+= xen.o
 
 obj-y				+= fixup.o
 obj-$(CONFIG_ACPI)		+= acpi.o
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
new file mode 100644
index 0000000..b19c873
--- /dev/null
+++ b/arch/x86/pci/xen.c
@@ -0,0 +1,147 @@
+/*
+ * Xen PCI Frontend Stub - puts some "dummy" functions in to the Linux
+ *			   x86 PCI core to support the Xen PCI Frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/acpi.h>
+
+#include <linux/io.h>
+#include <asm/pci_x86.h>
+
+#include <asm/xen/hypervisor.h>
+
+#include <xen/events.h>
+#include <asm/xen/pci.h>
+
+#if defined(CONFIG_PCI_MSI)
+#include <linux/msi.h>
+
+struct xen_pci_frontend_ops *xen_pci_frontend;
+EXPORT_SYMBOL_GPL(xen_pci_frontend);
+
+/*
+ * For MSI interrupts we have to use drivers/xen/event.s functions to
+ * allocate an irq_desc and setup the right */
+
+
+static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	int irq, ret, i;
+	struct msi_desc *msidesc;
+	int *v;
+
+	v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
+	if (!v)
+		return -ENOMEM;
+
+	if (!xen_initial_domain()) {
+		if (type == PCI_CAP_ID_MSIX)
+			ret = xen_pci_frontend_enable_msix(dev, &v, nvec);
+		else
+			ret = xen_pci_frontend_enable_msi(dev, &v);
+		if (ret)
+			goto error;
+	}
+	i = 0;
+	list_for_each_entry(msidesc, &dev->msi_list, list) {
+		irq = xen_allocate_pirq(v[i], 0, /* not sharable */
+			(type == PCI_CAP_ID_MSIX) ?
+			"pcifront-msi-x" : "pcifront-msi");
+		if (irq < 0)
+			return -1;
+
+		ret = set_irq_msi(irq, msidesc);
+		if (ret)
+			goto error_while;
+		i++;
+	}
+	kfree(v);
+	return 0;
+
+error_while:
+	unbind_from_irqhandler(irq, NULL);
+error:
+	if (ret == -ENODEV)
+		dev_err(&dev->dev, "Xen PCI frontend has not registered" \
+			" MSI/MSI-X support!\n");
+
+	kfree(v);
+	return ret;
+}
+
+static void xen_teardown_msi_irqs(struct pci_dev *dev)
+{
+	/* Only do this when were are in non-privileged mode.*/
+	if (!xen_initial_domain()) {
+		struct msi_desc *msidesc;
+
+		msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
+		if (msidesc->msi_attrib.is_msix)
+			xen_pci_frontend_disable_msix(dev);
+		else
+			xen_pci_frontend_disable_msi(dev);
+	}
+
+}
+
+static void xen_teardown_msi_irq(unsigned int irq)
+{
+	xen_destroy_irq(irq);
+}
+#endif
+
+static int xen_pcifront_enable_irq(struct pci_dev *dev)
+{
+	int rc;
+	int share = 1;
+
+	dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq);
+
+	if (dev->irq < 0)
+		return -EINVAL;
+
+	if (dev->irq < NR_IRQS_LEGACY)
+		share = 0;
+
+	rc = xen_allocate_pirq(dev->irq, share, "pcifront");
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n",
+			 dev->irq, rc);
+		return rc;
+	}
+	return 0;
+}
+
+int __init pci_xen_init(void)
+{
+	if (!xen_pv_domain() || xen_initial_domain())
+		return -ENODEV;
+
+	printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n");
+
+	pcibios_set_cache_line_size();
+
+	pcibios_enable_irq = xen_pcifront_enable_irq;
+	pcibios_disable_irq = NULL;
+
+#ifdef CONFIG_ACPI
+	/* Keep ACPI out of the picture */
+	acpi_noirq = 1;
+#endif
+
+#ifdef CONFIG_ISAPNP
+	/* Stop isapnp from probing */
+	isapnp_disable = 1;
+#endif
+
+#ifdef CONFIG_PCI_MSI
+	x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
+	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
+	x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
+#endif
+	return 0;
+}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 65d8d79..f7feba5 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -42,6 +42,7 @@
 #include <asm/paravirt.h>
 #include <asm/apic.h>
 #include <asm/page.h>
+#include <asm/xen/pci.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/fixmap.h>
@@ -1189,6 +1190,8 @@ asmlinkage void __init xen_start_kernel(void)
 		add_preferred_console("xenboot", 0, NULL);
 		add_preferred_console("tty", 0, NULL);
 		add_preferred_console("hvc", 0, NULL);
+		if (pci_xen)
+			x86_init.pci.arch_init = pci_xen_init;
 	} else {
 		/* Make sure ACS will be enabled */
 		pci_request_acs();
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 78c1525..249fbbd 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -561,7 +561,9 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
 		goto out;	/* XXX need refcount? */
 	}
 
-	if (identity_mapped_irq(gsi)) {
+	/* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore
+	 * we are using the !xen_initial_domain() to drop in the function.*/
+	if (identity_mapped_irq(gsi) || !xen_initial_domain()) {
 		irq = gsi;
 		irq_to_desc_alloc_node(irq, 0);
 		dynamic_irq_init(irq);
@@ -572,7 +574,13 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
 				      handle_level_irq, name);
 
 	irq_op.irq = irq;
-	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
+	irq_op.vector = 0;
+
+	/* Only the privileged domain can do this. For non-priv, the pcifront
+	 * driver provides a PCI bus that does the call to do exactly
+	 * this in the priv domain. */
+	if (xen_initial_domain() &&
+	    HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
 		dynamic_irq_cleanup(irq);
 		irq = -ENOSPC;
 		goto out;
@@ -587,6 +595,26 @@ out:
 	return irq;
 }
 
+int xen_destroy_irq(int irq)
+{
+	struct irq_desc *desc;
+	int rc = -ENOENT;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	desc = irq_to_desc(irq);
+	if (!desc)
+		goto out;
+
+	irq_info[irq] = mk_unbound_info();
+
+	dynamic_irq_cleanup(irq);
+
+out:
+	spin_unlock(&irq_mapping_update_lock);
+	return rc;
+}
+
 int xen_vector_from_irq(unsigned irq)
 {
 	return vector_from_irq(irq);
diff --git a/include/xen/events.h b/include/xen/events.h
index 20e27c3..3ef6624 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -65,6 +65,9 @@ unsigned irq_from_evtchn(unsigned int evtchn);
    usual. */
 int xen_allocate_pirq(unsigned gsi, int shareable, char *name);
 
+/* De-allocates the above mentioned physical interrupt. */
+int xen_destroy_irq(int irq);
+
 /* Return vector allocated to pirq */
 int xen_vector_from_irq(unsigned pirq);
 
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 18/20] xenbus: Xen paravirtualised PCI hotplug support.
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (16 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 19/20] xenbus: prevent warnings on unhandled enumeration values Konrad Rzeszutek Wilk
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Yosuke Iwamatsu, Noboru Iwamatsu,
	Konrad Rzeszutek Wilk, Jeremy Fitzhardinge

From: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>

The Xen PCI front driver adds two new states that are utilizez
for PCI hotplug support. This is a patch pulled from the
linux-2.6-xen-sparse tree.

Signed-off-by: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>
---
 drivers/xen/xenbus/xenbus_client.c |    2 ++
 include/xen/interface/io/xenbus.h  |    8 +++++++-
 2 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 7b3e973..6066eb9 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -50,6 +50,8 @@ const char *xenbus_strstate(enum xenbus_state state)
 		[ XenbusStateConnected    ] = "Connected",
 		[ XenbusStateClosing      ] = "Closing",
 		[ XenbusStateClosed	  ] = "Closed",
+		[XenbusStateReconfiguring] = "Reconfiguring",
+		[XenbusStateReconfigured] = "Reconfigured",
 	};
 	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
 }
diff --git a/include/xen/interface/io/xenbus.h b/include/xen/interface/io/xenbus.h
index 46508c7..9fda532 100644
--- a/include/xen/interface/io/xenbus.h
+++ b/include/xen/interface/io/xenbus.h
@@ -27,8 +27,14 @@ enum xenbus_state
 	XenbusStateClosing      = 5,  /* The device is being closed
 					 due to an error or an unplug
 					 event. */
-	XenbusStateClosed       = 6
+	XenbusStateClosed       = 6,
 
+	/*
+	* Reconfiguring: The device is being reconfigured.
+	*/
+	XenbusStateReconfiguring = 7,
+
+	XenbusStateReconfigured  = 8
 };
 
 #endif /* _XEN_PUBLIC_IO_XENBUS_H */
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 19/20] xenbus: prevent warnings on unhandled enumeration values
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (17 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 18/20] xenbus: Xen paravirtualised PCI hotplug support Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 18:19 ` [PATCH 20/20] xen-pcifront: Xen PCI frontend driver Konrad Rzeszutek Wilk
  2010-08-04 20:14 ` [Xen-devel] [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Noboru Iwamatsu, Jan Beulich,
	Konrad Rzeszutek Wilk, Jeremy Fitzhardinge

From: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>

XenbusStateReconfiguring/XenbusStateReconfigured were introduced by
c/s 437, but aren't handled in many switch statements.

.. also pulled from the linux-2.6-sparse-tree tree.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
---
 drivers/block/xen-blkfront.c |    2 ++
 drivers/input/xen-kbdfront.c |    2 ++
 drivers/net/xen-netfront.c   |    2 ++
 drivers/video/xen-fbfront.c  |    2 ++
 4 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 82ed403..61c6a11 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -967,6 +967,8 @@ static void backend_changed(struct xenbus_device *dev,
 	case XenbusStateInitialising:
 	case XenbusStateInitWait:
 	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
 	case XenbusStateUnknown:
 	case XenbusStateClosed:
 		break;
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
index e140816..067d430 100644
--- a/drivers/input/xen-kbdfront.c
+++ b/drivers/input/xen-kbdfront.c
@@ -276,6 +276,8 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
 	switch (backend_state) {
 	case XenbusStateInitialising:
 	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
 	case XenbusStateUnknown:
 	case XenbusStateClosed:
 		break;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d504e2b..3eae5db 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1610,6 +1610,8 @@ static void backend_changed(struct xenbus_device *dev,
 	switch (backend_state) {
 	case XenbusStateInitialising:
 	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
 	case XenbusStateConnected:
 	case XenbusStateUnknown:
 	case XenbusStateClosed:
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index fa97d3e..67fb98a 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -631,6 +631,8 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
 	switch (backend_state) {
 	case XenbusStateInitialising:
 	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
 	case XenbusStateUnknown:
 	case XenbusStateClosed:
 		break;
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH 20/20] xen-pcifront: Xen PCI frontend driver.
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (18 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 19/20] xenbus: prevent warnings on unhandled enumeration values Konrad Rzeszutek Wilk
@ 2010-08-04 18:19 ` Konrad Rzeszutek Wilk
  2010-08-04 20:14 ` [Xen-devel] [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 18:19 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: alex.williamson, Ryan Wilson, Konrad Rzeszutek Wilk

From: Ryan Wilson <hap9@epoch.ncsc.mil>

This is a port of the 2.6.18 Xen PCI front driver with fixes
to make it build under 2.6.34 and later (for the full list of
changes: git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git
historic/xen-pcifront-0.1). It also includes the fixes
to make it work properly.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 drivers/pci/Kconfig              |   16 +
 drivers/pci/Makefile             |    2 +
 drivers/pci/xen-pcifront.c       | 1157 ++++++++++++++++++++++++++++++++++++++
 include/xen/interface/io/pciif.h |  122 ++++
 4 files changed, 1297 insertions(+), 0 deletions(-)
 create mode 100644 drivers/pci/xen-pcifront.c
 create mode 100644 include/xen/interface/io/pciif.h

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 34ef70d..72a7d83 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -40,6 +40,22 @@ config PCI_STUB
 
 	  When in doubt, say N.
 
+config XEN_PCIDEV_FRONTEND
+        tristate "Xen PCI Frontend"
+        depends on X86
+        select HOTPLUG
+	select XEN_XENBUS_FRONTEND
+	select PCI_XEN
+	default y
+        help
+          The PCI device frontend driver allows the kernel to import arbitrary
+          PCI devices from a PCI backend to support PCI driver domains.
+
+config XEN_PCIDEV_FE_DEBUG
+        bool
+        depends on PCI_DEBUG
+        default n
+
 config HT_IRQ
 	bool "Interrupts on hypertransport devices"
 	default y
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 0b51857..8de352d 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -62,6 +62,8 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
 
 obj-$(CONFIG_PCI_STUB) += pci-stub.o
 
+obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
+
 ifeq ($(CONFIG_PCI_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
new file mode 100644
index 0000000..a48a733
--- /dev/null
+++ b/drivers/pci/xen-pcifront.c
@@ -0,0 +1,1157 @@
+/*
+ * Xen PCI Frontend.
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <xen/xenbus.h>
+#include <xen/events.h>
+#include <xen/grant_table.h>
+#include <xen/page.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <xen/xenbus.h>
+#include <xen/interface/io/pciif.h>
+#include <asm/xen/pci.h>
+#include <linux/interrupt.h>
+#include <asm/atomic.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/time.h>
+
+
+#ifndef __init_refok
+#define __init_refok
+#endif
+
+#define INVALID_GRANT_REF (0)
+#define INVALID_EVTCHN    (-1)
+
+
+struct pci_bus_entry {
+	struct list_head list;
+	struct pci_bus *bus;
+};
+
+#define _PDEVB_op_active		(0)
+#define PDEVB_op_active			(1 << (_PDEVB_op_active))
+
+struct pcifront_device {
+	struct xenbus_device *xdev;
+	struct list_head root_buses;
+
+	int evtchn;
+	int gnt_ref;
+
+	int irq;
+
+	/* Lock this when doing any operations in sh_info */
+	spinlock_t sh_info_lock;
+	struct xen_pci_sharedinfo *sh_info;
+	struct work_struct op_work;
+	unsigned long flags;
+
+};
+
+struct pcifront_sd {
+	int domain;
+	struct pcifront_device *pdev;
+};
+
+static inline struct pcifront_device *
+pcifront_get_pdev(struct pcifront_sd *sd)
+{
+	return sd->pdev;
+}
+
+static inline void pcifront_init_sd(struct pcifront_sd *sd,
+				    unsigned int domain, unsigned int bus,
+				    struct pcifront_device *pdev)
+{
+	sd->domain = domain;
+	sd->pdev = pdev;
+}
+
+static inline void pcifront_setup_root_resources(struct pci_bus *bus,
+						 struct pcifront_sd *sd)
+{
+}
+
+
+DEFINE_SPINLOCK(pcifront_dev_lock);
+static struct pcifront_device *pcifront_dev;
+
+static int verbose_request;
+module_param(verbose_request, int, 0644);
+
+static int errno_to_pcibios_err(int errno)
+{
+	switch (errno) {
+	case XEN_PCI_ERR_success:
+		return PCIBIOS_SUCCESSFUL;
+
+	case XEN_PCI_ERR_dev_not_found:
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	case XEN_PCI_ERR_invalid_offset:
+	case XEN_PCI_ERR_op_failed:
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	case XEN_PCI_ERR_not_implemented:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	case XEN_PCI_ERR_access_denied:
+		return PCIBIOS_SET_FAILED;
+	}
+	return errno;
+}
+
+static inline void schedule_pcifront_aer_op(struct pcifront_device *pdev)
+{
+	if (test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags)
+		&& !test_and_set_bit(_PDEVB_op_active, &pdev->flags)) {
+		dev_dbg(&pdev->xdev->dev, "schedule aer frontend job\n");
+		schedule_work(&pdev->op_work);
+	}
+}
+
+static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
+{
+	int err = 0;
+	struct xen_pci_op *active_op = &pdev->sh_info->op;
+	unsigned long irq_flags;
+	evtchn_port_t port = pdev->evtchn;
+	unsigned irq = pdev->irq;
+	s64 ns, ns_timeout;
+	struct timeval tv;
+
+	spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
+
+	memcpy(active_op, op, sizeof(struct xen_pci_op));
+
+	/* Go */
+	wmb();
+	set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
+	notify_remote_via_evtchn(port);
+
+	/*
+	 * We set a poll timeout of 3 seconds but give up on return after
+	 * 2 seconds. It is better to time out too late rather than too early
+	 * (in the latter case we end up continually re-executing poll() with a
+	 * timeout in the past). 1s difference gives plenty of slack for error.
+	 */
+	do_gettimeofday(&tv);
+	ns_timeout = timeval_to_ns(&tv) + 2 * (s64)NSEC_PER_SEC;
+
+	xen_clear_irq_pending(irq);
+
+	while (test_bit(_XEN_PCIF_active,
+			(unsigned long *)&pdev->sh_info->flags)) {
+		xen_poll_irq_timeout(irq, jiffies + 3*HZ);
+		xen_clear_irq_pending(irq);
+		do_gettimeofday(&tv);
+		ns = timeval_to_ns(&tv);
+		if (ns > ns_timeout) {
+			dev_err(&pdev->xdev->dev,
+				"pciback not responding!!!\n");
+			clear_bit(_XEN_PCIF_active,
+				  (unsigned long *)&pdev->sh_info->flags);
+			err = XEN_PCI_ERR_dev_not_found;
+			goto out;
+		}
+	}
+
+	/*
+	* We might lose backend service request since we
+	* reuse same evtchn with pci_conf backend response. So re-schedule
+	* aer pcifront service.
+	*/
+	if (test_bit(_XEN_PCIB_active,
+			(unsigned long *)&pdev->sh_info->flags)) {
+		dev_err(&pdev->xdev->dev,
+			"schedule aer pcifront service\n");
+		schedule_pcifront_aer_op(pdev);
+	}
+
+	memcpy(op, active_op, sizeof(struct xen_pci_op));
+
+	err = op->err;
+out:
+	spin_unlock_irqrestore(&pdev->sh_info_lock, irq_flags);
+	return err;
+}
+
+/* Access to this function is spinlocked in drivers/pci/access.c */
+static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 *val)
+{
+	int err = 0;
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_conf_read,
+		.domain = pci_domain_nr(bus),
+		.bus    = bus->number,
+		.devfn  = devfn,
+		.offset = where,
+		.size   = size,
+	};
+	struct pcifront_sd *sd = bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	if (verbose_request)
+		dev_info(&pdev->xdev->dev,
+			 "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
+			 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
+			 PCI_FUNC(devfn), where, size);
+
+	err = do_pci_op(pdev, &op);
+
+	if (likely(!err)) {
+		if (verbose_request)
+			dev_info(&pdev->xdev->dev, "read got back value %x\n",
+				 op.value);
+
+		*val = op.value;
+	} else if (err == -ENODEV) {
+		/* No device here, pretend that it just returned 0 */
+		err = 0;
+		*val = 0;
+	}
+
+	return errno_to_pcibios_err(err);
+}
+
+/* Access to this function is spinlocked in drivers/pci/access.c */
+static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 val)
+{
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_conf_write,
+		.domain = pci_domain_nr(bus),
+		.bus    = bus->number,
+		.devfn  = devfn,
+		.offset = where,
+		.size   = size,
+		.value  = val,
+	};
+	struct pcifront_sd *sd = bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	if (verbose_request)
+		dev_info(&pdev->xdev->dev,
+			 "write dev=%04x:%02x:%02x.%01x - "
+			 "offset %x size %d val %x\n",
+			 pci_domain_nr(bus), bus->number,
+			 PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
+
+	return errno_to_pcibios_err(do_pci_op(pdev, &op));
+}
+
+struct pci_ops pcifront_bus_ops = {
+	.read = pcifront_bus_read,
+	.write = pcifront_bus_write,
+};
+
+#ifdef CONFIG_PCI_MSI
+static int pci_frontend_enable_msix(struct pci_dev *dev,
+				    int **vector, int nvec)
+{
+	int err;
+	int i;
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_enable_msix,
+		.domain = pci_domain_nr(dev->bus),
+		.bus = dev->bus->number,
+		.devfn = dev->devfn,
+		.value = nvec,
+	};
+	struct pcifront_sd *sd = dev->bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+	struct msi_desc *entry;
+
+	if (nvec > SH_INFO_MAX_VEC) {
+		dev_err(&dev->dev, "too much vector for pci frontend: %x."
+				   " Increase SH_INFO_MAX_VEC.\n", nvec);
+		return -EINVAL;
+	}
+
+	i = 0;
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		op.msix_entries[i].entry = entry->msi_attrib.entry_nr;
+		/* Vector is useless at this point. */
+		op.msix_entries[i].vector = -1;
+		i++;
+	}
+
+	err = do_pci_op(pdev, &op);
+
+	if (likely(!err)) {
+		if (likely(!op.value)) {
+			/* we get the result */
+			for (i = 0; i < nvec; i++)
+				*(*vector+i) = op.msix_entries[i].vector;
+			return 0;
+		} else {
+			printk(KERN_DEBUG "enable msix get value %x\n",
+				op.value);
+			return op.value;
+		}
+	} else {
+		dev_err(&dev->dev, "enable msix get err %x\n", err);
+		return err;
+	}
+}
+
+static void pci_frontend_disable_msix(struct pci_dev *dev)
+{
+	int err;
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_disable_msix,
+		.domain = pci_domain_nr(dev->bus),
+		.bus = dev->bus->number,
+		.devfn = dev->devfn,
+	};
+	struct pcifront_sd *sd = dev->bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	err = do_pci_op(pdev, &op);
+
+	/* What should do for error ? */
+	if (err)
+		dev_err(&dev->dev, "pci_disable_msix get err %x\n", err);
+}
+
+static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector)
+{
+	int err;
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_enable_msi,
+		.domain = pci_domain_nr(dev->bus),
+		.bus = dev->bus->number,
+		.devfn = dev->devfn,
+	};
+	struct pcifront_sd *sd = dev->bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	err = do_pci_op(pdev, &op);
+	if (likely(!err)) {
+		*(*vector) = op.value;
+	} else {
+		dev_err(&dev->dev, "pci frontend enable msi failed for dev "
+				    "%x:%x\n", op.bus, op.devfn);
+		err = -EINVAL;
+	}
+	return err;
+}
+
+static void pci_frontend_disable_msi(struct pci_dev *dev)
+{
+	int err;
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_disable_msi,
+		.domain = pci_domain_nr(dev->bus),
+		.bus = dev->bus->number,
+		.devfn = dev->devfn,
+	};
+	struct pcifront_sd *sd = dev->bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	err = do_pci_op(pdev, &op);
+	if (err == XEN_PCI_ERR_dev_not_found) {
+		/* XXX No response from backend, what shall we do? */
+		printk(KERN_DEBUG "get no response from backend for disable MSI\n");
+		return;
+	}
+	if (err)
+		/* how can pciback notify us fail? */
+		printk(KERN_DEBUG "get fake response frombackend\n");
+}
+
+static struct xen_pci_frontend_ops pci_frontend_ops = {
+	.enable_msi = pci_frontend_enable_msi,
+	.disable_msi = pci_frontend_disable_msi,
+	.enable_msix = pci_frontend_enable_msix,
+	.disable_msix = pci_frontend_disable_msix,
+};
+
+static void pci_frontend_registrar(int enable)
+{
+	if (enable)
+		xen_pci_frontend = &pci_frontend_ops;
+	else
+		xen_pci_frontend = NULL;
+};
+#else
+static inline void pci_frontend_registrar(int enable) { };
+#endif /* CONFIG_PCI_MSI */
+
+/* Claim resources for the PCI frontend as-is, backend won't allow changes */
+static int pcifront_claim_resource(struct pci_dev *dev, void *data)
+{
+	struct pcifront_device *pdev = data;
+	int i;
+	struct resource *r;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		r = &dev->resource[i];
+
+		if (!r->parent && r->start && r->flags) {
+			dev_info(&pdev->xdev->dev, "claiming resource %s/%d\n",
+				pci_name(dev), i);
+			if (pci_claim_resource(dev, i)) {
+				dev_err(&pdev->xdev->dev, "Could not claim "
+					"resource %s/%d! Device offline. Try "
+					"giving less than 4GB to domain.\n",
+					pci_name(dev), i);
+			}
+		}
+	}
+
+	return 0;
+}
+
+int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
+				unsigned int domain, unsigned int bus,
+				struct pci_bus *b)
+{
+	struct pci_dev *d;
+	unsigned int devfn;
+
+	/* Scan the bus for functions and add.
+	 * We omit handling of PCI bridge attachment because pciback prevents
+	 * bridges from being exported.
+	 */
+	for (devfn = 0; devfn < 0x100; devfn++) {
+		d = pci_get_slot(b, devfn);
+		if (d) {
+			/* Device is already known. */
+			pci_dev_put(d);
+			continue;
+		}
+
+		d = pci_scan_single_device(b, devfn);
+		if (d)
+			dev_info(&pdev->xdev->dev, "New device on "
+				 "%04x:%02x:%02x.%02x found.\n", domain, bus,
+				 PCI_SLOT(devfn), PCI_FUNC(devfn));
+	}
+
+	return 0;
+}
+
+int __devinit pcifront_scan_root(struct pcifront_device *pdev,
+				 unsigned int domain, unsigned int bus)
+{
+	struct pci_bus *b;
+	struct pcifront_sd *sd = NULL;
+	struct pci_bus_entry *bus_entry = NULL;
+	int err = 0;
+
+#ifndef CONFIG_PCI_DOMAINS
+	if (domain != 0) {
+		dev_err(&pdev->xdev->dev,
+			"PCI Root in non-zero PCI Domain! domain=%d\n", domain);
+		dev_err(&pdev->xdev->dev,
+			"Please compile with CONFIG_PCI_DOMAINS\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+#endif
+
+	dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
+		 domain, bus);
+
+	bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
+	sd = kmalloc(sizeof(*sd), GFP_KERNEL);
+	if (!bus_entry || !sd) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	pcifront_init_sd(sd, domain, bus, pdev);
+
+	b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
+				  &pcifront_bus_ops, sd);
+	if (!b) {
+		dev_err(&pdev->xdev->dev,
+			"Error creating PCI Frontend Bus!\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	pcifront_setup_root_resources(b, sd);
+	bus_entry->bus = b;
+
+	list_add(&bus_entry->list, &pdev->root_buses);
+
+	/* pci_scan_bus_parented skips devices which do not have a have
+	* devfn==0. The pcifront_scan_bus enumerates all devfn. */
+	err = pcifront_scan_bus(pdev, domain, bus, b);
+
+	/* Claim resources before going "live" with our devices */
+	pci_walk_bus(b, pcifront_claim_resource, pdev);
+
+	/* Create SysFS and notify udev of the devices. Aka: "going live" */
+	pci_bus_add_devices(b);
+
+	return err;
+
+err_out:
+	kfree(bus_entry);
+	kfree(sd);
+
+	return err;
+}
+
+int __devinit pcifront_rescan_root(struct pcifront_device *pdev,
+				   unsigned int domain, unsigned int bus)
+{
+	int err;
+	struct pci_bus *b;
+
+#ifndef CONFIG_PCI_DOMAINS
+	if (domain != 0) {
+		dev_err(&pdev->xdev->dev,
+			"PCI Root in non-zero PCI Domain! domain=%d\n", domain);
+		dev_err(&pdev->xdev->dev,
+			"Please compile with CONFIG_PCI_DOMAINS\n");
+		return -EINVAL;
+	}
+#endif
+
+	dev_info(&pdev->xdev->dev, "Rescanning PCI Frontend Bus %04x:%02x\n",
+		 domain, bus);
+
+	b = pci_find_bus(domain, bus);
+	if (!b)
+		/* If the bus is unknown, create it. */
+		return pcifront_scan_root(pdev, domain, bus);
+
+	err = pcifront_scan_bus(pdev, domain, bus, b);
+
+	/* Claim resources before going "live" with our devices */
+	pci_walk_bus(b, pcifront_claim_resource, pdev);
+
+	/* Create SysFS and notify udev of the devices. Aka: "going live" */
+	pci_bus_add_devices(b);
+
+	return err;
+}
+
+static void free_root_bus_devs(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	while (!list_empty(&bus->devices)) {
+		dev = container_of(bus->devices.next, struct pci_dev,
+				   bus_list);
+		dev_dbg(&dev->dev, "removing device\n");
+		pci_remove_bus_device(dev);
+	}
+}
+
+void pcifront_free_roots(struct pcifront_device *pdev)
+{
+	struct pci_bus_entry *bus_entry, *t;
+
+	dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
+
+	list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
+		list_del(&bus_entry->list);
+
+		free_root_bus_devs(bus_entry->bus);
+
+		kfree(bus_entry->bus->sysdata);
+
+		device_unregister(bus_entry->bus->bridge);
+		pci_remove_bus(bus_entry->bus);
+
+		kfree(bus_entry);
+	}
+}
+
+static pci_ers_result_t pcifront_common_process(int cmd,
+						struct pcifront_device *pdev,
+						pci_channel_state_t state)
+{
+	pci_ers_result_t result;
+	struct pci_driver *pdrv;
+	int bus = pdev->sh_info->aer_op.bus;
+	int devfn = pdev->sh_info->aer_op.devfn;
+	struct pci_dev *pcidev;
+	int flag = 0;
+
+	dev_dbg(&pdev->xdev->dev,
+		"pcifront AER process: cmd %x (bus:%x, devfn%x)",
+		cmd, bus, devfn);
+	result = PCI_ERS_RESULT_NONE;
+
+	pcidev = pci_get_bus_and_slot(bus, devfn);
+	if (!pcidev || !pcidev->driver) {
+		dev_err(&pcidev->dev,
+			"device or driver is NULL\n");
+		return result;
+	}
+	pdrv = pcidev->driver;
+
+	if (get_driver(&pdrv->driver)) {
+		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
+			dev_dbg(&pcidev->dev,
+				"trying to call AER service\n");
+			if (pcidev) {
+				flag = 1;
+				switch (cmd) {
+				case XEN_PCI_OP_aer_detected:
+					result = pdrv->err_handler->
+						 error_detected(pcidev, state);
+					break;
+				case XEN_PCI_OP_aer_mmio:
+					result = pdrv->err_handler->
+						 mmio_enabled(pcidev);
+					break;
+				case XEN_PCI_OP_aer_slotreset:
+					result = pdrv->err_handler->
+						 slot_reset(pcidev);
+					break;
+				case XEN_PCI_OP_aer_resume:
+					pdrv->err_handler->resume(pcidev);
+					break;
+				default:
+					dev_err(&pdev->xdev->dev,
+						"bad request in aer recovery "
+						"operation!\n");
+
+				}
+			}
+		}
+		put_driver(&pdrv->driver);
+	}
+	if (!flag)
+		result = PCI_ERS_RESULT_NONE;
+
+	return result;
+}
+
+
+void pcifront_do_aer(struct work_struct *data)
+{
+	struct pcifront_device *pdev =
+		container_of(data, struct pcifront_device, op_work);
+	int cmd = pdev->sh_info->aer_op.cmd;
+	pci_channel_state_t state =
+		(pci_channel_state_t)pdev->sh_info->aer_op.err;
+
+	/*If a pci_conf op is in progress,
+		we have to wait until it is done before service aer op*/
+	dev_dbg(&pdev->xdev->dev,
+		"pcifront service aer bus %x devfn %x\n",
+		pdev->sh_info->aer_op.bus, pdev->sh_info->aer_op.devfn);
+
+	pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state);
+
+	/* Post the operation to the guest. */
+	wmb();
+	clear_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags);
+	notify_remote_via_evtchn(pdev->evtchn);
+
+	/*in case of we lost an aer request in four lines time_window*/
+	smp_mb__before_clear_bit();
+	clear_bit(_PDEVB_op_active, &pdev->flags);
+	smp_mb__after_clear_bit();
+
+	schedule_pcifront_aer_op(pdev);
+
+}
+
+irqreturn_t pcifront_handler_aer(int irq, void *dev)
+{
+	struct pcifront_device *pdev = dev;
+	schedule_pcifront_aer_op(pdev);
+	return IRQ_HANDLED;
+}
+int pcifront_connect(struct pcifront_device *pdev)
+{
+	int err = 0;
+
+	spin_lock(&pcifront_dev_lock);
+
+	if (!pcifront_dev) {
+		dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
+		pcifront_dev = pdev;
+	} else {
+		dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n");
+		err = -EEXIST;
+	}
+
+	spin_unlock(&pcifront_dev_lock);
+
+	return err;
+}
+
+void pcifront_disconnect(struct pcifront_device *pdev)
+{
+	spin_lock(&pcifront_dev_lock);
+
+	if (pdev == pcifront_dev) {
+		dev_info(&pdev->xdev->dev,
+			 "Disconnecting PCI Frontend Buses\n");
+		pcifront_dev = NULL;
+	}
+
+	spin_unlock(&pcifront_dev_lock);
+}
+static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev)
+{
+	struct pcifront_device *pdev;
+
+	pdev = kzalloc(sizeof(struct pcifront_device), GFP_KERNEL);
+	if (pdev == NULL)
+		goto out;
+
+	pdev->sh_info =
+	    (struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
+	if (pdev->sh_info == NULL) {
+		kfree(pdev);
+		pdev = NULL;
+		goto out;
+	}
+	pdev->sh_info->flags = 0;
+
+	/*Flag for registering PV AER handler*/
+	set_bit(_XEN_PCIB_AERHANDLER, (void *)&pdev->sh_info->flags);
+
+	dev_set_drvdata(&xdev->dev, pdev);
+	pdev->xdev = xdev;
+
+	INIT_LIST_HEAD(&pdev->root_buses);
+
+	spin_lock_init(&pdev->sh_info_lock);
+
+	pdev->evtchn = INVALID_EVTCHN;
+	pdev->gnt_ref = INVALID_GRANT_REF;
+	pdev->irq = -1;
+
+	INIT_WORK(&pdev->op_work, pcifront_do_aer);
+
+	dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
+		pdev, pdev->sh_info);
+out:
+	return pdev;
+}
+
+static void free_pdev(struct pcifront_device *pdev)
+{
+	dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
+
+	pcifront_free_roots(pdev);
+
+	/*For PCIE_AER error handling job*/
+	flush_scheduled_work();
+	unbind_from_irqhandler(pdev->irq, pdev);
+
+	if (pdev->evtchn != INVALID_EVTCHN)
+		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
+
+	if (pdev->gnt_ref != INVALID_GRANT_REF)
+		gnttab_end_foreign_access(pdev->gnt_ref, 0 /* r/w page */,
+					  (unsigned long)pdev->sh_info);
+
+	dev_set_drvdata(&pdev->xdev->dev, NULL);
+
+	kfree(pdev);
+}
+
+static int pcifront_publish_info(struct pcifront_device *pdev)
+{
+	int err = 0;
+	struct xenbus_transaction trans;
+
+	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
+	if (err < 0)
+		goto out;
+
+	pdev->gnt_ref = err;
+
+	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
+	if (err)
+		goto out;
+
+	err = bind_evtchn_to_irqhandler(pdev->evtchn, pcifront_handler_aer,
+		0, "pcifront", pdev);
+	if (err < 0) {
+		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
+		xenbus_dev_fatal(pdev->xdev, err, "Failed to bind evtchn to "
+				 "irqhandler.\n");
+		return err;
+	}
+	pdev->irq = err;
+
+do_publish:
+	err = xenbus_transaction_start(&trans);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error writing configuration for backend "
+				 "(start transaction)");
+		goto out;
+	}
+
+	err = xenbus_printf(trans, pdev->xdev->nodename,
+			    "pci-op-ref", "%u", pdev->gnt_ref);
+	if (!err)
+		err = xenbus_printf(trans, pdev->xdev->nodename,
+				    "event-channel", "%u", pdev->evtchn);
+	if (!err)
+		err = xenbus_printf(trans, pdev->xdev->nodename,
+				    "magic", XEN_PCI_MAGIC);
+
+	if (err) {
+		xenbus_transaction_end(trans, 1);
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error writing configuration for backend");
+		goto out;
+	} else {
+		err = xenbus_transaction_end(trans, 0);
+		if (err == -EAGAIN)
+			goto do_publish;
+		else if (err) {
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error completing transaction "
+					 "for backend");
+			goto out;
+		}
+	}
+
+	xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
+
+	dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
+
+out:
+	return err;
+}
+
+static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
+{
+	int err = -EFAULT;
+	int i, num_roots, len;
+	char str[64];
+	unsigned int domain, bus;
+
+
+	/* Only connect once */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateInitialised)
+		goto out;
+
+	err = pcifront_connect(pdev);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error connecting PCI Frontend");
+		goto out;
+	}
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
+			   "root_num", "%d", &num_roots);
+	if (err == -ENOENT) {
+		xenbus_dev_error(pdev->xdev, err,
+				 "No PCI Roots found, trying 0000:00");
+		err = pcifront_scan_root(pdev, 0, 0);
+		num_roots = 0;
+	} else if (err != 1) {
+		if (err == 0)
+			err = -EINVAL;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading number of PCI roots");
+		goto out;
+	}
+
+	for (i = 0; i < num_roots; i++) {
+		len = snprintf(str, sizeof(str), "root-%d", i);
+		if (unlikely(len >= (sizeof(str) - 1))) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
+				   "%x:%x", &domain, &bus);
+		if (err != 2) {
+			if (err >= 0)
+				err = -EINVAL;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error reading PCI root %d", i);
+			goto out;
+		}
+
+		err = pcifront_scan_root(pdev, domain, bus);
+		if (err) {
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error scanning PCI root %04x:%02x",
+					 domain, bus);
+			goto out;
+		}
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
+
+out:
+	return err;
+}
+
+static int pcifront_try_disconnect(struct pcifront_device *pdev)
+{
+	int err = 0;
+	enum xenbus_state prev_state;
+
+
+	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
+
+	if (prev_state >= XenbusStateClosing)
+		goto out;
+
+	if (prev_state == XenbusStateConnected) {
+		pcifront_free_roots(pdev);
+		pcifront_disconnect(pdev);
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateClosed);
+
+out:
+
+	return err;
+}
+
+static int __devinit pcifront_attach_devices(struct pcifront_device *pdev)
+{
+	int err = -EFAULT;
+	int i, num_roots, len;
+	unsigned int domain, bus;
+	char str[64];
+
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateReconfiguring)
+		goto out;
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
+			   "root_num", "%d", &num_roots);
+	if (err == -ENOENT) {
+		xenbus_dev_error(pdev->xdev, err,
+				 "No PCI Roots found, trying 0000:00");
+		err = pcifront_rescan_root(pdev, 0, 0);
+		num_roots = 0;
+	} else if (err != 1) {
+		if (err == 0)
+			err = -EINVAL;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading number of PCI roots");
+		goto out;
+	}
+
+	for (i = 0; i < num_roots; i++) {
+		len = snprintf(str, sizeof(str), "root-%d", i);
+		if (unlikely(len >= (sizeof(str) - 1))) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
+				   "%x:%x", &domain, &bus);
+		if (err != 2) {
+			if (err >= 0)
+				err = -EINVAL;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error reading PCI root %d", i);
+			goto out;
+		}
+
+		err = pcifront_rescan_root(pdev, domain, bus);
+		if (err) {
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error scanning PCI root %04x:%02x",
+					 domain, bus);
+			goto out;
+		}
+	}
+
+	xenbus_switch_state(pdev->xdev, XenbusStateConnected);
+
+out:
+	return err;
+}
+
+static int pcifront_detach_devices(struct pcifront_device *pdev)
+{
+	int err = 0;
+	int i, num_devs;
+	unsigned int domain, bus, slot, func;
+	struct pci_bus *pci_bus;
+	struct pci_dev *pci_dev;
+	char str[64];
+
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateConnected)
+		goto out;
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "num_devs", "%d",
+			   &num_devs);
+	if (err != 1) {
+		if (err >= 0)
+			err = -EINVAL;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading number of PCI devices");
+		goto out;
+	}
+
+	/* Find devices being detached and remove them. */
+	for (i = 0; i < num_devs; i++) {
+		int l, state;
+		l = snprintf(str, sizeof(str), "state-%d", i);
+		if (unlikely(l >= (sizeof(str) - 1))) {
+			err = -ENOMEM;
+			goto out;
+		}
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str, "%d",
+				   &state);
+		if (err != 1)
+			state = XenbusStateUnknown;
+
+		if (state != XenbusStateClosing)
+			continue;
+
+		/* Remove device. */
+		l = snprintf(str, sizeof(str), "vdev-%d", i);
+		if (unlikely(l >= (sizeof(str) - 1))) {
+			err = -ENOMEM;
+			goto out;
+		}
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
+				   "%x:%x:%x.%x", &domain, &bus, &slot, &func);
+		if (err != 4) {
+			if (err >= 0)
+				err = -EINVAL;
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error reading PCI device %d", i);
+			goto out;
+		}
+
+		pci_bus = pci_find_bus(domain, bus);
+		if (!pci_bus) {
+			dev_dbg(&pdev->xdev->dev, "Cannot get bus %04x:%02x\n",
+				domain, bus);
+			continue;
+		}
+		pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func));
+		if (!pci_dev) {
+			dev_dbg(&pdev->xdev->dev,
+				"Cannot get PCI device %04x:%02x:%02x.%02x\n",
+				domain, bus, slot, func);
+			continue;
+		}
+		pci_remove_bus_device(pci_dev);
+		pci_dev_put(pci_dev);
+
+		dev_dbg(&pdev->xdev->dev,
+			"PCI device %04x:%02x:%02x.%02x removed.\n",
+			domain, bus, slot, func);
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateReconfiguring);
+
+out:
+	return err;
+}
+
+static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
+						  enum xenbus_state be_state)
+{
+	struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
+
+	switch (be_state) {
+	case XenbusStateUnknown:
+	case XenbusStateInitialising:
+	case XenbusStateInitWait:
+	case XenbusStateInitialised:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateConnected:
+		pcifront_try_connect(pdev);
+		break;
+
+	case XenbusStateClosing:
+		dev_warn(&xdev->dev, "backend going away!\n");
+		pcifront_try_disconnect(pdev);
+		break;
+
+	case XenbusStateReconfiguring:
+		pcifront_detach_devices(pdev);
+		break;
+
+	case XenbusStateReconfigured:
+		pcifront_attach_devices(pdev);
+		break;
+	}
+}
+
+static int pcifront_xenbus_probe(struct xenbus_device *xdev,
+				 const struct xenbus_device_id *id)
+{
+	int err = 0;
+	struct pcifront_device *pdev = alloc_pdev(xdev);
+
+	if (pdev == NULL) {
+		err = -ENOMEM;
+		xenbus_dev_fatal(xdev, err,
+				 "Error allocating pcifront_device struct");
+		goto out;
+	}
+
+	err = pcifront_publish_info(pdev);
+
+out:
+	return err;
+}
+
+static int pcifront_xenbus_remove(struct xenbus_device *xdev)
+{
+	struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
+	if (pdev)
+		free_pdev(pdev);
+
+	return 0;
+}
+
+static const struct xenbus_device_id xenpci_ids[] = {
+	{"pci"},
+	{""},
+};
+
+static struct xenbus_driver xenbus_pcifront_driver = {
+	.name			= "pcifront",
+	.owner			= THIS_MODULE,
+	.ids			= xenpci_ids,
+	.probe			= pcifront_xenbus_probe,
+	.remove			= pcifront_xenbus_remove,
+	.otherend_changed	= pcifront_backend_changed,
+};
+
+static int __init pcifront_init(void)
+{
+	if (!xen_domain())
+		return -ENODEV;
+
+	pci_frontend_registrar(1 /* enable */);
+
+	return xenbus_register_frontend(&xenbus_pcifront_driver);
+}
+
+static void __exit pcifront_cleanup(void)
+{
+	xenbus_unregister_driver(&xenbus_pcifront_driver);
+	pci_frontend_registrar(0 /* disable */);
+}
+module_init(pcifront_init);
+module_exit(pcifront_cleanup);
+
+MODULE_DESCRIPTION("Xen PCI passthrough frontend.");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:pci");
diff --git a/include/xen/interface/io/pciif.h b/include/xen/interface/io/pciif.h
new file mode 100644
index 0000000..c955a1d
--- /dev/null
+++ b/include/xen/interface/io/pciif.h
@@ -0,0 +1,122 @@
+/*
+ * PCI Backend/Frontend Common Data Structures & Macros
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#ifndef __XEN_PCI_COMMON_H__
+#define __XEN_PCI_COMMON_H__
+
+/* Be sure to bump this number if you change this file */
+#define XEN_PCI_MAGIC "7"
+
+/* xen_pci_sharedinfo flags */
+#define	_XEN_PCIF_active		(0)
+#define	XEN_PCIF_active			(1<<_XEN_PCIF_active)
+#define	_XEN_PCIB_AERHANDLER		(1)
+#define	XEN_PCIB_AERHANDLER		(1<<_XEN_PCIB_AERHANDLER)
+#define	_XEN_PCIB_active		(2)
+#define	XEN_PCIB_active			(1<<_XEN_PCIB_active)
+
+/* xen_pci_op commands */
+#define	XEN_PCI_OP_conf_read		(0)
+#define	XEN_PCI_OP_conf_write		(1)
+#define	XEN_PCI_OP_enable_msi		(2)
+#define	XEN_PCI_OP_disable_msi		(3)
+#define	XEN_PCI_OP_enable_msix		(4)
+#define	XEN_PCI_OP_disable_msix		(5)
+#define	XEN_PCI_OP_aer_detected		(6)
+#define	XEN_PCI_OP_aer_resume		(7)
+#define	XEN_PCI_OP_aer_mmio		(8)
+#define	XEN_PCI_OP_aer_slotreset	(9)
+
+/* xen_pci_op error numbers */
+#define	XEN_PCI_ERR_success		(0)
+#define	XEN_PCI_ERR_dev_not_found	(-1)
+#define	XEN_PCI_ERR_invalid_offset	(-2)
+#define	XEN_PCI_ERR_access_denied	(-3)
+#define	XEN_PCI_ERR_not_implemented	(-4)
+/* XEN_PCI_ERR_op_failed - backend failed to complete the operation */
+#define XEN_PCI_ERR_op_failed		(-5)
+
+/*
+ * it should be PAGE_SIZE-sizeof(struct xen_pci_op))/sizeof(struct msix_entry))
+ * Should not exceed 128
+ */
+#define SH_INFO_MAX_VEC			128
+
+struct xen_msix_entry {
+    uint16_t vector;
+    uint16_t entry;
+};
+struct xen_pci_op {
+    /* IN: what action to perform: XEN_PCI_OP_* */
+    uint32_t cmd;
+
+    /* OUT: will contain an error number (if any) from errno.h */
+    int32_t err;
+
+    /* IN: which device to touch */
+    uint32_t domain; /* PCI Domain/Segment */
+    uint32_t bus;
+    uint32_t devfn;
+
+    /* IN: which configuration registers to touch */
+    int32_t offset;
+    int32_t size;
+
+    /* IN/OUT: Contains the result after a READ or the value to WRITE */
+    uint32_t value;
+    /* IN: Contains extra infor for this operation */
+    uint32_t info;
+    /*IN:  param for msi-x */
+    struct xen_msix_entry msix_entries[SH_INFO_MAX_VEC];
+};
+
+/*used for pcie aer handling*/
+struct xen_pcie_aer_op {
+    /* IN: what action to perform: XEN_PCI_OP_* */
+    uint32_t cmd;
+    /*IN/OUT: return aer_op result or carry error_detected state as input*/
+    int32_t err;
+
+    /* IN: which device to touch */
+    uint32_t domain; /* PCI Domain/Segment*/
+    uint32_t bus;
+    uint32_t devfn;
+};
+struct xen_pci_sharedinfo {
+    /* flags - XEN_PCIF_* */
+    uint32_t flags;
+    struct xen_pci_op op;
+    struct xen_pcie_aer_op aer_op;
+};
+
+#endif /* __XEN_PCI_COMMON_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.0.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [Xen-devel] [RFC PATCH] Xen PCI frontend driver (v0.5)
  2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
                   ` (19 preceding siblings ...)
  2010-08-04 18:19 ` [PATCH 20/20] xen-pcifront: Xen PCI frontend driver Konrad Rzeszutek Wilk
@ 2010-08-04 20:14 ` Konrad Rzeszutek Wilk
  20 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-04 20:14 UTC (permalink / raw)
  To: linux-kernel, xen-devel; +Cc: alex.williamson

On Wed, Aug 04, 2010 at 02:18:55PM -0400, Konrad Rzeszutek Wilk wrote:
> This patch set contains the groundwork and the driver itself for
> Xen Paravirtualized (PV) domains to use PCI pass-through devices.
> 
> These patches utilize the Xen-SWIOTLB library
> (http://lkml.org/lkml/2010/7/27/246) and I don't expect them to
> get in the 2.6.36 merge window.

<sigh>And when I say "them", I mean "this". Meaning this set of patches that
introduce the Xen PCI frontend driver. 

Sorry about the confusion.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem
  2010-08-04 18:19 ` [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem Konrad Rzeszutek Wilk
@ 2010-08-13 23:28   ` Jesse Barnes
  2010-10-04 18:30     ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 33+ messages in thread
From: Jesse Barnes @ 2010-08-13 23:28 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-kernel, xen-devel, alex.williamson, Alex Nixon,
	Jeremy Fitzhardinge, Ian Campbell, Stefano Stabellini,
	H. Peter Anvin, Matthew Wilcox, Qing He, Thomas Gleixner, x86

On Wed,  4 Aug 2010 14:19:12 -0400
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> wrote:

> From: Alex Nixon <alex.nixon@citrix.com>
> 
> The frontend stub lives in arch/x86/pci/xen.c, alongside other
> sub-arch PCI init code (e.g. olpc.c).
> 
> It provides a mechanism for Xen PCI frontend to setup/destroy
> legacy interrupts, MSI/MSI-X, and PCI configuration operations.
> 
> [ Impact: add core of Xen PCI support ]
> [ v2: Removed the IOMMU code and only focusing on PCI. Dropping:
> drivers/pci/Makefile, drivers/pci/xen-iommu.c, arch/x86/kernel/pci-dma.c
> and arch/x86/include/asm/xen/iommu.h]
> [ v3: removed usage of pci_scan_all_fns as that does not exist]
> [ v4: introduced pci_xen value to fix compile warnings]
> [ v5: squished fixes+features in one patch, changed Reviewed-by to Ccs]
> Signed-off-by: Alex Nixon <alex.nixon@citrix.com>
> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Matthew Wilcox <willy@linux.intel.com>
> Cc: Qing He <qing.he@intel.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: x86@kernel.org
> Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---

Fine with me if this stuff goes in with the rest of the Xen bits,
presumably through the x86 tree.

Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 16/20] x86: Introduce x86_msi_ops
  2010-08-04 18:19 ` [PATCH 16/20] x86: Introduce x86_msi_ops Konrad Rzeszutek Wilk
@ 2010-08-31 18:31     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-31 18:31 UTC (permalink / raw)
  To: linux-kernel, xen-devel, hpa
  Cc: alex.williamson, Stefano Stabellini, Thomas Gleixner,
	H. Peter Anvin, x86, Jesse Barnes

On Wed, Aug 04, 2010 at 02:19:11PM -0400, Konrad Rzeszutek Wilk wrote:
> From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> 
> Introduce an x86 specific indirect mechanism to setup MSIs.
> The MSI setup functions become function pointers in an x86_msi_ops
> struct, that defaults to the implementation in io_apic.c

Hey Peter,

I was wondering if you have time to take a look at this?

The patchset introduces a driver which takes care of allowing
pci_conf_read/write in a virtualized environements with PCI
passthrough devices. Unfortunatly for MSI operations that is not
so simple, so this patch alongside with the previous one
(https://patchwork.kernel.org/patch/117105/)
expands the arch_* calls. This makes it possible to register on top
of the native callback, the virtualized ones if required.

> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  arch/x86/include/asm/pci.h      |   26 +++++++++++++++++++++++---
>  arch/x86/include/asm/x86_init.h |    9 +++++++++
>  arch/x86/kernel/apic/io_apic.c  |    8 ++++----
>  arch/x86/kernel/x86_init.c      |    6 ++++++
>  4 files changed, 42 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index bcf84e1..861d0d0 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -7,6 +7,7 @@
>  #include <linux/string.h>
>  #include <asm/scatterlist.h>
>  #include <asm/io.h>
> +#include <asm/x86_init.h>
>  
>  #ifdef __KERNEL__
>  
> @@ -92,9 +93,28 @@ static inline void early_quirks(void) { }
>  
>  extern void pci_iommu_alloc(void);
>  
> -/* MSI arch hook */
> -#define arch_setup_msi_irqs arch_setup_msi_irqs
> -#define arch_teardown_msi_irqs arch_teardown_msi_irqs
> +/* MSI arch specific hooks */
> +static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> +{
> +	return x86_msi.setup_msi_irqs(dev, nvec, type);
> +}
> +
> +static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
> +{
> +	x86_msi.teardown_msi_irqs(dev);
> +}
> +
> +static inline void x86_teardown_msi_irq(unsigned int irq)
> +{
> +	x86_msi.teardown_msi_irq(irq);
> +}
> +
> +#define arch_setup_msi_irqs x86_setup_msi_irqs
> +#define arch_teardown_msi_irqs x86_teardown_msi_irqs
> +#define arch_teardown_msi_irq x86_teardown_msi_irq
> +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
> +void native_teardown_msi_irq(unsigned int irq);
> +void native_teardown_msi_irqs(struct pci_dev *dev);
>  
>  #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
>  
> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> index baa579c..64642ad 100644
> --- a/arch/x86/include/asm/x86_init.h
> +++ b/arch/x86/include/asm/x86_init.h
> @@ -154,9 +154,18 @@ struct x86_platform_ops {
>  	int (*i8042_detect)(void);
>  };
>  
> +struct pci_dev;
> +
> +struct x86_msi_ops {
> +	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
> +	void (*teardown_msi_irq)(unsigned int irq);
> +	void (*teardown_msi_irqs)(struct pci_dev *dev);
> +};
> +
>  extern struct x86_init_ops x86_init;
>  extern struct x86_cpuinit_ops x86_cpuinit;
>  extern struct x86_platform_ops x86_platform;
> +extern struct x86_msi_ops x86_msi;
>  
>  extern void x86_init_noop(void);
>  extern void x86_init_uint_noop(unsigned int unused);
> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> index a8d069e..0b552ec 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -3531,7 +3531,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
>  	return 0;
>  }
>  
> -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
>  {
>  	unsigned int irq;
>  	int ret, sub_handle;
> @@ -3592,12 +3592,12 @@ error:
>  	return ret;
>  }
>  
> -void arch_teardown_msi_irq(unsigned int irq)
> +void native_teardown_msi_irq(unsigned int irq)
>  {
>  	destroy_irq(irq);
>  }
>  
> -void arch_teardown_msi_irqs(struct pci_dev *dev)
> +void native_teardown_msi_irqs(struct pci_dev *dev)
>  {
>  	struct msi_desc *entry;
>  
> @@ -3607,7 +3607,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
>  			continue;
>  		nvec = 1 << entry->msi_attrib.multiple;
>  		for (i = 0; i < nvec; i++)
> -			arch_teardown_msi_irq(entry->irq + i);
> +			x86_msi.teardown_msi_irq(entry->irq + i);
>  	}
>  }
>  
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index cd6da6b..91b5209 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -6,6 +6,7 @@
>  #include <linux/init.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> +#include <linux/pci.h>
>  
>  #include <asm/bios_ebda.h>
>  #include <asm/paravirt.h>
> @@ -99,3 +100,8 @@ struct x86_platform_ops x86_platform = {
>  };
>  
>  EXPORT_SYMBOL_GPL(x86_platform);
> +struct x86_msi_ops x86_msi = {
> +	.setup_msi_irqs = native_setup_msi_irqs,
> +	.teardown_msi_irq = native_teardown_msi_irq,
> +	.teardown_msi_irqs = native_teardown_msi_irqs,
> +};
> -- 
> 1.7.0.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 16/20] x86: Introduce x86_msi_ops
@ 2010-08-31 18:31     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-08-31 18:31 UTC (permalink / raw)
  To: linux-kernel, xen-devel
  Cc: Stefano Stabellini, x86, Jesse Barnes, alex.williamson,
	H. Peter Anvin, Thomas Gleixner

On Wed, Aug 04, 2010 at 02:19:11PM -0400, Konrad Rzeszutek Wilk wrote:
> From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> 
> Introduce an x86 specific indirect mechanism to setup MSIs.
> The MSI setup functions become function pointers in an x86_msi_ops
> struct, that defaults to the implementation in io_apic.c

Hey Peter,

I was wondering if you have time to take a look at this?

The patchset introduces a driver which takes care of allowing
pci_conf_read/write in a virtualized environements with PCI
passthrough devices. Unfortunatly for MSI operations that is not
so simple, so this patch alongside with the previous one
(https://patchwork.kernel.org/patch/117105/)
expands the arch_* calls. This makes it possible to register on top
of the native callback, the virtualized ones if required.

> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  arch/x86/include/asm/pci.h      |   26 +++++++++++++++++++++++---
>  arch/x86/include/asm/x86_init.h |    9 +++++++++
>  arch/x86/kernel/apic/io_apic.c  |    8 ++++----
>  arch/x86/kernel/x86_init.c      |    6 ++++++
>  4 files changed, 42 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index bcf84e1..861d0d0 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -7,6 +7,7 @@
>  #include <linux/string.h>
>  #include <asm/scatterlist.h>
>  #include <asm/io.h>
> +#include <asm/x86_init.h>
>  
>  #ifdef __KERNEL__
>  
> @@ -92,9 +93,28 @@ static inline void early_quirks(void) { }
>  
>  extern void pci_iommu_alloc(void);
>  
> -/* MSI arch hook */
> -#define arch_setup_msi_irqs arch_setup_msi_irqs
> -#define arch_teardown_msi_irqs arch_teardown_msi_irqs
> +/* MSI arch specific hooks */
> +static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> +{
> +	return x86_msi.setup_msi_irqs(dev, nvec, type);
> +}
> +
> +static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
> +{
> +	x86_msi.teardown_msi_irqs(dev);
> +}
> +
> +static inline void x86_teardown_msi_irq(unsigned int irq)
> +{
> +	x86_msi.teardown_msi_irq(irq);
> +}
> +
> +#define arch_setup_msi_irqs x86_setup_msi_irqs
> +#define arch_teardown_msi_irqs x86_teardown_msi_irqs
> +#define arch_teardown_msi_irq x86_teardown_msi_irq
> +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
> +void native_teardown_msi_irq(unsigned int irq);
> +void native_teardown_msi_irqs(struct pci_dev *dev);
>  
>  #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
>  
> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> index baa579c..64642ad 100644
> --- a/arch/x86/include/asm/x86_init.h
> +++ b/arch/x86/include/asm/x86_init.h
> @@ -154,9 +154,18 @@ struct x86_platform_ops {
>  	int (*i8042_detect)(void);
>  };
>  
> +struct pci_dev;
> +
> +struct x86_msi_ops {
> +	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
> +	void (*teardown_msi_irq)(unsigned int irq);
> +	void (*teardown_msi_irqs)(struct pci_dev *dev);
> +};
> +
>  extern struct x86_init_ops x86_init;
>  extern struct x86_cpuinit_ops x86_cpuinit;
>  extern struct x86_platform_ops x86_platform;
> +extern struct x86_msi_ops x86_msi;
>  
>  extern void x86_init_noop(void);
>  extern void x86_init_uint_noop(unsigned int unused);
> diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> index a8d069e..0b552ec 100644
> --- a/arch/x86/kernel/apic/io_apic.c
> +++ b/arch/x86/kernel/apic/io_apic.c
> @@ -3531,7 +3531,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
>  	return 0;
>  }
>  
> -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
>  {
>  	unsigned int irq;
>  	int ret, sub_handle;
> @@ -3592,12 +3592,12 @@ error:
>  	return ret;
>  }
>  
> -void arch_teardown_msi_irq(unsigned int irq)
> +void native_teardown_msi_irq(unsigned int irq)
>  {
>  	destroy_irq(irq);
>  }
>  
> -void arch_teardown_msi_irqs(struct pci_dev *dev)
> +void native_teardown_msi_irqs(struct pci_dev *dev)
>  {
>  	struct msi_desc *entry;
>  
> @@ -3607,7 +3607,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
>  			continue;
>  		nvec = 1 << entry->msi_attrib.multiple;
>  		for (i = 0; i < nvec; i++)
> -			arch_teardown_msi_irq(entry->irq + i);
> +			x86_msi.teardown_msi_irq(entry->irq + i);
>  	}
>  }
>  
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index cd6da6b..91b5209 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -6,6 +6,7 @@
>  #include <linux/init.h>
>  #include <linux/ioport.h>
>  #include <linux/module.h>
> +#include <linux/pci.h>
>  
>  #include <asm/bios_ebda.h>
>  #include <asm/paravirt.h>
> @@ -99,3 +100,8 @@ struct x86_platform_ops x86_platform = {
>  };
>  
>  EXPORT_SYMBOL_GPL(x86_platform);
> +struct x86_msi_ops x86_msi = {
> +	.setup_msi_irqs = native_setup_msi_irqs,
> +	.teardown_msi_irq = native_teardown_msi_irq,
> +	.teardown_msi_irqs = native_teardown_msi_irqs,
> +};
> -- 
> 1.7.0.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 16/20] x86: Introduce x86_msi_ops
  2010-08-31 18:31     ` Konrad Rzeszutek Wilk
@ 2010-09-23 14:48       ` Konrad Rzeszutek Wilk
  -1 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-09-23 14:48 UTC (permalink / raw)
  To: linux-kernel, xen-devel, hpa
  Cc: alex.williamson, Stefano Stabellini, Thomas Gleixner, x86, Jesse Barnes

On Tue, Aug 31, 2010 at 02:31:40PM -0400, Konrad Rzeszutek Wilk wrote:
> On Wed, Aug 04, 2010 at 02:19:11PM -0400, Konrad Rzeszutek Wilk wrote:
> > From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > 
> > Introduce an x86 specific indirect mechanism to setup MSIs.
> > The MSI setup functions become function pointers in an x86_msi_ops
> > struct, that defaults to the implementation in io_apic.c
> 
> Hey Peter,
> 
> I was wondering if you have time to take a look at this?

ping?
> 
> The patchset introduces a driver which takes care of allowing
> pci_conf_read/write in a virtualized environements with PCI
> passthrough devices. Unfortunatly for MSI operations that is not
> so simple, so this patch alongside with the previous one
> (https://patchwork.kernel.org/patch/117105/)
> expands the arch_* calls. This makes it possible to register on top
> of the native callback (the virtualized ones can), if required.
> 
> > 
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: "H. Peter Anvin" <hpa@zytor.com>
> > Cc: x86@kernel.org
> > Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
> > ---
> >  arch/x86/include/asm/pci.h      |   26 +++++++++++++++++++++++---
> >  arch/x86/include/asm/x86_init.h |    9 +++++++++
> >  arch/x86/kernel/apic/io_apic.c  |    8 ++++----
> >  arch/x86/kernel/x86_init.c      |    6 ++++++
> >  4 files changed, 42 insertions(+), 7 deletions(-)
> > 
> > diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> > index bcf84e1..861d0d0 100644
> > --- a/arch/x86/include/asm/pci.h
> > +++ b/arch/x86/include/asm/pci.h
> > @@ -7,6 +7,7 @@
> >  #include <linux/string.h>
> >  #include <asm/scatterlist.h>
> >  #include <asm/io.h>
> > +#include <asm/x86_init.h>
> >  
> >  #ifdef __KERNEL__
> >  
> > @@ -92,9 +93,28 @@ static inline void early_quirks(void) { }
> >  
> >  extern void pci_iommu_alloc(void);
> >  
> > -/* MSI arch hook */
> > -#define arch_setup_msi_irqs arch_setup_msi_irqs
> > -#define arch_teardown_msi_irqs arch_teardown_msi_irqs
> > +/* MSI arch specific hooks */
> > +static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> > +{
> > +	return x86_msi.setup_msi_irqs(dev, nvec, type);
> > +}
> > +
> > +static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
> > +{
> > +	x86_msi.teardown_msi_irqs(dev);
> > +}
> > +
> > +static inline void x86_teardown_msi_irq(unsigned int irq)
> > +{
> > +	x86_msi.teardown_msi_irq(irq);
> > +}
> > +
> > +#define arch_setup_msi_irqs x86_setup_msi_irqs
> > +#define arch_teardown_msi_irqs x86_teardown_msi_irqs
> > +#define arch_teardown_msi_irq x86_teardown_msi_irq
> > +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
> > +void native_teardown_msi_irq(unsigned int irq);
> > +void native_teardown_msi_irqs(struct pci_dev *dev);
> >  
> >  #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
> >  
> > diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> > index baa579c..64642ad 100644
> > --- a/arch/x86/include/asm/x86_init.h
> > +++ b/arch/x86/include/asm/x86_init.h
> > @@ -154,9 +154,18 @@ struct x86_platform_ops {
> >  	int (*i8042_detect)(void);
> >  };
> >  
> > +struct pci_dev;
> > +
> > +struct x86_msi_ops {
> > +	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
> > +	void (*teardown_msi_irq)(unsigned int irq);
> > +	void (*teardown_msi_irqs)(struct pci_dev *dev);
> > +};
> > +
> >  extern struct x86_init_ops x86_init;
> >  extern struct x86_cpuinit_ops x86_cpuinit;
> >  extern struct x86_platform_ops x86_platform;
> > +extern struct x86_msi_ops x86_msi;
> >  
> >  extern void x86_init_noop(void);
> >  extern void x86_init_uint_noop(unsigned int unused);
> > diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> > index a8d069e..0b552ec 100644
> > --- a/arch/x86/kernel/apic/io_apic.c
> > +++ b/arch/x86/kernel/apic/io_apic.c
> > @@ -3531,7 +3531,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
> >  	return 0;
> >  }
> >  
> > -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> > +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> >  {
> >  	unsigned int irq;
> >  	int ret, sub_handle;
> > @@ -3592,12 +3592,12 @@ error:
> >  	return ret;
> >  }
> >  
> > -void arch_teardown_msi_irq(unsigned int irq)
> > +void native_teardown_msi_irq(unsigned int irq)
> >  {
> >  	destroy_irq(irq);
> >  }
> >  
> > -void arch_teardown_msi_irqs(struct pci_dev *dev)
> > +void native_teardown_msi_irqs(struct pci_dev *dev)
> >  {
> >  	struct msi_desc *entry;
> >  
> > @@ -3607,7 +3607,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
> >  			continue;
> >  		nvec = 1 << entry->msi_attrib.multiple;
> >  		for (i = 0; i < nvec; i++)
> > -			arch_teardown_msi_irq(entry->irq + i);
> > +			x86_msi.teardown_msi_irq(entry->irq + i);
> >  	}
> >  }
> >  
> > diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> > index cd6da6b..91b5209 100644
> > --- a/arch/x86/kernel/x86_init.c
> > +++ b/arch/x86/kernel/x86_init.c
> > @@ -6,6 +6,7 @@
> >  #include <linux/init.h>
> >  #include <linux/ioport.h>
> >  #include <linux/module.h>
> > +#include <linux/pci.h>
> >  
> >  #include <asm/bios_ebda.h>
> >  #include <asm/paravirt.h>
> > @@ -99,3 +100,8 @@ struct x86_platform_ops x86_platform = {
> >  };
> >  
> >  EXPORT_SYMBOL_GPL(x86_platform);
> > +struct x86_msi_ops x86_msi = {
> > +	.setup_msi_irqs = native_setup_msi_irqs,
> > +	.teardown_msi_irq = native_teardown_msi_irq,
> > +	.teardown_msi_irqs = native_teardown_msi_irqs,
> > +};
> > -- 
> > 1.7.0.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 16/20] x86: Introduce x86_msi_ops
@ 2010-09-23 14:48       ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-09-23 14:48 UTC (permalink / raw)
  To: linux-kernel, xen-devel, hpa
  Cc: alex.williamson, x86, Thomas Gleixner, Jesse Barnes, Stefano Stabellini

On Tue, Aug 31, 2010 at 02:31:40PM -0400, Konrad Rzeszutek Wilk wrote:
> On Wed, Aug 04, 2010 at 02:19:11PM -0400, Konrad Rzeszutek Wilk wrote:
> > From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > 
> > Introduce an x86 specific indirect mechanism to setup MSIs.
> > The MSI setup functions become function pointers in an x86_msi_ops
> > struct, that defaults to the implementation in io_apic.c
> 
> Hey Peter,
> 
> I was wondering if you have time to take a look at this?

ping?
> 
> The patchset introduces a driver which takes care of allowing
> pci_conf_read/write in a virtualized environements with PCI
> passthrough devices. Unfortunatly for MSI operations that is not
> so simple, so this patch alongside with the previous one
> (https://patchwork.kernel.org/patch/117105/)
> expands the arch_* calls. This makes it possible to register on top
> of the native callback (the virtualized ones can), if required.
> 
> > 
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: "H. Peter Anvin" <hpa@zytor.com>
> > Cc: x86@kernel.org
> > Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
> > ---
> >  arch/x86/include/asm/pci.h      |   26 +++++++++++++++++++++++---
> >  arch/x86/include/asm/x86_init.h |    9 +++++++++
> >  arch/x86/kernel/apic/io_apic.c  |    8 ++++----
> >  arch/x86/kernel/x86_init.c      |    6 ++++++
> >  4 files changed, 42 insertions(+), 7 deletions(-)
> > 
> > diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> > index bcf84e1..861d0d0 100644
> > --- a/arch/x86/include/asm/pci.h
> > +++ b/arch/x86/include/asm/pci.h
> > @@ -7,6 +7,7 @@
> >  #include <linux/string.h>
> >  #include <asm/scatterlist.h>
> >  #include <asm/io.h>
> > +#include <asm/x86_init.h>
> >  
> >  #ifdef __KERNEL__
> >  
> > @@ -92,9 +93,28 @@ static inline void early_quirks(void) { }
> >  
> >  extern void pci_iommu_alloc(void);
> >  
> > -/* MSI arch hook */
> > -#define arch_setup_msi_irqs arch_setup_msi_irqs
> > -#define arch_teardown_msi_irqs arch_teardown_msi_irqs
> > +/* MSI arch specific hooks */
> > +static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> > +{
> > +	return x86_msi.setup_msi_irqs(dev, nvec, type);
> > +}
> > +
> > +static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
> > +{
> > +	x86_msi.teardown_msi_irqs(dev);
> > +}
> > +
> > +static inline void x86_teardown_msi_irq(unsigned int irq)
> > +{
> > +	x86_msi.teardown_msi_irq(irq);
> > +}
> > +
> > +#define arch_setup_msi_irqs x86_setup_msi_irqs
> > +#define arch_teardown_msi_irqs x86_teardown_msi_irqs
> > +#define arch_teardown_msi_irq x86_teardown_msi_irq
> > +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
> > +void native_teardown_msi_irq(unsigned int irq);
> > +void native_teardown_msi_irqs(struct pci_dev *dev);
> >  
> >  #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
> >  
> > diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> > index baa579c..64642ad 100644
> > --- a/arch/x86/include/asm/x86_init.h
> > +++ b/arch/x86/include/asm/x86_init.h
> > @@ -154,9 +154,18 @@ struct x86_platform_ops {
> >  	int (*i8042_detect)(void);
> >  };
> >  
> > +struct pci_dev;
> > +
> > +struct x86_msi_ops {
> > +	int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
> > +	void (*teardown_msi_irq)(unsigned int irq);
> > +	void (*teardown_msi_irqs)(struct pci_dev *dev);
> > +};
> > +
> >  extern struct x86_init_ops x86_init;
> >  extern struct x86_cpuinit_ops x86_cpuinit;
> >  extern struct x86_platform_ops x86_platform;
> > +extern struct x86_msi_ops x86_msi;
> >  
> >  extern void x86_init_noop(void);
> >  extern void x86_init_uint_noop(unsigned int unused);
> > diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
> > index a8d069e..0b552ec 100644
> > --- a/arch/x86/kernel/apic/io_apic.c
> > +++ b/arch/x86/kernel/apic/io_apic.c
> > @@ -3531,7 +3531,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
> >  	return 0;
> >  }
> >  
> > -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> > +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> >  {
> >  	unsigned int irq;
> >  	int ret, sub_handle;
> > @@ -3592,12 +3592,12 @@ error:
> >  	return ret;
> >  }
> >  
> > -void arch_teardown_msi_irq(unsigned int irq)
> > +void native_teardown_msi_irq(unsigned int irq)
> >  {
> >  	destroy_irq(irq);
> >  }
> >  
> > -void arch_teardown_msi_irqs(struct pci_dev *dev)
> > +void native_teardown_msi_irqs(struct pci_dev *dev)
> >  {
> >  	struct msi_desc *entry;
> >  
> > @@ -3607,7 +3607,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
> >  			continue;
> >  		nvec = 1 << entry->msi_attrib.multiple;
> >  		for (i = 0; i < nvec; i++)
> > -			arch_teardown_msi_irq(entry->irq + i);
> > +			x86_msi.teardown_msi_irq(entry->irq + i);
> >  	}
> >  }
> >  
> > diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> > index cd6da6b..91b5209 100644
> > --- a/arch/x86/kernel/x86_init.c
> > +++ b/arch/x86/kernel/x86_init.c
> > @@ -6,6 +6,7 @@
> >  #include <linux/init.h>
> >  #include <linux/ioport.h>
> >  #include <linux/module.h>
> > +#include <linux/pci.h>
> >  
> >  #include <asm/bios_ebda.h>
> >  #include <asm/paravirt.h>
> > @@ -99,3 +100,8 @@ struct x86_platform_ops x86_platform = {
> >  };
> >  
> >  EXPORT_SYMBOL_GPL(x86_platform);
> > +struct x86_msi_ops x86_msi = {
> > +	.setup_msi_irqs = native_setup_msi_irqs,
> > +	.teardown_msi_irq = native_teardown_msi_irq,
> > +	.teardown_msi_irqs = native_teardown_msi_irqs,
> > +};
> > -- 
> > 1.7.0.1
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Xen-devel] Re: [PATCH 16/20] x86: Introduce x86_msi_ops
  2010-09-23 14:48       ` Konrad Rzeszutek Wilk
  (?)
@ 2010-09-23 23:18       ` Bruce Edge
  2010-10-07  2:59         ` Konrad Rzeszutek Wilk
  -1 siblings, 1 reply; 33+ messages in thread
From: Bruce Edge @ 2010-09-23 23:18 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-kernel, xen-devel, hpa, alex.williamson, x86,
	Thomas Gleixner, Jesse Barnes, Stefano Stabellini

On Thu, Sep 23, 2010 at 7:48 AM, Konrad Rzeszutek Wilk
<konrad.wilk@oracle.com> wrote:
> On Tue, Aug 31, 2010 at 02:31:40PM -0400, Konrad Rzeszutek Wilk wrote:
>> On Wed, Aug 04, 2010 at 02:19:11PM -0400, Konrad Rzeszutek Wilk wrote:
>> > From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>> >
>> > Introduce an x86 specific indirect mechanism to setup MSIs.
>> > The MSI setup functions become function pointers in an x86_msi_ops
>> > struct, that defaults to the implementation in io_apic.c
>>
>> Hey Peter,
>>
>> I was wondering if you have time to take a look at this?
>
> ping?
>>
>> The patchset introduces a driver which takes care of allowing
>> pci_conf_read/write in a virtualized environements with PCI
>> passthrough devices. Unfortunatly for MSI operations that is not
>> so simple, so this patch alongside with the previous one
>> (https://patchwork.kernel.org/patch/117105/)
>> expands the arch_* calls. This makes it possible to register on top
>> of the native callback (the virtualized ones can), if required.
>>

Is this patch required for PCI passthrough devices that use MSI interrupts?

I'm wondering because I'm seeing drivers for PCI passthrough  are able
to init the MSI interrupts OK, but never get any interrupts with pvops
domU kernels.

-Bruce

>> >
>> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>> > Cc: Thomas Gleixner <tglx@linutronix.de>
>> > Cc: "H. Peter Anvin" <hpa@zytor.com>
>> > Cc: x86@kernel.org
>> > Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
>> > ---
>> >  arch/x86/include/asm/pci.h      |   26 +++++++++++++++++++++++---
>> >  arch/x86/include/asm/x86_init.h |    9 +++++++++
>> >  arch/x86/kernel/apic/io_apic.c  |    8 ++++----
>> >  arch/x86/kernel/x86_init.c      |    6 ++++++
>> >  4 files changed, 42 insertions(+), 7 deletions(-)
>> >
>> > diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
>> > index bcf84e1..861d0d0 100644
>> > --- a/arch/x86/include/asm/pci.h
>> > +++ b/arch/x86/include/asm/pci.h
>> > @@ -7,6 +7,7 @@
>> >  #include <linux/string.h>
>> >  #include <asm/scatterlist.h>
>> >  #include <asm/io.h>
>> > +#include <asm/x86_init.h>
>> >
>> >  #ifdef __KERNEL__
>> >
>> > @@ -92,9 +93,28 @@ static inline void early_quirks(void) { }
>> >
>> >  extern void pci_iommu_alloc(void);
>> >
>> > -/* MSI arch hook */
>> > -#define arch_setup_msi_irqs arch_setup_msi_irqs
>> > -#define arch_teardown_msi_irqs arch_teardown_msi_irqs
>> > +/* MSI arch specific hooks */
>> > +static inline int x86_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
>> > +{
>> > +   return x86_msi.setup_msi_irqs(dev, nvec, type);
>> > +}
>> > +
>> > +static inline void x86_teardown_msi_irqs(struct pci_dev *dev)
>> > +{
>> > +   x86_msi.teardown_msi_irqs(dev);
>> > +}
>> > +
>> > +static inline void x86_teardown_msi_irq(unsigned int irq)
>> > +{
>> > +   x86_msi.teardown_msi_irq(irq);
>> > +}
>> > +
>> > +#define arch_setup_msi_irqs x86_setup_msi_irqs
>> > +#define arch_teardown_msi_irqs x86_teardown_msi_irqs
>> > +#define arch_teardown_msi_irq x86_teardown_msi_irq
>> > +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
>> > +void native_teardown_msi_irq(unsigned int irq);
>> > +void native_teardown_msi_irqs(struct pci_dev *dev);
>> >
>> >  #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
>> >
>> > diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
>> > index baa579c..64642ad 100644
>> > --- a/arch/x86/include/asm/x86_init.h
>> > +++ b/arch/x86/include/asm/x86_init.h
>> > @@ -154,9 +154,18 @@ struct x86_platform_ops {
>> >     int (*i8042_detect)(void);
>> >  };
>> >
>> > +struct pci_dev;
>> > +
>> > +struct x86_msi_ops {
>> > +   int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
>> > +   void (*teardown_msi_irq)(unsigned int irq);
>> > +   void (*teardown_msi_irqs)(struct pci_dev *dev);
>> > +};
>> > +
>> >  extern struct x86_init_ops x86_init;
>> >  extern struct x86_cpuinit_ops x86_cpuinit;
>> >  extern struct x86_platform_ops x86_platform;
>> > +extern struct x86_msi_ops x86_msi;
>> >
>> >  extern void x86_init_noop(void);
>> >  extern void x86_init_uint_noop(unsigned int unused);
>> > diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
>> > index a8d069e..0b552ec 100644
>> > --- a/arch/x86/kernel/apic/io_apic.c
>> > +++ b/arch/x86/kernel/apic/io_apic.c
>> > @@ -3531,7 +3531,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
>> >     return 0;
>> >  }
>> >
>> > -int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
>> > +int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
>> >  {
>> >     unsigned int irq;
>> >     int ret, sub_handle;
>> > @@ -3592,12 +3592,12 @@ error:
>> >     return ret;
>> >  }
>> >
>> > -void arch_teardown_msi_irq(unsigned int irq)
>> > +void native_teardown_msi_irq(unsigned int irq)
>> >  {
>> >     destroy_irq(irq);
>> >  }
>> >
>> > -void arch_teardown_msi_irqs(struct pci_dev *dev)
>> > +void native_teardown_msi_irqs(struct pci_dev *dev)
>> >  {
>> >     struct msi_desc *entry;
>> >
>> > @@ -3607,7 +3607,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
>> >                     continue;
>> >             nvec = 1 << entry->msi_attrib.multiple;
>> >             for (i = 0; i < nvec; i++)
>> > -                   arch_teardown_msi_irq(entry->irq + i);
>> > +                   x86_msi.teardown_msi_irq(entry->irq + i);
>> >     }
>> >  }
>> >
>> > diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
>> > index cd6da6b..91b5209 100644
>> > --- a/arch/x86/kernel/x86_init.c
>> > +++ b/arch/x86/kernel/x86_init.c
>> > @@ -6,6 +6,7 @@
>> >  #include <linux/init.h>
>> >  #include <linux/ioport.h>
>> >  #include <linux/module.h>
>> > +#include <linux/pci.h>
>> >
>> >  #include <asm/bios_ebda.h>
>> >  #include <asm/paravirt.h>
>> > @@ -99,3 +100,8 @@ struct x86_platform_ops x86_platform = {
>> >  };
>> >
>> >  EXPORT_SYMBOL_GPL(x86_platform);
>> > +struct x86_msi_ops x86_msi = {
>> > +   .setup_msi_irqs = native_setup_msi_irqs,
>> > +   .teardown_msi_irq = native_teardown_msi_irq,
>> > +   .teardown_msi_irqs = native_teardown_msi_irqs,
>> > +};
>> > --
>> > 1.7.0.1
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> > Please read the FAQ at  http://www.tux.org/lkml/
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem
  2010-08-13 23:28   ` Jesse Barnes
@ 2010-10-04 18:30     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-10-04 18:30 UTC (permalink / raw)
  To: Jesse Barnes
  Cc: linux-kernel, xen-devel, alex.williamson, Alex Nixon,
	Jeremy Fitzhardinge, Ian Campbell, Stefano Stabellini,
	H. Peter Anvin, Matthew Wilcox, Qing He, Thomas Gleixner, x86

> > Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
> > ---
> 
> Fine with me if this stuff goes in with the rest of the Xen bits,
> presumably through the x86 tree.
> 
> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Hey Jesse,

(Sorry for responding so late - I had this in my postponed and then lost
track of time).

Thank you for taking the time to look at it. Since the patches touch both
x86 and xen tree, I was thinking to push these patches to Linus myself.

That is of course once more folks have had a chance to look at the
x86 generic pieces (especially the MSI/MSI-X patch proposed by Stefano:
http://marc.info/?i=1286216015-9710-17-git-send-email-konrad.wilk@oracle.com).

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [Xen-devel] Re: [PATCH 16/20] x86: Introduce x86_msi_ops
  2010-09-23 23:18       ` [Xen-devel] " Bruce Edge
@ 2010-10-07  2:59         ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 33+ messages in thread
From: Konrad Rzeszutek Wilk @ 2010-10-07  2:59 UTC (permalink / raw)
  To: Bruce Edge
  Cc: linux-kernel, xen-devel, hpa, alex.williamson, x86,
	Thomas Gleixner, Jesse Barnes, Stefano Stabellini

On Thu, Sep 23, 2010 at 04:18:42PM -0700, Bruce Edge wrote:
> On Thu, Sep 23, 2010 at 7:48 AM, Konrad Rzeszutek Wilk
> <konrad.wilk@oracle.com> wrote:
> > On Tue, Aug 31, 2010 at 02:31:40PM -0400, Konrad Rzeszutek Wilk wrote:
> >> On Wed, Aug 04, 2010 at 02:19:11PM -0400, Konrad Rzeszutek Wilk wrote:
> >> > From: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> >> >
> >> > Introduce an x86 specific indirect mechanism to setup MSIs.
> >> > The MSI setup functions become function pointers in an x86_msi_ops
> >> > struct, that defaults to the implementation in io_apic.c
> >>
> >> Hey Peter,
> >>
> >> I was wondering if you have time to take a look at this?
> >
> > ping?
> >>
> >> The patchset introduces a driver which takes care of allowing
> >> pci_conf_read/write in a virtualized environements with PCI
> >> passthrough devices. Unfortunatly for MSI operations that is not
> >> so simple, so this patch alongside with the previous one
> >> (https://patchwork.kernel.org/patch/117105/)
> >> expands the arch_* calls. This makes it possible to register on top
> >> of the native callback (the virtualized ones can), if required.
> >>
> 
> Is this patch required for PCI passthrough devices that use MSI interrupts?

Yes. And also for MSI-X. However, I've just posted a new updated mechanism based
on Thomas's idea - which is superior to this one.

> 
> I'm wondering because I'm seeing drivers for PCI passthrough  are able
> to init the MSI interrupts OK, but never get any interrupts with pvops
> domU kernels.

The problem you are seeing is different, I think we can narrow it down
to the dom0 doing something wacked.


^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2010-10-07  3:02 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-04 18:18 [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk
2010-08-04 18:18 ` [PATCH 01/20] xen: Don't disable the I/O space Konrad Rzeszutek Wilk
2010-08-04 18:18 ` [PATCH 02/20] xen: define BIOVEC_PHYS_MERGEABLE() Konrad Rzeszutek Wilk
2010-08-04 18:18 ` [PATCH 03/20] xen: implement pirq type event channels Konrad Rzeszutek Wilk
2010-08-04 18:18 ` [PATCH 04/20] x86/io_apic: add get_nr_irqs_gsi() Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 05/20] xen: identity map gsi->irqs Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 06/20] xen: dynamically allocate irq & event structures Konrad Rzeszutek Wilk
2010-08-04 18:19   ` Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 07/20] xen: set pirq name to something useful Konrad Rzeszutek Wilk
2010-08-04 18:19   ` Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 08/20] xen: statically initialize cpu_evtchn_mask_p Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 09/20] xen: Find an unbound irq number in reverse order (high to low) Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 10/20] xen: Provide a variant of xen_poll_irq with timeout Konrad Rzeszutek Wilk
2010-08-04 18:19   ` Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 11/20] xen: fix shared irq device passthrough Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 12/20] x86/PCI: Clean up pci_cache_line_size Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 13/20] x86/PCI: make sure _PAGE_IOMAP it set on pci mappings Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 14/20] x86/PCI: Export pci_walk_bus function Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 15/20] x86: Copy-n-paste arch_teardown_msi_irqs from msi.c to io_apic.c Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 16/20] x86: Introduce x86_msi_ops Konrad Rzeszutek Wilk
2010-08-31 18:31   ` Konrad Rzeszutek Wilk
2010-08-31 18:31     ` Konrad Rzeszutek Wilk
2010-09-23 14:48     ` Konrad Rzeszutek Wilk
2010-09-23 14:48       ` Konrad Rzeszutek Wilk
2010-09-23 23:18       ` [Xen-devel] " Bruce Edge
2010-10-07  2:59         ` Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 17/20] xen/x86/PCI: Add support for the Xen PCI subsystem Konrad Rzeszutek Wilk
2010-08-13 23:28   ` Jesse Barnes
2010-10-04 18:30     ` Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 18/20] xenbus: Xen paravirtualised PCI hotplug support Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 19/20] xenbus: prevent warnings on unhandled enumeration values Konrad Rzeszutek Wilk
2010-08-04 18:19 ` [PATCH 20/20] xen-pcifront: Xen PCI frontend driver Konrad Rzeszutek Wilk
2010-08-04 20:14 ` [Xen-devel] [RFC PATCH] Xen PCI frontend driver (v0.5) Konrad Rzeszutek Wilk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.