linux/drivers/xen/xen-pciback/passthrough.c
<<
>>
Prefs
   1/*
   2 * PCI Backend - Provides restricted access to the real PCI bus topology
   3 *               to the frontend
   4 *
   5 *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
   6 */
   7
   8#include <linux/list.h>
   9#include <linux/pci.h>
  10#include <linux/mutex.h>
  11#include "pciback.h"
  12
  13struct passthrough_dev_data {
  14        /* Access to dev_list must be protected by lock */
  15        struct list_head dev_list;
  16        struct mutex lock;
  17};
  18
  19static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
  20                                               unsigned int domain,
  21                                               unsigned int bus,
  22                                               unsigned int devfn)
  23{
  24        struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
  25        struct pci_dev_entry *dev_entry;
  26        struct pci_dev *dev = NULL;
  27
  28        mutex_lock(&dev_data->lock);
  29
  30        list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
  31                if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus)
  32                    && bus == (unsigned int)dev_entry->dev->bus->number
  33                    && devfn == dev_entry->dev->devfn) {
  34                        dev = dev_entry->dev;
  35                        break;
  36                }
  37        }
  38
  39        mutex_unlock(&dev_data->lock);
  40
  41        return dev;
  42}
  43
  44static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
  45                                   struct pci_dev *dev,
  46                                   int devid, publish_pci_dev_cb publish_cb)
  47{
  48        struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
  49        struct pci_dev_entry *dev_entry;
  50        unsigned int domain, bus, devfn;
  51        int err;
  52
  53        dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
  54        if (!dev_entry)
  55                return -ENOMEM;
  56        dev_entry->dev = dev;
  57
  58        mutex_lock(&dev_data->lock);
  59        list_add_tail(&dev_entry->list, &dev_data->dev_list);
  60        mutex_unlock(&dev_data->lock);
  61
  62        /* Publish this device. */
  63        domain = (unsigned int)pci_domain_nr(dev->bus);
  64        bus = (unsigned int)dev->bus->number;
  65        devfn = dev->devfn;
  66        err = publish_cb(pdev, domain, bus, devfn, devid);
  67
  68        return err;
  69}
  70
  71static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
  72                                        struct pci_dev *dev)
  73{
  74        struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
  75        struct pci_dev_entry *dev_entry, *t;
  76        struct pci_dev *found_dev = NULL;
  77
  78        mutex_lock(&dev_data->lock);
  79
  80        list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
  81                if (dev_entry->dev == dev) {
  82                        list_del(&dev_entry->list);
  83                        found_dev = dev_entry->dev;
  84                        kfree(dev_entry);
  85                }
  86        }
  87
  88        mutex_unlock(&dev_data->lock);
  89
  90        if (found_dev)
  91                pcistub_put_pci_dev(found_dev);
  92}
  93
  94static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
  95{
  96        struct passthrough_dev_data *dev_data;
  97
  98        dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
  99        if (!dev_data)
 100                return -ENOMEM;
 101
 102        mutex_init(&dev_data->lock);
 103
 104        INIT_LIST_HEAD(&dev_data->dev_list);
 105
 106        pdev->pci_dev_data = dev_data;
 107
 108        return 0;
 109}
 110
 111static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
 112                                         publish_pci_root_cb publish_root_cb)
 113{
 114        int err = 0;
 115        struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
 116        struct pci_dev_entry *dev_entry, *e;
 117        struct pci_dev *dev;
 118        int found;
 119        unsigned int domain, bus;
 120
 121        mutex_lock(&dev_data->lock);
 122
 123        list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
 124                /* Only publish this device as a root if none of its
 125                 * parent bridges are exported
 126                 */
 127                found = 0;
 128                dev = dev_entry->dev->bus->self;
 129                for (; !found && dev != NULL; dev = dev->bus->self) {
 130                        list_for_each_entry(e, &dev_data->dev_list, list) {
 131                                if (dev == e->dev) {
 132                                        found = 1;
 133                                        break;
 134                                }
 135                        }
 136                }
 137
 138                domain = (unsigned int)pci_domain_nr(dev_entry->dev->bus);
 139                bus = (unsigned int)dev_entry->dev->bus->number;
 140
 141                if (!found) {
 142                        err = publish_root_cb(pdev, domain, bus);
 143                        if (err)
 144                                break;
 145                }
 146        }
 147
 148        mutex_unlock(&dev_data->lock);
 149
 150        return err;
 151}
 152
 153static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
 154{
 155        struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
 156        struct pci_dev_entry *dev_entry, *t;
 157
 158        list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
 159                list_del(&dev_entry->list);
 160                pcistub_put_pci_dev(dev_entry->dev);
 161                kfree(dev_entry);
 162        }
 163
 164        kfree(dev_data);
 165        pdev->pci_dev_data = NULL;
 166}
 167
 168static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
 169                                        struct xen_pcibk_device *pdev,
 170                                        unsigned int *domain, unsigned int *bus,
 171                                        unsigned int *devfn)
 172{
 173        *domain = pci_domain_nr(pcidev->bus);
 174        *bus = pcidev->bus->number;
 175        *devfn = pcidev->devfn;
 176        return 1;
 177}
 178
 179const struct xen_pcibk_backend xen_pcibk_passthrough_backend = {
 180        .name           = "passthrough",
 181        .init           = __xen_pcibk_init_devices,
 182        .free           = __xen_pcibk_release_devices,
 183        .find           = __xen_pcibk_get_pcifront_dev,
 184        .publish        = __xen_pcibk_publish_pci_roots,
 185        .release        = __xen_pcibk_release_pci_dev,
 186        .add            = __xen_pcibk_add_pci_dev,
 187        .get            = __xen_pcibk_get_pci_dev,
 188};
 189