xen/pciback: Allocate IRQ handler for device that is shared with guest.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / xen / xen-pciback / conf_space_capability_msi.c
blobd0d2255b5da9d2674325f0ad3bbb943159e17297
1 /*
2 * PCI Backend -- Configuration overlay for MSI capability
3 */
4 #include <linux/pci.h>
5 #include <linux/slab.h>
6 #include "conf_space.h"
7 #include "conf_space_capability.h"
8 #include <xen/interface/io/pciif.h>
9 #include <xen/events.h>
10 #include "pciback.h"
12 int pciback_enable_msi(struct pciback_device *pdev,
13 struct pci_dev *dev, struct xen_pci_op *op)
15 struct pciback_dev_data *dev_data;
16 int otherend = pdev->xdev->otherend_id;
17 int status;
19 status = pci_enable_msi(dev);
21 if (status) {
22 printk(KERN_ERR "error enable msi for guest %x status %x\n",
23 otherend, status);
24 op->value = 0;
25 return XEN_PCI_ERR_op_failed;
28 /* The value the guest needs is actually the IDT vector, not the
29 * the local domain's IRQ number. */
31 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
32 dev_data = pci_get_drvdata(dev);
33 if (dev_data)
34 dev_data->ack_intr = 0;
35 return 0;
38 int pciback_disable_msi(struct pciback_device *pdev,
39 struct pci_dev *dev, struct xen_pci_op *op)
41 struct pciback_dev_data *dev_data;
42 pci_disable_msi(dev);
44 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
45 dev_data = pci_get_drvdata(dev);
46 if (dev_data)
47 dev_data->ack_intr = 1;
48 return 0;
51 int pciback_enable_msix(struct pciback_device *pdev,
52 struct pci_dev *dev, struct xen_pci_op *op)
54 struct pciback_dev_data *dev_data;
55 int i, result;
56 struct msix_entry *entries;
58 if (op->value > SH_INFO_MAX_VEC)
59 return -EINVAL;
61 entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
62 if (entries == NULL)
63 return -ENOMEM;
65 for (i = 0; i < op->value; i++) {
66 entries[i].entry = op->msix_entries[i].entry;
67 entries[i].vector = op->msix_entries[i].vector;
70 result = pci_enable_msix(dev, entries, op->value);
72 if (result == 0) {
73 for (i = 0; i < op->value; i++) {
74 op->msix_entries[i].entry = entries[i].entry;
75 if (entries[i].vector)
76 op->msix_entries[i].vector =
77 xen_pirq_from_irq(entries[i].vector);
79 } else {
80 printk(KERN_WARNING "pciback: %s: failed to enable MSI-X: err %d!\n",
81 pci_name(dev), result);
83 kfree(entries);
85 op->value = result;
86 dev_data = pci_get_drvdata(dev);
87 if (dev_data)
88 dev_data->ack_intr = 0;
90 return result;
93 int pciback_disable_msix(struct pciback_device *pdev,
94 struct pci_dev *dev, struct xen_pci_op *op)
96 struct pciback_dev_data *dev_data;
98 pci_disable_msix(dev);
101 * SR-IOV devices (which don't have any legacy IRQ) have
102 * an undefined IRQ value of zero.
104 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
105 dev_data = pci_get_drvdata(dev);
106 if (dev_data)
107 dev_data->ack_intr = 1;
109 return 0;