WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] linux/pci-msi: translate Xen-provided

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] linux/pci-msi: translate Xen-provided PIRQs (take 2)
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 08 Sep 2008 12:40:21 -0700
Delivery-date: Mon, 08 Sep 2008 12:41:06 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1220876015 -3600
# Node ID 7886619f623ef822f02d38af8a948792d4d90121
# Parent  67ff2b5a88ec1873ef0ed698dc701640fbbbfd6f
linux/pci-msi: translate Xen-provided PIRQs (take 2)

Previously, the kernel depended upon Xen's NR_IRQS to be no larger
than the kernel's NR_PIRQS.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 arch/i386/kernel/io_apic-xen.c          |    3 -
 arch/x86_64/kernel/io_apic-xen.c        |    3 -
 drivers/pci/msi-xen.c                   |   16 ++++-
 drivers/xen/core/evtchn.c               |   86 ++++++++++++++++++++++++++++----
 include/asm-i386/mach-xen/irq_vectors.h |    8 ++
 include/xen/evtchn.h                    |    7 ++
 6 files changed, 107 insertions(+), 16 deletions(-)

diff -r 67ff2b5a88ec -r 7886619f623e arch/i386/kernel/io_apic-xen.c
--- a/arch/i386/kernel/io_apic-xen.c    Sat Sep 06 14:14:42 2008 +0100
+++ b/arch/i386/kernel/io_apic-xen.c    Mon Sep 08 13:13:35 2008 +0100
@@ -47,6 +47,7 @@
 
 #include <xen/interface/xen.h>
 #include <xen/interface/physdev.h>
+#include <xen/evtchn.h>
 
 /* Fake i8259 */
 #define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
@@ -1260,7 +1261,7 @@ static void ioapic_register_intr(int irq
        set_intr_gate(vector, interrupt[idx]);
 }
 #else
-#define ioapic_register_intr(_irq,_vector,_trigger) ((void)0)
+#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
 #endif
 
 static void __init setup_IO_APIC_irqs(void)
diff -r 67ff2b5a88ec -r 7886619f623e arch/x86_64/kernel/io_apic-xen.c
--- a/arch/x86_64/kernel/io_apic-xen.c  Sat Sep 06 14:14:42 2008 +0100
+++ b/arch/x86_64/kernel/io_apic-xen.c  Mon Sep 08 13:13:35 2008 +0100
@@ -95,6 +95,7 @@ int vector_irq[NR_VECTORS] __read_mostly
 
 #include <xen/interface/xen.h>
 #include <xen/interface/physdev.h>
+#include <xen/evtchn.h>
 
 /* Fake i8259 */
 #define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
@@ -940,7 +941,7 @@ static void ioapic_register_intr(int irq
        set_intr_gate(vector, interrupt[idx]);
 }
 #else
-#define ioapic_register_intr(_irq,_vector,_trigger) ((void)0)
+#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
 #endif /* !CONFIG_XEN */
 
 static void __init setup_IO_APIC_irqs(void)
diff -r 67ff2b5a88ec -r 7886619f623e drivers/pci/msi-xen.c
--- a/drivers/pci/msi-xen.c     Sat Sep 06 14:14:42 2008 +0100
+++ b/drivers/pci/msi-xen.c     Mon Sep 08 13:13:35 2008 +0100
@@ -15,6 +15,8 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 
+#include <xen/evtchn.h>
+
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -156,13 +158,15 @@ static int msi_unmap_pirq(struct pci_dev
        int rc;
 
        unmap.domid = msi_get_dev_owner(dev);
-       unmap.pirq = pirq;
+       unmap.pirq = evtchn_get_xen_pirq(pirq);
 
        if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
                printk(KERN_WARNING "unmap irq %x failed\n", pirq);
 
        if (rc < 0)
                return rc;
+
+       evtchn_map_pirq(pirq, 0);
        return 0;
 }
 
