[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] pci-msi: Dynamically map into Linux irq space.



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.