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 /* 93 * Keep multi-function devices together on the virtual PCI bus, except 94 * virtual functions. 95 */ 96 if (!dev->is_virtfn) { 97 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 98 if (list_empty(&vpci_dev->dev_list[slot])) 99 continue; 100 101 t = list_entry(list_first(&vpci_dev->dev_list[slot]), 102 struct pci_dev_entry, list); 103 104 if (match_slot(dev, t->dev)) { 105 pr_info(DRV_NAME ": vpci: %s: " 106 "assign to virtual slot %d func %d\n", 107 pci_name(dev), slot, 108 PCI_FUNC(dev->devfn)); 109 list_add_tail(&dev_entry->list, 110 &vpci_dev->dev_list[slot]); 111 func = PCI_FUNC(dev->devfn); 112 goto unlock; 113 } 114 } 115 } 116 117 /* Assign to a new slot on the virtual PCI bus */ 118 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 119 if (list_empty(&vpci_dev->dev_list[slot])) { 120 printk(KERN_INFO DRV_NAME 121 ": vpci: %s: assign to virtual slot %d\n", 122 pci_name(dev), slot); 123 list_add_tail(&dev_entry->list, 124 &vpci_dev->dev_list[slot]); 125 func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn); 126 goto unlock; 127 } 128 } 129 130 err = -ENOMEM; 131 xenbus_dev_fatal(pdev->xdev, err, 132 "No more space on root virtual PCI bus"); 133 134 unlock: 135 mutex_unlock(&vpci_dev->lock); 136 137 /* Publish this device. */ 138 if (!err) 139 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); 140 141 out: 142 return err; 143 } 144 145 static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 146 struct pci_dev *dev) 147 { 148 int slot; 149 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 150 struct pci_dev *found_dev = NULL; 151 152 mutex_lock(&vpci_dev->lock); 153 154 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 155 struct pci_dev_entry *e; 156 157 list_for_each_entry(e, &vpci_dev->dev_list[slot], list) { 158 if (e->dev == dev) { 159 list_del(&e->list); 160 found_dev = e->dev; 161 kfree(e); 162 goto out; 163 } 164 } 165 } 166 167 out: 168 mutex_unlock(&vpci_dev->lock); 169 170 if (found_dev) 171 pcistub_put_pci_dev(found_dev); 172 } 173 174 static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 175 { 176 int slot; 177 struct vpci_dev_data *vpci_dev; 178 179 vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL); 180 if (!vpci_dev) 181 return -ENOMEM; 182 183 mutex_init(&vpci_dev->lock); 184 185 for (slot = 0; slot < PCI_SLOT_MAX; slot++) 186 INIT_LIST_HEAD(&vpci_dev->dev_list[slot]); 187 188 pdev->pci_dev_data = vpci_dev; 189 190 return 0; 191 } 192 193 static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev, 194 publish_pci_root_cb publish_cb) 195 { 196 /* The Virtual PCI bus has only one root */ 197 return publish_cb(pdev, 0, 0); 198 } 199 200 static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev) 201 { 202 int slot; 203 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 204 205 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 206 struct pci_dev_entry *e, *tmp; 207 list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot], 208 list) { 209 list_del(&e->list); 210 pcistub_put_pci_dev(e->dev); 211 kfree(e); 212 } 213 } 214 215 kfree(vpci_dev); 216 pdev->pci_dev_data = NULL; 217 } 218 219 static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev, 220 struct xen_pcibk_device *pdev, 221 unsigned int *domain, unsigned int *bus, 222 unsigned int *devfn) 223 { 224 struct pci_dev_entry *entry; 225 struct pci_dev *dev = NULL; 226 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 227 int found = 0, slot; 228 229 mutex_lock(&vpci_dev->lock); 230 for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 231 list_for_each_entry(entry, 232 &vpci_dev->dev_list[slot], 233 list) { 234 dev = entry->dev; 235 if (dev && dev->bus->number == pcidev->bus->number 236 && pci_domain_nr(dev->bus) == 237 pci_domain_nr(pcidev->bus) 238 && dev->devfn == pcidev->devfn) { 239 found = 1; 240 *domain = 0; 241 *bus = 0; 242 *devfn = PCI_DEVFN(slot, 243 PCI_FUNC(pcidev->devfn)); 244 } 245 } 246 } 247 mutex_unlock(&vpci_dev->lock); 248 return found; 249 } 250 251 const struct xen_pcibk_backend xen_pcibk_vpci_backend = { 252 .name = "vpci", 253 .init = __xen_pcibk_init_devices, 254 .free = __xen_pcibk_release_devices, 255 .find = __xen_pcibk_get_pcifront_dev, 256 .publish = __xen_pcibk_publish_pci_roots, 257 .release = __xen_pcibk_release_pci_dev, 258 .add = __xen_pcibk_add_pci_dev, 259 .get = __xen_pcibk_get_pci_dev, 260 }; 261