Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
passthrough.c
Go to the documentation of this file.
1 /*
2  * PCI Backend - Provides restricted access to the real PCI bus topology
3  * to the frontend
4  *
5  * Author: Ryan Wilson <[email protected]>
6  */
7 
8 #include <linux/list.h>
9 #include <linux/pci.h>
10 #include <linux/mutex.h>
11 #include "pciback.h"
12 
14  /* Access to dev_list must be protected by lock */
16  struct mutex lock;
17 };
18 
19 static 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 {
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 
44 static 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 
71 static 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 
94 static 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 
111 static 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 
153 static 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 
168 static 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 
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 };