aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQing He <qing.he@intel.com>2010-10-11 10:30:09 -0400
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2010-10-22 16:25:44 -0400
commitf731e3ef02b4744f4d7ca2f63539b900e47db31f (patch)
tree865ef6f817c372b99f0b36dc6f2638df087d51e7
parent38aa66fcb79e0a46c24bba96b6f2b851a6ec2037 (diff)
xen: remap MSIs into pirqs when running as initial domain
Implement xen_create_msi_irq to create an msi and remap it as pirq. Use xen_create_msi_irq to implement an initial domain specific version of setup_msi_irqs. Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--arch/x86/pci/xen.c55
-rw-r--r--drivers/xen/events.c60
-rw-r--r--include/xen/events.h4
3 files changed, 101 insertions, 18 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index dd0b5fdb27b9..b3f4b30222fa 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -135,14 +135,12 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
135 if (!v) 135 if (!v)
136 return -ENOMEM; 136 return -ENOMEM;
137 137
138 if (!xen_initial_domain()) { 138 if (type == PCI_CAP_ID_MSIX)
139 if (type == PCI_CAP_ID_MSIX) 139 ret = xen_pci_frontend_enable_msix(dev, &v, nvec);
140 ret = xen_pci_frontend_enable_msix(dev, &v, nvec); 140 else
141 else 141 ret = xen_pci_frontend_enable_msi(dev, &v);
142 ret = xen_pci_frontend_enable_msi(dev, &v); 142 if (ret)
143 if (ret) 143 goto error;
144 goto error;
145 }
146 i = 0; 144 i = 0;
147 list_for_each_entry(msidesc, &dev->msi_list, list) { 145 list_for_each_entry(msidesc, &dev->msi_list, list) {
148 irq = xen_allocate_pirq(v[i], 0, /* not sharable */ 146 irq = xen_allocate_pirq(v[i], 0, /* not sharable */
@@ -172,23 +170,40 @@ error:
172 170
173static void xen_teardown_msi_irqs(struct pci_dev *dev) 171static void xen_teardown_msi_irqs(struct pci_dev *dev)
174{ 172{
175 /* Only do this when were are in non-privileged mode.*/ 173 struct msi_desc *msidesc;
176 if (!xen_initial_domain()) {
177 struct msi_desc *msidesc;
178
179 msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
180 if (msidesc->msi_attrib.is_msix)
181 xen_pci_frontend_disable_msix(dev);
182 else
183 xen_pci_frontend_disable_msi(dev);
184 }
185 174
175 msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
176 if (msidesc->msi_attrib.is_msix)
177 xen_pci_frontend_disable_msix(dev);
178 else
179 xen_pci_frontend_disable_msi(dev);
186} 180}
187 181
188static void xen_teardown_msi_irq(unsigned int irq) 182static void xen_teardown_msi_irq(unsigned int irq)
189{ 183{
190 xen_destroy_irq(irq); 184 xen_destroy_irq(irq);
191} 185}
186
187static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
188{
189 int irq, ret;
190 struct msi_desc *msidesc;
191
192 list_for_each_entry(msidesc, &dev->msi_list, list) {
193 irq = xen_create_msi_irq(dev, msidesc, type);
194 if (irq < 0)
195 return -1;
196
197 ret = set_irq_msi(irq, msidesc);
198 if (ret)
199 goto error;
200 }
201 return 0;
202
203error:
204 xen_destroy_irq(irq);
205 return ret;
206}
192#endif 207#endif
193 208
194static int xen_pcifront_enable_irq(struct pci_dev *dev) 209static int xen_pcifront_enable_irq(struct pci_dev *dev)
@@ -362,6 +377,10 @@ static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
362 377
363static int __init pci_xen_initial_domain(void) 378static int __init pci_xen_initial_domain(void)
364{ 379{
380#ifdef CONFIG_PCI_MSI
381 x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
382 x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
383#endif
365 xen_setup_acpi_sci(); 384 xen_setup_acpi_sci();
366 __acpi_register_gsi = acpi_register_gsi_xen; 385 __acpi_register_gsi = acpi_register_gsi_xen;
367 386
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index c649ac0aaeef..a7d9555e664d 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -29,6 +29,7 @@
29#include <linux/bootmem.h> 29#include <linux/bootmem.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/irqnr.h> 31#include <linux/irqnr.h>
32#include <linux/pci.h>
32 33
33#include <asm/desc.h> 34#include <asm/desc.h>
34#include <asm/ptrace.h> 35#include <asm/ptrace.h>
@@ -656,6 +657,10 @@ out:
656 return irq; 657 return irq;
657} 658}
658 659
660#ifdef CONFIG_PCI_MSI
661#include <linux/msi.h>
662#include "../pci/msi.h"
663
659void xen_allocate_pirq_msi(char *name, int *irq, int *pirq) 664void xen_allocate_pirq_msi(char *name, int *irq, int *pirq)
660{ 665{
661 spin_lock(&irq_mapping_update_lock); 666 spin_lock(&irq_mapping_update_lock);
@@ -678,6 +683,61 @@ out:
678 spin_unlock(&irq_mapping_update_lock); 683 spin_unlock(&irq_mapping_update_lock);
679} 684}
680 685
686int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type)
687{
688 int irq = -1;
689 struct physdev_map_pirq map_irq;
690 int rc;
691 int pos;
692 u32 table_offset, bir;
693
694 memset(&map_irq, 0, sizeof(map_irq));
695 map_irq.domid = DOMID_SELF;
696 map_irq.type = MAP_PIRQ_TYPE_MSI;
697 map_irq.index = -1;
698 map_irq.pirq = -1;
699 map_irq.bus = dev->bus->number;
700 map_irq.devfn = dev->devfn;
701
702 if (type == PCI_CAP_ID_MSIX) {
703 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
704
705 pci_read_config_dword(dev, msix_table_offset_reg(pos),
706 &table_offset);
707 bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
708
709 map_irq.table_base = pci_resource_start(dev, bir);
710 map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
711 }
712
713 spin_lock(&irq_mapping_update_lock);
714
715 irq = find_unbound_irq();
716
717 if (irq == -1)
718 goto out;
719
720 rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
721 if (rc) {
722 printk(KERN_WARNING "xen map irq failed %d\n", rc);
723
724 irq_free_desc(irq);
725
726 irq = -1;
727 goto out;
728 }
729 irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index);
730
731 set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
732 handle_level_irq,
733 (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi");
734
735out:
736 spin_unlock(&irq_mapping_update_lock);
737 return irq;
738}
739#endif
740
681int xen_destroy_irq(int irq) 741int xen_destroy_irq(int irq)
682{ 742{
683 struct irq_desc *desc; 743 struct irq_desc *desc;
diff --git a/include/xen/events.h b/include/xen/events.h
index 0c58db6ea3f4..8fa27dc7358b 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -72,8 +72,12 @@ void xen_hvm_evtchn_do_upcall(void);
72 * usual. */ 72 * usual. */
73int xen_allocate_pirq(unsigned gsi, int shareable, char *name); 73int xen_allocate_pirq(unsigned gsi, int shareable, char *name);
74int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); 74int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name);
75
76#ifdef CONFIG_PCI_MSI
75/* Allocate an irq and a pirq to be used with MSIs. */ 77/* Allocate an irq and a pirq to be used with MSIs. */
76void xen_allocate_pirq_msi(char *name, int *irq, int *pirq); 78void xen_allocate_pirq_msi(char *name, int *irq, int *pirq);
79int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type);
80#endif
77 81
78/* De-allocates the above mentioned physical interrupt. */ 82/* De-allocates the above mentioned physical interrupt. */
79int xen_destroy_irq(int irq); 83int xen_destroy_irq(int irq);