linux/drivers/xen/xen-pciback/vpci.c
<<
>>
Prefs
   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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9
  10#include <linux/list.h>
  11#include <linux/slab.h>
  12#include <linux/pci.h>
  13#include <linux/mutex.h>
  14#include "pciback.h"
  15
  16#define PCI_SLOT_MAX 32
  17
  18struct vpci_dev_data {
  19        /* Access to dev_list must be protected by lock */
  20        struct list_head dev_list[PCI_SLOT_MAX];
  21        struct mutex lock;
  22};
  23
  24static inline struct list_head *list_first(struct list_head *head)
  25{
  26        return head->next;
  27}
  28
  29static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
  30                                               unsigned int domain,
  31                                               unsigned int bus,
  32                                               unsigned int devfn)
  33{
  34        struct pci_dev_entry *entry;
  35        struct pci_dev *dev = NULL;
  36        struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
  37
  38        if (domain != 0 || bus != 0)
  39                return NULL;
  40
  41        if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
  42                mutex_lock(&vpci_dev->lock);
  43
  44                list_for_each_entry(entry,
  45                                    &vpci_dev->dev_list[PCI_SLOT(devfn)],
  46                                    list) {
  47                        if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
  48                                dev = entry->dev;
  49                                break;
  50                        }
  51                }
  52
  53                mutex_unlock(&vpci_dev->lock);
  54        }
  55        return dev;
  56}
  57
  58static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
  59{
  60        if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
  61            && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
  62                return 1;
  63
  64        return 0;
  65}
  66
  67static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
  68                                   struct pci_dev *dev, int devid,
  69                                   publish_pci_dev_cb publish_cb)
  70{
  71        int err = 0, slot, func = -1;
  72        struct pci_dev_entry *t, *dev_entry;
  73        struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
  74
  75        if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
  76                err = -EFAULT;
  77                xenbus_dev_fatal(pdev->xdev, err,
  78                                 "Can't export bridges on the virtual PCI bus");
  79                goto out;
  80        }
  81
  82        dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
  83        if (!dev_entry) {
  84                err = -ENOMEM;
  85                xenbus_dev_fatal(pdev->xdev, err,
  86                                 "Error adding entry to virtual PCI bus");
  87                goto out;
  88        }
  89
  90        dev_entry->dev = dev;
  91
  92        mutex_lock(&vpci_dev->lock);
  93
  94        /*
  95         * Keep multi-function devices together on the virtual PCI bus, except
  96         * virtual functions.
  97         */
  98        if (!dev->is_virtfn) {
  99                for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
 100                        if (list_empty(&vpci_dev->dev_list[slot]))
 101                                continue;
 102
 103                        t = list_entry(list_first(&vpci_dev->dev_list[slot]),
 104                                       struct pci_dev_entry, list);
 105
 106                        if (match_slot(dev, t->dev)) {
 107                                pr_info("vpci: %s: assign to virtual slot %d func %d\n",
 108                                        pci_name(dev), slot,
 109                                        PCI_FUNC(dev->devfn));
 110                                list_add_tail(&dev_entry->list,
 111                                              &vpci_dev->dev_list[slot]);
 112                                func = PCI_FUNC(dev->devfn);
 113                                goto unlock;
 114                        }
 115                }
 116        }
 117
 118        /* Assign to a new slot on the virtual PCI bus */
 119        for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
 120                if (list_empty(&vpci_dev->dev_list[slot])) {
 121                        pr_info("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
 134unlock:
 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
 141out:
 142        return err;
 143}
 144
 145static 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
 167out:
 168        mutex_unlock(&vpci_dev->lock);
 169
 170        if (found_dev)
 171                pcistub_put_pci_dev(found_dev);
 172}
 173
 174static 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
 193static 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
 200static 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
 219static 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
 251const 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