2 * PCI Backend - Provides restricted access to the real PCI bus topology
5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
8 #include <linux/list.h>
10 #include <linux/mutex.h>
13 struct passthrough_dev_data
{
14 /* Access to dev_list must be protected by lock */
15 struct list_head dev_list
;
19 static struct pci_dev
*__xen_pcibk_get_pci_dev(struct xen_pcibk_device
*pdev
,
24 struct passthrough_dev_data
*dev_data
= pdev
->pci_dev_data
;
25 struct pci_dev_entry
*dev_entry
;
26 struct pci_dev
*dev
= NULL
;
28 mutex_lock(&dev_data
->lock
);
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
) {
39 mutex_unlock(&dev_data
->lock
);
44 static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device
*pdev
,
46 int devid
, publish_pci_dev_cb publish_cb
)
48 struct passthrough_dev_data
*dev_data
= pdev
->pci_dev_data
;
49 struct pci_dev_entry
*dev_entry
;
50 unsigned int domain
, bus
, devfn
;
53 dev_entry
= kmalloc(sizeof(*dev_entry
), GFP_KERNEL
);
58 mutex_lock(&dev_data
->lock
);
59 list_add_tail(&dev_entry
->list
, &dev_data
->dev_list
);
60 mutex_unlock(&dev_data
->lock
);
62 /* Publish this device. */
63 domain
= (unsigned int)pci_domain_nr(dev
->bus
);
64 bus
= (unsigned int)dev
->bus
->number
;
66 err
= publish_cb(pdev
, domain
, bus
, devfn
, devid
);
71 static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device
*pdev
,
72 struct pci_dev
*dev
, bool lock
)
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
;
78 mutex_lock(&dev_data
->lock
);
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
;
88 mutex_unlock(&dev_data
->lock
);
92 device_lock(&found_dev
->dev
);
93 pcistub_put_pci_dev(found_dev
);
95 device_unlock(&found_dev
->dev
);
99 static int __xen_pcibk_init_devices(struct xen_pcibk_device
*pdev
)
101 struct passthrough_dev_data
*dev_data
;
103 dev_data
= kmalloc(sizeof(*dev_data
), GFP_KERNEL
);
107 mutex_init(&dev_data
->lock
);
109 INIT_LIST_HEAD(&dev_data
->dev_list
);
111 pdev
->pci_dev_data
= dev_data
;
116 static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device
*pdev
,
117 publish_pci_root_cb publish_root_cb
)
120 struct passthrough_dev_data
*dev_data
= pdev
->pci_dev_data
;
121 struct pci_dev_entry
*dev_entry
, *e
;
124 unsigned int domain
, bus
;
126 mutex_lock(&dev_data
->lock
);
128 list_for_each_entry(dev_entry
, &dev_data
->dev_list
, list
) {
129 /* Only publish this device as a root if none of its
130 * parent bridges are exported
133 dev
= dev_entry
->dev
->bus
->self
;
134 for (; !found
&& dev
!= NULL
; dev
= dev
->bus
->self
) {
135 list_for_each_entry(e
, &dev_data
->dev_list
, list
) {
143 domain
= (unsigned int)pci_domain_nr(dev_entry
->dev
->bus
);
144 bus
= (unsigned int)dev_entry
->dev
->bus
->number
;
147 err
= publish_root_cb(pdev
, domain
, bus
);
153 mutex_unlock(&dev_data
->lock
);
158 static void __xen_pcibk_release_devices(struct xen_pcibk_device
*pdev
)
160 struct passthrough_dev_data
*dev_data
= pdev
->pci_dev_data
;
161 struct pci_dev_entry
*dev_entry
, *t
;
163 list_for_each_entry_safe(dev_entry
, t
, &dev_data
->dev_list
, list
) {
164 struct pci_dev
*dev
= dev_entry
->dev
;
165 list_del(&dev_entry
->list
);
166 device_lock(&dev
->dev
);
167 pcistub_put_pci_dev(dev
);
168 device_unlock(&dev
->dev
);
173 pdev
->pci_dev_data
= NULL
;
176 static int __xen_pcibk_get_pcifront_dev(struct pci_dev
*pcidev
,
177 struct xen_pcibk_device
*pdev
,
178 unsigned int *domain
, unsigned int *bus
,
181 *domain
= pci_domain_nr(pcidev
->bus
);
182 *bus
= pcidev
->bus
->number
;
183 *devfn
= pcidev
->devfn
;
187 const struct xen_pcibk_backend xen_pcibk_passthrough_backend
= {
188 .name
= "passthrough",
189 .init
= __xen_pcibk_init_devices
,
190 .free
= __xen_pcibk_release_devices
,
191 .find
= __xen_pcibk_get_pcifront_dev
,
192 .publish
= __xen_pcibk_publish_pci_roots
,
193 .release
= __xen_pcibk_release_pci_dev
,
194 .add
= __xen_pcibk_add_pci_dev
,
195 .get
= __xen_pcibk_get_pci_dev
,