- supported.conf: Added sparse_keymap (eeepc_laptop depends on it)
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / pciback / conf_space_capability_msi.c
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 "pciback.h"
10
11 int pciback_enable_msi(struct pciback_device *pdev,
12                 struct pci_dev *dev, struct xen_pci_op *op)
13 {
14         int otherend = pdev->xdev->otherend_id;
15         int status;
16
17         status = pci_enable_msi(dev);
18
19         if (status) {
20                 printk("error enable msi for guest %x status %x\n", otherend, status);
21                 op->value = 0;
22                 return XEN_PCI_ERR_op_failed;
23         }
24
25         op->value = dev->irq;
26         return 0;
27 }
28
29 int pciback_disable_msi(struct pciback_device *pdev,
30                 struct pci_dev *dev, struct xen_pci_op *op)
31 {
32         pci_disable_msi(dev);
33
34         op->value = dev->irq;
35         return 0;
36 }
37
38 int pciback_enable_msix(struct pciback_device *pdev,
39                 struct pci_dev *dev, struct xen_pci_op *op)
40 {
41         int i, result;
42         struct msix_entry *entries;
43
44         if (op->value > SH_INFO_MAX_VEC)
45                 return -EINVAL;
46
47         entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
48         if (entries == NULL)
49                 return -ENOMEM;
50
51         for (i = 0; i < op->value; i++) {
52                 entries[i].entry = op->msix_entries[i].entry;
53                 entries[i].vector = op->msix_entries[i].vector;
54         }
55
56         result = pci_enable_msix(dev, entries, op->value);
57
58         for (i = 0; i < op->value; i++) {
59                 op->msix_entries[i].entry = entries[i].entry;
60                 op->msix_entries[i].vector = entries[i].vector;
61         }
62
63         kfree(entries);
64
65         op->value = result;
66
67         return result;
68 }
69
70 int pciback_disable_msix(struct pciback_device *pdev,
71                 struct pci_dev *dev, struct xen_pci_op *op)
72 {
73
74         pci_disable_msix(dev);
75
76         op->value = dev->irq;
77         return 0;
78 }
79