2 * PCI Backend - Provides a Virtual PCI bus (with real devices)
5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c)
6 * Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
9 #include <linux/list.h>
10 #include <linux/slab.h>
11 #include <linux/pci.h>
12 #include <linux/spinlock.h>
15 /* There are at most 32 slots in a pci bus. */
16 #define PCI_SLOT_MAX 32
20 struct slot_dev_data {
21 /* Access to dev_list must be protected by lock */
22 struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
26 struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
27 unsigned int domain, unsigned int bus,
30 struct pci_dev *dev = NULL;
31 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
34 if (domain != 0 || PCI_FUNC(devfn) != 0)
37 if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
40 spin_lock_irqsave(&slot_dev->lock, flags);
41 dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
42 spin_unlock_irqrestore(&slot_dev->lock, flags);
47 int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
49 int err = 0, slot, bus;
50 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
53 if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
55 xenbus_dev_fatal(pdev->xdev, err,
56 "Can't export bridges on the virtual PCI bus");
60 spin_lock_irqsave(&slot_dev->lock, flags);
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) {
67 "pciback: slot: %s: assign to virtual slot %d, bus %d\n",
68 pci_name(dev), slot, bus);
69 slot_dev->slots[bus][slot] = dev;
75 xenbus_dev_fatal(pdev->xdev, err,
76 "No more space on root virtual PCI bus");
79 spin_unlock_irqrestore(&slot_dev->lock, flags);
84 void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
87 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
88 struct pci_dev *found_dev = NULL;
91 spin_lock_irqsave(&slot_dev->lock, flags);
93 for (bus = 0; bus < PCI_BUS_NBR; bus++)
94 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
95 if (slot_dev->slots[bus][slot] == dev) {
96 slot_dev->slots[bus][slot] = NULL;
103 spin_unlock_irqrestore(&slot_dev->lock, flags);
106 pcistub_put_pci_dev(found_dev);
109 int pciback_init_devices(struct pciback_device *pdev)
112 struct slot_dev_data *slot_dev;
114 slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
118 spin_lock_init(&slot_dev->lock);
120 for (bus = 0; bus < PCI_BUS_NBR; bus++)
121 for (slot = 0; slot < PCI_SLOT_MAX; slot++)
122 slot_dev->slots[bus][slot] = NULL;
124 pdev->pci_dev_data = slot_dev;
129 int pciback_publish_pci_roots(struct pciback_device *pdev,
130 publish_pci_root_cb publish_cb)
132 /* The Virtual PCI bus has only one root */
133 return publish_cb(pdev, 0, 0);
136 void pciback_release_devices(struct pciback_device *pdev)
139 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
142 for (bus = 0; bus < PCI_BUS_NBR; bus++)
143 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
144 dev = slot_dev->slots[bus][slot];
146 pcistub_put_pci_dev(dev);
150 pdev->pci_dev_data = NULL;