xenbus.c revision a92336a1176b2119eaa990a1e8bf3109665fdbc6
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 <linux/workqueue.h> 1530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include "pciback.h" 1630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 17a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk#define DRV_NAME "xen-pciback" 1830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#define INVALID_EVTCHN_IRQ (-1) 19a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstruct workqueue_struct *xen_pcibk_wq; 2030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 21a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev) 2230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 23a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev; 2430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 25a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pdev = kzalloc(sizeof(struct xen_pcibk_device), GFP_KERNEL); 2630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev == NULL) 2730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 2830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev); 2930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 3030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->xdev = xdev; 3130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_set_drvdata(&xdev->dev, pdev); 3230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 3330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk spin_lock_init(&pdev->dev_lock); 3430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 3530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->sh_info = NULL; 3630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->evtchn_irq = INVALID_EVTCHN_IRQ; 3730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->be_watching = 0; 3830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 39a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk INIT_WORK(&pdev->op_work, xen_pcibk_do_op); 4030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 41a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (xen_pcibk_init_devices(pdev)) { 4230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk kfree(pdev); 4330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev = NULL; 4430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 4530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 4630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return pdev; 4730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 4830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 49a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_disconnect(struct xen_pcibk_device *pdev) 5030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 5130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk spin_lock(&pdev->dev_lock); 5230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 5330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Ensure the guest can't trigger our handler before removing devices */ 5430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) { 5530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unbind_from_irqhandler(pdev->evtchn_irq, pdev); 5630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->evtchn_irq = INVALID_EVTCHN_IRQ; 5730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 58494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk spin_unlock(&pdev->dev_lock); 5930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 6030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* If the driver domain started an op, make sure we complete it 6130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * before releasing the shared memory */ 62494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 63494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk /* Note, the workqueue does not use spinlocks at all.*/ 64a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk flush_workqueue(xen_pcibk_wq); 6530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 66494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk spin_lock(&pdev->dev_lock); 6730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev->sh_info != NULL) { 6830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info); 6930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->sh_info = NULL; 7030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 7130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk spin_unlock(&pdev->dev_lock); 72494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 7330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 7430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 75a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void free_pdev(struct xen_pcibk_device *pdev) 7630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 77494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk if (pdev->be_watching) { 7830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unregister_xenbus_watch(&pdev->be_watch); 79494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk pdev->be_watching = 0; 80494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk } 8130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 82a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_disconnect(pdev); 8330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 84a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_release_devices(pdev); 8530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 8630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_set_drvdata(&pdev->xdev->dev, NULL); 8730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->xdev = NULL; 8830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 8930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk kfree(pdev); 9030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 9130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 92a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref, 9330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int remote_evtchn) 9430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 9530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 9630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk void *vaddr; 9730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 9830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, 9930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Attaching to frontend resources - gnt_ref=%d evtchn=%d\n", 10030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk gnt_ref, remote_evtchn); 10130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 10230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr); 10330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 10430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 10530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error mapping other domain page in ours."); 10630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 10730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 108494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 109494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk spin_lock(&pdev->dev_lock); 11030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->sh_info = vaddr; 111494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk spin_unlock(&pdev->dev_lock); 11230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 11330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = bind_interdomain_evtchn_to_irqhandler( 114a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event, 115a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 0, DRV_NAME, pdev); 11630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 11730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 11830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error binding event channel to IRQ"); 11930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 12030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 121494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 122494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk spin_lock(&pdev->dev_lock); 12330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->evtchn_irq = err; 124494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk spin_unlock(&pdev->dev_lock); 12530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = 0; 12630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 12730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Attached!\n"); 12830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 12930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 13030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 13130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 132a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_attach(struct xen_pcibk_device *pdev) 13330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 13430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 13530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int gnt_ref, remote_evtchn; 13630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char *magic = NULL; 13730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 13830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 13930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Make sure we only do this setup once */ 14030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->nodename) != 14130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitialised) 14230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 14330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 14430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Wait for frontend to state that it has published the configuration */ 14530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->otherend) != 14630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitialised) 14730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 14830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 14930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Reading frontend config\n"); 15030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 15130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_gather(XBT_NIL, pdev->xdev->otherend, 15230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "pci-op-ref", "%u", &gnt_ref, 15330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "event-channel", "%u", &remote_evtchn, 15430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "magic", NULL, &magic, NULL); 15530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 15630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* If configuration didn't get read correctly, wait longer */ 15730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 15830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading configuration from frontend"); 15930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 16030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 16130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 16230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) { 16330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, -EFAULT, 16430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "version mismatch (%s/%s) with pcifront - " 165a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk "halting xen_pcibk", 16630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk magic, XEN_PCI_MAGIC); 16730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 16830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 16930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 170a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_do_attach(pdev, gnt_ref, remote_evtchn); 17130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 17230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 17330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 17430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Connecting...\n"); 17530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 17630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(pdev->xdev, XenbusStateConnected); 17730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 17830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 17930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching to connected state!"); 18030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 18130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err); 18230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 18330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 18430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk kfree(magic); 18530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 18630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 18730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 18830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 189a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_publish_pci_dev(struct xen_pcibk_device *pdev, 19030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int domain, unsigned int bus, 19130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int devfn, unsigned int devid) 19230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 19330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err; 19430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int len; 19530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char str[64]; 19630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 19730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(str, sizeof(str), "vdev-%d", devid); 19830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(str) - 1))) { 19930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 20030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 20130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 20230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 20330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str, 20430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%04x:%02x:%02x.%02x", domain, bus, 20530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk PCI_SLOT(devfn), PCI_FUNC(devfn)); 20630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 20730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 20830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 20930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 21030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 211a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_export_device(struct xen_pcibk_device *pdev, 21230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, int bus, int slot, int func, 21330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int devid) 21430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 21530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk struct pci_dev *dev; 21630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 21730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 21830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n", 21930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 22030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 22130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func); 22230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!dev) { 22330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 22430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 22530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Couldn't locate PCI device " 22630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "(%04x:%02x:%02x.%01x)! " 22730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "perhaps already in-use?", 22830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 22930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 23030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 23130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 232a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_add_pci_dev(pdev, dev, devid, 233a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_publish_pci_dev); 23430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 23530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 23630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 2376221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk dev_dbg(&dev->dev, "registering for %d\n", pdev->xdev->otherend_id); 2386221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk if (xen_register_device_domain_owner(dev, 2396221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk pdev->xdev->otherend_id) != 0) { 2406221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk dev_err(&dev->dev, "device has been assigned to another " \ 2416221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk "domain! Over-writting the ownership, but beware.\n"); 2426221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk xen_unregister_device_domain_owner(dev); 2436221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk xen_register_device_domain_owner(dev, pdev->xdev->otherend_id); 2446221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk } 2456221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk 24630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* TODO: It'd be nice to export a bridge and have all of its children 24730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * get exported with it. This may be best done in xend (which will 24830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * have to calculate resource usage anyway) but we probably want to 24930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * put something in here to ensure that if a bridge gets given to a 25030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * driver domain, that all devices under that bridge are not given 25130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * to other driver domains (as he who controls the bridge can disable 25230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * it and stop the other devices from working). 25330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 25430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 25530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 25630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 25730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 258a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_remove_device(struct xen_pcibk_device *pdev, 25930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, int bus, int slot, int func) 26030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 26130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 26230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk struct pci_dev *dev; 26330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 26430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "removing dom %x bus %x slot %x func %x\n", 26530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 26630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 267a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev = xen_pcibk_get_pci_dev(pdev, domain, bus, PCI_DEVFN(slot, func)); 26830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!dev) { 26930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 27030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device " 27130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "(%04x:%02x:%02x.%01x)! not owned by this domain\n", 27230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk domain, bus, slot, func); 27330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 27430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 27530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 2766221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id); 2776221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk xen_unregister_device_domain_owner(dev); 2786221a9b2a11acfb54e7b41da425e961b31e88553Konrad Rzeszutek Wilk 279a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_release_pci_dev(pdev, dev); 28030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 28130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 28230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 28330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 28430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 285a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_publish_pci_root(struct xen_pcibk_device *pdev, 28630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int domain, unsigned int bus) 28730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 28830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk unsigned int d, b; 28930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int i, root_num, len, err; 29030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char str[64]; 29130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 29230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n"); 29330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 29430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 29530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "root_num", "%d", &root_num); 29630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err == 0 || err == -ENOENT) 29730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk root_num = 0; 29830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk else if (err < 0) 29930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 30030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 30130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Verify that we haven't already published this pci root */ 30230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk for (i = 0; i < root_num; i++) { 30330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(str, sizeof(str), "root-%d", i); 30430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(str) - 1))) { 30530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 30630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 30730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 30830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 30930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 31030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk str, "%x:%x", &d, &b); 31130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) 31230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 31330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 2) { 31430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 31530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 31630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 31730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 31830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (d == domain && b == bus) { 31930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = 0; 32030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 32130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 32230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 32330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 32430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(str, sizeof(str), "root-%d", root_num); 32530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(str) - 1))) { 32630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 32730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 32830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 32930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 33030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n", 33130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk root_num, domain, bus); 33230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 33330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str, 33430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%04x:%02x", domain, bus); 33530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 33630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 33730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 33830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, 33930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "root_num", "%d", (root_num + 1)); 34030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 34130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 34230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 34330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 34430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 345a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev) 34630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 34730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 34830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int num_devs; 34930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, bus, slot, func; 35030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int substate; 35130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int i, len; 35230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char state_str[64]; 35330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char dev_str[64]; 35430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 35530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 35630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n"); 35730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 35830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Make sure we only reconfigure once */ 35930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->nodename) != 36030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateReconfiguring) 36130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 36230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 36330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d", 36430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &num_devs); 36530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 1) { 36630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err >= 0) 36730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 36830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 36930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading number of devices"); 37030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 37130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 37230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 37330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk for (i = 0; i < num_devs; i++) { 37430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(state_str, sizeof(state_str), "state-%d", i); 37530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(state_str) - 1))) { 37630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 37730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 37830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while reading " 37930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 38030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 38130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 38230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, state_str, 38330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%d", &substate); 38430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 1) 38530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk substate = XenbusStateUnknown; 38630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 38730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (substate) { 38830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateInitialising: 38930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Attaching dev-%d ...\n", i); 39030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 39130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(dev_str, sizeof(dev_str), "dev-%d", i); 39230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(dev_str) - 1))) { 39330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 39430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 39530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while " 39630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "reading configuration"); 39730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 39830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 39930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 40030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_str, "%x:%x:%x.%x", 40130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &domain, &bus, &slot, &func); 40230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 40330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 40430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading device " 40530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 40630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 40730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 40830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 4) { 40930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 41030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 41130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error parsing pci device " 41230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 41330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 41430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 41530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 416a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_export_device(pdev, domain, bus, slot, 41730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk func, i); 41830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 41930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 42030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 42130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Publish pci roots. */ 422a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_publish_pci_roots(pdev, 423a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_publish_pci_root); 42430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 42530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 42630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error while publish PCI root" 42730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "buses for frontend"); 42830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 42930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 43030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 43130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, 43230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk state_str, "%d", 43330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitialised); 43430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 43530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 43630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching substate of " 43730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "dev-%d\n", i); 43830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 43930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 44030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 44130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 44230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateClosing: 44330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "Detaching dev-%d ...\n", i); 44430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 44530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk len = snprintf(dev_str, sizeof(dev_str), "vdev-%d", i); 44630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(len >= (sizeof(dev_str) - 1))) { 44730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 44830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 44930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while " 45030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "reading configuration"); 45130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 45230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 45330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, 45430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_str, "%x:%x:%x.%x", 45530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &domain, &bus, &slot, &func); 45630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 45730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 45830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading device " 45930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 46030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 46130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 46230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 4) { 46330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 46430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 46530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error parsing pci device " 46630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 46730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 46830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 46930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 470a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_remove_device(pdev, domain, bus, slot, 47130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk func); 47230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 47330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 47430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 47530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* TODO: If at some point we implement support for pci 47630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * root hot-remove on pcifront side, we'll need to 47730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * remove unnecessary xenstore nodes of pci roots here. 47830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 47930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 48030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 48130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 48230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 48330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 48430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 48530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 48630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 48730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured); 48830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 48930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 49030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching to reconfigured state!"); 49130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 49230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 49330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 49430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 49530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return 0; 49630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 49730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 498a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_frontend_changed(struct xenbus_device *xdev, 49930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk enum xenbus_state fe_state) 50030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 501a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = dev_get_drvdata(&xdev->dev); 50230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 50330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state); 50430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 50530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (fe_state) { 50630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateInitialised: 507a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_attach(pdev); 50830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 50930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 51030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateReconfiguring: 511a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_reconfigure(pdev); 51230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 51330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 51430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateConnected: 51530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* pcifront switched its state from reconfiguring to connected. 51630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * Then switch to connected state. 51730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 51830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_switch_state(xdev, XenbusStateConnected); 51930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 52030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 52130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateClosing: 522a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_disconnect(pdev); 52330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_switch_state(xdev, XenbusStateClosing); 52430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 52530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 52630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateClosed: 527a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_disconnect(pdev); 52830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_switch_state(xdev, XenbusStateClosed); 52930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_dev_is_online(xdev)) 53030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 53130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* fall through if not online */ 53230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateUnknown: 53330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&xdev->dev, "frontend is gone! unregister device\n"); 53430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk device_unregister(&xdev->dev); 53530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 53630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 53730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 53830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 53930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 54030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 54130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 542a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev) 54330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 54430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Get configuration from xend (if available now) */ 54530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int domain, bus, slot, func; 54630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 54730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int i, num_devs; 54830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char dev_str[64]; 54930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk char state_str[64]; 55030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 55130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* It's possible we could get the call to setup twice, so make sure 55230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * we're not already connected. 55330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 55430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (xenbus_read_driver_state(pdev->xdev->nodename) != 55530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk XenbusStateInitWait) 55630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 55730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 55830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev_dbg(&pdev->xdev->dev, "getting be setup\n"); 55930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 56030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d", 56130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk &num_devs); 56230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 1) { 56330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err >= 0) 56430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 56530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 56630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading number of devices"); 56730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 56830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 56930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 57030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk for (i = 0; i < num_devs; i++) { 57130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i); 57230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(l >= (sizeof(dev_str) - 1))) { 57330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 57430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 57530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while reading " 57630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 57730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 57830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 57930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 58030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, dev_str, 58130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%x:%x:%x.%x", &domain, &bus, &slot, &func); 58230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err < 0) { 58330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 58430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error reading device configuration"); 58530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 58630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 58730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err != 4) { 58830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -EINVAL; 58930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 59030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error parsing pci device " 59130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 59230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 59330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 59430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 595a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_export_device(pdev, domain, bus, slot, func, i); 59630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 59730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 59830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 59930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Switch substate of this device. */ 60030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk l = snprintf(state_str, sizeof(state_str), "state-%d", i); 60130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (unlikely(l >= (sizeof(state_str) - 1))) { 60230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 60330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 60430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "String overflow while reading " 60530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "configuration"); 60630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 60730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 60830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, state_str, 60930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "%d", XenbusStateInitialised); 61030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 61130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, "Error switching " 61230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "substate of dev-%d\n", i); 61330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 61430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 61530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 61630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 617a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk err = xen_pcibk_publish_pci_roots(pdev, xen_pcibk_publish_pci_root); 61830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) { 61930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 62030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error while publish PCI root buses " 62130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "for frontend"); 62230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 62330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 62430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 62530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised); 62630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 62730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(pdev->xdev, err, 62830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk "Error switching to initialised state!"); 62930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 63030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 63130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!err) 63230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* see if pcifront is already configured (if not, we'll wait) */ 633a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_attach(pdev); 63430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 63530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 63630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 63730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 638a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_be_watch(struct xenbus_watch *watch, 63930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk const char **vec, unsigned int len) 64030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 641a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = 642a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk container_of(watch, struct xen_pcibk_device, be_watch); 64330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 64430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (xenbus_read_driver_state(pdev->xdev->nodename)) { 64530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XenbusStateInitWait: 646a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_setup_backend(pdev); 64730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 64830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 64930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 65030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 65130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 65230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 65330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 654a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_xenbus_probe(struct xenbus_device *dev, 65530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk const struct xenbus_device_id *id) 65630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 65730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk int err = 0; 658a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = alloc_pdev(dev); 65930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 66030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev == NULL) { 66130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = -ENOMEM; 66230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk xenbus_dev_fatal(dev, err, 663a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk "Error allocating xen_pcibk_device struct"); 66430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 66530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 66630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 66730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* wait for xend to configure us */ 66830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_switch_state(dev, XenbusStateInitWait); 66930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 67030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 67130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 67230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* watch the backend node for backend configuration information */ 67330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch, 674a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_be_watch); 67530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (err) 67630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk goto out; 677494ef20db6ea2e2ab1c3a45a1461e6e717fdcf48Konrad Rzeszutek Wilk 67830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pdev->be_watching = 1; 67930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 68030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* We need to force a call to our callback here in case 68130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * xend already configured us! 68230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 683a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_be_watch(&pdev->be_watch, NULL, 0); 68430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 68530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkout: 68630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return err; 68730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 68830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 689a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic int xen_pcibk_xenbus_remove(struct xenbus_device *dev) 69030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 691a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = dev_get_drvdata(&dev->dev); 69230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 69330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (pdev != NULL) 69430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk free_pdev(pdev); 69530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 69630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return 0; 69730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 69830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 69930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkstatic const struct xenbus_device_id xenpci_ids[] = { 70030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk {"pci"}, 70130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk {""}, 70230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk}; 70330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 704a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic struct xenbus_driver xenbus_xen_pcibk_driver = { 705a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .name = DRV_NAME, 7068bfd4e023f5fb5793d7d7483b6e17e04933c53e9Konrad Rzeszutek Wilk .owner = THIS_MODULE, 7078bfd4e023f5fb5793d7d7483b6e17e04933c53e9Konrad Rzeszutek Wilk .ids = xenpci_ids, 708a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .probe = xen_pcibk_xenbus_probe, 709a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .remove = xen_pcibk_xenbus_remove, 710a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk .otherend_changed = xen_pcibk_frontend_changed, 71130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk}; 71230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 713a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint __init xen_pcibk_xenbus_register(void) 71430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 715a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_wq = create_workqueue("xen_pciback_workqueue"); 716a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (!xen_pcibk_wq) { 7178bfd4e023f5fb5793d7d7483b6e17e04933c53e9Konrad Rzeszutek Wilk printk(KERN_ERR "%s: create" 718a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk "xen_pciback_workqueue failed\n", __func__); 71930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return -EFAULT; 72030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 721a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return xenbus_register_backend(&xenbus_xen_pcibk_driver); 72230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 72330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 724a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkvoid __exit xen_pcibk_xenbus_unregister(void) 72530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 726a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk destroy_workqueue(xen_pcibk_wq); 727a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xenbus_unregister_driver(&xenbus_xen_pcibk_driver); 72830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 729