blob: a0cf7285d320c3138555099dfdc0e04211399b89 [file] [log] [blame]
Konrad Rzeszutek Wilk30edc142009-10-13 17:22:20 -04001/*
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>
Konrad Rzeszutek Wilk6221a9b2009-12-09 17:43:15 -050013#include <asm/xen/pci.h>
Konrad Rzeszutek Wilk30edc142009-10-13 17:22:20 -040014#include <linux/workqueue.h>
15#include "pciback.h"
16
17#define INVALID_EVTCHN_IRQ (-1)
18struct workqueue_struct *pciback_wq;
19
20static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
21{
22 struct pciback_device *pdev;
23
24 pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL);
25 if (pdev == NULL)
26 goto out;
27 dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
28
29 pdev->xdev = xdev;
30 dev_set_drvdata(&xdev->dev, pdev);
31
32 spin_lock_init(&pdev->dev_lock);
33
34 pdev->sh_info = NULL;
35 pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
36 pdev->be_watching = 0;
37
38 INIT_WORK(&pdev->op_work, pciback_do_op);
39
40 if (pciback_init_devices(pdev)) {
41 kfree(pdev);
42 pdev = NULL;
43 }
44out:
45 return pdev;
46}
47
48static void pciback_disconnect(struct pciback_device *pdev)
49{
50 spin_lock(&pdev->dev_lock);
51
52 /* Ensure the guest can't trigger our handler before removing devices */
53 if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
54 unbind_from_irqhandler(pdev->evtchn_irq, pdev);
55 pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
56 }
57
58 /* If the driver domain started an op, make sure we complete it
59 * before releasing the shared memory */
60 flush_workqueue(pciback_wq);
61
62 if (pdev->sh_info != NULL) {
63 xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info);
64 pdev->sh_info = NULL;
65 }
66
67 spin_unlock(&pdev->dev_lock);
68}
69
70static void free_pdev(struct pciback_device *pdev)
71{
72 if (pdev->be_watching)
73 unregister_xenbus_watch(&pdev->be_watch);
74
75 pciback_disconnect(pdev);
76
77 pciback_release_devices(pdev);
78
79 dev_set_drvdata(&pdev->xdev->dev, NULL);
80 pdev->xdev = NULL;
81
82 kfree(pdev);
83}
84
85static int pciback_do_attach(struct pciback_device *pdev, int gnt_ref,
86 int remote_evtchn)
87{
88 int err = 0;
89 void *vaddr;
90
91 dev_dbg(&pdev->xdev->dev,
92 "Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
93 gnt_ref, remote_evtchn);
94
95 err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr);
96 if (err < 0) {
97 xenbus_dev_fatal(pdev->xdev, err,
98 "Error mapping other domain page in ours.");
99 goto out;
100 }
101 pdev->sh_info = vaddr;
102
103 err = bind_interdomain_evtchn_to_irqhandler(
104 pdev->xdev->otherend_id, remote_evtchn, pciback_handle_event,
105 0, "pciback", pdev);
106 if (err < 0) {
107 xenbus_dev_fatal(pdev->xdev, err,
108 "Error binding event channel to IRQ");
109 goto out;
110 }
111 pdev->evtchn_irq = err;
112 err = 0;
113
114 dev_dbg(&pdev->xdev->dev, "Attached!\n");
115out:
116 return err;
117}
118
119static int pciback_attach(struct pciback_device *pdev)
120{
121 int err = 0;
122 int gnt_ref, remote_evtchn;
123 char *magic = NULL;
124
125 spin_lock(&pdev->dev_lock);
126
127 /* Make sure we only do this setup once */
128 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
129 XenbusStateInitialised)
130 goto out;
131
132 /* Wait for frontend to state that it has published the configuration */
133 if (xenbus_read_driver_state(pdev->xdev->otherend) !=
134 XenbusStateInitialised)
135 goto out;
136
137 dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
138
139 err = xenbus_gather(XBT_NIL, pdev->xdev->otherend,
140 "pci-op-ref", "%u", &gnt_ref,
141 "event-channel", "%u", &remote_evtchn,
142 "magic", NULL, &magic, NULL);
143 if (err) {
144 /* If configuration didn't get read correctly, wait longer */
145 xenbus_dev_fatal(pdev->xdev, err,
146 "Error reading configuration from frontend");
147 goto out;
148 }
149
150 if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
151 xenbus_dev_fatal(pdev->xdev, -EFAULT,
152 "version mismatch (%s/%s) with pcifront - "
153 "halting pciback",
154 magic, XEN_PCI_MAGIC);
155 goto out;
156 }
157
158 err = pciback_do_attach(pdev, gnt_ref, remote_evtchn);
159 if (err)
160 goto out;
161
162 dev_dbg(&pdev->xdev->dev, "Connecting...\n");
163
164 err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
165 if (err)
166 xenbus_dev_fatal(pdev->xdev, err,
167 "Error switching to connected state!");
168
169 dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
170out:
171 spin_unlock(&pdev->dev_lock);
172
173 kfree(magic);
174
175 return err;
176}
177
178static int pciback_publish_pci_dev(struct pciback_device *pdev,
179 unsigned int domain, unsigned int bus,
180 unsigned int devfn, unsigned int devid)
181{
182 int err;
183 int len;
184 char str[64];
185
186 len = snprintf(str, sizeof(str), "vdev-%d", devid);
187 if (unlikely(len >= (sizeof(str) - 1))) {
188 err = -ENOMEM;
189 goto out;
190 }
191
192 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
193 "%04x:%02x:%02x.%02x", domain, bus,
194 PCI_SLOT(devfn), PCI_FUNC(devfn));
195
196out:
197 return err;
198}
199
200static int pciback_export_device(struct pciback_device *pdev,
201 int domain, int bus, int slot, int func,
202 int devid)
203{
204 struct pci_dev *dev;
205 int err = 0;
206
207 dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n",
208 domain, bus, slot, func);
209
210 dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func);
211 if (!dev) {
212 err = -EINVAL;
213 xenbus_dev_fatal(pdev->xdev, err,
214 "Couldn't locate PCI device "
215 "(%04x:%02x:%02x.%01x)! "
216 "perhaps already in-use?",
217 domain, bus, slot, func);
218 goto out;
219 }
220
221 err = pciback_add_pci_dev(pdev, dev, devid, pciback_publish_pci_dev);
222 if (err)
223 goto out;
224
Konrad Rzeszutek Wilk6221a9b2009-12-09 17:43:15 -0500225 dev_dbg(&dev->dev, "registering for %d\n", pdev->xdev->otherend_id);
226 if (xen_register_device_domain_owner(dev,
227 pdev->xdev->otherend_id) != 0) {
228 dev_err(&dev->dev, "device has been assigned to another " \
229 "domain! Over-writting the ownership, but beware.\n");
230 xen_unregister_device_domain_owner(dev);
231 xen_register_device_domain_owner(dev, pdev->xdev->otherend_id);
232 }
233
Konrad Rzeszutek Wilk30edc142009-10-13 17:22:20 -0400234 /* TODO: It'd be nice to export a bridge and have all of its children
235 * get exported with it. This may be best done in xend (which will
236 * have to calculate resource usage anyway) but we probably want to
237 * put something in here to ensure that if a bridge gets given to a
238 * driver domain, that all devices under that bridge are not given
239 * to other driver domains (as he who controls the bridge can disable
240 * it and stop the other devices from working).
241 */
242out:
243 return err;
244}
245
246static int pciback_remove_device(struct pciback_device *pdev,
247 int domain, int bus, int slot, int func)
248{
249 int err = 0;
250 struct pci_dev *dev;
251
252 dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n",
253 domain, bus, slot, func);
254
255 dev = pciback_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func));
256 if (!dev) {
257 err = -EINVAL;
258 dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device "
259 "(%04x:%02x:%02x.%01x)! not owned by this domain\n",
260 domain, bus, slot, func);
261 goto out;
262 }
263
Konrad Rzeszutek Wilk6221a9b2009-12-09 17:43:15 -0500264 dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id);
265 xen_unregister_device_domain_owner(dev);
266
Konrad Rzeszutek Wilk30edc142009-10-13 17:22:20 -0400267 pciback_release_pci_dev(pdev, dev);
268
269out:
270 return err;
271}
272
273static int pciback_publish_pci_root(struct pciback_device *pdev,
274 unsigned int domain, unsigned int bus)
275{
276 unsigned int d, b;
277 int i, root_num, len, err;
278 char str[64];
279
280 dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
281
282 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
283 "root_num", "%d", &root_num);
284 if (err == 0 || err == -ENOENT)
285 root_num = 0;
286 else if (err < 0)
287 goto out;
288
289 /* Verify that we haven't already published this pci root */
290 for (i = 0; i < root_num; i++) {
291 len = snprintf(str, sizeof(str), "root-%d", i);
292 if (unlikely(len >= (sizeof(str) - 1))) {
293 err = -ENOMEM;
294 goto out;
295 }
296
297 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
298 str, "%x:%x", &d, &b);
299 if (err < 0)
300 goto out;
301 if (err != 2) {
302 err = -EINVAL;
303 goto out;
304 }
305
306 if (d == domain && b == bus) {
307 err = 0;
308 goto out;
309 }
310 }
311
312 len = snprintf(str, sizeof(str), "root-%d", root_num);
313 if (unlikely(len >= (sizeof(str) - 1))) {
314 err = -ENOMEM;
315 goto out;
316 }
317
318 dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
319 root_num, domain, bus);
320
321 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
322 "%04x:%02x", domain, bus);
323 if (err)
324 goto out;
325
326 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
327 "root_num", "%d", (root_num + 1));
328
329out:
330 return err;
331}
332
333static int pciback_reconfigure(struct pciback_device *pdev)
334{
335 int err = 0;
336 int num_devs;
337 int domain, bus, slot, func;
338 int substate;
339 int i, len;
340 char state_str[64];
341 char dev_str[64];
342
343 spin_lock(&pdev->dev_lock);
344
345 dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
346
347 /* Make sure we only reconfigure once */
348 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
349 XenbusStateReconfiguring)
350 goto out;
351
352 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
353 &num_devs);
354 if (err != 1) {
355 if (err >= 0)
356 err = -EINVAL;
357 xenbus_dev_fatal(pdev->xdev, err,
358 "Error reading number of devices");
359 goto out;
360 }
361
362 for (i = 0; i < num_devs; i++) {
363 len = snprintf(state_str, sizeof(state_str), "state-%d", i);
364 if (unlikely(len >= (sizeof(state_str) - 1))) {
365 err = -ENOMEM;
366 xenbus_dev_fatal(pdev->xdev, err,
367 "String overflow while reading "
368 "configuration");
369 goto out;
370 }
371 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str,
372 "%d", &substate);
373 if (err != 1)
374 substate = XenbusStateUnknown;
375
376 switch (substate) {
377 case XenbusStateInitialising:
378 dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i);
379
380 len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
381 if (unlikely(len >= (sizeof(dev_str) - 1))) {
382 err = -ENOMEM;
383 xenbus_dev_fatal(pdev->xdev, err,
384 "String overflow while "
385 "reading configuration");
386 goto out;
387 }
388 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
389 dev_str, "%x:%x:%x.%x",
390 &domain, &bus, &slot, &func);
391 if (err < 0) {
392 xenbus_dev_fatal(pdev->xdev, err,
393 "Error reading device "
394 "configuration");
395 goto out;
396 }
397 if (err != 4) {
398 err = -EINVAL;
399 xenbus_dev_fatal(pdev->xdev, err,
400 "Error parsing pci device "
401 "configuration");
402 goto out;
403 }
404
405 err = pciback_export_device(pdev, domain, bus, slot,
406 func, i);
407 if (err)
408 goto out;
409
410 /* Publish pci roots. */
411 err = pciback_publish_pci_roots(pdev,
412 pciback_publish_pci_root);
413 if (err) {
414 xenbus_dev_fatal(pdev->xdev, err,
415 "Error while publish PCI root"
416 "buses for frontend");
417 goto out;
418 }
419
420 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
421 state_str, "%d",
422 XenbusStateInitialised);
423 if (err) {
424 xenbus_dev_fatal(pdev->xdev, err,
425 "Error switching substate of "
426 "dev-%d\n", i);
427 goto out;
428 }
429 break;
430
431 case XenbusStateClosing:
432 dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i);
433
434 len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i);
435 if (unlikely(len >= (sizeof(dev_str) - 1))) {
436 err = -ENOMEM;
437 xenbus_dev_fatal(pdev->xdev, err,
438 "String overflow while "
439 "reading configuration");
440 goto out;
441 }
442 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
443 dev_str, "%x:%x:%x.%x",
444 &domain, &bus, &slot, &func);
445 if (err < 0) {
446 xenbus_dev_fatal(pdev->xdev, err,
447 "Error reading device "
448 "configuration");
449 goto out;
450 }
451 if (err != 4) {
452 err = -EINVAL;
453 xenbus_dev_fatal(pdev->xdev, err,
454 "Error parsing pci device "
455 "configuration");
456 goto out;
457 }
458
459 err = pciback_remove_device(pdev, domain, bus, slot,
460 func);
461 if (err)
462 goto out;
463
464 /* TODO: If at some point we implement support for pci
465 * root hot-remove on pcifront side, we'll need to
466 * remove unnecessary xenstore nodes of pci roots here.
467 */
468
469 break;
470
471 default:
472 break;
473 }
474 }
475
476 err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured);
477 if (err) {
478 xenbus_dev_fatal(pdev->xdev, err,
479 "Error switching to reconfigured state!");
480 goto out;
481 }
482
483out:
484 spin_unlock(&pdev->dev_lock);
485
486 return 0;
487}
488
489static void pciback_frontend_changed(struct xenbus_device *xdev,
490 enum xenbus_state fe_state)
491{
492 struct pciback_device *pdev = dev_get_drvdata(&xdev->dev);
493
494 dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
495
496 switch (fe_state) {
497 case XenbusStateInitialised:
498 pciback_attach(pdev);
499 break;
500
501 case XenbusStateReconfiguring:
502 pciback_reconfigure(pdev);
503 break;
504
505 case XenbusStateConnected:
506 /* pcifront switched its state from reconfiguring to connected.
507 * Then switch to connected state.
508 */
509 xenbus_switch_state(xdev, XenbusStateConnected);
510 break;
511
512 case XenbusStateClosing:
513 pciback_disconnect(pdev);
514 xenbus_switch_state(xdev, XenbusStateClosing);
515 break;
516
517 case XenbusStateClosed:
518 pciback_disconnect(pdev);
519 xenbus_switch_state(xdev, XenbusStateClosed);
520 if (xenbus_dev_is_online(xdev))
521 break;
522 /* fall through if not online */
523 case XenbusStateUnknown:
524 dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
525 device_unregister(&xdev->dev);
526 break;
527
528 default:
529 break;
530 }
531}
532
533static int pciback_setup_backend(struct pciback_device *pdev)
534{
535 /* Get configuration from xend (if available now) */
536 int domain, bus, slot, func;
537 int err = 0;
538 int i, num_devs;
539 char dev_str[64];
540 char state_str[64];
541
542 spin_lock(&pdev->dev_lock);
543
544 /* It's possible we could get the call to setup twice, so make sure
545 * we're not already connected.
546 */
547 if (xenbus_read_driver_state(pdev->xdev->nodename) !=
548 XenbusStateInitWait)
549 goto out;
550
551 dev_dbg(&pdev->xdev->dev, "getting be setup\n");
552
553 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
554 &num_devs);
555 if (err != 1) {
556 if (err >= 0)
557 err = -EINVAL;
558 xenbus_dev_fatal(pdev->xdev, err,
559 "Error reading number of devices");
560 goto out;
561 }
562
563 for (i = 0; i < num_devs; i++) {
564 int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
565 if (unlikely(l >= (sizeof(dev_str) - 1))) {
566 err = -ENOMEM;
567 xenbus_dev_fatal(pdev->xdev, err,
568 "String overflow while reading "
569 "configuration");
570 goto out;
571 }
572
573 err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, dev_str,
574 "%x:%x:%x.%x", &domain, &bus, &slot, &func);
575 if (err < 0) {
576 xenbus_dev_fatal(pdev->xdev, err,
577 "Error reading device configuration");
578 goto out;
579 }
580 if (err != 4) {
581 err = -EINVAL;
582 xenbus_dev_fatal(pdev->xdev, err,
583 "Error parsing pci device "
584 "configuration");
585 goto out;
586 }
587
588 err = pciback_export_device(pdev, domain, bus, slot, func, i);
589 if (err)
590 goto out;
591
592 /* Switch substate of this device. */
593 l = snprintf(state_str, sizeof(state_str), "state-%d", i);
594 if (unlikely(l >= (sizeof(state_str) - 1))) {
595 err = -ENOMEM;
596 xenbus_dev_fatal(pdev->xdev, err,
597 "String overflow while reading "
598 "configuration");
599 goto out;
600 }
601 err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str,
602 "%d", XenbusStateInitialised);
603 if (err) {
604 xenbus_dev_fatal(pdev->xdev, err, "Error switching "
605 "substate of dev-%d\n", i);
606 goto out;
607 }
608 }
609
610 err = pciback_publish_pci_roots(pdev, pciback_publish_pci_root);
611 if (err) {
612 xenbus_dev_fatal(pdev->xdev, err,
613 "Error while publish PCI root buses "
614 "for frontend");
615 goto out;
616 }
617
618 err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
619 if (err)
620 xenbus_dev_fatal(pdev->xdev, err,
621 "Error switching to initialised state!");
622
623out:
624 spin_unlock(&pdev->dev_lock);
625
626 if (!err)
627 /* see if pcifront is already configured (if not, we'll wait) */
628 pciback_attach(pdev);
629
630 return err;
631}
632
633static void pciback_be_watch(struct xenbus_watch *watch,
634 const char **vec, unsigned int len)
635{
636 struct pciback_device *pdev =
637 container_of(watch, struct pciback_device, be_watch);
638
639 switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
640 case XenbusStateInitWait:
641 pciback_setup_backend(pdev);
642 break;
643
644 default:
645 break;
646 }
647}
648
649static int pciback_xenbus_probe(struct xenbus_device *dev,
650 const struct xenbus_device_id *id)
651{
652 int err = 0;
653 struct pciback_device *pdev = alloc_pdev(dev);
654
655 if (pdev == NULL) {
656 err = -ENOMEM;
657 xenbus_dev_fatal(dev, err,
658 "Error allocating pciback_device struct");
659 goto out;
660 }
661
662 /* wait for xend to configure us */
663 err = xenbus_switch_state(dev, XenbusStateInitWait);
664 if (err)
665 goto out;
666
667 /* watch the backend node for backend configuration information */
668 err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
669 pciback_be_watch);
670 if (err)
671 goto out;
672 pdev->be_watching = 1;
673
674 /* We need to force a call to our callback here in case
675 * xend already configured us!
676 */
677 pciback_be_watch(&pdev->be_watch, NULL, 0);
678
679out:
680 return err;
681}
682
683static int pciback_xenbus_remove(struct xenbus_device *dev)
684{
685 struct pciback_device *pdev = dev_get_drvdata(&dev->dev);
686
687 if (pdev != NULL)
688 free_pdev(pdev);
689
690 return 0;
691}
692
693static const struct xenbus_device_id xenpci_ids[] = {
694 {"pci"},
695 {""},
696};
697
698static struct xenbus_driver xenbus_pciback_driver = {
Konrad Rzeszutek Wilk8bfd4e02011-07-19 20:09:43 -0400699 .name = "pciback",
700 .owner = THIS_MODULE,
701 .ids = xenpci_ids,
702 .probe = pciback_xenbus_probe,
703 .remove = pciback_xenbus_remove,
704 .otherend_changed = pciback_frontend_changed,
Konrad Rzeszutek Wilk30edc142009-10-13 17:22:20 -0400705};
706
707int __init pciback_xenbus_register(void)
708{
709 pciback_wq = create_workqueue("pciback_workqueue");
710 if (!pciback_wq) {
Konrad Rzeszutek Wilk8bfd4e02011-07-19 20:09:43 -0400711 printk(KERN_ERR "%s: create"
712 "pciback_workqueue failed\n", __func__);
Konrad Rzeszutek Wilk30edc142009-10-13 17:22:20 -0400713 return -EFAULT;
714 }
715 return xenbus_register_backend(&xenbus_pciback_driver);
716}
717
718void __exit pciback_xenbus_unregister(void)
719{
720 destroy_workqueue(pciback_wq);
721 xenbus_unregister_driver(&xenbus_pciback_driver);
722}