aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xen-pciback
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2009-10-13 17:22:20 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-07-19 20:58:01 -0400
commit30edc14bf39afde24ef7db2de66c91805db80828 (patch)
tree1cf5b6f28a3ea4159a09bcef9d11be6d427e3558 /drivers/xen/xen-pciback
parent56299378726d5f2ba8d3c8cbbd13cb280ba45e4f (diff)
xen/pciback: xen pci backend driver.
This is the host side counterpart to the frontend driver in drivers/pci/xen-pcifront.c. The PV protocol is also implemented by frontend drivers in other OSes too, such as the BSDs. The PV protocol is rather simple. There is page shared with the guest, which has the 'struct xen_pci_sharedinfo' embossed in it. The backend has a thread that is kicked every-time the structure is changed and based on the operation field it performs specific tasks: XEN_PCI_OP_conf_[read|write]: Read/Write 0xCF8/0xCFC filtered data. (conf_space*.c) Based on which field is probed, we either enable/disable the PCI device, change power state, read VPD, etc. The major goal of this call is to provide a Physical IRQ (PIRQ) to the guest. The PIRQ is Xen hypervisor global IRQ value irrespective of the IRQ is tied in to the IO-APIC, or is a vector. For GSI type interrupts, the PIRQ==GSI holds. For MSI/MSI-X the PIRQ value != Linux IRQ number (thought PIRQ==vector). Please note, that with Xen, all interrupts (except those level shared ones) are injected directly to the guest - there is no host interaction. XEN_PCI_OP_[enable|disable]_msi[|x] (pciback_ops.c) Enables/disables the MSI/MSI-X capability of the device. These operations setup the MSI/MSI-X vectors for the guest and pass them to the frontend. When the device is activated, the interrupts are directly injected in the guest without involving the host. XEN_PCI_OP_aer_[detected|resume|mmio|slotreset]: In case of failure, perform the appropriate AER commands on the guest. Right now that is a cop-out - we just kill the guest. Besides implementing those commands, it can also - hide a PCI device from the host. When booting up, the user can specify xen-pciback.hide=(1:0:0)(BDF..) so that host does not try to use the device. The driver was lifted from linux-2.6.18.hg tree and fixed up so that it could compile under v3.0. Per suggestion from Jesse Barnes moved the driver to drivers/xen/xen-pciback. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'drivers/xen/xen-pciback')
-rw-r--r--drivers/xen/xen-pciback/Makefile17
-rw-r--r--drivers/xen/xen-pciback/conf_space.c435
-rw-r--r--drivers/xen/xen-pciback/conf_space.h126
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability.c66
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability.h26
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability_msi.c94
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability_pm.c113
-rw-r--r--drivers/xen/xen-pciback/conf_space_capability_vpd.c40
-rw-r--r--drivers/xen/xen-pciback/conf_space_header.c318
-rw-r--r--drivers/xen/xen-pciback/conf_space_quirks.c140
-rw-r--r--drivers/xen/xen-pciback/conf_space_quirks.h35
-rw-r--r--drivers/xen/xen-pciback/controller.c442
-rw-r--r--drivers/xen/xen-pciback/passthrough.c178
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c1285
-rw-r--r--drivers/xen/xen-pciback/pciback.h133
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c131
-rw-r--r--drivers/xen/xen-pciback/slot.c191
-rw-r--r--drivers/xen/xen-pciback/vpci.c244
-rw-r--r--drivers/xen/xen-pciback/xenbus.c709
19 files changed, 4723 insertions, 0 deletions
diff --git a/drivers/xen/xen-pciback/Makefile b/drivers/xen/xen-pciback/Makefile
new file mode 100644
index 000000000000..106dae748cdb
--- /dev/null
+++ b/drivers/xen/xen-pciback/Makefile
@@ -0,0 +1,17 @@
1obj-$(CONFIG_XEN_PCIDEV_BACKEND) += pciback.o
2
3pciback-y := pci_stub.o pciback_ops.o xenbus.o
4pciback-y += conf_space.o conf_space_header.o \
5 conf_space_capability.o \
6 conf_space_capability_vpd.o \
7 conf_space_capability_pm.o \
8 conf_space_quirks.o
9pciback-$(CONFIG_PCI_MSI) += conf_space_capability_msi.o
10pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
11pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o
12pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
13pciback-$(CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER) += controller.o
14
15ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
16EXTRA_CFLAGS += -DDEBUG
17endif
diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c
new file mode 100644
index 000000000000..370c18e58d7a
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space.c
@@ -0,0 +1,435 @@
1/*
2 * PCI Backend - Functions for creating a virtual configuration space for
3 * exported PCI Devices.
4 * It's dangerous to allow PCI Driver Domains to change their
5 * device's resources (memory, i/o ports, interrupts). We need to
6 * restrict changes to certain PCI Configuration registers:
7 * BARs, INTERRUPT_PIN, most registers in the header...
8 *
9 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
10 */
11
12#include <linux/kernel.h>
13#include <linux/pci.h>
14#include "pciback.h"
15#include "conf_space.h"
16#include "conf_space_quirks.h"
17
18static int permissive;
19module_param(permissive, bool, 0644);
20
21#define DEFINE_PCI_CONFIG(op, size, type) \
22int pciback_##op##_config_##size \
23(struct pci_dev *dev, int offset, type value, void *data) \
24{ \
25 return pci_##op##_config_##size(dev, offset, value); \
26}
27
28DEFINE_PCI_CONFIG(read, byte, u8 *)
29DEFINE_PCI_CONFIG(read, word, u16 *)
30DEFINE_PCI_CONFIG(read, dword, u32 *)
31
32DEFINE_PCI_CONFIG(write, byte, u8)
33DEFINE_PCI_CONFIG(write, word, u16)
34DEFINE_PCI_CONFIG(write, dword, u32)
35
36static int conf_space_read(struct pci_dev *dev,
37 const struct config_field_entry *entry,
38 int offset, u32 *value)
39{
40 int ret = 0;
41 const struct config_field *field = entry->field;
42
43 *value = 0;
44
45 switch (field->size) {
46 case 1:
47 if (field->u.b.read)
48 ret = field->u.b.read(dev, offset, (u8 *) value,
49 entry->data);
50 break;
51 case 2:
52 if (field->u.w.read)
53 ret = field->u.w.read(dev, offset, (u16 *) value,
54 entry->data);
55 break;
56 case 4:
57 if (field->u.dw.read)
58 ret = field->u.dw.read(dev, offset, value, entry->data);
59 break;
60 }
61 return ret;
62}
63
64static int conf_space_write(struct pci_dev *dev,
65 const struct config_field_entry *entry,
66 int offset, u32 value)
67{
68 int ret = 0;
69 const struct config_field *field = entry->field;
70
71 switch (field->size) {
72 case 1:
73 if (field->u.b.write)
74 ret = field->u.b.write(dev, offset, (u8) value,
75 entry->data);
76 break;
77 case 2:
78 if (field->u.w.write)
79 ret = field->u.w.write(dev, offset, (u16) value,
80 entry->data);
81 break;
82 case 4:
83 if (field->u.dw.write)
84 ret = field->u.dw.write(dev, offset, value,
85 entry->data);
86 break;
87 }
88 return ret;
89}
90
91static inline u32 get_mask(int size)
92{
93 if (size == 1)
94 return 0xff;
95 else if (size == 2)
96 return 0xffff;
97 else
98 return 0xffffffff;
99}
100
101static inline int valid_request(int offset, int size)
102{
103 /* Validate request (no un-aligned requests) */
104 if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
105 return 1;
106 return 0;
107}
108
109static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
110 int offset)
111{
112 if (offset >= 0) {
113 new_val_mask <<= (offset * 8);
114 new_val <<= (offset * 8);
115 } else {
116 new_val_mask >>= (offset * -8);
117 new_val >>= (offset * -8);
118 }
119 val = (val & ~new_val_mask) | (new_val & new_val_mask);
120
121 return val;
122}
123
124static int pcibios_err_to_errno(int err)
125{
126 switch (err) {
127 case PCIBIOS_SUCCESSFUL:
128 return XEN_PCI_ERR_success;
129 case PCIBIOS_DEVICE_NOT_FOUND:
130 return XEN_PCI_ERR_dev_not_found;
131 case PCIBIOS_BAD_REGISTER_NUMBER:
132 return XEN_PCI_ERR_invalid_offset;
133 case PCIBIOS_FUNC_NOT_SUPPORTED:
134 return XEN_PCI_ERR_not_implemented;
135 case PCIBIOS_SET_FAILED:
136 return XEN_PCI_ERR_access_denied;
137 }
138 return err;
139}
140
141int pciback_config_read(struct pci_dev *dev, int offset, int size,
142 u32 *ret_val)
143{
144 int err = 0;
145 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
146 const struct config_field_entry *cfg_entry;
147 const struct config_field *field;
148 int req_start, req_end, field_start, field_end;
149 /* if read fails for any reason, return 0
150 * (as if device didn't respond) */
151 u32 value = 0, tmp_val;
152
153 if (unlikely(verbose_request))
154 printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x\n",
155 pci_name(dev), size, offset);
156
157 if (!valid_request(offset, size)) {
158 err = XEN_PCI_ERR_invalid_offset;
159 goto out;
160 }
161
162 /* Get the real value first, then modify as appropriate */
163 switch (size) {
164 case 1:
165 err = pci_read_config_byte(dev, offset, (u8 *) &value);
166 break;
167 case 2:
168 err = pci_read_config_word(dev, offset, (u16 *) &value);
169 break;
170 case 4:
171 err = pci_read_config_dword(dev, offset, &value);
172 break;
173 }
174
175 list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
176 field = cfg_entry->field;
177
178 req_start = offset;
179 req_end = offset + size;
180 field_start = OFFSET(cfg_entry);
181 field_end = OFFSET(cfg_entry) + field->size;
182
183 if ((req_start >= field_start && req_start < field_end)
184 || (req_end > field_start && req_end <= field_end)) {
185 err = conf_space_read(dev, cfg_entry, field_start,
186 &tmp_val);
187 if (err)
188 goto out;
189
190 value = merge_value(value, tmp_val,
191 get_mask(field->size),
192 field_start - req_start);
193 }
194 }
195
196out:
197 if (unlikely(verbose_request))
198 printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x = %x\n",
199 pci_name(dev), size, offset, value);
200
201 *ret_val = value;
202 return pcibios_err_to_errno(err);
203}
204
205int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
206{
207 int err = 0, handled = 0;
208 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
209 const struct config_field_entry *cfg_entry;
210 const struct config_field *field;
211 u32 tmp_val;
212 int req_start, req_end, field_start, field_end;
213
214 if (unlikely(verbose_request))
215 printk(KERN_DEBUG
216 "pciback: %s: write request %d bytes at 0x%x = %x\n",
217 pci_name(dev), size, offset, value);
218
219 if (!valid_request(offset, size))
220 return XEN_PCI_ERR_invalid_offset;
221
222 list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
223 field = cfg_entry->field;
224
225 req_start = offset;
226 req_end = offset + size;
227 field_start = OFFSET(cfg_entry);
228 field_end = OFFSET(cfg_entry) + field->size;
229
230 if ((req_start >= field_start && req_start < field_end)
231 || (req_end > field_start && req_end <= field_end)) {
232 tmp_val = 0;
233
234 err = pciback_config_read(dev, field_start,
235 field->size, &tmp_val);
236 if (err)
237 break;
238
239 tmp_val = merge_value(tmp_val, value, get_mask(size),
240 req_start - field_start);
241
242 err = conf_space_write(dev, cfg_entry, field_start,
243 tmp_val);
244
245 /* handled is set true here, but not every byte
246 * may have been written! Properly detecting if
247 * every byte is handled is unnecessary as the
248 * flag is used to detect devices that need
249 * special helpers to work correctly.
250 */
251 handled = 1;
252 }
253 }
254
255 if (!handled && !err) {
256 /* By default, anything not specificially handled above is
257 * read-only. The permissive flag changes this behavior so
258 * that anything not specifically handled above is writable.
259 * This means that some fields may still be read-only because
260 * they have entries in the config_field list that intercept
261 * the write and do nothing. */
262 if (dev_data->permissive || permissive) {
263 switch (size) {
264 case 1:
265 err = pci_write_config_byte(dev, offset,
266 (u8) value);
267 break;
268 case 2:
269 err = pci_write_config_word(dev, offset,
270 (u16) value);
271 break;
272 case 4:
273 err = pci_write_config_dword(dev, offset,
274 (u32) value);
275 break;
276 }
277 } else if (!dev_data->warned_on_write) {
278 dev_data->warned_on_write = 1;
279 dev_warn(&dev->dev, "Driver tried to write to a "
280 "read-only configuration space field at offset"
281 " 0x%x, size %d. This may be harmless, but if "
282 "you have problems with your device:\n"
283 "1) see permissive attribute in sysfs\n"
284 "2) report problems to the xen-devel "
285 "mailing list along with details of your "
286 "device obtained from lspci.\n", offset, size);
287 }
288 }
289
290 return pcibios_err_to_errno(err);
291}
292
293void pciback_config_free_dyn_fields(struct pci_dev *dev)
294{
295 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
296 struct config_field_entry *cfg_entry, *t;
297 const struct config_field *field;
298
299 dev_dbg(&dev->dev, "free-ing dynamically allocated virtual "
300 "configuration space fields\n");
301 if (!dev_data)
302 return;
303
304 list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
305 field = cfg_entry->field;
306
307 if (field->clean) {
308 field->clean((struct config_field *)field);
309
310 kfree(cfg_entry->data);
311
312 list_del(&cfg_entry->list);
313 kfree(cfg_entry);
314 }
315
316 }
317}
318
319void pciback_config_reset_dev(struct pci_dev *dev)
320{
321 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
322 const struct config_field_entry *cfg_entry;
323 const struct config_field *field;
324
325 dev_dbg(&dev->dev, "resetting virtual configuration space\n");
326 if (!dev_data)
327 return;
328
329 list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
330 field = cfg_entry->field;
331
332 if (field->reset)
333 field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
334 }
335}
336
337void pciback_config_free_dev(struct pci_dev *dev)
338{
339 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
340 struct config_field_entry *cfg_entry, *t;
341 const struct config_field *field;
342
343 dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
344 if (!dev_data)
345 return;
346
347 list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
348 list_del(&cfg_entry->list);
349
350 field = cfg_entry->field;
351
352 if (field->release)
353 field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
354
355 kfree(cfg_entry);
356 }
357}
358
359int pciback_config_add_field_offset(struct pci_dev *dev,
360 const struct config_field *field,
361 unsigned int base_offset)
362{
363 int err = 0;
364 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
365 struct config_field_entry *cfg_entry;
366 void *tmp;
367
368 cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
369 if (!cfg_entry) {
370 err = -ENOMEM;
371 goto out;
372 }
373
374 cfg_entry->data = NULL;
375 cfg_entry->field = field;
376 cfg_entry->base_offset = base_offset;
377
378 /* silently ignore duplicate fields */
379 err = pciback_field_is_dup(dev, OFFSET(cfg_entry));
380 if (err)
381 goto out;
382
383 if (field->init) {
384 tmp = field->init(dev, OFFSET(cfg_entry));
385
386 if (IS_ERR(tmp)) {
387 err = PTR_ERR(tmp);
388 goto out;
389 }
390
391 cfg_entry->data = tmp;
392 }
393
394 dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
395 OFFSET(cfg_entry));
396 list_add_tail(&cfg_entry->list, &dev_data->config_fields);
397
398out:
399 if (err)
400 kfree(cfg_entry);
401
402 return err;
403}
404
405/* This sets up the device's virtual configuration space to keep track of
406 * certain registers (like the base address registers (BARs) so that we can
407 * keep the client from manipulating them directly.
408 */
409int pciback_config_init_dev(struct pci_dev *dev)
410{
411 int err = 0;
412 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
413
414 dev_dbg(&dev->dev, "initializing virtual configuration space\n");
415
416 INIT_LIST_HEAD(&dev_data->config_fields);
417
418 err = pciback_config_header_add_fields(dev);
419 if (err)
420 goto out;
421
422 err = pciback_config_capability_add_fields(dev);
423 if (err)
424 goto out;
425
426 err = pciback_config_quirks_init(dev);
427
428out:
429 return err;
430}
431
432int pciback_config_init(void)
433{
434 return pciback_config_capability_init();
435}
diff --git a/drivers/xen/xen-pciback/conf_space.h b/drivers/xen/xen-pciback/conf_space.h
new file mode 100644
index 000000000000..50ebef216828
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space.h
@@ -0,0 +1,126 @@
1/*
2 * PCI Backend - Common data structures for overriding the configuration space
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6
7#ifndef __XEN_PCIBACK_CONF_SPACE_H__
8#define __XEN_PCIBACK_CONF_SPACE_H__
9
10#include <linux/list.h>
11#include <linux/err.h>
12
13/* conf_field_init can return an errno in a ptr with ERR_PTR() */
14typedef void *(*conf_field_init) (struct pci_dev *dev, int offset);
15typedef void (*conf_field_reset) (struct pci_dev *dev, int offset, void *data);
16typedef void (*conf_field_free) (struct pci_dev *dev, int offset, void *data);
17
18typedef int (*conf_dword_write) (struct pci_dev *dev, int offset, u32 value,
19 void *data);
20typedef int (*conf_word_write) (struct pci_dev *dev, int offset, u16 value,
21 void *data);
22typedef int (*conf_byte_write) (struct pci_dev *dev, int offset, u8 value,
23 void *data);
24typedef int (*conf_dword_read) (struct pci_dev *dev, int offset, u32 *value,
25 void *data);
26typedef int (*conf_word_read) (struct pci_dev *dev, int offset, u16 *value,
27 void *data);
28typedef int (*conf_byte_read) (struct pci_dev *dev, int offset, u8 *value,
29 void *data);
30
31/* These are the fields within the configuration space which we
32 * are interested in intercepting reads/writes to and changing their
33 * values.
34 */
35struct config_field {
36 unsigned int offset;
37 unsigned int size;
38 unsigned int mask;
39 conf_field_init init;
40 conf_field_reset reset;
41 conf_field_free release;
42 void (*clean) (struct config_field *field);
43 union {
44 struct {
45 conf_dword_write write;
46 conf_dword_read read;
47 } dw;
48 struct {
49 conf_word_write write;
50 conf_word_read read;
51 } w;
52 struct {
53 conf_byte_write write;
54 conf_byte_read read;
55 } b;
56 } u;
57 struct list_head list;
58};
59
60struct config_field_entry {
61 struct list_head list;
62 const struct config_field *field;
63 unsigned int base_offset;
64 void *data;
65};
66
67#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
68
69/* Add fields to a device - the add_fields macro expects to get a pointer to
70 * the first entry in an array (of which the ending is marked by size==0)
71 */
72int pciback_config_add_field_offset(struct pci_dev *dev,
73 const struct config_field *field,
74 unsigned int offset);
75
76static inline int pciback_config_add_field(struct pci_dev *dev,
77 const struct config_field *field)
78{
79 return pciback_config_add_field_offset(dev, field, 0);
80}
81
82static inline int pciback_config_add_fields(struct pci_dev *dev,
83 const struct config_field *field)
84{
85 int i, err = 0;
86 for (i = 0; field[i].size != 0; i++) {
87 err = pciback_config_add_field(dev, &field[i]);
88 if (err)
89 break;
90 }
91 return err;
92}
93
94static inline int pciback_config_add_fields_offset(struct pci_dev *dev,
95 const struct config_field *field,
96 unsigned int offset)
97{
98 int i, err = 0;
99 for (i = 0; field[i].size != 0; i++) {
100 err = pciback_config_add_field_offset(dev, &field[i], offset);
101 if (err)
102 break;
103 }
104 return err;
105}
106
107/* Read/Write the real configuration space */
108int pciback_read_config_byte(struct pci_dev *dev, int offset, u8 *value,
109 void *data);
110int pciback_read_config_word(struct pci_dev *dev, int offset, u16 *value,
111 void *data);
112int pciback_read_config_dword(struct pci_dev *dev, int offset, u32 *value,
113 void *data);
114int pciback_write_config_byte(struct pci_dev *dev, int offset, u8 value,
115 void *data);
116int pciback_write_config_word(struct pci_dev *dev, int offset, u16 value,
117 void *data);
118int pciback_write_config_dword(struct pci_dev *dev, int offset, u32 value,
119 void *data);
120
121int pciback_config_capability_init(void);
122
123int pciback_config_header_add_fields(struct pci_dev *dev);
124int pciback_config_capability_add_fields(struct pci_dev *dev);
125
126#endif /* __XEN_PCIBACK_CONF_SPACE_H__ */
diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c
new file mode 100644
index 000000000000..0ea84d6335f4
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_capability.c
@@ -0,0 +1,66 @@
1/*
2 * PCI Backend - Handles the virtual fields found on the capability lists
3 * in the configuration space.
4 *
5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
6 */
7
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include "pciback.h"
11#include "conf_space.h"
12#include "conf_space_capability.h"
13
14static LIST_HEAD(capabilities);
15
16static const struct config_field caplist_header[] = {
17 {
18 .offset = PCI_CAP_LIST_ID,
19 .size = 2, /* encompass PCI_CAP_LIST_ID & PCI_CAP_LIST_NEXT */
20 .u.w.read = pciback_read_config_word,
21 .u.w.write = NULL,
22 },
23 {}
24};
25
26static inline void register_capability(struct pciback_config_capability *cap)
27{
28 list_add_tail(&cap->cap_list, &capabilities);
29}
30
31int pciback_config_capability_add_fields(struct pci_dev *dev)
32{
33 int err = 0;
34 struct pciback_config_capability *cap;
35 int cap_offset;
36
37 list_for_each_entry(cap, &capabilities, cap_list) {
38 cap_offset = pci_find_capability(dev, cap->capability);
39 if (cap_offset) {
40 dev_dbg(&dev->dev, "Found capability 0x%x at 0x%x\n",
41 cap->capability, cap_offset);
42
43 err = pciback_config_add_fields_offset(dev,
44 caplist_header,
45 cap_offset);
46 if (err)
47 goto out;
48 err = pciback_config_add_fields_offset(dev,
49 cap->fields,
50 cap_offset);
51 if (err)
52 goto out;
53 }
54 }
55
56out:
57 return err;
58}
59
60int pciback_config_capability_init(void)
61{
62 register_capability(&pciback_config_capability_vpd);
63 register_capability(&pciback_config_capability_pm);
64
65 return 0;
66}
diff --git a/drivers/xen/xen-pciback/conf_space_capability.h b/drivers/xen/xen-pciback/conf_space_capability.h
new file mode 100644
index 000000000000..8da3ac415f29
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_capability.h
@@ -0,0 +1,26 @@
1/*
2 * PCI Backend - Data structures for special overlays for structures on
3 * the capability list.
4 *
5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
6 */
7
8#ifndef __PCIBACK_CONFIG_CAPABILITY_H__
9#define __PCIBACK_CONFIG_CAPABILITY_H__
10
11#include <linux/pci.h>
12#include <linux/list.h>
13
14struct pciback_config_capability {
15 struct list_head cap_list;
16
17 int capability;
18
19 /* If the device has the capability found above, add these fields */
20 const struct config_field *fields;
21};
22
23extern struct pciback_config_capability pciback_config_capability_vpd;
24extern struct pciback_config_capability pciback_config_capability_pm;
25
26#endif
diff --git a/drivers/xen/xen-pciback/conf_space_capability_msi.c b/drivers/xen/xen-pciback/conf_space_capability_msi.c
new file mode 100644
index 000000000000..78f74b1852d4
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_capability_msi.c
@@ -0,0 +1,94 @@
1/*
2 * PCI Backend -- Configuration overlay for MSI capability
3 */
4#include <linux/pci.h>
5#include <linux/slab.h>
6#include "conf_space.h"
7#include "conf_space_capability.h"
8#include <xen/interface/io/pciif.h>
9#include <xen/events.h>
10#include "pciback.h"
11
12int pciback_enable_msi(struct pciback_device *pdev,
13 struct pci_dev *dev, struct xen_pci_op *op)
14{
15 int otherend = pdev->xdev->otherend_id;
16 int status;
17
18 status = pci_enable_msi(dev);
19
20 if (status) {
21 printk(KERN_ERR "error enable msi for guest %x status %x\n",
22 otherend, status);
23 op->value = 0;
24 return XEN_PCI_ERR_op_failed;
25 }
26
27 /* The value the guest needs is actually the IDT vector, not the
28 * the local domain's IRQ number. */
29
30 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
31 return 0;
32}
33
34int pciback_disable_msi(struct pciback_device *pdev,
35 struct pci_dev *dev, struct xen_pci_op *op)
36{
37 pci_disable_msi(dev);
38
39 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
40 return 0;
41}
42
43int pciback_enable_msix(struct pciback_device *pdev,
44 struct pci_dev *dev, struct xen_pci_op *op)
45{
46 int i, result;
47 struct msix_entry *entries;
48
49 if (op->value > SH_INFO_MAX_VEC)
50 return -EINVAL;
51
52 entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
53 if (entries == NULL)
54 return -ENOMEM;
55
56 for (i = 0; i < op->value; i++) {
57 entries[i].entry = op->msix_entries[i].entry;
58 entries[i].vector = op->msix_entries[i].vector;
59 }
60
61 result = pci_enable_msix(dev, entries, op->value);
62
63 if (result == 0) {
64 for (i = 0; i < op->value; i++) {
65 op->msix_entries[i].entry = entries[i].entry;
66 if (entries[i].vector)
67 op->msix_entries[i].vector =
68 xen_pirq_from_irq(entries[i].vector);
69 }
70 } else {
71 printk(KERN_WARNING "pciback: %s: failed to enable MSI-X: err %d!\n",
72 pci_name(dev), result);
73 }
74 kfree(entries);
75
76 op->value = result;
77
78 return result;
79}
80
81int pciback_disable_msix(struct pciback_device *pdev,
82 struct pci_dev *dev, struct xen_pci_op *op)
83{
84
85 pci_disable_msix(dev);
86
87 /*
88 * SR-IOV devices (which don't have any legacy IRQ) have
89 * an undefined IRQ value of zero.
90 */
91 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
92 return 0;
93}
94
diff --git a/drivers/xen/xen-pciback/conf_space_capability_pm.c b/drivers/xen/xen-pciback/conf_space_capability_pm.c
new file mode 100644
index 000000000000..04426165a9e5
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_capability_pm.c
@@ -0,0 +1,113 @@
1/*
2 * PCI Backend - Configuration space overlay for power management
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6
7#include <linux/pci.h>
8#include "conf_space.h"
9#include "conf_space_capability.h"
10
11static int pm_caps_read(struct pci_dev *dev, int offset, u16 *value,
12 void *data)
13{
14 int err;
15 u16 real_value;
16
17 err = pci_read_config_word(dev, offset, &real_value);
18 if (err)
19 goto out;
20
21 *value = real_value & ~PCI_PM_CAP_PME_MASK;
22
23out:
24 return err;
25}
26
27/* PM_OK_BITS specifies the bits that the driver domain is allowed to change.
28 * Can't allow driver domain to enable PMEs - they're shared */
29#define PM_OK_BITS (PCI_PM_CTRL_PME_STATUS|PCI_PM_CTRL_DATA_SEL_MASK)
30
31static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
32 void *data)
33{
34 int err;
35 u16 old_value;
36 pci_power_t new_state, old_state;
37
38 err = pci_read_config_word(dev, offset, &old_value);
39 if (err)
40 goto out;
41
42 old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK);
43 new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
44
45 new_value &= PM_OK_BITS;
46 if ((old_value & PM_OK_BITS) != new_value) {
47 new_value = (old_value & ~PM_OK_BITS) | new_value;
48 err = pci_write_config_word(dev, offset, new_value);
49 if (err)
50 goto out;
51 }
52
53 /* Let pci core handle the power management change */
54 dev_dbg(&dev->dev, "set power state to %x\n", new_state);
55 err = pci_set_power_state(dev, new_state);
56 if (err) {
57 err = PCIBIOS_SET_FAILED;
58 goto out;
59 }
60
61 out:
62 return err;
63}
64
65/* Ensure PMEs are disabled */
66static void *pm_ctrl_init(struct pci_dev *dev, int offset)
67{
68 int err;
69 u16 value;
70
71 err = pci_read_config_word(dev, offset, &value);
72 if (err)
73 goto out;
74
75 if (value & PCI_PM_CTRL_PME_ENABLE) {
76 value &= ~PCI_PM_CTRL_PME_ENABLE;
77 err = pci_write_config_word(dev, offset, value);
78 }
79
80out:
81 return ERR_PTR(err);
82}
83
84static const struct config_field caplist_pm[] = {
85 {
86 .offset = PCI_PM_PMC,
87 .size = 2,
88 .u.w.read = pm_caps_read,
89 },
90 {
91 .offset = PCI_PM_CTRL,
92 .size = 2,
93 .init = pm_ctrl_init,
94 .u.w.read = pciback_read_config_word,
95 .u.w.write = pm_ctrl_write,
96 },
97 {
98 .offset = PCI_PM_PPB_EXTENSIONS,
99 .size = 1,
100 .u.b.read = pciback_read_config_byte,
101 },
102 {
103 .offset = PCI_PM_DATA_REGISTER,
104 .size = 1,
105 .u.b.read = pciback_read_config_byte,
106 },
107 {}
108};
109
110struct pciback_config_capability pciback_config_capability_pm = {
111 .capability = PCI_CAP_ID_PM,
112 .fields = caplist_pm,
113};
diff --git a/drivers/xen/xen-pciback/conf_space_capability_vpd.c b/drivers/xen/xen-pciback/conf_space_capability_vpd.c
new file mode 100644
index 000000000000..e7b4d662b53d
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_capability_vpd.c
@@ -0,0 +1,40 @@
1/*
2 * PCI Backend - Configuration space overlay for Vital Product Data
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6
7#include <linux/pci.h>
8#include "conf_space.h"
9#include "conf_space_capability.h"
10
11static int vpd_address_write(struct pci_dev *dev, int offset, u16 value,
12 void *data)
13{
14 /* Disallow writes to the vital product data */
15 if (value & PCI_VPD_ADDR_F)
16 return PCIBIOS_SET_FAILED;
17 else
18 return pci_write_config_word(dev, offset, value);
19}
20
21static const struct config_field caplist_vpd[] = {
22 {
23 .offset = PCI_VPD_ADDR,
24 .size = 2,
25 .u.w.read = pciback_read_config_word,
26 .u.w.write = vpd_address_write,
27 },
28 {
29 .offset = PCI_VPD_DATA,
30 .size = 4,
31 .u.dw.read = pciback_read_config_dword,
32 .u.dw.write = NULL,
33 },
34 {}
35};
36
37struct pciback_config_capability pciback_config_capability_vpd = {
38 .capability = PCI_CAP_ID_VPD,
39 .fields = caplist_vpd,
40};
diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c
new file mode 100644
index 000000000000..3ae7da137f7e
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_header.c
@@ -0,0 +1,318 @@
1/*
2 * PCI Backend - Handles the virtual fields in the configuration space headers.
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6
7#include <linux/kernel.h>
8#include <linux/pci.h>
9#include "pciback.h"
10#include "conf_space.h"
11
12struct pci_bar_info {
13 u32 val;
14 u32 len_val;
15 int which;
16};
17
18#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
19#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
20
21static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
22{
23 int err;
24
25 if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
26 if (unlikely(verbose_request))
27 printk(KERN_DEBUG "pciback: %s: enable\n",
28 pci_name(dev));
29 err = pci_enable_device(dev);
30 if (err)
31 return err;
32 } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
33 if (unlikely(verbose_request))
34 printk(KERN_DEBUG "pciback: %s: disable\n",
35 pci_name(dev));
36 pci_disable_device(dev);
37 }
38
39 if (!dev->is_busmaster && is_master_cmd(value)) {
40 if (unlikely(verbose_request))
41 printk(KERN_DEBUG "pciback: %s: set bus master\n",
42 pci_name(dev));
43 pci_set_master(dev);
44 }
45
46 if (value & PCI_COMMAND_INVALIDATE) {
47 if (unlikely(verbose_request))
48 printk(KERN_DEBUG
49 "pciback: %s: enable memory-write-invalidate\n",
50 pci_name(dev));
51 err = pci_set_mwi(dev);
52 if (err) {
53 printk(KERN_WARNING
54 "pciback: %s: cannot enable "
55 "memory-write-invalidate (%d)\n",
56 pci_name(dev), err);
57 value &= ~PCI_COMMAND_INVALIDATE;
58 }
59 }
60
61 return pci_write_config_word(dev, offset, value);
62}
63
64static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
65{
66 struct pci_bar_info *bar = data;
67
68 if (unlikely(!bar)) {
69 printk(KERN_WARNING "pciback: driver data not found for %s\n",
70 pci_name(dev));
71 return XEN_PCI_ERR_op_failed;
72 }
73
74 /* A write to obtain the length must happen as a 32-bit write.
75 * This does not (yet) support writing individual bytes
76 */
77 if (value == ~PCI_ROM_ADDRESS_ENABLE)
78 bar->which = 1;
79 else {
80 u32 tmpval;
81 pci_read_config_dword(dev, offset, &tmpval);
82 if (tmpval != bar->val && value == bar->val) {
83 /* Allow restoration of bar value. */
84 pci_write_config_dword(dev, offset, bar->val);
85 }
86 bar->which = 0;
87 }
88
89 /* Do we need to support enabling/disabling the rom address here? */
90
91 return 0;
92}
93
94/* For the BARs, only allow writes which write ~0 or
95 * the correct resource information
96 * (Needed for when the driver probes the resource usage)
97 */
98static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
99{
100 struct pci_bar_info *bar = data;
101
102 if (unlikely(!bar)) {
103 printk(KERN_WARNING "pciback: driver data not found for %s\n",
104 pci_name(dev));
105 return XEN_PCI_ERR_op_failed;
106 }
107
108 /* A write to obtain the length must happen as a 32-bit write.
109 * This does not (yet) support writing individual bytes
110 */
111 if (value == ~0)
112 bar->which = 1;
113 else {
114 u32 tmpval;
115 pci_read_config_dword(dev, offset, &tmpval);
116 if (tmpval != bar->val && value == bar->val) {
117 /* Allow restoration of bar value. */
118 pci_write_config_dword(dev, offset, bar->val);
119 }
120 bar->which = 0;
121 }
122
123 return 0;
124}
125
126static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
127{
128 struct pci_bar_info *bar = data;
129
130 if (unlikely(!bar)) {
131 printk(KERN_WARNING "pciback: driver data not found for %s\n",
132 pci_name(dev));
133 return XEN_PCI_ERR_op_failed;
134 }
135
136 *value = bar->which ? bar->len_val : bar->val;
137
138 return 0;
139}
140
141static inline void read_dev_bar(struct pci_dev *dev,
142 struct pci_bar_info *bar_info, int offset,
143 u32 len_mask)
144{
145 pci_read_config_dword(dev, offset, &bar_info->val);
146 pci_write_config_dword(dev, offset, len_mask);
147 pci_read_config_dword(dev, offset, &bar_info->len_val);
148 pci_write_config_dword(dev, offset, bar_info->val);
149}
150
151static void *bar_init(struct pci_dev *dev, int offset)
152{
153 struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
154
155 if (!bar)
156 return ERR_PTR(-ENOMEM);
157
158 read_dev_bar(dev, bar, offset, ~0);
159 bar->which = 0;
160
161 return bar;
162}
163
164static void *rom_init(struct pci_dev *dev, int offset)
165{
166 struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
167
168 if (!bar)
169 return ERR_PTR(-ENOMEM);
170
171 read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
172 bar->which = 0;
173
174 return bar;
175}
176
177static void bar_reset(struct pci_dev *dev, int offset, void *data)
178{
179 struct pci_bar_info *bar = data;
180
181 bar->which = 0;
182}
183
184static void bar_release(struct pci_dev *dev, int offset, void *data)
185{
186 kfree(data);
187}
188
189static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
190 void *data)
191{
192 *value = (u8) dev->irq;
193
194 return 0;
195}
196
197static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
198{
199 u8 cur_value;
200 int err;
201
202 err = pci_read_config_byte(dev, offset, &cur_value);
203 if (err)
204 goto out;
205
206 if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
207 || value == PCI_BIST_START)
208 err = pci_write_config_byte(dev, offset, value);
209
210out:
211 return err;
212}
213
214static const struct config_field header_common[] = {
215 {
216 .offset = PCI_COMMAND,
217 .size = 2,
218 .u.w.read = pciback_read_config_word,
219 .u.w.write = command_write,
220 },
221 {
222 .offset = PCI_INTERRUPT_LINE,
223 .size = 1,
224 .u.b.read = interrupt_read,
225 },
226 {
227 .offset = PCI_INTERRUPT_PIN,
228 .size = 1,
229 .u.b.read = pciback_read_config_byte,
230 },
231 {
232 /* Any side effects of letting driver domain control cache line? */
233 .offset = PCI_CACHE_LINE_SIZE,
234 .size = 1,
235 .u.b.read = pciback_read_config_byte,
236 .u.b.write = pciback_write_config_byte,
237 },
238 {
239 .offset = PCI_LATENCY_TIMER,
240 .size = 1,
241 .u.b.read = pciback_read_config_byte,
242 },
243 {
244 .offset = PCI_BIST,
245 .size = 1,
246 .u.b.read = pciback_read_config_byte,
247 .u.b.write = bist_write,
248 },
249 {}
250};
251
252#define CFG_FIELD_BAR(reg_offset) \
253 { \
254 .offset = reg_offset, \
255 .size = 4, \
256 .init = bar_init, \
257 .reset = bar_reset, \
258 .release = bar_release, \
259 .u.dw.read = bar_read, \
260 .u.dw.write = bar_write, \
261 }
262
263#define CFG_FIELD_ROM(reg_offset) \
264 { \
265 .offset = reg_offset, \
266 .size = 4, \
267 .init = rom_init, \
268 .reset = bar_reset, \
269 .release = bar_release, \
270 .u.dw.read = bar_read, \
271 .u.dw.write = rom_write, \
272 }
273
274static const struct config_field header_0[] = {
275 CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
276 CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
277 CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
278 CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
279 CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
280 CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
281 CFG_FIELD_ROM(PCI_ROM_ADDRESS),
282 {}
283};
284
285static const struct config_field header_1[] = {
286 CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
287 CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
288 CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
289 {}
290};
291
292int pciback_config_header_add_fields(struct pci_dev *dev)
293{
294 int err;
295
296 err = pciback_config_add_fields(dev, header_common);
297 if (err)
298 goto out;
299
300 switch (dev->hdr_type) {
301 case PCI_HEADER_TYPE_NORMAL:
302 err = pciback_config_add_fields(dev, header_0);
303 break;
304
305 case PCI_HEADER_TYPE_BRIDGE:
306 err = pciback_config_add_fields(dev, header_1);
307 break;
308
309 default:
310 err = -EINVAL;
311 printk(KERN_ERR "pciback: %s: Unsupported header type %d!\n",
312 pci_name(dev), dev->hdr_type);
313 break;
314 }
315
316out:
317 return err;
318}
diff --git a/drivers/xen/xen-pciback/conf_space_quirks.c b/drivers/xen/xen-pciback/conf_space_quirks.c
new file mode 100644
index 000000000000..45c31fb391ec
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_quirks.c
@@ -0,0 +1,140 @@
1/*
2 * PCI Backend - Handle special overlays for broken devices.
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 * Author: Chris Bookholt <hap10@epoch.ncsc.mil>
6 */
7
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include "pciback.h"
11#include "conf_space.h"
12#include "conf_space_quirks.h"
13
14LIST_HEAD(pciback_quirks);
15
16static inline const struct pci_device_id *
17match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
18{
19 if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
20 (id->device == PCI_ANY_ID || id->device == dev->device) &&
21 (id->subvendor == PCI_ANY_ID ||
22 id->subvendor == dev->subsystem_vendor) &&
23 (id->subdevice == PCI_ANY_ID ||
24 id->subdevice == dev->subsystem_device) &&
25 !((id->class ^ dev->class) & id->class_mask))
26 return id;
27 return NULL;
28}
29
30struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev)
31{
32 struct pciback_config_quirk *tmp_quirk;
33
34 list_for_each_entry(tmp_quirk, &pciback_quirks, quirks_list)
35 if (match_one_device(&tmp_quirk->devid, dev) != NULL)
36 goto out;
37 tmp_quirk = NULL;
38 printk(KERN_DEBUG
39 "quirk didn't match any device pciback knows about\n");
40out:
41 return tmp_quirk;
42}
43
44static inline void register_quirk(struct pciback_config_quirk *quirk)
45{
46 list_add_tail(&quirk->quirks_list, &pciback_quirks);
47}
48
49int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg)
50{
51 int ret = 0;
52 struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
53 struct config_field_entry *cfg_entry;
54
55 list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
56 if (OFFSET(cfg_entry) == reg) {
57 ret = 1;
58 break;
59 }
60 }
61 return ret;
62}
63
64int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
65 *field)
66{
67 int err = 0;
68
69 switch (field->size) {
70 case 1:
71 field->u.b.read = pciback_read_config_byte;
72 field->u.b.write = pciback_write_config_byte;
73 break;
74 case 2:
75 field->u.w.read = pciback_read_config_word;
76 field->u.w.write = pciback_write_config_word;
77 break;
78 case 4:
79 field->u.dw.read = pciback_read_config_dword;
80 field->u.dw.write = pciback_write_config_dword;
81 break;
82 default:
83 err = -EINVAL;
84 goto out;
85 }
86
87 pciback_config_add_field(dev, field);
88
89out:
90 return err;
91}
92
93int pciback_config_quirks_init(struct pci_dev *dev)
94{
95 struct pciback_config_quirk *quirk;
96 int ret = 0;
97
98 quirk = kzalloc(sizeof(*quirk), GFP_ATOMIC);
99 if (!quirk) {
100 ret = -ENOMEM;
101 goto out;
102 }
103
104 quirk->devid.vendor = dev->vendor;
105 quirk->devid.device = dev->device;
106 quirk->devid.subvendor = dev->subsystem_vendor;
107 quirk->devid.subdevice = dev->subsystem_device;
108 quirk->devid.class = 0;
109 quirk->devid.class_mask = 0;
110 quirk->devid.driver_data = 0UL;
111
112 quirk->pdev = dev;
113
114 register_quirk(quirk);
115out:
116 return ret;
117}
118
119void pciback_config_field_free(struct config_field *field)
120{
121 kfree(field);
122}
123
124int pciback_config_quirk_release(struct pci_dev *dev)
125{
126 struct pciback_config_quirk *quirk;
127 int ret = 0;
128
129 quirk = pciback_find_quirk(dev);
130 if (!quirk) {
131 ret = -ENXIO;
132 goto out;
133 }
134
135 list_del(&quirk->quirks_list);
136 kfree(quirk);
137
138out:
139 return ret;
140}
diff --git a/drivers/xen/xen-pciback/conf_space_quirks.h b/drivers/xen/xen-pciback/conf_space_quirks.h
new file mode 100644
index 000000000000..acd0e1ae8fc5
--- /dev/null
+++ b/drivers/xen/xen-pciback/conf_space_quirks.h
@@ -0,0 +1,35 @@
1/*
2 * PCI Backend - Data structures for special overlays for broken devices.
3 *
4 * Ryan Wilson <hap9@epoch.ncsc.mil>
5 * Chris Bookholt <hap10@epoch.ncsc.mil>
6 */
7
8#ifndef __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
9#define __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
10
11#include <linux/pci.h>
12#include <linux/list.h>
13
14struct pciback_config_quirk {
15 struct list_head quirks_list;
16 struct pci_device_id devid;
17 struct pci_dev *pdev;
18};
19
20struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev);
21
22int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
23 *field);
24
25int pciback_config_quirks_remove_field(struct pci_dev *dev, int reg);
26
27int pciback_config_quirks_init(struct pci_dev *dev);
28
29void pciback_config_field_free(struct config_field *field);
30
31int pciback_config_quirk_release(struct pci_dev *dev);
32
33int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
34
35#endif
diff --git a/drivers/xen/xen-pciback/controller.c b/drivers/xen/xen-pciback/controller.c
new file mode 100644
index 000000000000..7f04f116daec
--- /dev/null
+++ b/drivers/xen/xen-pciback/controller.c
@@ -0,0 +1,442 @@
1/*
2 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
3 * Alex Williamson <alex.williamson@hp.com>
4 *
5 * PCI "Controller" Backend - virtualize PCI bus topology based on PCI
6 * controllers. Devices under the same PCI controller are exposed on the
7 * same virtual domain:bus. Within a bus, device slots are virtualized
8 * to compact the bus.
9 *
10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
26
27#include <linux/acpi.h>
28#include <linux/list.h>
29#include <linux/pci.h>
30#include <linux/spinlock.h>
31#include "pciback.h"
32
33#define PCI_MAX_BUSSES 255
34#define PCI_MAX_SLOTS 32
35
36struct controller_dev_entry {
37 struct list_head list;
38 struct pci_dev *dev;
39 unsigned int devfn;
40};
41
42struct controller_list_entry {
43 struct list_head list;
44 struct pci_controller *controller;
45 unsigned int domain;
46 unsigned int bus;
47 unsigned int next_devfn;
48 struct list_head dev_list;
49};
50
51struct controller_dev_data {
52 struct list_head list;
53 unsigned int next_domain;
54 unsigned int next_bus;
55 spinlock_t lock;
56};
57
58struct walk_info {
59 struct pciback_device *pdev;
60 int resource_count;
61 int root_num;
62};
63
64struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
65 unsigned int domain, unsigned int bus,
66 unsigned int devfn)
67{
68 struct controller_dev_data *dev_data = pdev->pci_dev_data;
69 struct controller_dev_entry *dev_entry;
70 struct controller_list_entry *cntrl_entry;
71 struct pci_dev *dev = NULL;
72 unsigned long flags;
73
74 spin_lock_irqsave(&dev_data->lock, flags);
75
76 list_for_each_entry(cntrl_entry, &dev_data->list, list) {
77 if (cntrl_entry->domain != domain ||
78 cntrl_entry->bus != bus)
79 continue;
80
81 list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
82 if (devfn == dev_entry->devfn) {
83 dev = dev_entry->dev;
84 goto found;
85 }
86 }
87 }
88found:
89 spin_unlock_irqrestore(&dev_data->lock, flags);
90
91 return dev;
92}
93
94int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
95 int devid, publish_pci_dev_cb publish_cb)
96{
97 struct controller_dev_data *dev_data = pdev->pci_dev_data;
98 struct controller_dev_entry *dev_entry;
99 struct controller_list_entry *cntrl_entry;
100 struct pci_controller *dev_controller = PCI_CONTROLLER(dev);
101 unsigned long flags;
102 int ret = 0, found = 0;
103
104 spin_lock_irqsave(&dev_data->lock, flags);
105
106 /* Look to see if we already have a domain:bus for this controller */
107 list_for_each_entry(cntrl_entry, &dev_data->list, list) {
108 if (cntrl_entry->controller == dev_controller) {
109 found = 1;
110 break;
111 }
112 }
113
114 if (!found) {
115 cntrl_entry = kmalloc(sizeof(*cntrl_entry), GFP_ATOMIC);
116 if (!cntrl_entry) {
117 ret = -ENOMEM;
118 goto out;
119 }
120
121 cntrl_entry->controller = dev_controller;
122 cntrl_entry->next_devfn = PCI_DEVFN(0, 0);
123
124 cntrl_entry->domain = dev_data->next_domain;
125 cntrl_entry->bus = dev_data->next_bus++;
126 if (dev_data->next_bus > PCI_MAX_BUSSES) {
127 dev_data->next_domain++;
128 dev_data->next_bus = 0;
129 }
130
131 INIT_LIST_HEAD(&cntrl_entry->dev_list);
132
133 list_add_tail(&cntrl_entry->list, &dev_data->list);
134 }
135
136 if (PCI_SLOT(cntrl_entry->next_devfn) > PCI_MAX_SLOTS) {
137 /*
138 * While it seems unlikely, this can actually happen if
139 * a controller has P2P bridges under it.
140 */
141 xenbus_dev_fatal(pdev->xdev, -ENOSPC, "Virtual bus %04x:%02x "
142 "is full, no room to export %04x:%02x:%02x.%x",
143 cntrl_entry->domain, cntrl_entry->bus,
144 pci_domain_nr(dev->bus), dev->bus->number,
145 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
146 ret = -ENOSPC;
147 goto out;
148 }
149
150 dev_entry = kmalloc(sizeof(*dev_entry), GFP_ATOMIC);
151 if (!dev_entry) {
152 if (list_empty(&cntrl_entry->dev_list)) {
153 list_del(&cntrl_entry->list);
154 kfree(cntrl_entry);
155 }
156 ret = -ENOMEM;
157 goto out;
158 }
159
160 dev_entry->dev = dev;
161 dev_entry->devfn = cntrl_entry->next_devfn;
162
163 list_add_tail(&dev_entry->list, &cntrl_entry->dev_list);
164
165 cntrl_entry->next_devfn += PCI_DEVFN(1, 0);
166
167out:
168 spin_unlock_irqrestore(&dev_data->lock, flags);
169
170 /* TODO: Publish virtual domain:bus:slot.func here. */
171
172 return ret;
173}
174
175void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
176{
177 struct controller_dev_data *dev_data = pdev->pci_dev_data;
178 struct controller_list_entry *cntrl_entry;
179 struct controller_dev_entry *dev_entry = NULL;
180 struct pci_dev *found_dev = NULL;
181 unsigned long flags;
182
183 spin_lock_irqsave(&dev_data->lock, flags);
184
185 list_for_each_entry(cntrl_entry, &dev_data->list, list) {
186 if (cntrl_entry->controller != PCI_CONTROLLER(dev))
187 continue;
188
189 list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
190 if (dev_entry->dev == dev) {
191 found_dev = dev_entry->dev;
192 break;
193 }
194 }
195 }
196
197 if (!found_dev) {
198 spin_unlock_irqrestore(&dev_data->lock, flags);
199 return;
200 }
201
202 list_del(&dev_entry->list);
203 kfree(dev_entry);
204
205 if (list_empty(&cntrl_entry->dev_list)) {
206 list_del(&cntrl_entry->list);
207 kfree(cntrl_entry);
208 }
209
210 spin_unlock_irqrestore(&dev_data->lock, flags);
211 pcistub_put_pci_dev(found_dev);
212}
213
214int pciback_init_devices(struct pciback_device *pdev)
215{
216 struct controller_dev_data *dev_data;
217
218 dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
219 if (!dev_data)
220 return -ENOMEM;
221
222 spin_lock_init(&dev_data->lock);
223
224 INIT_LIST_HEAD(&dev_data->list);
225
226 /* Starting domain:bus numbers */
227 dev_data->next_domain = 0;
228 dev_data->next_bus = 0;
229
230 pdev->pci_dev_data = dev_data;
231
232 return 0;
233}
234
235static acpi_status write_xenbus_resource(struct acpi_resource *res, void *data)
236{
237 struct walk_info *info = data;
238 struct acpi_resource_address64 addr;
239 acpi_status status;
240 int i, len, err;
241 char str[32], tmp[3];
242 unsigned char *ptr, *buf;
243
244 status = acpi_resource_to_address64(res, &addr);
245
246 /* Do we care about this range? Let's check. */
247 if (!ACPI_SUCCESS(status) ||
248 !(addr.resource_type == ACPI_MEMORY_RANGE ||
249 addr.resource_type == ACPI_IO_RANGE) ||
250 !addr.address_length || addr.producer_consumer != ACPI_PRODUCER)
251 return AE_OK;
252
253 /*
254 * Furthermore, we really only care to tell the guest about
255 * address ranges that require address translation of some sort.
256 */
257 if (!(addr.resource_type == ACPI_MEMORY_RANGE &&
258 addr.info.mem.translation) &&
259 !(addr.resource_type == ACPI_IO_RANGE &&
260 addr.info.io.translation))
261 return AE_OK;
262
263 /* Store the resource in xenbus for the guest */
264 len = snprintf(str, sizeof(str), "root-%d-resource-%d",
265 info->root_num, info->resource_count);
266 if (unlikely(len >= (sizeof(str) - 1)))
267 return AE_OK;
268
269 buf = kzalloc((sizeof(*res) * 2) + 1, GFP_KERNEL);
270 if (!buf)
271 return AE_OK;
272
273 /* Clean out resource_source */
274 res->data.address64.resource_source.index = 0xFF;
275 res->data.address64.resource_source.string_length = 0;
276 res->data.address64.resource_source.string_ptr = NULL;
277
278 ptr = (unsigned char *)res;
279
280 /* Turn the acpi_resource into an ASCII byte stream */
281 for (i = 0; i < sizeof(*res); i++) {
282 snprintf(tmp, sizeof(tmp), "%02x", ptr[i]);
283 strncat(buf, tmp, 2);
284 }
285
286 err = xenbus_printf(XBT_NIL, info->pdev->xdev->nodename,
287 str, "%s", buf);
288
289 if (!err)
290 info->resource_count++;
291
292 kfree(buf);
293
294 return AE_OK;
295}
296
297int pciback_publish_pci_roots(struct pciback_device *pdev,
298 publish_pci_root_cb publish_root_cb)
299{
300 struct controller_dev_data *dev_data = pdev->pci_dev_data;
301 struct controller_list_entry *cntrl_entry;
302 int i, root_num, len, err = 0;
303 unsigned int domain, bus;
304 char str[64];
305 struct walk_info info;
306
307 spin_lock(&dev_data->lock);
308
309 list_for_each_entry(cntrl_entry, &dev_data->list, list) {
310 /* First publish all the domain:bus info */
311 err = publish_root_cb(pdev, cntrl_entry->domain,
312 cntrl_entry->bus);
313 if (err)
314 goto out;
315
316 /*
317 * Now figure out which root-%d this belongs to
318 * so we can associate resources with it.
319 */
320 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
321 "root_num", "%d", &root_num);
322
323 if (err != 1)
324 goto out;
325
326 for (i = 0; i < root_num; i++) {
327 len = snprintf(str, sizeof(str), "root-%d", i);
328 if (unlikely(len >= (sizeof(str) - 1))) {
329 err = -ENOMEM;
330 goto out;
331 }
332
333 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
334 str, "%x:%x", &domain, &bus);
335 if (err != 2)
336 goto out;
337
338 /* Is this the one we just published? */
339 if (domain == cntrl_entry->domain &&
340 bus == cntrl_entry->bus)
341 break;
342 }
343
344 if (i == root_num)
345 goto out;
346
347 info.pdev = pdev;
348 info.resource_count = 0;
349 info.root_num = i;
350
351 /* Let ACPI do the heavy lifting on decoding resources */
352 acpi_walk_resources(cntrl_entry->controller->acpi_handle,
353 METHOD_NAME__CRS, write_xenbus_resource,
354 &info);
355
356 /* No resouces. OK. On to the next one */
357 if (!info.resource_count)
358 continue;
359
360 /* Store the number of resources we wrote for this root-%d */
361 len = snprintf(str, sizeof(str), "root-%d-resources", i);
362 if (unlikely(len >= (sizeof(str) - 1))) {
363 err = -ENOMEM;
364 goto out;
365 }
366
367 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
368 "%d", info.resource_count);
369 if (err)
370 goto out;
371 }
372
373 /* Finally, write some magic to synchronize with the guest. */
374 len = snprintf(str, sizeof(str), "root-resource-magic");
375 if (unlikely(len >= (sizeof(str) - 1))) {
376 err = -ENOMEM;
377 goto out;
378 }
379
380 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
381 "%lx", (sizeof(struct acpi_resource) * 2) + 1);
382
383out:
384 spin_unlock(&dev_data->lock);
385
386 return err;
387}
388
389void pciback_release_devices(struct pciback_device *pdev)
390{
391 struct controller_dev_data *dev_data = pdev->pci_dev_data;
392 struct controller_list_entry *cntrl_entry, *c;
393 struct controller_dev_entry *dev_entry, *d;
394
395 list_for_each_entry_safe(cntrl_entry, c, &dev_data->list, list) {
396 list_for_each_entry_safe(dev_entry, d,
397 &cntrl_entry->dev_list, list) {
398 list_del(&dev_entry->list);
399 pcistub_put_pci_dev(dev_entry->dev);
400 kfree(dev_entry);
401 }
402 list_del(&cntrl_entry->list);
403 kfree(cntrl_entry);
404 }
405
406 kfree(dev_data);
407 pdev->pci_dev_data = NULL;
408}
409
410int pciback_get_pcifront_dev(struct pci_dev *pcidev,
411 struct pciback_device *pdev,
412 unsigned int *domain, unsigned int *bus, unsigned int *devfn)
413{
414 struct controller_dev_data *dev_data = pdev->pci_dev_data;
415 struct controller_dev_entry *dev_entry;
416 struct controller_list_entry *cntrl_entry;
417 unsigned long flags;
418 int found = 0;
419 spin_lock_irqsave(&dev_data->lock, flags);
420
421 list_for_each_entry(cntrl_entry, &dev_data->list, list) {
422 list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
423 if ((dev_entry->dev->bus->number ==
424 pcidev->bus->number) &&
425 (dev_entry->dev->devfn ==
426 pcidev->devfn) &&
427 (pci_domain_nr(dev_entry->dev->bus) ==
428 pci_domain_nr(pcidev->bus))) {
429 found = 1;
430 *domain = cntrl_entry->domain;
431 *bus = cntrl_entry->bus;
432 *devfn = dev_entry->devfn;
433 goto out;
434 }
435 }
436 }
437out:
438 spin_unlock_irqrestore(&dev_data->lock, flags);
439 return found;
440
441}
442
diff --git a/drivers/xen/xen-pciback/passthrough.c b/drivers/xen/xen-pciback/passthrough.c
new file mode 100644
index 000000000000..5386bebf7f9a
--- /dev/null
+++ b/drivers/xen/xen-pciback/passthrough.c
@@ -0,0 +1,178 @@
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/spinlock.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 spinlock_t lock;
17};
18
19struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
20 unsigned int domain, unsigned int bus,
21 unsigned int devfn)
22{
23 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
24 struct pci_dev_entry *dev_entry;
25 struct pci_dev *dev = NULL;
26 unsigned long flags;
27
28 spin_lock_irqsave(&dev_data->lock, flags);
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 spin_unlock_irqrestore(&dev_data->lock, flags);
40
41 return dev;
42}
43
44int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
45 int devid, publish_pci_dev_cb publish_cb)
46{
47 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
48 struct pci_dev_entry *dev_entry;
49 unsigned long flags;
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 spin_lock_irqsave(&dev_data->lock, flags);
59 list_add_tail(&dev_entry->list, &dev_data->dev_list);
60 spin_unlock_irqrestore(&dev_data->lock, flags);
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
71void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
72{
73 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
74 struct pci_dev_entry *dev_entry, *t;
75 struct pci_dev *found_dev = NULL;
76 unsigned long flags;
77
78 spin_lock_irqsave(&dev_data->lock, flags);
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 spin_unlock_irqrestore(&dev_data->lock, flags);
89
90 if (found_dev)
91 pcistub_put_pci_dev(found_dev);
92}
93
94int pciback_init_devices(struct pciback_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 spin_lock_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
111int pciback_publish_pci_roots(struct pciback_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 spin_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 spin_unlock(&dev_data->lock);
149
150 return err;
151}
152
153void pciback_release_devices(struct pciback_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
168int pciback_get_pcifront_dev(struct pci_dev *pcidev,
169 struct pciback_device *pdev,
170 unsigned int *domain, unsigned int *bus,
171 unsigned int *devfn)
172
173{
174 *domain = pci_domain_nr(pcidev->bus);
175 *bus = pcidev->bus->number;
176 *devfn = pcidev->devfn;
177 return 1;
178}
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
new file mode 100644
index 000000000000..0b5a16b81c8c
--- /dev/null
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -0,0 +1,1285 @@
1/*
2 * PCI Stub Driver - Grabs devices in backend to be exported later
3 *
4 * Ryan Wilson <hap9@epoch.ncsc.mil>
5 * Chris Bookholt <hap10@epoch.ncsc.mil>
6 */
7#include <linux/module.h>
8#include <linux/init.h>
9#include <linux/rwsem.h>
10#include <linux/list.h>
11#include <linux/spinlock.h>
12#include <linux/kref.h>
13#include <linux/pci.h>
14#include <linux/wait.h>
15#include <linux/sched.h>
16#include <asm/atomic.h>
17#include <xen/events.h>
18#include <asm/xen/pci.h>
19#include <asm/xen/hypervisor.h>
20#include "pciback.h"
21#include "conf_space.h"
22#include "conf_space_quirks.h"
23
24static char *pci_devs_to_hide;
25wait_queue_head_t aer_wait_queue;
26/*Add sem for sync AER handling and pciback remove/reconfigue ops,
27* We want to avoid in middle of AER ops, pciback devices is being removed
28*/
29static DECLARE_RWSEM(pcistub_sem);
30module_param_named(hide, pci_devs_to_hide, charp, 0444);
31
32struct pcistub_device_id {
33 struct list_head slot_list;
34 int domain;
35 unsigned char bus;
36 unsigned int devfn;
37};
38static LIST_HEAD(pcistub_device_ids);
39static DEFINE_SPINLOCK(device_ids_lock);
40
41struct pcistub_device {
42 struct kref kref;
43 struct list_head dev_list;
44 spinlock_t lock;
45
46 struct pci_dev *dev;
47 struct pciback_device *pdev;/* non-NULL if struct pci_dev is in use */
48};
49
50/* Access to pcistub_devices & seized_devices lists and the initialize_devices
51 * flag must be locked with pcistub_devices_lock
52 */
53static DEFINE_SPINLOCK(pcistub_devices_lock);
54static LIST_HEAD(pcistub_devices);
55
56/* wait for device_initcall before initializing our devices
57 * (see pcistub_init_devices_late)
58 */
59static int initialize_devices;
60static LIST_HEAD(seized_devices);
61
62static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
63{
64 struct pcistub_device *psdev;
65
66 dev_dbg(&dev->dev, "pcistub_device_alloc\n");
67
68 psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC);
69 if (!psdev)
70 return NULL;
71
72 psdev->dev = pci_dev_get(dev);
73 if (!psdev->dev) {
74 kfree(psdev);
75 return NULL;
76 }
77
78 kref_init(&psdev->kref);
79 spin_lock_init(&psdev->lock);
80
81 return psdev;
82}
83
84/* Don't call this directly as it's called by pcistub_device_put */
85static void pcistub_device_release(struct kref *kref)
86{
87 struct pcistub_device *psdev;
88
89 psdev = container_of(kref, struct pcistub_device, kref);
90
91 dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
92
93 /* Clean-up the device */
94 pciback_reset_device(psdev->dev);
95 pciback_config_free_dyn_fields(psdev->dev);
96 pciback_config_free_dev(psdev->dev);
97 kfree(pci_get_drvdata(psdev->dev));
98 pci_set_drvdata(psdev->dev, NULL);
99
100 pci_dev_put(psdev->dev);
101
102 kfree(psdev);
103}
104
105static inline void pcistub_device_get(struct pcistub_device *psdev)
106{
107 kref_get(&psdev->kref);
108}
109
110static inline void pcistub_device_put(struct pcistub_device *psdev)
111{
112 kref_put(&psdev->kref, pcistub_device_release);
113}
114
115static struct pcistub_device *pcistub_device_find(int domain, int bus,
116 int slot, int func)
117{
118 struct pcistub_device *psdev = NULL;
119 unsigned long flags;
120
121 spin_lock_irqsave(&pcistub_devices_lock, flags);
122
123 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
124 if (psdev->dev != NULL
125 && domain == pci_domain_nr(psdev->dev->bus)
126 && bus == psdev->dev->bus->number
127 && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
128 pcistub_device_get(psdev);
129 goto out;
130 }
131 }
132
133 /* didn't find it */
134 psdev = NULL;
135
136out:
137 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
138 return psdev;
139}
140
141static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
142 struct pcistub_device *psdev)
143{
144 struct pci_dev *pci_dev = NULL;
145 unsigned long flags;
146
147 pcistub_device_get(psdev);
148
149 spin_lock_irqsave(&psdev->lock, flags);
150 if (!psdev->pdev) {
151 psdev->pdev = pdev;
152 pci_dev = psdev->dev;
153 }
154 spin_unlock_irqrestore(&psdev->lock, flags);
155
156 if (!pci_dev)
157 pcistub_device_put(psdev);
158
159 return pci_dev;
160}
161
162struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
163 int domain, int bus,
164 int slot, int func)
165{
166 struct pcistub_device *psdev;
167 struct pci_dev *found_dev = NULL;
168 unsigned long flags;
169
170 spin_lock_irqsave(&pcistub_devices_lock, flags);
171
172 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
173 if (psdev->dev != NULL
174 && domain == pci_domain_nr(psdev->dev->bus)
175 && bus == psdev->dev->bus->number
176 && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
177 found_dev = pcistub_device_get_pci_dev(pdev, psdev);
178 break;
179 }
180 }
181
182 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
183 return found_dev;
184}
185
186struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
187 struct pci_dev *dev)
188{
189 struct pcistub_device *psdev;
190 struct pci_dev *found_dev = NULL;
191 unsigned long flags;
192
193 spin_lock_irqsave(&pcistub_devices_lock, flags);
194
195 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
196 if (psdev->dev == dev) {
197 found_dev = pcistub_device_get_pci_dev(pdev, psdev);
198 break;
199 }
200 }
201
202 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
203 return found_dev;
204}
205
206void pcistub_put_pci_dev(struct pci_dev *dev)
207{
208 struct pcistub_device *psdev, *found_psdev = NULL;
209 unsigned long flags;
210
211 spin_lock_irqsave(&pcistub_devices_lock, flags);
212
213 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
214 if (psdev->dev == dev) {
215 found_psdev = psdev;
216 break;
217 }
218 }
219
220 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
221
222 /*hold this lock for avoiding breaking link between
223 * pcistub and pciback when AER is in processing
224 */
225 down_write(&pcistub_sem);
226 /* Cleanup our device
227 * (so it's ready for the next domain)
228 */
229 pciback_reset_device(found_psdev->dev);
230 pciback_config_free_dyn_fields(found_psdev->dev);
231 pciback_config_reset_dev(found_psdev->dev);
232
233 spin_lock_irqsave(&found_psdev->lock, flags);
234 found_psdev->pdev = NULL;
235 spin_unlock_irqrestore(&found_psdev->lock, flags);
236
237 pcistub_device_put(found_psdev);
238 up_write(&pcistub_sem);
239}
240
241static int __devinit pcistub_match_one(struct pci_dev *dev,
242 struct pcistub_device_id *pdev_id)
243{
244 /* Match the specified device by domain, bus, slot, func and also if
245 * any of the device's parent bridges match.
246 */
247 for (; dev != NULL; dev = dev->bus->self) {
248 if (pci_domain_nr(dev->bus) == pdev_id->domain
249 && dev->bus->number == pdev_id->bus
250 && dev->devfn == pdev_id->devfn)
251 return 1;
252
253 /* Sometimes topmost bridge links to itself. */
254 if (dev == dev->bus->self)
255 break;
256 }
257
258 return 0;
259}
260
261static int __devinit pcistub_match(struct pci_dev *dev)
262{
263 struct pcistub_device_id *pdev_id;
264 unsigned long flags;
265 int found = 0;
266
267 spin_lock_irqsave(&device_ids_lock, flags);
268 list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
269 if (pcistub_match_one(dev, pdev_id)) {
270 found = 1;
271 break;
272 }
273 }
274 spin_unlock_irqrestore(&device_ids_lock, flags);
275
276 return found;
277}
278
279static int __devinit pcistub_init_device(struct pci_dev *dev)
280{
281 struct pciback_dev_data *dev_data;
282 int err = 0;
283
284 dev_dbg(&dev->dev, "initializing...\n");
285
286 /* The PCI backend is not intended to be a module (or to work with
287 * removable PCI devices (yet). If it were, pciback_config_free()
288 * would need to be called somewhere to free the memory allocated
289 * here and then to call kfree(pci_get_drvdata(psdev->dev)).
290 */
291 dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC);
292 if (!dev_data) {
293 err = -ENOMEM;
294 goto out;
295 }
296 pci_set_drvdata(dev, dev_data);
297
298 dev_dbg(&dev->dev, "initializing config\n");
299
300 init_waitqueue_head(&aer_wait_queue);
301 err = pciback_config_init_dev(dev);
302 if (err)
303 goto out;
304
305 /* HACK: Force device (& ACPI) to determine what IRQ it's on - we
306 * must do this here because pcibios_enable_device may specify
307 * the pci device's true irq (and possibly its other resources)
308 * if they differ from what's in the configuration space.
309 * This makes the assumption that the device's resources won't
310 * change after this point (otherwise this code may break!)
311 */
312 dev_dbg(&dev->dev, "enabling device\n");
313 err = pci_enable_device(dev);
314 if (err)
315 goto config_release;
316
317 /* Now disable the device (this also ensures some private device
318 * data is setup before we export)
319 */
320 dev_dbg(&dev->dev, "reset device\n");
321 pciback_reset_device(dev);
322
323 return 0;
324
325config_release:
326 pciback_config_free_dev(dev);
327
328out:
329 pci_set_drvdata(dev, NULL);
330 kfree(dev_data);
331 return err;
332}
333
334/*
335 * Because some initialization still happens on
336 * devices during fs_initcall, we need to defer
337 * full initialization of our devices until
338 * device_initcall.
339 */
340static int __init pcistub_init_devices_late(void)
341{
342 struct pcistub_device *psdev;
343 unsigned long flags;
344 int err = 0;
345
346 pr_debug("pciback: pcistub_init_devices_late\n");
347
348 spin_lock_irqsave(&pcistub_devices_lock, flags);
349
350 while (!list_empty(&seized_devices)) {
351 psdev = container_of(seized_devices.next,
352 struct pcistub_device, dev_list);
353 list_del(&psdev->dev_list);
354
355 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
356
357 err = pcistub_init_device(psdev->dev);
358 if (err) {
359 dev_err(&psdev->dev->dev,
360 "error %d initializing device\n", err);
361 kfree(psdev);
362 psdev = NULL;
363 }
364
365 spin_lock_irqsave(&pcistub_devices_lock, flags);
366
367 if (psdev)
368 list_add_tail(&psdev->dev_list, &pcistub_devices);
369 }
370
371 initialize_devices = 1;
372
373 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
374
375 return 0;
376}
377
378static int __devinit pcistub_seize(struct pci_dev *dev)
379{
380 struct pcistub_device *psdev;
381 unsigned long flags;
382 int err = 0;
383
384 psdev = pcistub_device_alloc(dev);
385 if (!psdev)
386 return -ENOMEM;
387
388 spin_lock_irqsave(&pcistub_devices_lock, flags);
389
390 if (initialize_devices) {
391 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
392
393 /* don't want irqs disabled when calling pcistub_init_device */
394 err = pcistub_init_device(psdev->dev);
395
396 spin_lock_irqsave(&pcistub_devices_lock, flags);
397
398 if (!err)
399 list_add(&psdev->dev_list, &pcistub_devices);
400 } else {
401 dev_dbg(&dev->dev, "deferring initialization\n");
402 list_add(&psdev->dev_list, &seized_devices);
403 }
404
405 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
406
407 if (err)
408 pcistub_device_put(psdev);
409
410 return err;
411}
412
413static int __devinit pcistub_probe(struct pci_dev *dev,
414 const struct pci_device_id *id)
415{
416 int err = 0;
417
418 dev_dbg(&dev->dev, "probing...\n");
419
420 if (pcistub_match(dev)) {
421
422 if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
423 && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
424 dev_err(&dev->dev, "can't export pci devices that "
425 "don't have a normal (0) or bridge (1) "
426 "header type!\n");
427 err = -ENODEV;
428 goto out;
429 }
430
431 dev_info(&dev->dev, "seizing device\n");
432 err = pcistub_seize(dev);
433 } else
434 /* Didn't find the device */
435 err = -ENODEV;
436
437out:
438 return err;
439}
440
441static void pcistub_remove(struct pci_dev *dev)
442{
443 struct pcistub_device *psdev, *found_psdev = NULL;
444 unsigned long flags;
445
446 dev_dbg(&dev->dev, "removing\n");
447
448 spin_lock_irqsave(&pcistub_devices_lock, flags);
449
450 pciback_config_quirk_release(dev);
451
452 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
453 if (psdev->dev == dev) {
454 found_psdev = psdev;
455 break;
456 }
457 }
458
459 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
460
461 if (found_psdev) {
462 dev_dbg(&dev->dev, "found device to remove - in use? %p\n",
463 found_psdev->pdev);
464
465 if (found_psdev->pdev) {
466 printk(KERN_WARNING "pciback: ****** removing device "
467 "%s while still in-use! ******\n",
468 pci_name(found_psdev->dev));
469 printk(KERN_WARNING "pciback: ****** driver domain may "
470 "still access this device's i/o resources!\n");
471 printk(KERN_WARNING "pciback: ****** shutdown driver "
472 "domain before binding device\n");
473 printk(KERN_WARNING "pciback: ****** to other drivers "
474 "or domains\n");
475
476 pciback_release_pci_dev(found_psdev->pdev,
477 found_psdev->dev);
478 }
479
480 spin_lock_irqsave(&pcistub_devices_lock, flags);
481 list_del(&found_psdev->dev_list);
482 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
483
484 /* the final put for releasing from the list */
485 pcistub_device_put(found_psdev);
486 }
487}
488
489static const struct pci_device_id pcistub_ids[] = {
490 {
491 .vendor = PCI_ANY_ID,
492 .device = PCI_ANY_ID,
493 .subvendor = PCI_ANY_ID,
494 .subdevice = PCI_ANY_ID,
495 },
496 {0,},
497};
498
499#define PCI_NODENAME_MAX 40
500static void kill_domain_by_device(struct pcistub_device *psdev)
501{
502 struct xenbus_transaction xbt;
503 int err;
504 char nodename[PCI_NODENAME_MAX];
505
506 if (!psdev)
507 dev_err(&psdev->dev->dev,
508 "device is NULL when do AER recovery/kill_domain\n");
509 snprintf(nodename, PCI_NODENAME_MAX, "/local/domain/0/backend/pci/%d/0",
510 psdev->pdev->xdev->otherend_id);
511 nodename[strlen(nodename)] = '\0';
512
513again:
514 err = xenbus_transaction_start(&xbt);
515 if (err) {
516 dev_err(&psdev->dev->dev,
517 "error %d when start xenbus transaction\n", err);
518 return;
519 }
520 /*PV AER handlers will set this flag*/
521 xenbus_printf(xbt, nodename, "aerState" , "aerfail");
522 err = xenbus_transaction_end(xbt, 0);
523 if (err) {
524 if (err == -EAGAIN)
525 goto again;
526 dev_err(&psdev->dev->dev,
527 "error %d when end xenbus transaction\n", err);
528 return;
529 }
530}
531
532/* For each aer recovery step error_detected, mmio_enabled, etc, front_end and
533 * backend need to have cooperation. In pciback, those steps will do similar
534 * jobs: send service request and waiting for front_end response.
535*/
536static pci_ers_result_t common_process(struct pcistub_device *psdev,
537 pci_channel_state_t state, int aer_cmd, pci_ers_result_t result)
538{
539 pci_ers_result_t res = result;
540 struct xen_pcie_aer_op *aer_op;
541 int ret;
542
543 /*with PV AER drivers*/
544 aer_op = &(psdev->pdev->sh_info->aer_op);
545 aer_op->cmd = aer_cmd ;
546 /*useful for error_detected callback*/
547 aer_op->err = state;
548 /*pcifront_end BDF*/
549 ret = pciback_get_pcifront_dev(psdev->dev, psdev->pdev,
550 &aer_op->domain, &aer_op->bus, &aer_op->devfn);
551 if (!ret) {
552 dev_err(&psdev->dev->dev,
553 "pciback: failed to get pcifront device\n");
554 return PCI_ERS_RESULT_NONE;
555 }
556 wmb();
557
558 dev_dbg(&psdev->dev->dev,
559 "pciback: aer_op %x dom %x bus %x devfn %x\n",
560 aer_cmd, aer_op->domain, aer_op->bus, aer_op->devfn);
561 /*local flag to mark there's aer request, pciback callback will use this
562 * flag to judge whether we need to check pci-front give aer service
563 * ack signal
564 */
565 set_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
566
567 /*It is possible that a pcifront conf_read_write ops request invokes
568 * the callback which cause the spurious execution of wake_up.
569 * Yet it is harmless and better than a spinlock here
570 */
571 set_bit(_XEN_PCIB_active,
572 (unsigned long *)&psdev->pdev->sh_info->flags);
573 wmb();
574 notify_remote_via_irq(psdev->pdev->evtchn_irq);
575
576 ret = wait_event_timeout(aer_wait_queue, !(test_bit(_XEN_PCIB_active,
577 (unsigned long *)&psdev->pdev->sh_info->flags)), 300*HZ);
578
579 if (!ret) {
580 if (test_bit(_XEN_PCIB_active,
581 (unsigned long *)&psdev->pdev->sh_info->flags)) {
582 dev_err(&psdev->dev->dev,
583 "pcifront aer process not responding!\n");
584 clear_bit(_XEN_PCIB_active,
585 (unsigned long *)&psdev->pdev->sh_info->flags);
586 aer_op->err = PCI_ERS_RESULT_NONE;
587 return res;
588 }
589 }
590 clear_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
591
592 if (test_bit(_XEN_PCIF_active,
593 (unsigned long *)&psdev->pdev->sh_info->flags)) {
594 dev_dbg(&psdev->dev->dev,
595 "schedule pci_conf service in pciback \n");
596 test_and_schedule_op(psdev->pdev);
597 }
598
599 res = (pci_ers_result_t)aer_op->err;
600 return res;
601}
602
603/*
604* pciback_slot_reset: it will send the slot_reset request to pcifront in case
605* of the device driver could provide this service, and then wait for pcifront
606* ack.
607* @dev: pointer to PCI devices
608* return value is used by aer_core do_recovery policy
609*/
610static pci_ers_result_t pciback_slot_reset(struct pci_dev *dev)
611{
612 struct pcistub_device *psdev;
613 pci_ers_result_t result;
614
615 result = PCI_ERS_RESULT_RECOVERED;
616 dev_dbg(&dev->dev, "pciback_slot_reset(bus:%x,devfn:%x)\n",
617 dev->bus->number, dev->devfn);
618
619 down_write(&pcistub_sem);
620 psdev = pcistub_device_find(pci_domain_nr(dev->bus),
621 dev->bus->number,
622 PCI_SLOT(dev->devfn),
623 PCI_FUNC(dev->devfn));
624
625 if (!psdev || !psdev->pdev) {
626 dev_err(&dev->dev,
627 "pciback device is not found/assigned\n");
628 goto end;
629 }
630
631 if (!psdev->pdev->sh_info) {
632 dev_err(&dev->dev, "pciback device is not connected or owned"
633 " by HVM, kill it\n");
634 kill_domain_by_device(psdev);
635 goto release;
636 }
637
638 if (!test_bit(_XEN_PCIB_AERHANDLER,
639 (unsigned long *)&psdev->pdev->sh_info->flags)) {
640 dev_err(&dev->dev,
641 "guest with no AER driver should have been killed\n");
642 goto release;
643 }
644 result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
645
646 if (result == PCI_ERS_RESULT_NONE ||
647 result == PCI_ERS_RESULT_DISCONNECT) {
648 dev_dbg(&dev->dev,
649 "No AER slot_reset service or disconnected!\n");
650 kill_domain_by_device(psdev);
651 }
652release:
653 pcistub_device_put(psdev);
654end:
655 up_write(&pcistub_sem);
656 return result;
657
658}
659
660
661/*pciback_mmio_enabled: it will send the mmio_enabled request to pcifront
662* in case of the device driver could provide this service, and then wait
663* for pcifront ack
664* @dev: pointer to PCI devices
665* return value is used by aer_core do_recovery policy
666*/
667
668static pci_ers_result_t pciback_mmio_enabled(struct pci_dev *dev)
669{
670 struct pcistub_device *psdev;
671 pci_ers_result_t result;
672
673 result = PCI_ERS_RESULT_RECOVERED;
674 dev_dbg(&dev->dev, "pciback_mmio_enabled(bus:%x,devfn:%x)\n",
675 dev->bus->number, dev->devfn);
676
677 down_write(&pcistub_sem);
678 psdev = pcistub_device_find(pci_domain_nr(dev->bus),
679 dev->bus->number,
680 PCI_SLOT(dev->devfn),
681 PCI_FUNC(dev->devfn));
682
683 if (!psdev || !psdev->pdev) {
684 dev_err(&dev->dev,
685 "pciback device is not found/assigned\n");
686 goto end;
687 }
688
689 if (!psdev->pdev->sh_info) {
690 dev_err(&dev->dev, "pciback device is not connected or owned"
691 " by HVM, kill it\n");
692 kill_domain_by_device(psdev);
693 goto release;
694 }
695
696 if (!test_bit(_XEN_PCIB_AERHANDLER,
697 (unsigned long *)&psdev->pdev->sh_info->flags)) {
698 dev_err(&dev->dev,
699 "guest with no AER driver should have been killed\n");
700 goto release;
701 }
702 result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
703
704 if (result == PCI_ERS_RESULT_NONE ||
705 result == PCI_ERS_RESULT_DISCONNECT) {
706 dev_dbg(&dev->dev,
707 "No AER mmio_enabled service or disconnected!\n");
708 kill_domain_by_device(psdev);
709 }
710release:
711 pcistub_device_put(psdev);
712end:
713 up_write(&pcistub_sem);
714 return result;
715}
716
717/*pciback_error_detected: it will send the error_detected request to pcifront
718* in case of the device driver could provide this service, and then wait
719* for pcifront ack.
720* @dev: pointer to PCI devices
721* @error: the current PCI connection state
722* return value is used by aer_core do_recovery policy
723*/
724
725static pci_ers_result_t pciback_error_detected(struct pci_dev *dev,
726 pci_channel_state_t error)
727{
728 struct pcistub_device *psdev;
729 pci_ers_result_t result;
730
731 result = PCI_ERS_RESULT_CAN_RECOVER;
732 dev_dbg(&dev->dev, "pciback_error_detected(bus:%x,devfn:%x)\n",
733 dev->bus->number, dev->devfn);
734
735 down_write(&pcistub_sem);
736 psdev = pcistub_device_find(pci_domain_nr(dev->bus),
737 dev->bus->number,
738 PCI_SLOT(dev->devfn),
739 PCI_FUNC(dev->devfn));
740
741 if (!psdev || !psdev->pdev) {
742 dev_err(&dev->dev,
743 "pciback device is not found/assigned\n");
744 goto end;
745 }
746
747 if (!psdev->pdev->sh_info) {
748 dev_err(&dev->dev, "pciback device is not connected or owned"
749 " by HVM, kill it\n");
750 kill_domain_by_device(psdev);
751 goto release;
752 }
753
754 /*Guest owns the device yet no aer handler regiested, kill guest*/
755 if (!test_bit(_XEN_PCIB_AERHANDLER,
756 (unsigned long *)&psdev->pdev->sh_info->flags)) {
757 dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n");
758 kill_domain_by_device(psdev);
759 goto release;
760 }
761 result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result);
762
763 if (result == PCI_ERS_RESULT_NONE ||
764 result == PCI_ERS_RESULT_DISCONNECT) {
765 dev_dbg(&dev->dev,
766 "No AER error_detected service or disconnected!\n");
767 kill_domain_by_device(psdev);
768 }
769release:
770 pcistub_device_put(psdev);
771end:
772 up_write(&pcistub_sem);
773 return result;
774}
775
776/*pciback_error_resume: it will send the error_resume request to pcifront
777* in case of the device driver could provide this service, and then wait
778* for pcifront ack.
779* @dev: pointer to PCI devices
780*/
781
782static void pciback_error_resume(struct pci_dev *dev)
783{
784 struct pcistub_device *psdev;
785
786 dev_dbg(&dev->dev, "pciback_error_resume(bus:%x,devfn:%x)\n",
787 dev->bus->number, dev->devfn);
788
789 down_write(&pcistub_sem);
790 psdev = pcistub_device_find(pci_domain_nr(dev->bus),
791 dev->bus->number,
792 PCI_SLOT(dev->devfn),
793 PCI_FUNC(dev->devfn));
794
795 if (!psdev || !psdev->pdev) {
796 dev_err(&dev->dev,
797 "pciback device is not found/assigned\n");
798 goto end;
799 }
800
801 if (!psdev->pdev->sh_info) {
802 dev_err(&dev->dev, "pciback device is not connected or owned"
803 " by HVM, kill it\n");
804 kill_domain_by_device(psdev);
805 goto release;
806 }
807
808 if (!test_bit(_XEN_PCIB_AERHANDLER,
809 (unsigned long *)&psdev->pdev->sh_info->flags)) {
810 dev_err(&dev->dev,
811 "guest with no AER driver should have been killed\n");
812 kill_domain_by_device(psdev);
813 goto release;
814 }
815 common_process(psdev, 1, XEN_PCI_OP_aer_resume,
816 PCI_ERS_RESULT_RECOVERED);
817release:
818 pcistub_device_put(psdev);
819end:
820 up_write(&pcistub_sem);
821 return;
822}
823
824/*add pciback AER handling*/
825static struct pci_error_handlers pciback_error_handler = {
826 .error_detected = pciback_error_detected,
827 .mmio_enabled = pciback_mmio_enabled,
828 .slot_reset = pciback_slot_reset,
829 .resume = pciback_error_resume,
830};
831
832/*
833 * Note: There is no MODULE_DEVICE_TABLE entry here because this isn't
834 * for a normal device. I don't want it to be loaded automatically.
835 */
836
837static struct pci_driver pciback_pci_driver = {
838 .name = "pciback",
839 .id_table = pcistub_ids,
840 .probe = pcistub_probe,
841 .remove = pcistub_remove,
842 .err_handler = &pciback_error_handler,
843};
844
845static inline int str_to_slot(const char *buf, int *domain, int *bus,
846 int *slot, int *func)
847{
848 int err;
849
850 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
851 if (err == 4)
852 return 0;
853 else if (err < 0)
854 return -EINVAL;
855
856 /* try again without domain */
857 *domain = 0;
858 err = sscanf(buf, " %x:%x.%x", bus, slot, func);
859 if (err == 3)
860 return 0;
861
862 return -EINVAL;
863}
864
865static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
866 *slot, int *func, int *reg, int *size, int *mask)
867{
868 int err;
869
870 err =
871 sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
872 func, reg, size, mask);
873 if (err == 7)
874 return 0;
875 return -EINVAL;
876}
877
878static int pcistub_device_id_add(int domain, int bus, int slot, int func)
879{
880 struct pcistub_device_id *pci_dev_id;
881 unsigned long flags;
882
883 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
884 if (!pci_dev_id)
885 return -ENOMEM;
886
887 pci_dev_id->domain = domain;
888 pci_dev_id->bus = bus;
889 pci_dev_id->devfn = PCI_DEVFN(slot, func);
890
891 pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
892 domain, bus, slot, func);
893
894 spin_lock_irqsave(&device_ids_lock, flags);
895 list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
896 spin_unlock_irqrestore(&device_ids_lock, flags);
897
898 return 0;
899}
900
901static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
902{
903 struct pcistub_device_id *pci_dev_id, *t;
904 int devfn = PCI_DEVFN(slot, func);
905 int err = -ENOENT;
906 unsigned long flags;
907
908 spin_lock_irqsave(&device_ids_lock, flags);
909 list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids,
910 slot_list) {
911 if (pci_dev_id->domain == domain
912 && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) {
913 /* Don't break; here because it's possible the same
914 * slot could be in the list more than once
915 */
916 list_del(&pci_dev_id->slot_list);
917 kfree(pci_dev_id);
918
919 err = 0;
920
921 pr_debug("pciback: removed %04x:%02x:%02x.%01x from "
922 "seize list\n", domain, bus, slot, func);
923 }
924 }
925 spin_unlock_irqrestore(&device_ids_lock, flags);
926
927 return err;
928}
929
930static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
931 int size, int mask)
932{
933 int err = 0;
934 struct pcistub_device *psdev;
935 struct pci_dev *dev;
936 struct config_field *field;
937
938 psdev = pcistub_device_find(domain, bus, slot, func);
939 if (!psdev || !psdev->dev) {
940 err = -ENODEV;
941 goto out;
942 }
943 dev = psdev->dev;
944
945 field = kzalloc(sizeof(*field), GFP_ATOMIC);
946 if (!field) {
947 err = -ENOMEM;
948 goto out;
949 }
950
951 field->offset = reg;
952 field->size = size;
953 field->mask = mask;
954 field->init = NULL;
955 field->reset = NULL;
956 field->release = NULL;
957 field->clean = pciback_config_field_free;
958
959 err = pciback_config_quirks_add_field(dev, field);
960 if (err)
961 kfree(field);
962out:
963 return err;
964}
965
966static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
967 size_t count)
968{
969 int domain, bus, slot, func;
970 int err;
971
972 err = str_to_slot(buf, &domain, &bus, &slot, &func);
973 if (err)
974 goto out;
975
976 err = pcistub_device_id_add(domain, bus, slot, func);
977
978out:
979 if (!err)
980 err = count;
981 return err;
982}
983
984DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add);
985
986static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf,
987 size_t count)
988{
989 int domain, bus, slot, func;
990 int err;
991
992 err = str_to_slot(buf, &domain, &bus, &slot, &func);
993 if (err)
994 goto out;
995
996 err = pcistub_device_id_remove(domain, bus, slot, func);
997
998out:
999 if (!err)
1000 err = count;
1001 return err;
1002}
1003
1004DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove);
1005
1006static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
1007{
1008 struct pcistub_device_id *pci_dev_id;
1009 size_t count = 0;
1010 unsigned long flags;
1011
1012 spin_lock_irqsave(&device_ids_lock, flags);
1013 list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) {
1014 if (count >= PAGE_SIZE)
1015 break;
1016
1017 count += scnprintf(buf + count, PAGE_SIZE - count,
1018 "%04x:%02x:%02x.%01x\n",
1019 pci_dev_id->domain, pci_dev_id->bus,
1020 PCI_SLOT(pci_dev_id->devfn),
1021 PCI_FUNC(pci_dev_id->devfn));
1022 }
1023 spin_unlock_irqrestore(&device_ids_lock, flags);
1024
1025 return count;
1026}
1027
1028DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
1029
1030static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
1031 size_t count)
1032{
1033 int domain, bus, slot, func, reg, size, mask;
1034 int err;
1035
1036 err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
1037 &mask);
1038 if (err)
1039 goto out;
1040
1041 err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
1042
1043out:
1044 if (!err)
1045 err = count;
1046 return err;
1047}
1048
1049static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
1050{
1051 int count = 0;
1052 unsigned long flags;
1053 struct pciback_config_quirk *quirk;
1054 struct pciback_dev_data *dev_data;
1055 const struct config_field *field;
1056 const struct config_field_entry *cfg_entry;
1057
1058 spin_lock_irqsave(&device_ids_lock, flags);
1059 list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
1060 if (count >= PAGE_SIZE)
1061 goto out;
1062
1063 count += scnprintf(buf + count, PAGE_SIZE - count,
1064 "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
1065 quirk->pdev->bus->number,
1066 PCI_SLOT(quirk->pdev->devfn),
1067 PCI_FUNC(quirk->pdev->devfn),
1068 quirk->devid.vendor, quirk->devid.device,
1069 quirk->devid.subvendor,
1070 quirk->devid.subdevice);
1071
1072 dev_data = pci_get_drvdata(quirk->pdev);
1073
1074 list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
1075 field = cfg_entry->field;
1076 if (count >= PAGE_SIZE)
1077 goto out;
1078
1079 count += scnprintf(buf + count, PAGE_SIZE - count,
1080 "\t\t%08x:%01x:%08x\n",
1081 cfg_entry->base_offset +
1082 field->offset, field->size,
1083 field->mask);
1084 }
1085 }
1086
1087out:
1088 spin_unlock_irqrestore(&device_ids_lock, flags);
1089
1090 return count;
1091}
1092
1093DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
1094
1095static ssize_t permissive_add(struct device_driver *drv, const char *buf,
1096 size_t count)
1097{
1098 int domain, bus, slot, func;
1099 int err;
1100 struct pcistub_device *psdev;
1101 struct pciback_dev_data *dev_data;
1102 err = str_to_slot(buf, &domain, &bus, &slot, &func);
1103 if (err)
1104 goto out;
1105 psdev = pcistub_device_find(domain, bus, slot, func);
1106 if (!psdev) {
1107 err = -ENODEV;
1108 goto out;
1109 }
1110 if (!psdev->dev) {
1111 err = -ENODEV;
1112 goto release;
1113 }
1114 dev_data = pci_get_drvdata(psdev->dev);
1115 /* the driver data for a device should never be null at this point */
1116 if (!dev_data) {
1117 err = -ENXIO;
1118 goto release;
1119 }
1120 if (!dev_data->permissive) {
1121 dev_data->permissive = 1;
1122 /* Let user know that what they're doing could be unsafe */
1123 dev_warn(&psdev->dev->dev, "enabling permissive mode "
1124 "configuration space accesses!\n");
1125 dev_warn(&psdev->dev->dev,
1126 "permissive mode is potentially unsafe!\n");
1127 }
1128release:
1129 pcistub_device_put(psdev);
1130out:
1131 if (!err)
1132 err = count;
1133 return err;
1134}
1135
1136static ssize_t permissive_show(struct device_driver *drv, char *buf)
1137{
1138 struct pcistub_device *psdev;
1139 struct pciback_dev_data *dev_data;
1140 size_t count = 0;
1141 unsigned long flags;
1142 spin_lock_irqsave(&pcistub_devices_lock, flags);
1143 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
1144 if (count >= PAGE_SIZE)
1145 break;
1146 if (!psdev->dev)
1147 continue;
1148 dev_data = pci_get_drvdata(psdev->dev);
1149 if (!dev_data || !dev_data->permissive)
1150 continue;
1151 count +=
1152 scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
1153 pci_name(psdev->dev));
1154 }
1155 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
1156 return count;
1157}
1158
1159DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
1160
1161static void pcistub_exit(void)
1162{
1163 driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot);
1164 driver_remove_file(&pciback_pci_driver.driver,
1165 &driver_attr_remove_slot);
1166 driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
1167 driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
1168 driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
1169
1170 pci_unregister_driver(&pciback_pci_driver);
1171}
1172
1173static int __init pcistub_init(void)
1174{
1175 int pos = 0;
1176 int err = 0;
1177 int domain, bus, slot, func;
1178 int parsed;
1179
1180 if (pci_devs_to_hide && *pci_devs_to_hide) {
1181 do {
1182 parsed = 0;
1183
1184 err = sscanf(pci_devs_to_hide + pos,
1185 " (%x:%x:%x.%x) %n",
1186 &domain, &bus, &slot, &func, &parsed);
1187 if (err != 4) {
1188 domain = 0;
1189 err = sscanf(pci_devs_to_hide + pos,
1190 " (%x:%x.%x) %n",
1191 &bus, &slot, &func, &parsed);
1192 if (err != 3)
1193 goto parse_error;
1194 }
1195
1196 err = pcistub_device_id_add(domain, bus, slot, func);
1197 if (err)
1198 goto out;
1199
1200 /* if parsed<=0, we've reached the end of the string */
1201 pos += parsed;
1202 } while (parsed > 0 && pci_devs_to_hide[pos]);
1203 }
1204
1205 /* If we're the first PCI Device Driver to register, we're the
1206 * first one to get offered PCI devices as they become
1207 * available (and thus we can be the first to grab them)
1208 */
1209 err = pci_register_driver(&pciback_pci_driver);
1210 if (err < 0)
1211 goto out;
1212
1213 err = driver_create_file(&pciback_pci_driver.driver,
1214 &driver_attr_new_slot);
1215 if (!err)
1216 err = driver_create_file(&pciback_pci_driver.driver,
1217 &driver_attr_remove_slot);
1218 if (!err)
1219 err = driver_create_file(&pciback_pci_driver.driver,
1220 &driver_attr_slots);
1221 if (!err)
1222 err = driver_create_file(&pciback_pci_driver.driver,
1223 &driver_attr_quirks);
1224 if (!err)
1225 err = driver_create_file(&pciback_pci_driver.driver,
1226 &driver_attr_permissive);
1227
1228 if (err)
1229 pcistub_exit();
1230
1231out:
1232 return err;
1233
1234parse_error:
1235 printk(KERN_ERR "pciback: Error parsing pci_devs_to_hide at \"%s\"\n",
1236 pci_devs_to_hide + pos);
1237 return -EINVAL;
1238}
1239
1240#ifndef MODULE
1241/*
1242 * fs_initcall happens before device_initcall
1243 * so pciback *should* get called first (b/c we
1244 * want to suck up any device before other drivers
1245 * get a chance by being the first pci device
1246 * driver to register)
1247 */
1248fs_initcall(pcistub_init);
1249#endif
1250
1251static int __init pciback_init(void)
1252{
1253 int err;
1254
1255 if (!xen_initial_domain())
1256 return -ENODEV;
1257
1258 err = pciback_config_init();
1259 if (err)
1260 return err;
1261
1262#ifdef MODULE
1263 err = pcistub_init();
1264 if (err < 0)
1265 return err;
1266#endif
1267
1268 pcistub_init_devices_late();
1269 err = pciback_xenbus_register();
1270 if (err)
1271 pcistub_exit();
1272
1273 return err;
1274}
1275
1276static void __exit pciback_cleanup(void)
1277{
1278 pciback_xenbus_unregister();
1279 pcistub_exit();
1280}
1281
1282module_init(pciback_init);
1283module_exit(pciback_cleanup);
1284
1285MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
new file mode 100644
index 000000000000..98e29127abf9
--- /dev/null
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -0,0 +1,133 @@
1/*
2 * PCI Backend Common Data Structures & Function Declarations
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6#ifndef __XEN_PCIBACK_H__
7#define __XEN_PCIBACK_H__
8
9#include <linux/pci.h>
10#include <linux/interrupt.h>
11#include <xen/xenbus.h>
12#include <linux/list.h>
13#include <linux/spinlock.h>
14#include <linux/workqueue.h>
15#include <asm/atomic.h>
16#include <xen/interface/io/pciif.h>
17
18struct pci_dev_entry {
19 struct list_head list;
20 struct pci_dev *dev;
21};
22
23#define _PDEVF_op_active (0)
24#define PDEVF_op_active (1<<(_PDEVF_op_active))
25#define _PCIB_op_pending (1)
26#define PCIB_op_pending (1<<(_PCIB_op_pending))
27
28struct pciback_device {
29 void *pci_dev_data;
30 spinlock_t dev_lock;
31
32 struct xenbus_device *xdev;
33
34 struct xenbus_watch be_watch;
35 u8 be_watching;
36
37 int evtchn_irq;
38
39 struct xen_pci_sharedinfo *sh_info;
40
41 unsigned long flags;
42
43 struct work_struct op_work;
44};
45
46struct pciback_dev_data {
47 struct list_head config_fields;
48 int permissive;
49 int warned_on_write;
50};
51
52/* Used by XenBus and pciback_ops.c */
53extern wait_queue_head_t aer_wait_queue;
54extern struct workqueue_struct *pciback_wq;
55/* Used by pcistub.c and conf_space_quirks.c */
56extern struct list_head pciback_quirks;
57
58/* Get/Put PCI Devices that are hidden from the PCI Backend Domain */
59struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
60 int domain, int bus,
61 int slot, int func);
62struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
63 struct pci_dev *dev);
64void pcistub_put_pci_dev(struct pci_dev *dev);
65
66/* Ensure a device is turned off or reset */
67void pciback_reset_device(struct pci_dev *pdev);
68
69/* Access a virtual configuration space for a PCI device */
70int pciback_config_init(void);
71int pciback_config_init_dev(struct pci_dev *dev);
72void pciback_config_free_dyn_fields(struct pci_dev *dev);
73void pciback_config_reset_dev(struct pci_dev *dev);
74void pciback_config_free_dev(struct pci_dev *dev);
75int pciback_config_read(struct pci_dev *dev, int offset, int size,
76 u32 *ret_val);
77int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value);
78
79/* Handle requests for specific devices from the frontend */
80typedef int (*publish_pci_dev_cb) (struct pciback_device *pdev,
81 unsigned int domain, unsigned int bus,
82 unsigned int devfn, unsigned int devid);
83typedef int (*publish_pci_root_cb) (struct pciback_device *pdev,
84 unsigned int domain, unsigned int bus);
85int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
86 int devid, publish_pci_dev_cb publish_cb);
87void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
88struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
89 unsigned int domain, unsigned int bus,
90 unsigned int devfn);
91
92/**
93* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in pciback
94* before sending aer request to pcifront, so that guest could identify
95* device, coopearte with pciback to finish aer recovery job if device driver
96* has the capability
97*/
98
99int pciback_get_pcifront_dev(struct pci_dev *pcidev,
100 struct pciback_device *pdev,
101 unsigned int *domain, unsigned int *bus,
102 unsigned int *devfn);
103int pciback_init_devices(struct pciback_device *pdev);
104int pciback_publish_pci_roots(struct pciback_device *pdev,
105 publish_pci_root_cb cb);
106void pciback_release_devices(struct pciback_device *pdev);
107
108/* Handles events from front-end */
109irqreturn_t pciback_handle_event(int irq, void *dev_id);
110void pciback_do_op(struct work_struct *data);
111
112int pciback_xenbus_register(void);
113void pciback_xenbus_unregister(void);
114
115#ifdef CONFIG_PCI_MSI
116int pciback_enable_msi(struct pciback_device *pdev,
117 struct pci_dev *dev, struct xen_pci_op *op);
118
119int pciback_disable_msi(struct pciback_device *pdev,
120 struct pci_dev *dev, struct xen_pci_op *op);
121
122
123int pciback_enable_msix(struct pciback_device *pdev,
124 struct pci_dev *dev, struct xen_pci_op *op);
125
126int pciback_disable_msix(struct pciback_device *pdev,
127 struct pci_dev *dev, struct xen_pci_op *op);
128#endif
129extern int verbose_request;
130
131void test_and_schedule_op(struct pciback_device *pdev);
132#endif
133
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
new file mode 100644
index 000000000000..2b9a93e1fdee
--- /dev/null
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -0,0 +1,131 @@
1/*
2 * PCI Backend Operations - respond to PCI requests from Frontend
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6#include <linux/module.h>
7#include <linux/wait.h>
8#include <linux/bitops.h>
9#include <xen/events.h>
10#include <linux/sched.h>
11#include "pciback.h"
12
13int verbose_request;
14module_param(verbose_request, int, 0644);
15
16/* Ensure a device is "turned off" and ready to be exported.
17 * (Also see pciback_config_reset to ensure virtual configuration space is
18 * ready to be re-exported)
19 */
20void pciback_reset_device(struct pci_dev *dev)
21{
22 u16 cmd;
23
24 /* Disable devices (but not bridges) */
25 if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
26 pci_disable_device(dev);
27
28 pci_write_config_word(dev, PCI_COMMAND, 0);
29
30 dev->is_busmaster = 0;
31 } else {
32 pci_read_config_word(dev, PCI_COMMAND, &cmd);
33 if (cmd & (PCI_COMMAND_INVALIDATE)) {
34 cmd &= ~(PCI_COMMAND_INVALIDATE);
35 pci_write_config_word(dev, PCI_COMMAND, cmd);
36
37 dev->is_busmaster = 0;
38 }
39 }
40}
41/*
42* Now the same evtchn is used for both pcifront conf_read_write request
43* as well as pcie aer front end ack. We use a new work_queue to schedule
44* pciback conf_read_write service for avoiding confict with aer_core
45* do_recovery job which also use the system default work_queue
46*/
47void test_and_schedule_op(struct pciback_device *pdev)
48{
49 /* Check that frontend is requesting an operation and that we are not
50 * already processing a request */
51 if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)
52 && !test_and_set_bit(_PDEVF_op_active, &pdev->flags)) {
53 queue_work(pciback_wq, &pdev->op_work);
54 }
55 /*_XEN_PCIB_active should have been cleared by pcifront. And also make
56 sure pciback is waiting for ack by checking _PCIB_op_pending*/
57 if (!test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags)
58 && test_bit(_PCIB_op_pending, &pdev->flags)) {
59 wake_up(&aer_wait_queue);
60 }
61}
62
63/* Performing the configuration space reads/writes must not be done in atomic
64 * context because some of the pci_* functions can sleep (mostly due to ACPI
65 * use of semaphores). This function is intended to be called from a work
66 * queue in process context taking a struct pciback_device as a parameter */
67
68void pciback_do_op(struct work_struct *data)
69{
70 struct pciback_device *pdev =
71 container_of(data, struct pciback_device, op_work);
72 struct pci_dev *dev;
73 struct xen_pci_op *op = &pdev->sh_info->op;
74
75 dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
76
77 if (dev == NULL)
78 op->err = XEN_PCI_ERR_dev_not_found;
79 else {
80 switch (op->cmd) {
81 case XEN_PCI_OP_conf_read:
82 op->err = pciback_config_read(dev,
83 op->offset, op->size, &op->value);
84 break;
85 case XEN_PCI_OP_conf_write:
86 op->err = pciback_config_write(dev,
87 op->offset, op->size, op->value);
88 break;
89#ifdef CONFIG_PCI_MSI
90 case XEN_PCI_OP_enable_msi:
91 op->err = pciback_enable_msi(pdev, dev, op);
92 break;
93 case XEN_PCI_OP_disable_msi:
94 op->err = pciback_disable_msi(pdev, dev, op);
95 break;
96 case XEN_PCI_OP_enable_msix:
97 op->err = pciback_enable_msix(pdev, dev, op);
98 break;
99 case XEN_PCI_OP_disable_msix:
100 op->err = pciback_disable_msix(pdev, dev, op);
101 break;
102#endif
103 default:
104 op->err = XEN_PCI_ERR_not_implemented;
105 break;
106 }
107 }
108 /* Tell the driver domain that we're done. */
109 wmb();
110 clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
111 notify_remote_via_irq(pdev->evtchn_irq);
112
113 /* Mark that we're done. */
114 smp_mb__before_clear_bit(); /* /after/ clearing PCIF_active */
115 clear_bit(_PDEVF_op_active, &pdev->flags);
116 smp_mb__after_clear_bit(); /* /before/ final check for work */
117
118 /* Check to see if the driver domain tried to start another request in
119 * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active.
120 */
121 test_and_schedule_op(pdev);
122}
123
124irqreturn_t pciback_handle_event(int irq, void *dev_id)
125{
126 struct pciback_device *pdev = dev_id;
127
128 test_and_schedule_op(pdev);
129
130 return IRQ_HANDLED;
131}
diff --git a/drivers/xen/xen-pciback/slot.c b/drivers/xen/xen-pciback/slot.c
new file mode 100644
index 000000000000..efb922d6f78e
--- /dev/null
+++ b/drivers/xen/xen-pciback/slot.c
@@ -0,0 +1,191 @@
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> (vpci.c)
6 * Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
7 */
8
9#include <linux/list.h>
10#include <linux/slab.h>
11#include <linux/pci.h>
12#include <linux/spinlock.h>
13#include "pciback.h"
14
15/* There are at most 32 slots in a pci bus. */
16#define PCI_SLOT_MAX 32
17
18#define PCI_BUS_NBR 2
19
20struct slot_dev_data {
21 /* Access to dev_list must be protected by lock */
22 struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
23 spinlock_t lock;
24};
25
26struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
27 unsigned int domain, unsigned int bus,
28 unsigned int devfn)
29{
30 struct pci_dev *dev = NULL;
31 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
32 unsigned long flags;
33
34 if (domain != 0 || PCI_FUNC(devfn) != 0)
35 return NULL;
36
37 if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
38 return NULL;
39
40 spin_lock_irqsave(&slot_dev->lock, flags);
41 dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
42 spin_unlock_irqrestore(&slot_dev->lock, flags);
43
44 return dev;
45}
46
47int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
48 int devid, publish_pci_dev_cb publish_cb)
49{
50 int err = 0, slot, bus;
51 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
52 unsigned long flags;
53
54 if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
55 err = -EFAULT;
56 xenbus_dev_fatal(pdev->xdev, err,
57 "Can't export bridges on the virtual PCI bus");
58 goto out;
59 }
60
61 spin_lock_irqsave(&slot_dev->lock, flags);
62
63 /* Assign to a new slot on the virtual PCI bus */
64 for (bus = 0; bus < PCI_BUS_NBR; bus++)
65 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
66 if (slot_dev->slots[bus][slot] == NULL) {
67 printk(KERN_INFO
68 "pciback: slot: %s: assign to virtual "
69 "slot %d, bus %d\n",
70 pci_name(dev), slot, bus);
71 slot_dev->slots[bus][slot] = dev;
72 goto unlock;
73 }
74 }
75
76 err = -ENOMEM;
77 xenbus_dev_fatal(pdev->xdev, err,
78 "No more space on root virtual PCI bus");
79
80unlock:
81 spin_unlock_irqrestore(&slot_dev->lock, flags);
82
83 /* Publish this device. */
84 if (!err)
85 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, 0), devid);
86
87out:
88 return err;
89}
90
91void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
92{
93 int slot, bus;
94 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
95 struct pci_dev *found_dev = NULL;
96 unsigned long flags;
97
98 spin_lock_irqsave(&slot_dev->lock, flags);
99
100 for (bus = 0; bus < PCI_BUS_NBR; bus++)
101 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
102 if (slot_dev->slots[bus][slot] == dev) {
103 slot_dev->slots[bus][slot] = NULL;
104 found_dev = dev;
105 goto out;
106 }
107 }
108
109out:
110 spin_unlock_irqrestore(&slot_dev->lock, flags);
111
112 if (found_dev)
113 pcistub_put_pci_dev(found_dev);
114}
115
116int pciback_init_devices(struct pciback_device *pdev)
117{
118 int slot, bus;
119 struct slot_dev_data *slot_dev;
120
121 slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
122 if (!slot_dev)
123 return -ENOMEM;
124
125 spin_lock_init(&slot_dev->lock);
126
127 for (bus = 0; bus < PCI_BUS_NBR; bus++)
128 for (slot = 0; slot < PCI_SLOT_MAX; slot++)
129 slot_dev->slots[bus][slot] = NULL;
130
131 pdev->pci_dev_data = slot_dev;
132
133 return 0;
134}
135
136int pciback_publish_pci_roots(struct pciback_device *pdev,
137 publish_pci_root_cb publish_cb)
138{
139 /* The Virtual PCI bus has only one root */
140 return publish_cb(pdev, 0, 0);
141}
142
143void pciback_release_devices(struct pciback_device *pdev)
144{
145 int slot, bus;
146 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
147 struct pci_dev *dev;
148
149 for (bus = 0; bus < PCI_BUS_NBR; bus++)
150 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
151 dev = slot_dev->slots[bus][slot];
152 if (dev != NULL)
153 pcistub_put_pci_dev(dev);
154 }
155
156 kfree(slot_dev);
157 pdev->pci_dev_data = NULL;
158}
159
160int pciback_get_pcifront_dev(struct pci_dev *pcidev,
161 struct pciback_device *pdev,
162 unsigned int *domain, unsigned int *bus,
163 unsigned int *devfn)
164{
165 int slot, busnr;
166 struct slot_dev_data *slot_dev = pdev->pci_dev_data;
167 struct pci_dev *dev;
168 int found = 0;
169 unsigned long flags;
170
171 spin_lock_irqsave(&slot_dev->lock, flags);
172
173 for (busnr = 0; busnr < PCI_BUS_NBR; bus++)
174 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
175 dev = slot_dev->slots[busnr][slot];
176 if (dev && dev->bus->number == pcidev->bus->number
177 && dev->devfn == pcidev->devfn
178 && pci_domain_nr(dev->bus) ==
179 pci_domain_nr(pcidev->bus)) {
180 found = 1;
181 *domain = 0;
182 *bus = busnr;
183 *devfn = PCI_DEVFN(slot, 0);
184 goto out;
185 }
186 }
187out:
188 spin_unlock_irqrestore(&slot_dev->lock, flags);
189 return found;
190
191}
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c
new file mode 100644
index 000000000000..2857ab892f02
--- /dev/null
+++ b/drivers/xen/xen-pciback/vpci.c
@@ -0,0 +1,244 @@
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#include <linux/list.h>
9#include <linux/slab.h>
10#include <linux/pci.h>
11#include <linux/spinlock.h>
12#include "pciback.h"
13
14#define PCI_SLOT_MAX 32
15
16struct vpci_dev_data {
17 /* Access to dev_list must be protected by lock */
18 struct list_head dev_list[PCI_SLOT_MAX];
19 spinlock_t lock;
20};
21
22static inline struct list_head *list_first(struct list_head *head)
23{
24 return head->next;
25}
26
27struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
28 unsigned int domain, unsigned int bus,
29 unsigned int devfn)
30{
31 struct pci_dev_entry *entry;
32 struct pci_dev *dev = NULL;
33 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
34 unsigned long flags;
35
36 if (domain != 0 || bus != 0)
37 return NULL;
38
39 if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
40 spin_lock_irqsave(&vpci_dev->lock, flags);
41
42 list_for_each_entry(entry,
43 &vpci_dev->dev_list[PCI_SLOT(devfn)],
44 list) {
45 if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
46 dev = entry->dev;
47 break;
48 }
49 }
50
51 spin_unlock_irqrestore(&vpci_dev->lock, flags);
52 }
53 return dev;
54}
55
56static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
57{
58 if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
59 && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
60 return 1;
61
62 return 0;
63}
64
65int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
66 int devid, publish_pci_dev_cb publish_cb)
67{
68 int err = 0, slot, func = -1;
69 struct pci_dev_entry *t, *dev_entry;
70 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
71 unsigned long flags;
72
73 if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
74 err = -EFAULT;
75 xenbus_dev_fatal(pdev->xdev, err,
76 "Can't export bridges on the virtual PCI bus");
77 goto out;
78 }
79
80 dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
81 if (!dev_entry) {
82 err = -ENOMEM;
83 xenbus_dev_fatal(pdev->xdev, err,
84 "Error adding entry to virtual PCI bus");
85 goto out;
86 }
87
88 dev_entry->dev = dev;
89
90 spin_lock_irqsave(&vpci_dev->lock, flags);
91
92 /* Keep multi-function devices together on the virtual PCI bus */
93 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
94 if (!list_empty(&vpci_dev->dev_list[slot])) {
95 t = list_entry(list_first(&vpci_dev->dev_list[slot]),
96 struct pci_dev_entry, list);
97
98 if (match_slot(dev, t->dev)) {
99 pr_info("pciback: vpci: %s: "
100 "assign to virtual slot %d func %d\n",
101 pci_name(dev), slot,
102 PCI_FUNC(dev->devfn));
103 list_add_tail(&dev_entry->list,
104 &vpci_dev->dev_list[slot]);
105 func = PCI_FUNC(dev->devfn);
106 goto unlock;
107 }
108 }
109 }
110
111 /* Assign to a new slot on the virtual PCI bus */
112 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
113 if (list_empty(&vpci_dev->dev_list[slot])) {
114 printk(KERN_INFO
115 "pciback: vpci: %s: assign to virtual slot %d\n",
116 pci_name(dev), slot);
117 list_add_tail(&dev_entry->list,
118 &vpci_dev->dev_list[slot]);
119 func = PCI_FUNC(dev->devfn);
120 goto unlock;
121 }
122 }
123
124 err = -ENOMEM;
125 xenbus_dev_fatal(pdev->xdev, err,
126 "No more space on root virtual PCI bus");
127
128unlock:
129 spin_unlock_irqrestore(&vpci_dev->lock, flags);
130
131 /* Publish this device. */
132 if (!err)
133 err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
134
135out:
136 return err;
137}
138
139void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
140{
141 int slot;
142 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
143 struct pci_dev *found_dev = NULL;
144 unsigned long flags;
145
146 spin_lock_irqsave(&vpci_dev->lock, flags);
147
148 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
149 struct pci_dev_entry *e, *tmp;
150 list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
151 list) {
152 if (e->dev == dev) {
153 list_del(&e->list);
154 found_dev = e->dev;
155 kfree(e);
156 goto out;
157 }
158 }
159 }
160
161out:
162 spin_unlock_irqrestore(&vpci_dev->lock, flags);
163
164 if (found_dev)
165 pcistub_put_pci_dev(found_dev);
166}
167
168int pciback_init_devices(struct pciback_device *pdev)
169{
170 int slot;
171 struct vpci_dev_data *vpci_dev;
172
173 vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
174 if (!vpci_dev)
175 return -ENOMEM;
176
177 spin_lock_init(&vpci_dev->lock);
178
179 for (slot = 0; slot < PCI_SLOT_MAX; slot++)
180 INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
181
182 pdev->pci_dev_data = vpci_dev;
183
184 return 0;
185}
186
187int pciback_publish_pci_roots(struct pciback_device *pdev,
188 publish_pci_root_cb publish_cb)
189{
190 /* The Virtual PCI bus has only one root */
191 return publish_cb(pdev, 0, 0);
192}
193
194void pciback_release_devices(struct pciback_device *pdev)
195{
196 int slot;
197 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
198
199 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
200 struct pci_dev_entry *e, *tmp;
201 list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
202 list) {
203 list_del(&e->list);
204 pcistub_put_pci_dev(e->dev);
205 kfree(e);
206 }
207 }
208
209 kfree(vpci_dev);
210 pdev->pci_dev_data = NULL;
211}
212
213int pciback_get_pcifront_dev(struct pci_dev *pcidev,
214 struct pciback_device *pdev,
215 unsigned int *domain, unsigned int *bus,
216 unsigned int *devfn)
217{
218 struct pci_dev_entry *entry;
219 struct pci_dev *dev = NULL;
220 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
221 unsigned long flags;
222 int found = 0, slot;
223
224 spin_lock_irqsave(&vpci_dev->lock, flags);
225 for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
226 list_for_each_entry(entry,
227 &vpci_dev->dev_list[slot],
228 list) {
229 dev = entry->dev;
230 if (dev && dev->bus->number == pcidev->bus->number
231 && pci_domain_nr(dev->bus) ==
232 pci_domain_nr(pcidev->bus)
233 && dev->devfn == pcidev->devfn) {
234 found = 1;
235 *domain = 0;
236 *bus = 0;
237 *devfn = PCI_DEVFN(slot,
238 PCI_FUNC(pcidev->devfn));
239 }
240 }
241 }
242 spin_unlock_irqrestore(&vpci_dev->lock, flags);
243 return found;
244}
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
new file mode 100644
index 000000000000..af6c25a1d729
--- /dev/null
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -0,0 +1,709 @@
1/*
2 * PCI Backend Xenbus Setup - handles setup with frontend and xend
3 *
4 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
5 */
6#include <linux/module.h>
7#include <linux/init.h>
8#include <linux/list.h>
9#include <linux/vmalloc.h>
10#include <linux/workqueue.h>
11#include <xen/xenbus.h>
12#include <xen/events.h>
13#include <linux/workqueue.h>
14#include "pciback.h"
15
16#define INVALID_EVTCHN_IRQ (-1)
17struct workqueue_struct *pciback_wq;
18
19static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
20{
21 struct pciback_device *pdev;
22
23 pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL);
24 if (pdev == NULL)
25 goto out;
26 dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
27
28 pdev->xdev = xdev;
29 dev_set_drvdata(&xdev->dev, pdev);
30
31 spin_lock_init(&pdev->dev_lock);
32
33 pdev->sh_info = NULL;
34 pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
35 pdev->be_watching = 0;
36
37 INIT_WORK(&pdev->op_work, pciback_do_op);
38
39 if (pciback_init_devices(pdev)) {
40 kfree(pdev);
41 pdev = NULL;
42 }
43out:
44 return pdev;
45}
46
47static void pciback_disconnect(struct pciback_device *pdev)
48{
49 spin_lock(&pdev->dev_lock);
50
51 /* Ensure the guest can't trigger our handler before removing devices */
52 if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
53 unbind_from_irqhandler(pdev->evtchn_irq, pdev);
54 pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
55 }
56
57 /* If the driver domain started an op, make sure we complete it
58 * before releasing the shared memory */
59 flush_workqueue(pciback_wq);
60
61 if (pdev->sh_info != NULL) {
62 xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info);
63 pdev->sh_info = NULL;
64 }
65
66 spin_unlock(&pdev->dev_lock);
67}
68
69static void free_pdev(struct pciback_device *pdev)
70{
71 if (pdev->be_watching)
72 unregister_xenbus_watch(&pdev->be_watch);
73
74 pciback_disconnect(pdev);
75
76 pciback_release_devices(pdev);
77
78 dev_set_drvdata(&pdev->xdev->dev, NULL);
79 pdev->xdev = NULL;
80
81 kfree(pdev);
82}
83
84static int pciback_do_attach(struct pciback_device *pdev, int gnt_ref,
85 int remote_evtchn)
86{
87 int err = 0;
88 void *vaddr;
89
90 dev_dbg(&pdev->xdev->dev,
91 "Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
92 gnt_ref, remote_evtchn);
93
94 err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr);
95 if (err < 0) {
96 xenbus_dev_fatal(pdev->xdev, err,
97 "Error mapping other domain page in ours.");
98 goto out;
99 }
100 pdev->sh_info = vaddr;
101
102 err = bind_interdomain_evtchn_to_irqhandler(
103 pdev->xdev->otherend_id, remote_evtchn, pciback_handle_event,
104 0, "pciback", pdev);
105 if (err < 0) {
106 xenbus_dev_fatal(pdev->xdev, err,
107 "Error binding event channel to IRQ");
108 goto out;
109 }
110 pdev->evtchn_irq = err;
111 err = 0;
112
113 dev_dbg(&pdev->xdev->dev, "Attached!\n");
114out:
115 return err;
116}
117
118static int pciback_attach(struct pciback_device *pdev)
119{
120 int err = 0;
121 int gnt_ref, remote_evtchn;
122 char *magic = NULL;
123
124 spin_lock(&pdev->dev_lock);
125
126 /* Make sure we only do this setup once */
127 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
128 XenbusStateInitialised)
129 goto out;
130
131 /* Wait for frontend to state that it has published the configuration */
132 if (xenbus_read_driver_state(pdev->xdev->otherend) !=
133 XenbusStateInitialised)
134 goto out;
135
136 dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
137
138 err = xenbus_gather(XBT_NIL, pdev->xdev->otherend,
139 "pci-op-ref", "%u", &gnt_ref,
140 "event-channel", "%u", &remote_evtchn,
141 "magic", NULL, &magic, NULL);
142 if (err) {
143 /* If configuration didn't get read correctly, wait longer */
144 xenbus_dev_fatal(pdev->xdev, err,
145 "Error reading configuration from frontend");
146 goto out;
147 }
148
149 if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
150 xenbus_dev_fatal(pdev->xdev, -EFAULT,
151 "version mismatch (%s/%s) with pcifront - "
152 "halting pciback",
153 magic, XEN_PCI_MAGIC);
154 goto out;
155 }
156
157 err = pciback_do_attach(pdev, gnt_ref, remote_evtchn);
158 if (err)
159 goto out;
160
161 dev_dbg(&pdev->xdev->dev, "Connecting...\n");
162
163 err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
164 if (err)
165 xenbus_dev_fatal(pdev->xdev, err,
166 "Error switching to connected state!");
167
168 dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
169out:
170 spin_unlock(&pdev->dev_lock);
171
172 kfree(magic);
173
174 return err;
175}
176
177static int pciback_publish_pci_dev(struct pciback_device *pdev,
178 unsigned int domain, unsigned int bus,
179 unsigned int devfn, unsigned int devid)
180{
181 int err;
182 int len;
183 char str[64];
184
185 len = snprintf(str, sizeof(str), "vdev-%d", devid);
186 if (unlikely(len >= (sizeof(str) - 1))) {
187 err = -ENOMEM;
188 goto out;
189 }
190
191 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
192 "%04x:%02x:%02x.%02x", domain, bus,
193 PCI_SLOT(devfn), PCI_FUNC(devfn));
194
195out:
196 return err;
197}
198
199static int pciback_export_device(struct pciback_device *pdev,
200 int domain, int bus, int slot, int func,
201 int devid)
202{
203 struct pci_dev *dev;
204 int err = 0;
205
206 dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
207 domain, bus, slot, func);
208
209 dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
210 if (!dev) {
211 err = -EINVAL;
212 xenbus_dev_fatal(pdev->xdev, err,
213 "Couldn't locate PCI device "
214 "(%04x:%02x:%02x.%01x)! "
215 "perhaps already in-use?",
216 domain, bus, slot, func);
217 goto out;
218 }
219
220 err = pciback_add_pci_dev(pdev, dev, devid, pciback_publish_pci_dev);
221 if (err)
222 goto out;
223
224 /* TODO: It'd be nice to export a bridge and have all of its children
225 * get exported with it. This may be best done in xend (which will
226 * have to calculate resource usage anyway) but we probably want to
227 * put something in here to ensure that if a bridge gets given to a
228 * driver domain, that all devices under that bridge are not given
229 * to other driver domains (as he who controls the bridge can disable
230 * it and stop the other devices from working).
231 */
232out:
233 return err;
234}
235
236static int pciback_remove_device(struct pciback_device *pdev,
237 int domain, int bus, int slot, int func)
238{
239 int err = 0;
240 struct pci_dev *dev;
241
242 dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n",
243 domain, bus, slot, func);
244
245 dev = pciback_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func));
246 if (!dev) {
247 err = -EINVAL;
248 dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
249 "(%04x:%02x:%02x.%01x)! not owned by this domain\n",
250 domain, bus, slot, func);
251 goto out;
252 }
253
254 pciback_release_pci_dev(pdev, dev);
255
256out:
257 return err;
258}
259
260static int pciback_publish_pci_root(struct pciback_device *pdev,
261 unsigned int domain, unsigned int bus)
262{
263 unsigned int d, b;
264 int i, root_num, len, err;
265 char str[64];
266
267 dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
268
269 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
270 "root_num", "%d", &root_num);
271 if (err == 0 || err == -ENOENT)
272 root_num = 0;
273 else if (err < 0)
274 goto out;
275
276 /* Verify that we haven't already published this pci root */
277 for (i = 0; i < root_num; i++) {
278 len = snprintf(str, sizeof(str), "root-%d", i);
279 if (unlikely(len >= (sizeof(str) - 1))) {
280 err = -ENOMEM;
281 goto out;
282 }
283
284 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
285 str, "%x:%x", &d, &b);
286 if (err < 0)
287 goto out;
288 if (err != 2) {
289 err = -EINVAL;
290 goto out;
291 }
292
293 if (d == domain && b == bus) {
294 err = 0;
295 goto out;
296 }
297 }
298
299 len = snprintf(str, sizeof(str), "root-%d", root_num);
300 if (unlikely(len >= (sizeof(str) - 1))) {
301 err = -ENOMEM;
302 goto out;
303 }
304
305 dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
306 root_num, domain, bus);
307
308 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
309 "%04x:%02x", domain, bus);
310 if (err)
311 goto out;
312
313 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
314 "root_num", "%d", (root_num + 1));
315
316out:
317 return err;
318}
319
320static int pciback_reconfigure(struct pciback_device *pdev)
321{
322 int err = 0;
323 int num_devs;
324 int domain, bus, slot, func;
325 int substate;
326 int i, len;
327 char state_str[64];
328 char dev_str[64];
329
330 spin_lock(&pdev->dev_lock);
331
332 dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
333
334 /* Make sure we only reconfigure once */
335 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
336 XenbusStateReconfiguring)
337 goto out;
338
339 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
340 &num_devs);
341 if (err != 1) {
342 if (err >= 0)
343 err = -EINVAL;
344 xenbus_dev_fatal(pdev->xdev, err,
345 "Error reading number of devices");
346 goto out;
347 }
348
349 for (i = 0; i < num_devs; i++) {
350 len = snprintf(state_str, sizeof(state_str), "state-%d", i);
351 if (unlikely(len >= (sizeof(state_str) - 1))) {
352 err = -ENOMEM;
353 xenbus_dev_fatal(pdev->xdev, err,
354 "String overflow while reading "
355 "configuration");
356 goto out;
357 }
358 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str,
359 "%d", &substate);
360 if (err != 1)
361 substate = XenbusStateUnknown;
362
363 switch (substate) {
364 case XenbusStateInitialising:
365 dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i);
366
367 len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
368 if (unlikely(len >= (sizeof(dev_str) - 1))) {
369 err = -ENOMEM;
370 xenbus_dev_fatal(pdev->xdev, err,
371 "String overflow while "
372 "reading configuration");
373 goto out;
374 }
375 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
376 dev_str, "%x:%x:%x.%x",
377 &domain, &bus, &slot, &func);
378 if (err < 0) {
379 xenbus_dev_fatal(pdev->xdev, err,
380 "Error reading device "
381 "configuration");
382 goto out;
383 }
384 if (err != 4) {
385 err = -EINVAL;
386 xenbus_dev_fatal(pdev->xdev, err,
387 "Error parsing pci device "
388 "configuration");
389 goto out;
390 }
391
392 err = pciback_export_device(pdev, domain, bus, slot,
393 func, i);
394 if (err)
395 goto out;
396
397 /* Publish pci roots. */
398 err = pciback_publish_pci_roots(pdev,
399 pciback_publish_pci_root);
400 if (err) {
401 xenbus_dev_fatal(pdev->xdev, err,
402 "Error while publish PCI root"
403 "buses for frontend");
404 goto out;
405 }
406
407 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
408 state_str, "%d",
409 XenbusStateInitialised);
410 if (err) {
411 xenbus_dev_fatal(pdev->xdev, err,
412 "Error switching substate of "
413 "dev-%d\n", i);
414 goto out;
415 }
416 break;
417
418 case XenbusStateClosing:
419 dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i);
420
421 len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i);
422 if (unlikely(len >= (sizeof(dev_str) - 1))) {
423 err = -ENOMEM;
424 xenbus_dev_fatal(pdev->xdev, err,
425 "String overflow while "
426 "reading configuration");
427 goto out;
428 }
429 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
430 dev_str, "%x:%x:%x.%x",
431 &domain, &bus, &slot, &func);
432 if (err < 0) {
433 xenbus_dev_fatal(pdev->xdev, err,
434 "Error reading device "
435 "configuration");
436 goto out;
437 }
438 if (err != 4) {
439 err = -EINVAL;
440 xenbus_dev_fatal(pdev->xdev, err,
441 "Error parsing pci device "
442 "configuration");
443 goto out;
444 }
445
446 err = pciback_remove_device(pdev, domain, bus, slot,
447 func);
448 if (err)
449 goto out;
450
451 /* TODO: If at some point we implement support for pci
452 * root hot-remove on pcifront side, we'll need to
453 * remove unnecessary xenstore nodes of pci roots here.
454 */
455
456 break;
457
458 default:
459 break;
460 }
461 }
462
463 err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured);
464 if (err) {
465 xenbus_dev_fatal(pdev->xdev, err,
466 "Error switching to reconfigured state!");
467 goto out;
468 }
469
470out:
471 spin_unlock(&pdev->dev_lock);
472
473 return 0;
474}
475
476static void pciback_frontend_changed(struct xenbus_device *xdev,
477 enum xenbus_state fe_state)
478{
479 struct pciback_device *pdev = dev_get_drvdata(&xdev->dev);
480
481 dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
482
483 switch (fe_state) {
484 case XenbusStateInitialised:
485 pciback_attach(pdev);
486 break;
487
488 case XenbusStateReconfiguring:
489 pciback_reconfigure(pdev);
490 break;
491
492 case XenbusStateConnected:
493 /* pcifront switched its state from reconfiguring to connected.
494 * Then switch to connected state.
495 */
496 xenbus_switch_state(xdev, XenbusStateConnected);
497 break;
498
499 case XenbusStateClosing:
500 pciback_disconnect(pdev);
501 xenbus_switch_state(xdev, XenbusStateClosing);
502 break;
503
504 case XenbusStateClosed:
505 pciback_disconnect(pdev);
506 xenbus_switch_state(xdev, XenbusStateClosed);
507 if (xenbus_dev_is_online(xdev))
508 break;
509 /* fall through if not online */
510 case XenbusStateUnknown:
511 dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
512 device_unregister(&xdev->dev);
513 break;
514
515 default:
516 break;
517 }
518}
519
520static int pciback_setup_backend(struct pciback_device *pdev)
521{
522 /* Get configuration from xend (if available now) */
523 int domain, bus, slot, func;
524 int err = 0;
525 int i, num_devs;
526 char dev_str[64];
527 char state_str[64];
528
529 spin_lock(&pdev->dev_lock);
530
531 /* It's possible we could get the call to setup twice, so make sure
532 * we're not already connected.
533 */
534 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
535 XenbusStateInitWait)
536 goto out;
537
538 dev_dbg(&pdev->xdev->dev, "getting be setup\n");
539
540 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
541 &num_devs);
542 if (err != 1) {
543 if (err >= 0)
544 err = -EINVAL;
545 xenbus_dev_fatal(pdev->xdev, err,
546 "Error reading number of devices");
547 goto out;
548 }
549
550 for (i = 0; i < num_devs; i++) {
551 int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
552 if (unlikely(l >= (sizeof(dev_str) - 1))) {
553 err = -ENOMEM;
554 xenbus_dev_fatal(pdev->xdev, err,
555 "String overflow while reading "
556 "configuration");
557 goto out;
558 }
559
560 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, dev_str,
561 "%x:%x:%x.%x", &domain, &bus, &slot, &func);
562 if (err < 0) {
563 xenbus_dev_fatal(pdev->xdev, err,
564 "Error reading device configuration");
565 goto out;
566 }
567 if (err != 4) {
568 err = -EINVAL;
569 xenbus_dev_fatal(pdev->xdev, err,
570 "Error parsing pci device "
571 "configuration");
572 goto out;
573 }
574
575 err = pciback_export_device(pdev, domain, bus, slot, func, i);
576 if (err)
577 goto out;
578
579 /* Switch substate of this device. */
580 l = snprintf(state_str, sizeof(state_str), "state-%d", i);
581 if (unlikely(l >= (sizeof(state_str) - 1))) {
582 err = -ENOMEM;
583 xenbus_dev_fatal(pdev->xdev, err,
584 "String overflow while reading "
585 "configuration");
586 goto out;
587 }
588 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str,
589 "%d", XenbusStateInitialised);
590 if (err) {
591 xenbus_dev_fatal(pdev->xdev, err, "Error switching "
592 "substate of dev-%d\n", i);
593 goto out;
594 }
595 }
596
597 err = pciback_publish_pci_roots(pdev, pciback_publish_pci_root);
598 if (err) {
599 xenbus_dev_fatal(pdev->xdev, err,
600 "Error while publish PCI root buses "
601 "for frontend");
602 goto out;
603 }
604
605 err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
606 if (err)
607 xenbus_dev_fatal(pdev->xdev, err,
608 "Error switching to initialised state!");
609
610out:
611 spin_unlock(&pdev->dev_lock);
612
613 if (!err)
614 /* see if pcifront is already configured (if not, we'll wait) */
615 pciback_attach(pdev);
616
617 return err;
618}
619
620static void pciback_be_watch(struct xenbus_watch *watch,
621 const char **vec, unsigned int len)
622{
623 struct pciback_device *pdev =
624 container_of(watch, struct pciback_device, be_watch);
625
626 switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
627 case XenbusStateInitWait:
628 pciback_setup_backend(pdev);
629 break;
630
631 default:
632 break;
633 }
634}
635
636static int pciback_xenbus_probe(struct xenbus_device *dev,
637 const struct xenbus_device_id *id)
638{
639 int err = 0;
640 struct pciback_device *pdev = alloc_pdev(dev);
641
642 if (pdev == NULL) {
643 err = -ENOMEM;
644 xenbus_dev_fatal(dev, err,
645 "Error allocating pciback_device struct");
646 goto out;
647 }
648
649 /* wait for xend to configure us */
650 err = xenbus_switch_state(dev, XenbusStateInitWait);
651 if (err)
652 goto out;
653
654 /* watch the backend node for backend configuration information */
655 err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
656 pciback_be_watch);
657 if (err)
658 goto out;
659 pdev->be_watching = 1;
660
661 /* We need to force a call to our callback here in case
662 * xend already configured us!
663 */
664 pciback_be_watch(&pdev->be_watch, NULL, 0);
665
666out:
667 return err;
668}
669
670static int pciback_xenbus_remove(struct xenbus_device *dev)
671{
672 struct pciback_device *pdev = dev_get_drvdata(&dev->dev);
673
674 if (pdev != NULL)
675 free_pdev(pdev);
676
677 return 0;
678}
679
680static const struct xenbus_device_id xenpci_ids[] = {
681 {"pci"},
682 {""},
683};
684
685static struct xenbus_driver xenbus_pciback_driver = {
686 .name = "pciback",
687 .owner = THIS_MODULE,
688 .ids = xenpci_ids,
689 .probe = pciback_xenbus_probe,
690 .remove = pciback_xenbus_remove,
691 .otherend_changed = pciback_frontend_changed,
692};
693
694int __init pciback_xenbus_register(void)
695{
696 pciback_wq = create_workqueue("pciback_workqueue");
697 if (!pciback_wq) {
698 printk(KERN_ERR "pciback_xenbus_register: create"
699 "pciback_workqueue failed\n");
700 return -EFAULT;
701 }
702 return xenbus_register_backend(&xenbus_pciback_driver);
703}
704
705void __exit pciback_xenbus_unregister(void)
706{
707 destroy_workqueue(pciback_wq);
708 xenbus_unregister_driver(&xenbus_pciback_driver);
709}