xen/pciback: Allocate IRQ handler for device that is shared with guest.
[deliverable/linux.git] / drivers / xen / xen-pciback / conf_space_capability_msi.c
CommitLineData
30edc14b
KRW
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"
11
12int pciback_enable_msi(struct pciback_device *pdev,
13 struct pci_dev *dev, struct xen_pci_op *op)
14{
0513fe9e 15 struct pciback_dev_data *dev_data;
30edc14b
KRW
16 int otherend = pdev->xdev->otherend_id;
17 int status;
18
19 status = pci_enable_msi(dev);
20
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;
26 }
27
28 /* The value the guest needs is actually the IDT vector, not the
29 * the local domain's IRQ number. */
30
31 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
0513fe9e
KRW
32 dev_data = pci_get_drvdata(dev);
33 if (dev_data)
34 dev_data->ack_intr = 0;
30edc14b
KRW
35 return 0;
36}
37
38int pciback_disable_msi(struct pciback_device *pdev,
39 struct pci_dev *dev, struct xen_pci_op *op)
40{
0513fe9e 41 struct pciback_dev_data *dev_data;
30edc14b
KRW
42 pci_disable_msi(dev);
43
44 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
0513fe9e
KRW
45 dev_data = pci_get_drvdata(dev);
46 if (dev_data)
47 dev_data->ack_intr = 1;
30edc14b
KRW
48 return 0;
49}
50
51int pciback_enable_msix(struct pciback_device *pdev,
52 struct pci_dev *dev, struct xen_pci_op *op)
53{
0513fe9e 54 struct pciback_dev_data *dev_data;
30edc14b
KRW
55 int i, result;
56 struct msix_entry *entries;
57
58 if (op->value > SH_INFO_MAX_VEC)
59 return -EINVAL;
60
61 entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
62 if (entries == NULL)
63 return -ENOMEM;
64
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;
68 }
69
70 result = pci_enable_msix(dev, entries, op->value);
71
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);
78 }
79 } else {
80 printk(KERN_WARNING "pciback: %s: failed to enable MSI-X: err %d!\n",
81 pci_name(dev), result);
82 }
83 kfree(entries);
84
85 op->value = result;
0513fe9e
KRW
86 dev_data = pci_get_drvdata(dev);
87 if (dev_data)
88 dev_data->ack_intr = 0;
30edc14b
KRW
89
90 return result;
91}
92
93int pciback_disable_msix(struct pciback_device *pdev,
94 struct pci_dev *dev, struct xen_pci_op *op)
95{
0513fe9e 96 struct pciback_dev_data *dev_data;
30edc14b
KRW
97
98 pci_disable_msix(dev);
99
100 /*
101 * SR-IOV devices (which don't have any legacy IRQ) have
102 * an undefined IRQ value of zero.
103 */
104 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
0513fe9e
KRW
105 dev_data = pci_get_drvdata(dev);
106 if (dev_data)
107 dev_data->ack_intr = 1;
108
30edc14b
KRW
109 return 0;
110}
111
This page took 0.027939 seconds and 5 git commands to generate.