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
|