]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/xen/xen-pciback/conf_space_capability_msi.c
xen/pciback: Print out the MSI/MSI-X (PIRQ) values
[karo-tx-linux.git] / drivers / xen / 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 <xen/events.h>
10 #include "pciback.h"
11
12 int pciback_enable_msi(struct pciback_device *pdev,
13                 struct pci_dev *dev, struct xen_pci_op *op)
14 {
15         struct pciback_dev_data *dev_data;
16         int otherend = pdev->xdev->otherend_id;
17         int status;
18
19         if (unlikely(verbose_request))
20                 printk(KERN_DEBUG "pciback: %s: enable MSI\n", pci_name(dev));
21
22         status = pci_enable_msi(dev);
23
24         if (status) {
25                 printk(KERN_ERR "error enable msi for guest %x status %x\n",
26                         otherend, status);
27                 op->value = 0;
28                 return XEN_PCI_ERR_op_failed;
29         }
30
31         /* The value the guest needs is actually the IDT vector, not the
32          * the local domain's IRQ number. */
33
34         op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
35         if (unlikely(verbose_request))
36                 printk(KERN_DEBUG "pciback: %s: MSI: %d\n", pci_name(dev),
37                         op->value);
38
39         dev_data = pci_get_drvdata(dev);
40         if (dev_data)
41                 dev_data->ack_intr = 0;
42
43         return 0;
44 }
45
46 int pciback_disable_msi(struct pciback_device *pdev,
47                 struct pci_dev *dev, struct xen_pci_op *op)
48 {
49         struct pciback_dev_data *dev_data;
50
51         if (unlikely(verbose_request))
52                 printk(KERN_DEBUG "pciback: %s: disable MSI\n", pci_name(dev));
53
54         pci_disable_msi(dev);
55
56         op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
57         if (unlikely(verbose_request))
58                 printk(KERN_DEBUG "pciback: %s: MSI: %d\n", pci_name(dev),
59                         op->value);
60         dev_data = pci_get_drvdata(dev);
61         if (dev_data)
62                 dev_data->ack_intr = 1;
63         return 0;
64 }
65
66 int pciback_enable_msix(struct pciback_device *pdev,
67                 struct pci_dev *dev, struct xen_pci_op *op)
68 {
69         struct pciback_dev_data *dev_data;
70         int i, result;
71         struct msix_entry *entries;
72
73         if (unlikely(verbose_request))
74                 printk(KERN_DEBUG "pciback: %s: enable MSI-X\n",
75                        pci_name(dev));
76
77         if (op->value > SH_INFO_MAX_VEC)
78                 return -EINVAL;
79
80         entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
81         if (entries == NULL)
82                 return -ENOMEM;
83
84         for (i = 0; i < op->value; i++) {
85                 entries[i].entry = op->msix_entries[i].entry;
86                 entries[i].vector = op->msix_entries[i].vector;
87         }
88
89         result = pci_enable_msix(dev, entries, op->value);
90
91         if (result == 0) {
92                 for (i = 0; i < op->value; i++) {
93                         op->msix_entries[i].entry = entries[i].entry;
94                         if (entries[i].vector)
95                                 op->msix_entries[i].vector =
96                                         xen_pirq_from_irq(entries[i].vector);
97                                 if (unlikely(verbose_request))
98                                         printk(KERN_DEBUG "pciback: %s: " \
99                                                 "MSI-X[%d]: %d\n",
100                                                 pci_name(dev), i,
101                                                 op->msix_entries[i].vector);
102                 }
103         } else {
104                 printk(KERN_WARNING "pciback: %s: failed to enable MSI-X: err %d!\n",
105                         pci_name(dev), result);
106         }
107         kfree(entries);
108
109         op->value = result;
110         dev_data = pci_get_drvdata(dev);
111         if (dev_data)
112                 dev_data->ack_intr = 0;
113
114         return result;
115 }
116
117 int pciback_disable_msix(struct pciback_device *pdev,
118                 struct pci_dev *dev, struct xen_pci_op *op)
119 {
120         struct pciback_dev_data *dev_data;
121
122         if (unlikely(verbose_request))
123                 printk(KERN_DEBUG "pciback: %s: disable MSI-X\n",
124                        pci_name(dev));
125
126         pci_disable_msix(dev);
127
128         /*
129          * SR-IOV devices (which don't have any legacy IRQ) have
130          * an undefined IRQ value of zero.
131          */
132         op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
133         if (unlikely(verbose_request))
134                 printk(KERN_DEBUG "pciback: %s: MSI-X: %d\n", pci_name(dev),
135                         op->value);
136         dev_data = pci_get_drvdata(dev);
137         if (dev_data)
138                 dev_data->ack_intr = 1;
139
140         return 0;
141 }
142