@@ -197,7 +201,7 @@ static int msi_map_pirq_to_vector(struct
        map_irq.domid = domid;
        map_irq.type = MAP_PIRQ_TYPE_MSI;
        map_irq.index = -1;
-       map_irq.pirq = pirq;
+       map_irq.pirq = pirq < 0 ? -1 : evtchn_get_xen_pirq(pirq);
        map_irq.bus = dev->bus->number;
        map_irq.devfn = dev->devfn;
        map_irq.entry_nr = entry_nr;
@@ -208,8 +212,12 @@ static int msi_map_pirq_to_vector(struct
 
        if (rc < 0)
                return rc;
-
-       return map_irq.pirq;
+       /* This happens when MSI support is not enabled in Xen. */
+       if (rc == 0 && map_irq.pirq < 0)
+               return -ENOSYS;
+
+       BUG_ON(map_irq.pirq <= 0);
+       return evtchn_map_pirq(pirq, map_irq.pirq);
 }
 
 static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
diff -r 67ff2b5a88ec -r 7886619f623e drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Sat Sep 06 14:14:42 2008 +0100
+++ b/drivers/xen/core/evtchn.c Mon Sep 08 13:13:35 2008 +0100
@@ -66,13 +66,27 @@ enum {
        IRQT_VIRQ,
        IRQT_IPI,
        IRQT_LOCAL_PORT,
-       IRQT_CALLER_PORT
+       IRQT_CALLER_PORT,
+       _IRQT_COUNT
 };
+
+#define _IRQT_BITS 4
+#define _EVTCHN_BITS 12
+#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
 
 /* Constructor for packed IRQ information. */
 static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn)
 {
-       return ((type << 24) | (index << 16) | evtchn);
+       BUILD_BUG_ON(_IRQT_COUNT > (1U << _IRQT_BITS));
+
+       BUILD_BUG_ON(NR_PIRQS > (1U << _INDEX_BITS));
+       BUILD_BUG_ON(NR_VIRQS > (1U << _INDEX_BITS));
+       BUILD_BUG_ON(NR_IPIS > (1U << _INDEX_BITS));
+       BUG_ON(index >> _INDEX_BITS);
+
+       BUILD_BUG_ON(NR_EVENT_CHANNELS > (1U << _EVTCHN_BITS));
+
+       return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
 }
 
 /* Convenient shorthand for packed representation of an unbound IRQ. */
@@ -84,17 +98,17 @@ static inline u32 mk_irq_info(u32 type, 
 
 static inline unsigned int evtchn_from_irq(int irq)
 {
-       return (u16)(irq_info[irq]);
+       return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1);
 }
 
 static inline unsigned int index_from_irq(int irq)
 {
-       return (u8)(irq_info[irq] >> 16);
+       return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1);
 }
 
 static inline unsigned int type_from_irq(int irq)
 {
-       return (u8)(irq_info[irq] >> 24);
+       return irq_info[irq] >> (32 - _IRQT_BITS);
 }
 
 /* IRQ <-> VIRQ mapping. */
@@ -742,6 +756,60 @@ static struct hw_interrupt_type dynirq_t
        .retrigger = resend_irq_on_evtchn,
 };
 
