# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1222357213 -3600
# Node ID 583086d5cd26936a2cd96a98e48720a86ca60dd0
# Parent 2afa279661de721d7165268d69828a625677344f
pci-msi: Dynamically map into Linux irq space.
Signed-off-by: Shan Haitao <haitao.shan@xxxxxxxxx>
---
drivers/pci/msi-xen.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 52 insertions(+), 4 deletions(-)
diff -r 2afa279661de -r 583086d5cd26 drivers/pci/msi-xen.c
--- a/drivers/pci/msi-xen.c Thu Sep 25 13:10:57 2008 +0100
+++ b/drivers/pci/msi-xen.c Thu Sep 25 16:40:13 2008 +0100
@@ -158,7 +158,11 @@ static int msi_unmap_pirq(struct pci_dev
int rc;
unmap.domid = msi_get_dev_owner(dev);
- unmap.pirq = evtchn_get_xen_pirq(pirq);
+ /* See comments in msi_map_pirq_to_vector, input parameter pirq
+ * mean irq number only if the device belongs to dom0 itself.
+ */
+ unmap.pirq = (unmap.domid != DOMID_SELF)
+ ? pirq : evtchn_get_xen_pirq(pirq);
if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
printk(KERN_WARNING "unmap irq %x failed\n", pirq);
@@ -166,7 +170,9 @@ static int msi_unmap_pirq(struct pci_dev
if (rc < 0)
return rc;
- evtchn_map_pirq(pirq, 0);
+ if (unmap.domid == DOMID_SELF)
+ evtchn_map_pirq(pirq, 0);
+
return 0;
}
@@ -217,7 +223,14 @@ static int msi_map_pirq_to_vector(struct
return -ENOSYS;
BUG_ON(map_irq.pirq <= 0);
- return evtchn_map_pirq(pirq, map_irq.pirq);
+
+ /* If mapping of this particular MSI is on behalf of another domain,
+ * we do not need to get an irq in dom0. This also implies:
+ * dev->irq in dom0 will be 'Xen pirq' if this device belongs to
+ * to another domain, and will be 'Linux irq' if it belongs to dom0.
+ */
+ return ((domid != DOMID_SELF) ?
+ map_irq.pirq : evtchn_map_pirq(pirq, map_irq.pirq));
}
static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
@@ -520,6 +533,7 @@ int pci_enable_msi(struct pci_dev* dev)
if (ret)
return ret;
+ dev->irq = evtchn_map_pirq(-1, dev->irq);
dev->irq_old = temp;
return ret;
@@ -563,6 +577,7 @@ void pci_disable_msi(struct pci_dev* dev
#ifdef CONFIG_XEN_PCIDEV_FRONTEND
if (!is_initial_xendomain()) {
+ evtchn_map_pirq(dev->irq, 0);
pci_frontend_disable_msi(dev);
dev->irq = dev->irq_old;
return;
@@ -618,7 +633,9 @@ int pci_enable_msix(struct pci_dev* dev,
#ifdef CONFIG_XEN_PCIDEV_FRONTEND
if (!is_initial_xendomain()) {
- int ret;
+ struct msi_dev_list *msi_dev_entry;
+ struct msi_pirq_entry *pirq_entry;
+ int ret, irq;
ret = pci_frontend_enable_msix(dev, entries, nvec);
if (ret) {
@@ -626,6 +643,25 @@ int pci_enable_msix(struct pci_dev* dev,
return ret;
}
+ msi_dev_entry = get_msi_dev_pirq_list(dev);
+ for (i = 0; i < nvec; i++) {
+ int mapped = 0;
+
+ list_for_each_entry(pirq_entry,
&msi_dev_entry->pirq_list_head, list) {
+ if (pirq_entry->entry_nr == entries[i].entry) {
+ irq = pirq_entry->pirq;
+ BUG_ON(entries[i].vector !=
evtchn_get_xen_pirq(irq));
+ entries[i].vector = irq;
+ mapped = 1;
+ break;
+ }
+ }
+ if (mapped)
+ continue;
+ irq = evtchn_map_pirq(-1, entries[i].vector);
+ attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
+ entries[i].vector = irq;
+ }
return 0;
}
#endif
@@ -687,7 +723,19 @@ void pci_disable_msix(struct pci_dev* de
#ifdef CONFIG_XEN_PCIDEV_FRONTEND
if (!is_initial_xendomain()) {
+ struct msi_dev_list *msi_dev_entry;
+ struct msi_pirq_entry *pirq_entry, *tmp;
+
pci_frontend_disable_msix(dev);
+
+ msi_dev_entry = get_msi_dev_pirq_list(dev);
+ list_for_each_entry_safe(pirq_entry, tmp,
+ &msi_dev_entry->pirq_list_head, list) {
+ evtchn_map_pirq(pirq_entry->pirq, 0);
+ list_del(&pirq_entry->list);
+ kfree(pirq_entry);
+ }
+
dev->irq = dev->irq_old;
return;
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|