aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hpet.c2
-rw-r--r--xen/arch/x86/hvm/vmsi.c4
-rw-r--r--xen/arch/x86/io_apic.c38
-rw-r--r--xen/arch/x86/irq.c15
-rw-r--r--xen/arch/x86/msi.c110
-rw-r--r--xen/include/asm-x86/msi.h16
6 files changed, 96 insertions, 89 deletions
diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index 262ed0e439..508bb4ae51 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -312,7 +312,7 @@ static void __hpet_setup_msi_irq(struct irq_desc *desc)
{
struct msi_msg msg;
- msi_compose_msg(desc->irq, &msg);
+ msi_compose_msg(desc, &msg);
hpet_msi_write(desc->action->dev_id, &msg);
}
diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 9db092befd..9ea861fca6 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -382,7 +382,7 @@ int msixtbl_pt_register(struct domain *d, struct pirq *pirq, uint64_t gtable)
return r;
}
- if ( irq_desc->handler != &pci_msi_type )
+ if ( !irq_desc->msi_desc )
goto out;
msi_desc = irq_desc->msi_desc;
@@ -426,7 +426,7 @@ void msixtbl_pt_unregister(struct domain *d, struct pirq *pirq)
if ( !irq_desc )
return;
- if ( irq_desc->handler != &pci_msi_type )
+ if ( !irq_desc->msi_desc )
goto out;
msi_desc = irq_desc->msi_desc;
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index b337024653..a7081570ca 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -1882,44 +1882,6 @@ static hw_irq_controller ioapic_level_type = {
.set_affinity = set_ioapic_affinity_irq,
};
-static unsigned int startup_msi_irq(struct irq_desc *desc)
-{
- unmask_msi_irq(desc);
- return 0;
-}
-
-static void ack_msi_irq(struct irq_desc *desc)
-{
- irq_complete_move(desc);
- move_native_irq(desc);
-
- if ( msi_maskable_irq(desc->msi_desc) )
- ack_APIC_irq(); /* ACKTYPE_NONE */
-}
-
-static void end_msi_irq(struct irq_desc *desc, u8 vector)
-{
- if ( !msi_maskable_irq(desc->msi_desc) )
- ack_APIC_irq(); /* ACKTYPE_EOI */
-}
-
-#define shutdown_msi_irq mask_msi_irq
-
-/*
- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI or MSI-X Capability Structure.
- */
-hw_irq_controller pci_msi_type = {
- .typename = "PCI-MSI",
- .startup = startup_msi_irq,
- .shutdown = shutdown_msi_irq,
- .enable = unmask_msi_irq,
- .disable = mask_msi_irq,
- .ack = ack_msi_irq,
- .end = end_msi_irq,
- .set_affinity = set_msi_affinity,
-};
-
static inline void init_IO_APIC_traps(void)
{
int irq;
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 71ea764868..9606ae2c1e 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1304,7 +1304,7 @@ static int pirq_acktype(struct domain *d, int pirq)
* MSIs are treated as edge-triggered interrupts, except
* when there is no proper way to mask them.
*/
- if ( desc->handler == &pci_msi_type )
+ if ( desc->msi_desc )
return msi_maskable_irq(desc->msi_desc) ? ACKTYPE_NONE : ACKTYPE_EOI;
/*
@@ -1723,7 +1723,7 @@ int map_domain_pirq(
if ( desc->handler != &no_irq_type )
dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n",
d->domain_id, irq);
- desc->handler = &pci_msi_type;
+ setup_msi_handler(desc, msi_desc);
if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV
&& !desc->chip_data->used_vectors )
@@ -1739,7 +1739,7 @@ int map_domain_pirq(
}
set_domain_irq_pirq(d, irq, info);
- setup_msi_irq(msi_desc, irq);
+ setup_msi_irq(desc);
spin_unlock_irqrestore(&desc->lock, flags);
}
else
@@ -1807,6 +1807,12 @@ int unmap_domain_pirq(struct domain *d, int pirq)
radix_tree_int_to_ptr(-pirq));
}
+ if ( msi_desc )
+ {
+ desc->handler = &no_irq_type;
+ desc->msi_desc = NULL;
+ }
+
spin_unlock_irqrestore(&desc->lock, flags);
if (msi_desc)
msi_free_irq(msi_desc);
@@ -1819,9 +1825,6 @@ int unmap_domain_pirq(struct domain *d, int pirq)
dprintk(XENLOG_G_ERR, "dom%d: could not deny access to irq %d\n",
d->domain_id, pirq);
- if ( desc->handler == &pci_msi_type )
- desc->handler = &no_irq_type;
-
done:
return ret;
}
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 5ff4e3d098..c6f938503e 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -120,11 +120,11 @@ static void msix_put_fixmap(struct pci_dev *dev, int idx)
/*
* MSI message composition
*/
-void msi_compose_msg(int irq, struct msi_msg *msg)
+void msi_compose_msg(struct irq_desc *desc, struct msi_msg *msg)
{
unsigned dest;
cpumask_t domain;
- struct irq_cfg *cfg = irq_cfg(irq);
+ struct irq_cfg *cfg = desc->chip_data;
int vector = cfg->vector;
domain = cfg->cpu_mask;
@@ -205,19 +205,6 @@ static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
iommu_read_msi_from_ire(entry, msg);
}
-static int set_irq_msi(struct msi_desc *entry)
-{
- if ( entry->irq >= nr_irqs )
- {
- dprintk(XENLOG_ERR, "Trying to install msi data for irq %d\n",
- entry->irq);
- return -EINVAL;
- }
-
- irq_desc[entry->irq].msi_desc = entry;
- return 0;
-}
-
static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
entry->msg = *msg;
@@ -266,7 +253,7 @@ static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
}
}
-void set_msi_affinity(struct irq_desc *desc, const cpumask_t *mask)
+static void set_msi_affinity(struct irq_desc *desc, const cpumask_t *mask)
{
struct msi_msg msg;
unsigned int dest;
@@ -387,16 +374,65 @@ static int msi_get_mask_bit(const struct msi_desc *entry)
return -1;
}
-void mask_msi_irq(struct irq_desc *desc)
+static void mask_msi_irq(struct irq_desc *desc)
{
msi_set_mask_bit(desc, 1);
}
-void unmask_msi_irq(struct irq_desc *desc)
+static void unmask_msi_irq(struct irq_desc *desc)
{
msi_set_mask_bit(desc, 0);
}
+static unsigned int startup_msi_irq(struct irq_desc *desc)
+{
+ unmask_msi_irq(desc);
+ return 0;
+}
+
+static void ack_nonmaskable_msi_irq(struct irq_desc *desc)
+{
+ irq_complete_move(desc);
+ move_native_irq(desc);
+}
+
+static void ack_maskable_msi_irq(struct irq_desc *desc)
+{
+ ack_nonmaskable_msi_irq(desc);
+ ack_APIC_irq(); /* ACKTYPE_NONE */
+}
+
+static void end_nonmaskable_msi_irq(struct irq_desc *desc, u8 vector)
+{
+ ack_APIC_irq(); /* ACKTYPE_EOI */
+}
+
+/*
+ * IRQ chip for MSI PCI/PCI-X/PCI-Express devices,
+ * which implement the MSI or MSI-X capability structure.
+ */
+static hw_irq_controller pci_msi_maskable = {
+ .typename = "PCI-MSI/-X",
+ .startup = startup_msi_irq,
+ .shutdown = mask_msi_irq,
+ .enable = unmask_msi_irq,
+ .disable = mask_msi_irq,
+ .ack = ack_maskable_msi_irq,
+ .set_affinity = set_msi_affinity
+};
+
+/* As above, but without having masking capability. */
+static hw_irq_controller pci_msi_nonmaskable = {
+ .typename = "PCI-MSI",
+ .startup = irq_startup_none,
+ .shutdown = irq_shutdown_none,
+ .enable = irq_enable_none,
+ .disable = irq_disable_none,
+ .ack = ack_nonmaskable_msi_irq,
+ .end = end_nonmaskable_msi_irq,
+ .set_affinity = set_msi_affinity
+};
+
static struct msi_desc* alloc_msi_entry(void)
{
struct msi_desc *entry;
@@ -412,15 +448,19 @@ static struct msi_desc* alloc_msi_entry(void)
return entry;
}
-int setup_msi_irq(struct msi_desc *msidesc, int irq)
+void setup_msi_handler(struct irq_desc *desc, struct msi_desc *msidesc)
{
- struct msi_msg msg;
+ desc->msi_desc = msidesc;
+ desc->handler = msi_maskable_irq(msidesc) ? &pci_msi_maskable
+ : &pci_msi_nonmaskable;
+}
- msi_compose_msg(irq, &msg);
- set_irq_msi(msidesc);
- write_msi_msg(irq_desc[irq].msi_desc, &msg);
+void setup_msi_irq(struct irq_desc *desc)
+{
+ struct msi_msg msg;
- return 0;
+ msi_compose_msg(desc, &msg);
+ write_msi_msg(desc->msi_desc, &msg);
}
int msi_free_irq(struct msi_desc *entry)
@@ -1022,19 +1062,20 @@ static void dump_msi(unsigned char key)
{
struct irq_desc *desc = irq_to_desc(irq);
const struct msi_desc *entry;
- u32 addr, data;
+ u32 addr, data, dest32;
+ int mask;
+ struct msi_attrib attr;
unsigned long flags;
char type;
spin_lock_irqsave(&desc->lock, flags);
entry = desc->msi_desc;
- type = desc->handler == &pci_msi_type && entry;
-
- spin_unlock_irqrestore(&desc->lock, flags);
-
- if ( !type )
+ if ( !entry )
+ {
+ spin_unlock_irqrestore(&desc->lock, flags);
continue;
+ }
switch ( entry->msi_attrib.type )
{
@@ -1045,6 +1086,11 @@ static void dump_msi(unsigned char key)
data = entry->msg.data;
addr = entry->msg.address_lo;
+ dest32 = entry->msg.dest32;
+ attr = entry->msi_attrib;
+ mask = msi_get_mask_bit(entry);
+
+ spin_unlock_irqrestore(&desc->lock, flags);
printk(" MSI%c %4u vec=%02x%7s%6s%3sassert%5s%7s"
" dest=%08x mask=%d/%d/%d\n",
@@ -1055,9 +1101,7 @@ static void dump_msi(unsigned char key)
data & MSI_DATA_LEVEL_ASSERT ? "" : "de",
addr & MSI_ADDR_DESTMODE_LOGIC ? "log" : "phys",
addr & MSI_ADDR_REDIRECTION_LOWPRI ? "lowest" : "cpu",
- entry->msg.dest32,
- entry->msi_attrib.maskbit, entry->msi_attrib.masked,
- msi_get_mask_bit(entry));
+ dest32, attr.maskbit, attr.masked, mask);
}
}
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index 5917746a39..09d4231ece 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -74,15 +74,14 @@ struct msi_msg {
u32 dest32; /* used when Interrupt Remapping with EIM is enabled */
};
+struct irq_desc;
struct msi_desc;
/* Helper functions */
-extern void mask_msi_irq(struct irq_desc *);
-extern void unmask_msi_irq(struct irq_desc *);
-extern void set_msi_affinity(struct irq_desc *, const cpumask_t *);
extern int pci_enable_msi(struct msi_info *msi, struct msi_desc **desc);
extern void pci_disable_msi(struct msi_desc *desc);
extern void pci_cleanup_msi(struct pci_dev *pdev);
-extern int setup_msi_irq(struct msi_desc *desc, int irq);
+extern void setup_msi_handler(struct irq_desc *, struct msi_desc *);
+extern void setup_msi_irq(struct irq_desc *);
extern void teardown_msi_irq(int irq);
extern int msi_free_vector(struct msi_desc *entry);
extern int pci_restore_msi_state(struct pci_dev *pdev);
@@ -90,14 +89,14 @@ extern int pci_restore_msi_state(struct pci_dev *pdev);
extern unsigned int pci_msix_get_table_len(struct pci_dev *pdev);
struct msi_desc {
- struct {
+ struct msi_attrib {
__u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
__u8 maskbit : 1; /* mask-pending bit supported ? */
__u8 masked : 1;
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
__u8 pos; /* Location of the msi capability */
__u16 entry_nr; /* specific enabled entry */
- }msi_attrib;
+ } msi_attrib;
struct list_head list;
@@ -123,8 +122,6 @@ int msi_free_irq(struct msi_desc *entry);
*/
#define NR_HP_RESERVED_VECTORS 20
-extern const struct hw_interrupt_type pci_msi_type;
-
#define PCI_MSIX_ENTRY_SIZE 16
#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
@@ -222,5 +219,6 @@ struct msg_address {
__u32 hi_address;
} __attribute__ ((packed));
-void msi_compose_msg(int irq, struct msi_msg *);
+void msi_compose_msg(struct irq_desc *, struct msi_msg *);
+
#endif /* __ASM_MSI_H */