aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/xen/Kconfig32
-rw-r--r--drivers/xen/xen-pciback/Makefile5
-rw-r--r--drivers/xen/xen-pciback/passthrough.c43
-rw-r--r--drivers/xen/xen-pciback/pciback.h94
-rw-r--r--drivers/xen/xen-pciback/vpci.c43
-rw-r--r--drivers/xen/xen-pciback/xenbus.c21
6 files changed, 166 insertions, 72 deletions
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 0b6989f92041..9b700b4a987a 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -109,34 +109,22 @@ config XEN_PCIDEV_BACKEND
109 tristate "Xen PCI-device backend driver" 109 tristate "Xen PCI-device backend driver"
110 depends on PCI && X86 && XEN 110 depends on PCI && X86 && XEN
111 depends on XEN_BACKEND 111 depends on XEN_BACKEND
112 default m
112 help 113 help
113 The PCI device backend driver allows the kernel to export arbitrary 114 The PCI device backend driver allows the kernel to export arbitrary
114 PCI devices to other guests. If you select this to be a module, you 115 PCI devices to other guests. If you select this to be a module, you
115 will need to make sure no other driver has bound to the device(s) 116 will need to make sure no other driver has bound to the device(s)
116 you want to make visible to other guests. 117 you want to make visible to other guests.
117 118
118choice 119 The parameter "passthrough" allows you specify how you want the PCI
119 prompt "PCI Backend Mode" 120 devices to appear in the guest. You can choose the default (0) where
120 depends on XEN_PCIDEV_BACKEND 121 PCI topology starts at 00.00.0, or (1) for passthrough if you want
121 122 the PCI devices topology appear the same as in the host.
122config XEN_PCIDEV_BACKEND_VPCI
123 bool "Virtual PCI"
124 help
125 This PCI Backend hides the true PCI topology and makes the frontend
126 think there is a single PCI bus with only the exported devices on it.
127 For example, a device at 03:05.0 will be re-assigned to 00:00.0. A
128 second device at 02:1a.1 will be re-assigned to 00:01.1.
129
130config XEN_PCIDEV_BACKEND_PASS
131 bool "Passthrough"
132 help
133 This PCI Backend provides a real view of the PCI topology to the
134 frontend (for example, a device at 06:01.b will still appear at
135 06:01.b to the frontend). This is similar to how Xen 2.0.x exposed
136 PCI devices to its driver domains. This may be required for drivers
137 which depend on finding their hardward in certain bus/slot
138 locations.
139 123
140endchoice 124 The "hide" parameter (only applicable if backend driver is compiled
125 into the kernel) allows you to bind the PCI devices to this module
126 from the default device drivers. The argument is the list of PCI BDFs:
127 xen-pciback.hide=(03:00.0)(04:00.0)
141 128
129 If in doubt, say m.
142endmenu 130endmenu
diff --git a/drivers/xen/xen-pciback/Makefile b/drivers/xen/xen-pciback/Makefile
index 290396766f07..ffe0ad3438bd 100644
--- a/drivers/xen/xen-pciback/Makefile
+++ b/drivers/xen/xen-pciback/Makefile
@@ -3,6 +3,5 @@ obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback.o
3xen-pciback-y := pci_stub.o pciback_ops.o xenbus.o 3xen-pciback-y := pci_stub.o pciback_ops.o xenbus.o
4xen-pciback-y += conf_space.o conf_space_header.o \ 4xen-pciback-y += conf_space.o conf_space_header.o \
5 conf_space_capability.o \ 5 conf_space_capability.o \
6 conf_space_quirks.o 6 conf_space_quirks.o vpci.o \
7xen-pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o 7 passthrough.o
8xen-pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
diff --git a/drivers/xen/xen-pciback/passthrough.c b/drivers/xen/xen-pciback/passthrough.c
index b451cb8dd2ff..1d32a9a42c01 100644
--- a/drivers/xen/xen-pciback/passthrough.c
+++ b/drivers/xen/xen-pciback/passthrough.c
@@ -16,9 +16,10 @@ struct passthrough_dev_data {
16 spinlock_t lock; 16 spinlock_t lock;
17}; 17};
18 18
19struct pci_dev *xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev, 19static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
20 unsigned int domain, unsigned int bus, 20 unsigned int domain,
21 unsigned int devfn) 21 unsigned int bus,
22 unsigned int devfn)
22{ 23{
23 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 24 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
24 struct pci_dev_entry *dev_entry; 25 struct pci_dev_entry *dev_entry;
@@ -41,8 +42,9 @@ struct pci_dev *xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
41 return dev; 42 return dev;
42} 43}
43 44
44int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, struct pci_dev *dev, 45static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
45 int devid, publish_pci_dev_cb publish_cb) 46 struct pci_dev *dev,
47 int devid, publish_pci_dev_cb publish_cb)
46{ 48{
47 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 49 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
48 struct pci_dev_entry *dev_entry; 50 struct pci_dev_entry *dev_entry;
@@ -68,8 +70,8 @@ int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, struct pci_dev *dev,
68 return err; 70 return err;
69} 71}
70 72
71void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 73static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
72 struct pci_dev *dev) 74 struct pci_dev *dev)
73{ 75{
74 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 76 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
75 struct pci_dev_entry *dev_entry, *t; 77 struct pci_dev_entry *dev_entry, *t;
@@ -92,7 +94,7 @@ void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
92 pcistub_put_pci_dev(found_dev); 94 pcistub_put_pci_dev(found_dev);
93} 95}
94 96
95int xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 97static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
96{ 98{
97 struct passthrough_dev_data *dev_data; 99 struct passthrough_dev_data *dev_data;
98 100
@@ -109,8 +111,8 @@ int xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
109 return 0; 111 return 0;
110} 112}
111 113
112int xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev, 114static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
113 publish_pci_root_cb publish_root_cb) 115 publish_pci_root_cb publish_root_cb)
114{ 116{
115 int err = 0; 117 int err = 0;
116 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 118 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
@@ -154,7 +156,7 @@ int xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
154 return err; 156 return err;
155} 157}
156 158
157void xen_pcibk_release_devices(struct xen_pcibk_device *pdev) 159static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
158{ 160{
159 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 161 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
160 struct pci_dev_entry *dev_entry, *t; 162 struct pci_dev_entry *dev_entry, *t;
@@ -169,13 +171,24 @@ void xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
169 pdev->pci_dev_data = NULL; 171 pdev->pci_dev_data = NULL;
170} 172}
171 173
172int xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev, 174static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
173 struct xen_pcibk_device *pdev, 175 struct xen_pcibk_device *pdev,
174 unsigned int *domain, unsigned int *bus, 176 unsigned int *domain, unsigned int *bus,
175 unsigned int *devfn) 177 unsigned int *devfn)
176{ 178{
177 *domain = pci_domain_nr(pcidev->bus); 179 *domain = pci_domain_nr(pcidev->bus);
178 *bus = pcidev->bus->number; 180 *bus = pcidev->bus->number;
179 *devfn = pcidev->devfn; 181 *devfn = pcidev->devfn;
180 return 1; 182 return 1;
181} 183}
184
185struct xen_pcibk_backend xen_pcibk_passthrough_backend = {
186 .name = "passthrough",
187 .init = __xen_pcibk_init_devices,
188 .free = __xen_pcibk_release_devices,
189 .find = __xen_pcibk_get_pcifront_dev,
190 .publish = __xen_pcibk_publish_pci_roots,
191 .release = __xen_pcibk_release_pci_dev,
192 .add = __xen_pcibk_add_pci_dev,
193 .get = __xen_pcibk_get_pci_dev,
194};
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
index 427b7fd01356..a0e131a81503 100644
--- a/drivers/xen/xen-pciback/pciback.h
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -83,30 +83,90 @@ typedef int (*publish_pci_dev_cb) (struct xen_pcibk_device *pdev,
83 unsigned int devfn, unsigned int devid); 83 unsigned int devfn, unsigned int devid);
84typedef int (*publish_pci_root_cb) (struct xen_pcibk_device *pdev, 84typedef int (*publish_pci_root_cb) (struct xen_pcibk_device *pdev,
85 unsigned int domain, unsigned int bus); 85 unsigned int domain, unsigned int bus);
86int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, struct pci_dev *dev,
87 int devid, publish_pci_dev_cb publish_cb);
88void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
89 struct pci_dev *dev);
90struct pci_dev *xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
91 unsigned int domain, unsigned int bus,
92 unsigned int devfn);
93 86
87/* Backend registration for the two types of BDF representation:
88 * vpci - BDFs start at 00
89 * passthrough - BDFs are exactly like in the host.
90 */
91struct xen_pcibk_backend {
92 char *name;
93 int (*init)(struct xen_pcibk_device *pdev);
94 void (*free)(struct xen_pcibk_device *pdev);
95 int (*find)(struct pci_dev *pcidev, struct xen_pcibk_device *pdev,
96 unsigned int *domain, unsigned int *bus,
97 unsigned int *devfn);
98 int (*publish)(struct xen_pcibk_device *pdev, publish_pci_root_cb cb);
99 void (*release)(struct xen_pcibk_device *pdev, struct pci_dev *dev);
100 int (*add)(struct xen_pcibk_device *pdev, struct pci_dev *dev,
101 int devid, publish_pci_dev_cb publish_cb);
102 struct pci_dev *(*get)(struct xen_pcibk_device *pdev,
103 unsigned int domain, unsigned int bus,
104 unsigned int devfn);
105};
106
107extern struct xen_pcibk_backend xen_pcibk_vpci_backend;
108extern struct xen_pcibk_backend xen_pcibk_passthrough_backend;
109extern struct xen_pcibk_backend *xen_pcibk_backend;
110
111static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
112 struct pci_dev *dev,
113 int devid,
114 publish_pci_dev_cb publish_cb)
115{
116 if (xen_pcibk_backend && xen_pcibk_backend->add)
117 return xen_pcibk_backend->add(pdev, dev, devid, publish_cb);
118 return -1;
119};
120static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
121 struct pci_dev *dev)
122{
123 if (xen_pcibk_backend && xen_pcibk_backend->free)
124 return xen_pcibk_backend->release(pdev, dev);
125};
126
127static inline struct pci_dev *
128xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev, unsigned int domain,
129 unsigned int bus, unsigned int devfn)
130{
131 if (xen_pcibk_backend && xen_pcibk_backend->get)
132 return xen_pcibk_backend->get(pdev, domain, bus, devfn);
133 return NULL;
134};
94/** 135/**
95* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in xen_pcibk 136* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in xen_pcibk
96* before sending aer request to pcifront, so that guest could identify 137* before sending aer request to pcifront, so that guest could identify
97* device, coopearte with xen_pcibk to finish aer recovery job if device driver 138* device, coopearte with xen_pcibk to finish aer recovery job if device driver
98* has the capability 139* has the capability
99*/ 140*/
100 141static inline int xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
101int xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev, 142 struct xen_pcibk_device *pdev,
102 struct xen_pcibk_device *pdev, 143 unsigned int *domain,
103 unsigned int *domain, unsigned int *bus, 144 unsigned int *bus,
104 unsigned int *devfn); 145 unsigned int *devfn)
105int xen_pcibk_init_devices(struct xen_pcibk_device *pdev); 146{
106int xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev, 147 if (xen_pcibk_backend && xen_pcibk_backend->find)
107 publish_pci_root_cb cb); 148 return xen_pcibk_backend->find(pcidev, pdev, domain, bus,
108void xen_pcibk_release_devices(struct xen_pcibk_device *pdev); 149 devfn);
109 150 return -1;
151};
152static inline int xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
153{
154 if (xen_pcibk_backend && xen_pcibk_backend->init)
155 return xen_pcibk_backend->init(pdev);
156 return -1;
157};
158static inline int xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
159 publish_pci_root_cb cb)
160{
161 if (xen_pcibk_backend && xen_pcibk_backend->publish)
162 return xen_pcibk_backend->publish(pdev, cb);
163 return -1;
164};
165static inline void xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
166{
167 if (xen_pcibk_backend && xen_pcibk_backend->free)
168 return xen_pcibk_backend->free(pdev);
169};
110/* Handles events from front-end */ 170/* Handles events from front-end */
111irqreturn_t xen_pcibk_handle_event(int irq, void *dev_id); 171irqreturn_t xen_pcibk_handle_event(int irq, void *dev_id);
112void xen_pcibk_do_op(struct work_struct *data); 172void xen_pcibk_do_op(struct work_struct *data);
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c
index 7d5c192a1505..4a42cfb0959d 100644
--- a/drivers/xen/xen-pciback/vpci.c
+++ b/drivers/xen/xen-pciback/vpci.c
@@ -25,9 +25,10 @@ static inline struct list_head *list_first(struct list_head *head)
25 return head->next; 25 return head->next;
26} 26}
27 27
28struct pci_dev *xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev, 28static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
29 unsigned int domain, unsigned int bus, 29 unsigned int domain,
30 unsigned int devfn) 30 unsigned int bus,
31 unsigned int devfn)
31{ 32{
32 struct pci_dev_entry *entry; 33 struct pci_dev_entry *entry;
33 struct pci_dev *dev = NULL; 34 struct pci_dev *dev = NULL;
@@ -63,8 +64,9 @@ static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
63 return 0; 64 return 0;
64} 65}
65 66
66int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, struct pci_dev *dev, 67static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
67 int devid, publish_pci_dev_cb publish_cb) 68 struct pci_dev *dev, int devid,
69 publish_pci_dev_cb publish_cb)
68{ 70{
69 int err = 0, slot, func = -1; 71 int err = 0, slot, func = -1;
70 struct pci_dev_entry *t, *dev_entry; 72 struct pci_dev_entry *t, *dev_entry;
@@ -137,8 +139,8 @@ out:
137 return err; 139 return err;
138} 140}
139 141
140void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 142static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
141 struct pci_dev *dev) 143 struct pci_dev *dev)
142{ 144{
143 int slot; 145 int slot;
144 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 146 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
@@ -167,7 +169,7 @@ out:
167 pcistub_put_pci_dev(found_dev); 169 pcistub_put_pci_dev(found_dev);
168} 170}
169 171
170int xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 172static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
171{ 173{
172 int slot; 174 int slot;
173 struct vpci_dev_data *vpci_dev; 175 struct vpci_dev_data *vpci_dev;
@@ -186,14 +188,14 @@ int xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
186 return 0; 188 return 0;
187} 189}
188 190
189int xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev, 191static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
190 publish_pci_root_cb publish_cb) 192 publish_pci_root_cb publish_cb)
191{ 193{
192 /* The Virtual PCI bus has only one root */ 194 /* The Virtual PCI bus has only one root */
193 return publish_cb(pdev, 0, 0); 195 return publish_cb(pdev, 0, 0);
194} 196}
195 197
196void xen_pcibk_release_devices(struct xen_pcibk_device *pdev) 198static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
197{ 199{
198 int slot; 200 int slot;
199 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 201 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
@@ -212,10 +214,10 @@ void xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
212 pdev->pci_dev_data = NULL; 214 pdev->pci_dev_data = NULL;
213} 215}
214 216
215int xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev, 217static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
216 struct xen_pcibk_device *pdev, 218 struct xen_pcibk_device *pdev,
217 unsigned int *domain, unsigned int *bus, 219 unsigned int *domain, unsigned int *bus,
218 unsigned int *devfn) 220 unsigned int *devfn)
219{ 221{
220 struct pci_dev_entry *entry; 222 struct pci_dev_entry *entry;
221 struct pci_dev *dev = NULL; 223 struct pci_dev *dev = NULL;
@@ -244,3 +246,14 @@ int xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
244 spin_unlock_irqrestore(&vpci_dev->lock, flags); 246 spin_unlock_irqrestore(&vpci_dev->lock, flags);
245 return found; 247 return found;
246} 248}
249
250struct xen_pcibk_backend xen_pcibk_vpci_backend = {
251 .name = "vpci",
252 .init = __xen_pcibk_init_devices,
253 .free = __xen_pcibk_release_devices,
254 .find = __xen_pcibk_get_pcifront_dev,
255 .publish = __xen_pcibk_publish_pci_roots,
256 .release = __xen_pcibk_release_pci_dev,
257 .add = __xen_pcibk_add_pci_dev,
258 .get = __xen_pcibk_get_pci_dev,
259};
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index 1e5ba85c0d33..206c4ce030bc 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -18,6 +18,21 @@
18#define INVALID_EVTCHN_IRQ (-1) 18#define INVALID_EVTCHN_IRQ (-1)
19struct workqueue_struct *xen_pcibk_wq; 19struct workqueue_struct *xen_pcibk_wq;
20 20
21static int __read_mostly passthrough;
22module_param(passthrough, bool, S_IRUGO);
23MODULE_PARM_DESC(passthrough,
24 "Option to specify how to export PCI topology to guest:\n"\
25 " 0 - (default) Hide the true PCI topology and makes the frontend\n"\
26 " there is a single PCI bus with only the exported devices on it.\n"\
27 " For example, a device at 03:05.0 will be re-assigned to 00:00.0\n"\
28 " while second device at 02:1a.1 will be re-assigned to 00:01.1.\n"\
29 " 1 - Passthrough provides a real view of the PCI topology to the\n"\
30 " frontend (for example, a device at 06:01.b will still appear at\n"\
31 " 06:01.b to the frontend). This is similar to how Xen 2.0.x\n"\
32 " exposed PCI devices to its driver domains. This may be required\n"\
33 " for drivers which depend on finding their hardward in certain\n"\
34 " bus/slot locations.");
35
21static struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev) 36static struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev)
22{ 37{
23 struct xen_pcibk_device *pdev; 38 struct xen_pcibk_device *pdev;
@@ -710,6 +725,8 @@ static struct xenbus_driver xenbus_xen_pcibk_driver = {
710 .otherend_changed = xen_pcibk_frontend_changed, 725 .otherend_changed = xen_pcibk_frontend_changed,
711}; 726};
712 727
728struct xen_pcibk_backend *xen_pcibk_backend;
729
713int __init xen_pcibk_xenbus_register(void) 730int __init xen_pcibk_xenbus_register(void)
714{ 731{
715 xen_pcibk_wq = create_workqueue("xen_pciback_workqueue"); 732 xen_pcibk_wq = create_workqueue("xen_pciback_workqueue");
@@ -718,6 +735,10 @@ int __init xen_pcibk_xenbus_register(void)
718 "xen_pciback_workqueue failed\n", __func__); 735 "xen_pciback_workqueue failed\n", __func__);
719 return -EFAULT; 736 return -EFAULT;
720 } 737 }
738 xen_pcibk_backend = &xen_pcibk_vpci_backend;
739 if (passthrough)
740 xen_pcibk_backend = &xen_pcibk_passthrough_backend;
741 pr_info(DRV_NAME ": backend is %s\n", xen_pcibk_backend->name);
721 return xenbus_register_backend(&xenbus_xen_pcibk_driver); 742 return xenbus_register_backend(&xenbus_xen_pcibk_driver);
722} 743}
723 744