|
@@ -20,7 +20,8 @@
|
|
|
#include <asm/xen/pci.h>
|
|
|
|
|
|
#ifdef CONFIG_ACPI
|
|
|
-static int xen_hvm_register_pirq(u32 gsi, int triggering)
|
|
|
+static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
|
|
|
+ int trigger, int polarity)
|
|
|
{
|
|
|
int rc, irq;
|
|
|
struct physdev_map_pirq map_irq;
|
|
@@ -41,7 +42,7 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (triggering == ACPI_EDGE_SENSITIVE) {
|
|
|
+ if (trigger == ACPI_EDGE_SENSITIVE) {
|
|
|
shareable = 0;
|
|
|
name = "ioapic-edge";
|
|
|
} else {
|
|
@@ -55,12 +56,6 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering)
|
|
|
|
|
|
return irq;
|
|
|
}
|
|
|
-
|
|
|
-static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
|
|
|
- int trigger, int polarity)
|
|
|
-{
|
|
|
- return xen_hvm_register_pirq(gsi, trigger);
|
|
|
-}
|
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_PCI_MSI)
|
|
@@ -91,7 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
|
|
|
|
|
|
static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
{
|
|
|
- int irq, pirq, ret = 0;
|
|
|
+ int irq, pirq;
|
|
|
struct msi_desc *msidesc;
|
|
|
struct msi_msg msg;
|
|
|
|
|
@@ -99,39 +94,32 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
__read_msi_msg(msidesc, &msg);
|
|
|
pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
|
|
|
((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
|
|
|
- if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) {
|
|
|
- xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
|
|
|
- "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ);
|
|
|
- if (irq < 0)
|
|
|
+ if (msg.data != XEN_PIRQ_MSI_DATA ||
|
|
|
+ xen_irq_from_pirq(pirq) < 0) {
|
|
|
+ pirq = xen_allocate_pirq_msi(dev, msidesc);
|
|
|
+ if (pirq < 0)
|
|
|
goto error;
|
|
|
- ret = set_irq_msi(irq, msidesc);
|
|
|
- if (ret < 0)
|
|
|
- goto error_while;
|
|
|
- printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d"
|
|
|
- " pirq=%d\n", irq, pirq);
|
|
|
- return 0;
|
|
|
+ xen_msi_compose_msg(dev, pirq, &msg);
|
|
|
+ __write_msi_msg(msidesc, &msg);
|
|
|
+ dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
|
|
|
+ } else {
|
|
|
+ dev_dbg(&dev->dev,
|
|
|
+ "xen: msi already bound to pirq=%d\n", pirq);
|
|
|
}
|
|
|
- xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
|
|
|
- "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ));
|
|
|
- if (irq < 0 || pirq < 0)
|
|
|
+ irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
|
|
|
+ (type == PCI_CAP_ID_MSIX) ?
|
|
|
+ "msi-x" : "msi");
|
|
|
+ if (irq < 0)
|
|
|
goto error;
|
|
|
- printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq);
|
|
|
- xen_msi_compose_msg(dev, pirq, &msg);
|
|
|
- ret = set_irq_msi(irq, msidesc);
|
|
|
- if (ret < 0)
|
|
|
- goto error_while;
|
|
|
- write_msi_msg(irq, &msg);
|
|
|
+ dev_dbg(&dev->dev,
|
|
|
+ "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
|
|
|
}
|
|
|
return 0;
|
|
|
|
|
|
-error_while:
|
|
|
- unbind_from_irqhandler(irq, NULL);
|
|
|
error:
|
|
|
- if (ret == -ENODEV)
|
|
|
- dev_err(&dev->dev, "Xen PCI frontend has not registered" \
|
|
|
- " MSI/MSI-X support!\n");
|
|
|
-
|
|
|
- return ret;
|
|
|
+ dev_err(&dev->dev,
|
|
|
+ "Xen PCI frontend has not registered MSI/MSI-X support!\n");
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -157,28 +145,19 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
goto error;
|
|
|
i = 0;
|
|
|
list_for_each_entry(msidesc, &dev->msi_list, list) {
|
|
|
- xen_allocate_pirq_msi(
|
|
|
- (type == PCI_CAP_ID_MSIX) ?
|
|
|
- "pcifront-msi-x" : "pcifront-msi",
|
|
|
- &irq, &v[i], XEN_ALLOC_IRQ);
|
|
|
- if (irq < 0) {
|
|
|
- ret = -1;
|
|
|
+ irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
|
|
|
+ (type == PCI_CAP_ID_MSIX) ?
|
|
|
+ "pcifront-msi-x" :
|
|
|
+ "pcifront-msi");
|
|
|
+ if (irq < 0)
|
|
|
goto free;
|
|
|
- }
|
|
|
- ret = set_irq_msi(irq, msidesc);
|
|
|
- if (ret)
|
|
|
- goto error_while;
|
|
|
i++;
|
|
|
}
|
|
|
kfree(v);
|
|
|
return 0;
|
|
|
|
|
|
-error_while:
|
|
|
- unbind_from_irqhandler(irq, NULL);
|
|
|
error:
|
|
|
- if (ret == -ENODEV)
|
|
|
- dev_err(&dev->dev, "Xen PCI frontend has not registered" \
|
|
|
- " MSI/MSI-X support!\n");
|
|
|
+ dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
|
|
|
free:
|
|
|
kfree(v);
|
|
|
return ret;
|
|
@@ -203,27 +182,56 @@ static void xen_teardown_msi_irq(unsigned int irq)
|
|
|
xen_destroy_irq(irq);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_XEN_DOM0
|
|
|
static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
{
|
|
|
- int irq, ret;
|
|
|
+ int ret = 0;
|
|
|
struct msi_desc *msidesc;
|
|
|
|
|
|
list_for_each_entry(msidesc, &dev->msi_list, list) {
|
|
|
- irq = xen_create_msi_irq(dev, msidesc, type);
|
|
|
- if (irq < 0)
|
|
|
- return -1;
|
|
|
+ struct physdev_map_pirq map_irq;
|
|
|
|
|
|
- ret = set_irq_msi(irq, msidesc);
|
|
|
- if (ret)
|
|
|
- goto error;
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ memset(&map_irq, 0, sizeof(map_irq));
|
|
|
+ map_irq.domid = DOMID_SELF;
|
|
|
+ map_irq.type = MAP_PIRQ_TYPE_MSI;
|
|
|
+ map_irq.index = -1;
|
|
|
+ map_irq.pirq = -1;
|
|
|
+ map_irq.bus = dev->bus->number;
|
|
|
+ map_irq.devfn = dev->devfn;
|
|
|
|
|
|
-error:
|
|
|
- xen_destroy_irq(irq);
|
|
|
+ if (type == PCI_CAP_ID_MSIX) {
|
|
|
+ int pos;
|
|
|
+ u32 table_offset, bir;
|
|
|
+
|
|
|
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
|
|
|
+
|
|
|
+ pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
|
|
|
+ &table_offset);
|
|
|
+ bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
|
|
|
+
|
|
|
+ map_irq.table_base = pci_resource_start(dev, bir);
|
|
|
+ map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
|
|
|
+ if (ret) {
|
|
|
+ dev_warn(&dev->dev, "xen map irq failed %d\n", ret);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
|
|
|
+ map_irq.pirq, map_irq.index,
|
|
|
+ (type == PCI_CAP_ID_MSIX) ?
|
|
|
+ "msi-x" : "msi");
|
|
|
+ if (ret < 0)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ ret = 0;
|
|
|
+out:
|
|
|
return ret;
|
|
|
}
|
|
|
#endif
|
|
|
+#endif
|
|
|
|
|
|
static int xen_pcifront_enable_irq(struct pci_dev *dev)
|
|
|
{
|