130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* 230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * PCI Backend Xenbus Setup - handles setup with frontend and xend 330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * 430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/module.h> 730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/init.h> 830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/list.h> 930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/vmalloc.h> 1030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/workqueue.h> 1130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <xen/xenbus.h> 1230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <xen/events.h> 136221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk#include <asm/xen/pci.h> 1430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include "pciback.h" 1530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 1630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#define INVALID_EVTCHN_IRQ (-1) 17a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstruct workqueue_struct *xen_pcibk_wq; 1830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 1990ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool __read_mostly passthrough; 202ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilkmodule_param(passthrough, bool, S_IRUGO); 212ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek WilkMODULE_PARM_DESC(passthrough, 222ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk "Option to specify how to export PCI topology to guest:\n"\ 232ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " 0 - (default) Hide the true PCI topology and makes the frontend\n"\ 242ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " there is a single PCI bus with only the exported devices on it.\n"\ 252ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " For example, a device at 03:05.0 will be re-assigned to 00:00.0\n"\ 262ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " while second device at 02:1a.1 will be re-assigned to 00:01.1.\n"\ 272ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " 1 - Passthrough provides a real view of the PCI topology to the\n"\ 282ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " frontend (for example, a device at 06:01.b will still appear at\n"\ 292ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " 06:01.b to the frontend). This is similar to how Xen 2.0.x\n"\ 302ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " exposed PCI devices to its driver domains. This may be required\n"\ 312ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " for drivers which depend on finding their hardward in certain\n"\ 322ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk " bus/slot locations."); 332ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk 34a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev) 3530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 36a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev; 3730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 38a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pdev = kzalloc(sizeof(struct xen_pcibk_device), GFP_KERNEL); 3930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev == NULL) 4030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 4130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev); 4230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 4330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->xdev = xdev; 4430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_set_drvdata(&xdev->dev, pdev); 4530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 46b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_init(&pdev->dev_lock); 4730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 4830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->sh_info = NULL; 4930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->evtchn_irq = INVALID_EVTCHN_IRQ; 5030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->be_watching = 0; 5130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 52a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk INIT_WORK(&pdev->op_work, xen_pcibk_do_op); 5330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 54a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (xen_pcibk_init_devices(pdev)) { 5530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk kfree(pdev); 5630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev = NULL; 5730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 5830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 5930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return pdev; 6030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 6130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 62a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_disconnect(struct xen_pcibk_device *pdev) 6330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 64b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_lock(&pdev->dev_lock); 6530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Ensure the guest can't trigger our handler before removing devices */ 6630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) { 6730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unbind_from_irqhandler(pdev->evtchn_irq, pdev); 6830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->evtchn_irq = INVALID_EVTCHN_IRQ; 6930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 7030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 7130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* If the driver domain started an op, make sure we complete it 7230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * before releasing the shared memory */ 73494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 74494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk /* Note, the workqueue does not use spinlocks at all.*/ 75a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk flush_workqueue(xen_pcibk_wq); 7630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 7730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev->sh_info != NULL) { 7830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info); 7930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->sh_info = NULL; 8030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 81b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_unlock(&pdev->dev_lock); 8230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 8330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 84a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void free_pdev(struct xen_pcibk_device *pdev) 8530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 86494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk if (pdev->be_watching) { 8730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unregister_xenbus_watch(&pdev->be_watch); 88494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk pdev->be_watching = 0; 89494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk } 9030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 91a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_disconnect(pdev); 9230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 93a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_release_devices(pdev); 9430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 9530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_set_drvdata(&pdev->xdev->dev, NULL); 9630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->xdev = NULL; 9730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 9830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk kfree(pdev); 9930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 10030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 101a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref, 10230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int remote_evtchn) 10330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 10430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 10530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk void *vaddr; 10630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 10730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, 10830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Attaching to frontend resources - gnt_ref=%d evtchn=%d\n", 10930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk gnt_ref, remote_evtchn); 11030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 11130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr); 11230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 11330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 11430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error mapping other domain page in ours."); 11530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 11630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 117494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 11830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->sh_info = vaddr; 11930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 12030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = bind_interdomain_evtchn_to_irqhandler( 121a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event, 122a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 0, DRV_NAME, pdev); 12330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 12430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 12530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error binding event channel to IRQ"); 12630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 12730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 12830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->evtchn_irq = err; 12930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = 0; 13030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 13130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Attached!\n"); 13230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 13330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 13430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 13530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 136a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_attach(struct xen_pcibk_device *pdev) 13730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 13830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 13930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int gnt_ref, remote_evtchn; 14030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char *magic = NULL; 14130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 14230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 143b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_lock(&pdev->dev_lock); 14430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Make sure we only do this setup once */ 14530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->nodename) != 14630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitialised) 14730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 14830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 14930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Wait for frontend to state that it has published the configuration */ 15030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->otherend) != 15130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitialised) 15230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 15330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 15430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Reading frontend config\n"); 15530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 15630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_gather(XBT_NIL, pdev->xdev->otherend, 15730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "pci-op-ref", "%u", &gnt_ref, 15830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "event-channel", "%u", &remote_evtchn, 15930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "magic", NULL, &magic, NULL); 16030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 16130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* If configuration didn't get read correctly, wait longer */ 16230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 16330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading configuration from frontend"); 16430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 16530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 16630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 16730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) { 16830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, -EFAULT, 16930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "version mismatch (%s/%s) with pcifront - " 170402c5e15b44070461dcc2f41536c16d0cfbca9c3Jan Beulich "halting " DRV_NAME, 17130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk magic, XEN_PCI_MAGIC); 17230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 17330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 17430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 175a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_do_attach(pdev, gnt_ref, remote_evtchn); 17630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 17730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 17830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 17930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Connecting...\n"); 18030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 18130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(pdev->xdev, XenbusStateConnected); 18230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 18330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 18430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching to connected state!"); 18530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 18630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err); 18730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 188b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_unlock(&pdev->dev_lock); 18930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 19030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk kfree(magic); 19130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 19230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 19330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 19430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 195a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_publish_pci_dev(struct xen_pcibk_device *pdev, 19630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int domain, unsigned int bus, 19730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int devfn, unsigned int devid) 19830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 19930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err; 20030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int len; 20130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char str[64]; 20230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 20330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(str, sizeof(str), "vdev-%d", devid); 20430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(str) - 1))) { 20530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 20630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 20730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 20830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 209e4de866a834620ef974f5ba86d394a13d2f0cf66Konrad Rzeszutek Wilk /* Note: The PV protocol uses %02x, don't change it */ 21030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str, 21130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%04x:%02x:%02x.%02x", domain, bus, 21230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk PCI_SLOT(devfn), PCI_FUNC(devfn)); 21330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 21430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 21530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 21630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 21730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 218a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_export_device(struct xen_pcibk_device *pdev, 21930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, int bus, int slot, int func, 22030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int devid) 22130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 22230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk struct pci_dev *dev; 22330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 22430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 22530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n", 22630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 22730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 22830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func); 22930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!dev) { 23030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 23130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 23230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Couldn't locate PCI device " 233e4de866a834620ef974f5ba86d394a13d2f0cf66Konrad Rzeszutek Wilk "(%04x:%02x:%02x.%d)! " 23430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "perhaps already in-use?", 23530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 23630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 23730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 23830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 239a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_add_pci_dev(pdev, dev, devid, 240a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_publish_pci_dev); 24130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 24230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 24330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 2446221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk dev_dbg(&dev->dev, "registering for %d\n", pdev->xdev->otherend_id); 2456221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk if (xen_register_device_domain_owner(dev, 2466221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk pdev->xdev->otherend_id) != 0) { 2476c254de16a1d14c1ac931d3aa08dc88ac9fc582bKonrad Rzeszutek Wilk dev_err(&dev->dev, "Stealing ownership from dom%d.\n", 2486c254de16a1d14c1ac931d3aa08dc88ac9fc582bKonrad Rzeszutek Wilk xen_find_device_domain_owner(dev)); 2496221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk xen_unregister_device_domain_owner(dev); 2506221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk xen_register_device_domain_owner(dev, pdev->xdev->otherend_id); 2516221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk } 2526221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk 25330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* TODO: It'd be nice to export a bridge and have all of its children 25430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * get exported with it. This may be best done in xend (which will 25530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * have to calculate resource usage anyway) but we probably want to 25630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * put something in here to ensure that if a bridge gets given to a 25730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * driver domain, that all devices under that bridge are not given 25830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * to other driver domains (as he who controls the bridge can disable 25930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * it and stop the other devices from working). 26030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 26130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 26230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 26330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 26430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 265a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_remove_device(struct xen_pcibk_device *pdev, 26630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, int bus, int slot, int func) 26730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 26830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 26930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk struct pci_dev *dev; 27030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 27130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n", 27230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 27330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 274a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev = xen_pcibk_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func)); 27530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!dev) { 27630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 27730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device " 278e4de866a834620ef974f5ba86d394a13d2f0cf66Konrad Rzeszutek Wilk "(%04x:%02x:%02x.%d)! not owned by this domain\n", 27930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 28030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 28130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 28230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 2836221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id); 2846221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk xen_unregister_device_domain_owner(dev); 2856221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk 286a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_release_pci_dev(pdev, dev); 28730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 28830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 28930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 29030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 29130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 292a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_publish_pci_root(struct xen_pcibk_device *pdev, 29330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int domain, unsigned int bus) 29430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 29530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int d, b; 29630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int i, root_num, len, err; 29730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char str[64]; 29830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 29930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n"); 30030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 30130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 30230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "root_num", "%d", &root_num); 30330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err == 0 || err == -ENOENT) 30430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk root_num = 0; 30530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk else if (err < 0) 30630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 30730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 30830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Verify that we haven't already published this pci root */ 30930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk for (i = 0; i < root_num; i++) { 31030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(str, sizeof(str), "root-%d", i); 31130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(str) - 1))) { 31230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 31330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 31430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 31530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 31630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 31730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk str, "%x:%x", &d, &b); 31830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) 31930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 32030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 2) { 32130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 32230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 32330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 32430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 32530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (d == domain && b == bus) { 32630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = 0; 32730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 32830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 32930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 33030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 33130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(str, sizeof(str), "root-%d", root_num); 33230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(str) - 1))) { 33330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 33430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 33530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 33630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 33730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n", 33830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk root_num, domain, bus); 33930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 34030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str, 34130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%04x:%02x", domain, bus); 34230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 34330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 34430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 34530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, 34630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "root_num", "%d", (root_num + 1)); 34730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 34830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 34930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 35030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 35130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 352a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev) 35330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 35430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 35530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int num_devs; 35630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, bus, slot, func; 35730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int substate; 35830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int i, len; 35930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char state_str[64]; 36030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char dev_str[64]; 36130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 36230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 36330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n"); 36430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 365b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_lock(&pdev->dev_lock); 36630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Make sure we only reconfigure once */ 36730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->nodename) != 36830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateReconfiguring) 36930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 37030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 37130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d", 37230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &num_devs); 37330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 1) { 37430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err >= 0) 37530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 37630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 37730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading number of devices"); 37830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 37930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 38030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 38130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk for (i = 0; i < num_devs; i++) { 38230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(state_str, sizeof(state_str), "state-%d", i); 38330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(state_str) - 1))) { 38430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 38530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 38630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while reading " 38730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 38830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 38930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 39030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str, 39130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%d", &substate); 39230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 1) 39330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk substate = XenbusStateUnknown; 39430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 39530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (substate) { 39630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateInitialising: 39730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i); 39830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 39930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i); 40030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(dev_str) - 1))) { 40130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 40230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 40330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while " 40430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "reading configuration"); 40530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 40630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 40730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 40830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_str, "%x:%x:%x.%x", 40930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &domain, &bus, &slot, &func); 41030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 41130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 41230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading device " 41330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 41430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 41530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 41630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 4) { 41730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 41830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 41930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error parsing pci device " 42030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 42130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 42230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 42330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 424a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_export_device(pdev, domain, bus, slot, 42530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk func, i); 42630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 42730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 42830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 42930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Publish pci roots. */ 430a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_publish_pci_roots(pdev, 431a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_publish_pci_root); 43230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 43330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 43430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error while publish PCI root" 43530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "buses for frontend"); 43630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 43730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 43830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 43930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, 44030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk state_str, "%d", 44130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitialised); 44230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 44330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 44430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching substate of " 44530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "dev-%d\n", i); 44630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 44730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 44830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 44930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 45030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateClosing: 45130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i); 45230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 45330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i); 45430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(dev_str) - 1))) { 45530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 45630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 45730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while " 45830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "reading configuration"); 45930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 46030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 46130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 46230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_str, "%x:%x:%x.%x", 46330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &domain, &bus, &slot, &func); 46430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 46530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 46630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading device " 46730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 46830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 46930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 47030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 4) { 47130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 47230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 47330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error parsing pci device " 47430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 47530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 47630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 47730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 478a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_remove_device(pdev, domain, bus, slot, 47930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk func); 48030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 48130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 48230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 48330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* TODO: If at some point we implement support for pci 48430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * root hot-remove on pcifront side, we'll need to 48530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * remove unnecessary xenstore nodes of pci roots here. 48630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 48730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 48830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 48930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 49030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 49130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 49230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 49330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 49430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 49530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured); 49630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 49730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 49830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching to reconfigured state!"); 49930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 50030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 50130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 50230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 503b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_unlock(&pdev->dev_lock); 50430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return 0; 50530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 50630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 507a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_frontend_changed(struct xenbus_device *xdev, 50830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk enum xenbus_state fe_state) 50930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 510a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = dev_get_drvdata(&xdev->dev); 51130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 51230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state); 51330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 51430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (fe_state) { 51530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateInitialised: 516a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_attach(pdev); 51730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 51830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 51930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateReconfiguring: 520a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_reconfigure(pdev); 52130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 52230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 52330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateConnected: 52430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* pcifront switched its state from reconfiguring to connected. 52530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * Then switch to connected state. 52630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 52730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_switch_state(xdev, XenbusStateConnected); 52830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 52930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 53030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateClosing: 531a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_disconnect(pdev); 53230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_switch_state(xdev, XenbusStateClosing); 53330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 53430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 53530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateClosed: 536a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_disconnect(pdev); 53730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_switch_state(xdev, XenbusStateClosed); 53830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_dev_is_online(xdev)) 53930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 54030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* fall through if not online */ 54130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateUnknown: 54230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&xdev->dev, "frontend is gone! unregister device\n"); 54330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk device_unregister(&xdev->dev); 54430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 54530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 54630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 54730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 54830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 54930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 55030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 551a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev) 55230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 55330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Get configuration from xend (if available now) */ 55430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, bus, slot, func; 55530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 55630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int i, num_devs; 55730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char dev_str[64]; 55830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char state_str[64]; 55930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 560b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_lock(&pdev->dev_lock); 56130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* It's possible we could get the call to setup twice, so make sure 56230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * we're not already connected. 56330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 56430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->nodename) != 56530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitWait) 56630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 56730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 56830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "getting be setup\n"); 56930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 57030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d", 57130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &num_devs); 57230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 1) { 57330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err >= 0) 57430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 57530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 57630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading number of devices"); 57730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 57830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 57930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 58030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk for (i = 0; i < num_devs; i++) { 58130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i); 58230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(l >= (sizeof(dev_str) - 1))) { 58330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 58430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 58530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while reading " 58630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 58730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 58830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 58930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 59030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, dev_str, 59130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%x:%x:%x.%x", &domain, &bus, &slot, &func); 59230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 59330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 59430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading device configuration"); 59530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 59630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 59730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 4) { 59830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 59930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 60030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error parsing pci device " 60130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 60230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 60330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 60430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 605a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_export_device(pdev, domain, bus, slot, func, i); 60630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 60730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 60830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 60930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Switch substate of this device. */ 61030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk l = snprintf(state_str, sizeof(state_str), "state-%d", i); 61130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(l >= (sizeof(state_str) - 1))) { 61230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 61330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 61430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while reading " 61530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 61630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 61730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 61830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str, 61930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%d", XenbusStateInitialised); 62030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 62130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, "Error switching " 62230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "substate of dev-%d\n", i); 62330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 62430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 62530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 62630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 627a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_publish_pci_roots(pdev, xen_pcibk_publish_pci_root); 62830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 62930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 63030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error while publish PCI root buses " 63130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "for frontend"); 63230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 63330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 63430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 63530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised); 63630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 63730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 63830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching to initialised state!"); 63930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 64030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 641b1766b62890e3bba1a778a20ef8bf9348d6096c2Konrad Rzeszutek Wilk mutex_unlock(&pdev->dev_lock); 64230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!err) 64330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* see if pcifront is already configured (if not, we'll wait) */ 644a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_attach(pdev); 64530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 64630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 64730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 648a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_be_watch(struct xenbus_watch *watch, 64930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk const char **vec, unsigned int len) 65030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 651a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = 652a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk container_of(watch, struct xen_pcibk_device, be_watch); 65330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 65430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (xenbus_read_driver_state(pdev->xdev->nodename)) { 65530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateInitWait: 656a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_setup_backend(pdev); 65730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 65830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 65930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 66030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 66130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 66230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 66330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 664a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_xenbus_probe(struct xenbus_device *dev, 66530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk const struct xenbus_device_id *id) 66630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 66730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 668a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = alloc_pdev(dev); 66930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 67030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev == NULL) { 67130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 67230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(dev, err, 673a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk "Error allocating xen_pcibk_device struct"); 67430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 67530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 67630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 67730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* wait for xend to configure us */ 67830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(dev, XenbusStateInitWait); 67930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 68030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 68130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 68230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* watch the backend node for backend configuration information */ 68330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch, 684a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_be_watch); 68530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 68630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 687494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 68830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->be_watching = 1; 68930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 69030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* We need to force a call to our callback here in case 69130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * xend already configured us! 69230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 693a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_be_watch(&pdev->be_watch, NULL, 0); 69430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 69530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 69630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 69730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 69830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 699a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_xenbus_remove(struct xenbus_device *dev) 70030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 701a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = dev_get_drvdata(&dev->dev); 70230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 70330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev != NULL) 70430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk free_pdev(pdev); 70530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 70630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return 0; 70730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 70830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 70973db144b58a32fc39733db6a7e1fe582072ad26aJan Beulichstatic const struct xenbus_device_id xen_pcibk_ids[] = { 71030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk {"pci"}, 71130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk {""}, 71230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk}; 71330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 71473db144b58a32fc39733db6a7e1fe582072ad26aJan Beulichstatic DEFINE_XENBUS_DRIVER(xen_pcibk, DRV_NAME, 715a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .probe = xen_pcibk_xenbus_probe, 716a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .remove = xen_pcibk_xenbus_remove, 717a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .otherend_changed = xen_pcibk_frontend_changed, 71873db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich); 71930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 720402c5e15b44070461dcc2f41536c16d0cfbca9c3Jan Beulichconst struct xen_pcibk_backend *__read_mostly xen_pcibk_backend; 7212ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk 722a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint __init xen_pcibk_xenbus_register(void) 72330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 724a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_wq = create_workqueue("xen_pciback_workqueue"); 725a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (!xen_pcibk_wq) { 7268bfd4e023f5fb5793d7d7483b6e17e04933c53e9Konrad Rzeszutek Wilk printk(KERN_ERR "%s: create" 727a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk "xen_pciback_workqueue failed\n", __func__); 72830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return -EFAULT; 72930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 7302ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk xen_pcibk_backend = &xen_pcibk_vpci_backend; 7312ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk if (passthrough) 7322ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk xen_pcibk_backend = &xen_pcibk_passthrough_backend; 7332ebdc4263022e0015341016b123fe7f44f9cf396Konrad Rzeszutek Wilk pr_info(DRV_NAME ": backend is %s\n", xen_pcibk_backend->name); 73473db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich return xenbus_register_backend(&xen_pcibk_driver); 73530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 73630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 737a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkvoid __exit xen_pcibk_xenbus_unregister(void) 73830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 739a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk destroy_workqueue(xen_pcibk_wq); 74073db144b58a32fc39733db6a7e1fe582072ad26aJan Beulich xenbus_unregister_driver(&xen_pcibk_driver); 74130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 742