Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / xen-pciback / slot.c
1 /*
2  * PCI Backend - Provides a Virtual PCI bus (with real devices)
3  *               to the frontend
4  *
5  *   Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c)
6  *   Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
7  */
8
9 #include <linux/spinlock.h>
10 #include "pciback.h"
11
12 /* There are at most 32 slots in a pci bus.  */
13 #define PCI_SLOT_MAX 32
14
15 #define PCI_BUS_NBR 2
16
17 struct slot_dev_data {
18         /* Access to dev_list must be protected by lock */
19         struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
20         spinlock_t lock;
21 };
22
23 static struct pci_dev *_xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
24                                               unsigned int domain,
25                                               unsigned int bus,
26                                               unsigned int devfn)
27 {
28         struct pci_dev *dev = NULL;
29         struct slot_dev_data *slot_dev = pdev->pci_dev_data;
30         unsigned long flags;
31
32         if (domain != 0 || PCI_FUNC(devfn) != 0)
33                 return NULL;
34
35         if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
36                 return NULL;
37
38         spin_lock_irqsave(&slot_dev->lock, flags);
39         dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
40         spin_unlock_irqrestore(&slot_dev->lock, flags);
41
42         return dev;
43 }
44
45 static int _xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
46                                   struct pci_dev *dev, int devid,
47                                   publish_pci_dev_cb publish_cb)
48 {
49         int err = 0, slot, bus;
50         struct slot_dev_data *slot_dev = pdev->pci_dev_data;
51         unsigned long flags;
52
53         if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
54                 err = -EFAULT;
55                 xenbus_dev_fatal(pdev->xdev, err,
56                                  "Can't export bridges on the virtual PCI bus");
57                 goto out;
58         }
59
60         spin_lock_irqsave(&slot_dev->lock, flags);
61
62         /* Assign to a new slot on the virtual PCI bus */
63         for (bus = 0; bus < PCI_BUS_NBR; bus++)
64                 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
65                         if (slot_dev->slots[bus][slot] == NULL) {
66                                 pr_info("pciback: slot: %s: assign to"
67                                         " virtual slot %d, bus %d\n",
68                                         pci_name(dev), slot, bus);
69                                 slot_dev->slots[bus][slot] = dev;
70                                 goto unlock;
71                         }
72                 }
73
74         err = -ENOMEM;
75         xenbus_dev_fatal(pdev->xdev, err,
76                          "No more space on root virtual PCI bus");
77
78       unlock:
79         spin_unlock_irqrestore(&slot_dev->lock, flags);
80
81         /* Publish this device. */
82         if(!err)
83                 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, 0), devid);
84
85       out:
86         return err;
87 }
88
89 static void _xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
90                                        struct pci_dev *dev)
91 {
92         int slot, bus;
93         struct slot_dev_data *slot_dev = pdev->pci_dev_data;
94         struct pci_dev *found_dev = NULL;
95         unsigned long flags;
96
97         spin_lock_irqsave(&slot_dev->lock, flags);
98
99         for (bus = 0; bus < PCI_BUS_NBR; bus++)
100                 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
101                         if (slot_dev->slots[bus][slot] == dev) {
102                                 slot_dev->slots[bus][slot] = NULL;
103                                 found_dev = dev;
104                                 goto out;
105                         }
106                 }
107
108       out:
109         spin_unlock_irqrestore(&slot_dev->lock, flags);
110
111         if (found_dev)
112                 pcistub_put_pci_dev(found_dev);
113 }
114
115 static int _xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
116 {
117         int slot, bus;
118         struct slot_dev_data *slot_dev;
119
120         slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
121         if (!slot_dev)
122                 return -ENOMEM;
123
124         spin_lock_init(&slot_dev->lock);
125
126         for (bus = 0; bus < PCI_BUS_NBR; bus++)
127                 for (slot = 0; slot < PCI_SLOT_MAX; slot++)
128                         slot_dev->slots[bus][slot] = NULL;
129
130         pdev->pci_dev_data = slot_dev;
131
132         return 0;
133 }
134
135 static int _xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
136                                         publish_pci_root_cb publish_cb)
137 {
138         /* The Virtual PCI bus has only one root */
139         return publish_cb(pdev, 0, 0);
140 }
141
142 static void _xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
143 {
144         int slot, bus;
145         struct slot_dev_data *slot_dev = pdev->pci_dev_data;
146         struct pci_dev *dev;
147
148         for (bus = 0; bus < PCI_BUS_NBR; bus++)
149                 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
150                         dev = slot_dev->slots[bus][slot];
151                         if (dev != NULL)
152                                 pcistub_put_pci_dev(dev);
153                 }
154
155         kfree(slot_dev);
156         pdev->pci_dev_data = NULL;
157 }
158
159 static int _xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
160                                        struct xen_pcibk_device *pdev,
161                                        unsigned int *domain,
162                                        unsigned int *bus, unsigned int *devfn)
163 {
164         int slot, busnr;
165         struct slot_dev_data *slot_dev = pdev->pci_dev_data;
166         struct pci_dev *dev;
167         int found = 0;
168         unsigned long flags;
169
170         spin_lock_irqsave(&slot_dev->lock, flags);
171
172         for (busnr = 0; busnr < PCI_BUS_NBR; bus++)
173                 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
174                         dev = slot_dev->slots[busnr][slot];
175                         if (dev && dev->bus->number == pcidev->bus->number
176                                 && dev->devfn == pcidev->devfn
177                                 && pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)) {
178                                 found = 1;
179                                 *domain = 0;
180                                 *bus = busnr;
181                                 *devfn = PCI_DEVFN(slot,0);
182                                 goto out;
183                         }
184                 }
185 out:
186         spin_unlock_irqrestore(&slot_dev->lock, flags);
187         return found;
188
189 }
190
191 const struct xen_pcibk_backend xen_pcibk_slot_backend = {
192         .name           = "slot",
193         .init           = _xen_pcibk_init_devices,
194         .free           = _xen_pcibk_release_devices,
195         .find           = _xen_pcibk_get_pcifront_dev,
196         .publish        = _xen_pcibk_publish_pci_roots,
197         .release        = _xen_pcibk_release_pci_dev,
198         .add            = _xen_pcibk_add_pci_dev,
199         .get            = _xen_pcibk_get_pci_dev,
200 };