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> 6 */ 7 8 #include <linux/list.h> 9 #include <linux/slab.h> 10 #include <linux/pci.h> 11 #include <linux/mutex.h> 12 #include "pciback.h" 13 14 #define PCI_SLOT_MAX 32 15 16 struct vpci_dev_data { 17 /* Access to dev_list must be protected by lock */ 18 struct list_head dev_list[PCI_SLOT_MAX]; 19 struct mutex lock; 20 }; 21 22 static inline struct list_head *list_first(struct list_head *head) 23 { 24 return head->next; 25 } 26 27 static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev, 28 unsigned int domain, 29 unsigned int bus, 30 unsigned int devfn) 31 { 32 struct pci_dev_entry *entry; 33 struct pci_dev *dev = NULL; 34 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 35 36 if (domain != 0 || bus != 0) 37 return NULL; 38 39 if (PCI_SLOT(devfn) < PCI_SLOT_MAX) { 40 mutex_lock(&vpci_dev->lock); 41 42 list_for_each_entry(entry, 43 &vpci_dev->dev_list[PCI_SLOT(devfn)], 44 list) { 45 if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) { 46 dev = entry->dev; 47 break; 48 } 49 } 50 51 mutex_unlock(&vpci_dev->lock); 52 } 53 return dev; 54 } 55 56 static inline int match_slot(struct pci_dev *l, struct pci_dev *r) 57 { 58 if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus) 59 && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn)) 60 return 1; 61 62 return 0; 63 } 64 65 static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, 66 struct pci_dev *dev, int devid, 67 publish_pci_dev_cb publish_cb) 68 { 69 int err = 0, slot, func = -1; 70 struct pci_dev_entry *t, *dev_entry; 71 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 72 73 if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) { 74 err = -EFAULT; 75 xenbus_dev_fatal(pdev->xdev, err, 76 "Can't export bridges on the virtual PCI bus"); 77 goto out; 78 } 79 80 dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL); 81 if (!dev_entry) { 82 err = -ENOMEM; 83 xenbus_dev_fatal(pdev->xdev, err, 84 "Error adding entry to virtual PCI bus"); 85 goto out; 86 } 87 88 dev_entry->dev = dev; 89 90 mutex_lock(&vpci_dev->lock); 91 92 /* Keep multi-function devices together on the virtual PCI bus */ 93 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 94 if (!list_empty(&vpci_dev->dev_list[slot])) { 95 t = list_entry(list_first(&vpci_dev->dev_list[slot]), 96 struct pci_dev_entry, list); 97 98 if (match_slot(dev, t->dev)) { 99 pr_info(DRV_NAME ": vpci: %s: " 100 "assign to virtual slot %d func %d\n", 101 pci_name(dev), slot, 102 PCI_FUNC(dev->devfn)); 103 list_add_tail(&dev_entry->list, 104 &vpci_dev->dev_list[slot]); 105 func = PCI_FUNC(dev->devfn); 106 goto unlock; 107 } 108 } 109 } 110 111 /* Assign to a new slot on the virtual PCI bus */ 112 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 113 if (list_empty(&vpci_dev->dev_list[slot])) { 114 printk(KERN_INFO DRV_NAME 115 ": vpci: %s: assign to virtual slot %d\n", 116 pci_name(dev), slot); 117 list_add_tail(&dev_entry->list, 118 &vpci_dev->dev_list[slot]); 119 func = PCI_FUNC(dev->devfn); 120 goto unlock; 121 } 122 } 123 124 err = -ENOMEM; 125 xenbus_dev_fatal(pdev->xdev, err, 126 "No more space on root virtual PCI bus"); 127 128 unlock: 129 mutex_unlock(&vpci_dev->lock); 130 131 /* Publish this device. */ 132 if (!err) 133 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); 134 135 out: 136 return err; 137 } 138 139 static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 140 struct pci_dev *dev) 141 { 142 int slot; 143 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 144 struct pci_dev *found_dev = NULL; 145 146 mutex_lock(&vpci_dev->lock); 147 148 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 149 struct pci_dev_entry *e; 150 151 list_for_each_entry(e, &vpci_dev->dev_list[slot], list) { 152 if (e->dev == dev) { 153 list_del(&e->list); 154 found_dev = e->dev; 155 kfree(e); 156 goto out; 157 } 158 } 159 } 160 161 out: 162 mutex_unlock(&vpci_dev->lock); 163 164 if (found_dev) 165 pcistub_put_pci_dev(found_dev); 166 } 167 168 static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 169 { 170 int slot; 171 struct vpci_dev_data *vpci_dev; 172 173 vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL); 174 if (!vpci_dev) 175 return -ENOMEM; 176 177 mutex_init(&vpci_dev->lock); 178 179 for (slot = 0; slot < PCI_SLOT_MAX; slot++) 180 INIT_LIST_HEAD(&vpci_dev->dev_list[slot]); 181 182 pdev->pci_dev_data = vpci_dev; 183 184 return 0; 185 } 186 187 static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev, 188 publish_pci_root_cb publish_cb) 189 { 190 /* The Virtual PCI bus has only one root */ 191 return publish_cb(pdev, 0, 0); 192 } 193 194 static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev) 195 { 196 int slot; 197 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 198 199 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 200 struct pci_dev_entry *e, *tmp; 201 list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot], 202 list) { 203 list_del(&e->list); 204 pcistub_put_pci_dev(e->dev); 205 kfree(e); 206 } 207 } 208 209 kfree(vpci_dev); 210 pdev->pci_dev_data = NULL; 211 } 212 213 static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev, 214 struct xen_pcibk_device *pdev, 215 unsigned int *domain, unsigned int *bus, 216 unsigned int *devfn) 217 { 218 struct pci_dev_entry *entry; 219 struct pci_dev *dev = NULL; 220 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 221 int found = 0, slot; 222 223 mutex_lock(&vpci_dev->lock); 224 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 225 list_for_each_entry(entry, 226 &vpci_dev->dev_list[slot], 227 list) { 228 dev = entry->dev; 229 if (dev && dev->bus->number == pcidev->bus->number 230 && pci_domain_nr(dev->bus) == 231 pci_domain_nr(pcidev->bus) 232 && dev->devfn == pcidev->devfn) { 233 found = 1; 234 *domain = 0; 235 *bus = 0; 236 *devfn = PCI_DEVFN(slot, 237 PCI_FUNC(pcidev->devfn)); 238 } 239 } 240 } 241 mutex_unlock(&vpci_dev->lock); 242 return found; 243 } 244 245 const struct xen_pcibk_backend xen_pcibk_vpci_backend = { 246 .name = "vpci", 247 .init = __xen_pcibk_init_devices, 248 .free = __xen_pcibk_release_devices, 249 .find = __xen_pcibk_get_pcifront_dev, 250 .publish = __xen_pcibk_publish_pci_roots, 251 .release = __xen_pcibk_release_pci_dev, 252 .add = __xen_pcibk_add_pci_dev, 253 .get = __xen_pcibk_get_pci_dev, 254 }; 255