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

[Xen-changelog] [qemu-xen-unstable] passthrough: Read the interrupt pin from hardware



commit 7ee1be75ae25cd733b48cbc6a95a03f89eb14704
Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date:   Thu Jun 25 18:26:00 2009 +0100

    passthrough: Read the interrupt pin from hardware
    
    Preparation for multi-fucntion devices in guests.
    
    Up until now guests have only seen devices with one function,
    so it is both safe and sensible to always use INTA. But if
    if multiple functions appear, it makes sense to use
    the interrupt pin specified by the hardware.
    
    Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx>
    Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
    Cc: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
    Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
    
    [1/8; cross-compatibility issues with xen-unstable.hg]
---
 hw/pass-through.c |   66 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 hw/pass-through.h |    2 +
 hw/pt-msi.c       |    8 ++----
 3 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/hw/pass-through.c b/hw/pass-through.c
index a848164..ec79afe 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -2296,8 +2296,7 @@ static int pt_init_pci_config(struct pt_dev *ptdev)
     if (ret < 0 && ptdev->machine_irq != 0)
     {
         uint8_t e_device = PCI_SLOT(ptdev->dev.devfn);
-        /* fix virtual interrupt pin to INTA# */
-        uint8_t e_intx = 0;
+        uint8_t e_intx = pci_intx(ptdev);
 
         ret = xc_domain_bind_pt_pci_irq(xc_handle, domid, ptdev->machine_irq,
                                        0, e_device, e_intx);
@@ -3580,7 +3579,6 @@ static int pt_msgctrl_reg_write(struct pt_dev *ptdev,
     uint16_t writable_mask = 0;
     uint16_t throughable_mask = 0;
     uint16_t old_ctrl = cfg_entry->data;
-    uint8_t e_device, e_intx;
     PCIDevice *pd = (PCIDevice *)ptdev;
     uint16_t val;
 
@@ -4106,7 +4104,7 @@ static struct pt_dev * register_real_device(PCIBus *e_bus,
     {
         e_device = PCI_SLOT(assigned_device->dev.devfn);
         /* fix virtual interrupt pin to INTA# */
-        e_intx = 0;
+        e_intx = pci_intx(assigned_device);
 
         rc = xc_domain_bind_pt_pci_irq(xc_handle, domid, machine_irq, 0,
                                        e_device, e_intx);
@@ -4164,8 +4162,7 @@ static int unregister_real_device(int slot)
 
     /* Unbind interrupt */
     e_device = PCI_SLOT(assigned_device->dev.devfn);
-    /* fix virtual interrupt pin to INTA# */
-    e_intx = 0;
+    e_intx = pci_intx(assigned_device);
     machine_irq = assigned_device->machine_irq;
 
     if ( assigned_device->msi_trans_en == 0 && machine_irq ) {
@@ -4258,3 +4255,60 @@ int pt_init(PCIBus *e_bus)
     return 0;
 }
 
+/* The PCI Local Bus Specification, Rev. 3.0,
+ * Section 6.2.4 Miscellaneous Registers, pp 223
+ * outlines 5 valid values for the intertupt pin (intx).
+ *  0: For devices (or device functions) that don't use an interrupt in
+ *  1: INTA#
+ *  2: INTB#
+ *  3: INTC#
+ *  4: INTD#
+ *
+ * Xen uses the following 4 values for intx
+ *  0: INTA#
+ *  1: INTB#
+ *  2: INTC#
+ *  3: INTD#
+ *
+ * Observing that these list of values are not the same, pci_read_intx()
+ * uses the following mapping from hw to xen values.
+ * This seems to reflect the current usage within Xen.
+ *
+ * PCI hardware    | Xen | Notes
+ * ----------------+-----+----------------------------------------------------
+ * 0               | 0   | No interrupt
+ * 1               | 0   | INTA#
+ * 2               | 1   | INTB#
+ * 3               | 2   | INTC#
+ * 4               | 3   | INTD#
+ * any other value | 0   | This should never happen, log error message
+ */
+static uint8_t pci_read_intx(struct pt_dev *ptdev)
+{
+    uint8_t r_val = pci_read_byte(ptdev->pci_dev, PCI_INTERRUPT_PIN);
+
+    PT_LOG("intx=%i\n", r_val);
+    if (r_val < 1 || r_val > 4)
+    {
+        PT_LOG("Interrupt pin read from hardware is out of range: "
+               "value=%i, acceptable range is 1 - 4\n", r_val);
+        r_val = 0;
+    }
+    else
+    {
+        r_val -= 1;
+    }
+
+    return r_val;
+}
+
+/*
+ * For virtual function 0, always use INTA#,
+ * otherwise use the hardware value
+ */
+uint8_t pci_intx(struct pt_dev *ptdev)
+{
+    if (!PCI_FUNC(ptdev->dev.devfn))
+        return 0;
+    return pci_read_intx(ptdev);
+}
diff --git a/hw/pass-through.h b/hw/pass-through.h
index a87e5b8..028a03e 100644
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -402,5 +402,7 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base)
     return base & PCI_ADDR_MEM_MASK;
 }
 
+uint8_t pci_intx(struct pt_dev *ptdev);
+
 #endif /* __PASSTHROUGH_H__ */
 
diff --git a/hw/pt-msi.c b/hw/pt-msi.c
index be22e09..6f923d0 100644
--- a/hw/pt-msi.c
+++ b/hw/pt-msi.c
@@ -153,8 +153,7 @@ void pt_msi_disable(struct pt_dev *dev)
     msi_set_enable(dev, 0);
 
     e_device = PCI_SLOT(dev->dev.devfn);
-    /* fix virtual interrupt pin to INTA# */
-    e_intx = 0;
+    e_intx = pci_intx(dev);
 
     if (dev->msi_trans_en)
     {
@@ -224,7 +223,7 @@ int pt_enable_msi_translate(struct pt_dev* dev)
 
     e_device = PCI_SLOT(dev->dev.devfn);
     /* fix virtual interrupt pin to INTA# */
-    e_intx = 0;
+    e_intx = pci_intx(dev);
 
     if (xc_domain_bind_pt_irq(xc_handle, domid, dev->msi->pirq,
                                PT_IRQ_TYPE_MSI_TRANSLATE, 0,
@@ -253,8 +252,7 @@ void pt_disable_msi_translate(struct pt_dev *dev)
     msi_set_enable(dev, 0);
 
     e_device = PCI_SLOT(dev->dev.devfn);
-    /* fix virtual interrupt pin to INTA# */
-    e_intx = 0;
+    e_intx = pci_intx(dev);
 
     if (xc_domain_unbind_pt_irq(xc_handle, domid, dev->msi->pirq,
                                  PT_IRQ_TYPE_MSI_TRANSLATE, 0,
--
generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git

_______________________________________________
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®.