+void evtchn_register_pirq(int irq)
+{
+       irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
+}
+
+#ifndef CONFIG_X86_IO_APIC
+#undef IO_APIC_IRQ
+#define IO_APIC_IRQ(irq) ((irq) >= pirq_to_irq(16))
+#endif
+
+int evtchn_map_pirq(int irq, int xen_pirq)
+{
+       if (irq < 0) {
+               static DEFINE_SPINLOCK(irq_alloc_lock);
+
+               irq = pirq_to_irq(NR_PIRQS - 1);
+               spin_lock(&irq_alloc_lock);
+               do {
+                       if (!IO_APIC_IRQ(irq))
+                               continue;
+                       if (!index_from_irq(irq)) {
+                               BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
+                               irq_info[irq] = mk_irq_info(IRQT_PIRQ,
+                                                           xen_pirq, 0);
+                               break;
+                       }
+               } while (--irq);
+               spin_unlock(&irq_alloc_lock);
+               if (irq < pirq_to_irq(16))
+                       return -ENOSPC;
+       } else if (!xen_pirq) {
+               if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
+                       return -EINVAL;
+               irq_info[irq] = IRQ_UNBOUND;
+               return 0;
+       } else if (type_from_irq(irq) != IRQT_PIRQ
+                  || index_from_irq(irq) != xen_pirq) {
+               printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
+                               "cannot map to PIRQ#%u\n",
+                      irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
+               return -EINVAL;
+       }
+       return index_from_irq(irq) ? irq : -EINVAL;
+}
+
+int evtchn_get_xen_pirq(int irq)
+{
+       if (!IO_APIC_IRQ(irq))
+               return irq;
+       if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
+               return 0;
+       return index_from_irq(irq);
+}
+
 static inline void pirq_unmask_notify(int pirq)
 {
        struct physdev_eoi eoi = { .irq = pirq };
@@ -774,7 +842,7 @@ static unsigned int startup_pirq(unsigne
        if (VALID_EVTCHN(evtchn))
                goto out;
 
-       bind_pirq.pirq  = irq;
+       bind_pirq.pirq = evtchn_get_xen_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) {
@@ -789,7 +857,7 @@ static unsigned int startup_pirq(unsigne
 
        evtchn_to_irq[evtchn] = irq;
        bind_evtchn_to_cpu(evtchn, 0);
-       irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, evtchn);
+       irq_info[irq] = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
 
  out:
        unmask_evtchn(evtchn);
@@ -814,7 +882,7 @@ static void shutdown_pirq(unsigned int i
 
        bind_evtchn_to_cpu(evtchn, 0);
        evtchn_to_irq[evtchn] = -1;
-       irq_info[irq] = IRQ_UNBOUND;
+       irq_info[irq] = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
 }
 
 static void enable_pirq(unsigned int irq)
@@ -1008,7 +1076,7 @@ void irq_resume(void)
 
        /* No IRQ <-> event-channel mappings. */
        for (irq = 0; irq < NR_IRQS; irq++)
-               irq_info[irq] &= ~0xFFFF; /* zap event-channel binding */
+               irq_info[irq] &= ~((1U << _EVTCHN_BITS) - 1);
        for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
                evtchn_to_irq[evtchn] = -1;
 
diff -r 67ff2b5a88ec -r 7886619f623e include/asm-i386/mach-xen/irq_vectors.h
--- a/include/asm-i386/mach-xen/irq_vectors.h   Sat Sep 06 14:14:42 2008 +0100
+++ b/include/asm-i386/mach-xen/irq_vectors.h   Mon Sep 08 13:13:35 2008 +0100
@@ -108,7 +108,13 @@
  */
 
 #define PIRQ_BASE              0
-#define NR_PIRQS               256
+#if !defined(MAX_IO_APICS)
+# define NR_PIRQS              (NR_VECTORS + 32 * NR_CPUS)
+#elif NR_CPUS < MAX_IO_APICS
+# define NR_PIRQS              (NR_VECTORS + 32 * NR_CPUS)
+#else
+# define NR_PIRQS              (NR_VECTORS + 32 * MAX_IO_APICS)
+#endif
 
 #define DYNIRQ_BASE            (PIRQ_BASE + NR_PIRQS)
 #define NR_DYNIRQS             256
diff -r 67ff2b5a88ec -r 7886619f623e include/xen/evtchn.h
--- a/include/xen/evtchn.h      Sat Sep 06 14:14:42 2008 +0100
+++ b/include/xen/evtchn.h      Mon Sep 08 13:13:35 2008 +0100
@@ -101,6 +101,13 @@ asmlinkage void evtchn_do_upcall(struct 
 /* Entry point for notifications into the userland character device. */
 void evtchn_device_upcall(int port);
 
+/* Mark a PIRQ as unavailable for dynamic allocation. */
+void evtchn_register_pirq(int irq);
+/* Map a Xen-supplied PIRQ to a dynamically allocated one. */
+int evtchn_map_pirq(int irq, int xen_pirq);
+/* Look up a Xen-supplied PIRQ for a dynamically allocated one. */
+int evtchn_get_xen_pirq(int irq);
+
 void mask_evtchn(int port);
 void disable_all_local_evtchn(void);
 void unmask_evtchn(int port);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] linux/pci-msi: translate Xen-provided PIRQs (take 2), Xen patchbot-linux-2.6.18-xen <=