static void connect(struct backend_info *be) { int err; struct xenbus_device *dev = be->dev; rtnl_lock(); err = xen_net_read_mac(dev, be->netif->fe_dev_addr); if (err) { xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); goto out; } xen_net_read_rate(dev, &be->netif->credit_bytes, &be->netif->credit_usec); be->netif->remaining_credit = be->netif->credit_bytes; err = connect_rings(be); if (err) goto out; /* May not get a kick from the frontend, so start the tx_queue now. */ if (!netbk_can_queue(be->netif->dev)) netif_wake_queue(be->netif->dev); out: rtnl_unlock(); }
static int tpmfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { struct tpm_private *priv; int rv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { xenbus_dev_fatal(dev, -ENOMEM, "allocating priv structure"); return -ENOMEM; } rv = setup_chip(&dev->dev, priv); if (rv) { kfree(priv); return rv; } rv = setup_ring(dev, priv); if (rv) { tpm_remove_hardware(&dev->dev); ring_free(priv); return rv; } tpm_get_timeouts(priv->chip); dev_set_drvdata(&dev->dev, priv->chip); return rv; }
static void backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { int val; switch (backend_state) { case XenbusStateInitialised: case XenbusStateConnected: if (dev->state == XenbusStateConnected) break; if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-protocol-v2", "%d", &val) < 0) val = 0; if (!val) { xenbus_dev_fatal(dev, -EINVAL, "vTPM protocol 2 required"); return; } xenbus_switch_state(dev, XenbusStateConnected); break; case XenbusStateClosing: case XenbusStateClosed: device_unregister(&dev->dev); xenbus_frontend_closed(dev); break; default: break; } }
int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) { int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0); if (err < 0) xenbus_dev_fatal(dev, err, "granting access to ring page"); return err; }
/** * Handle the creation of the hotplug script environment. We add the script * and vif variables to the environment, for the benefit of the vif-* hotplug * scripts. */ static int netback_uevent(struct xenbus_device *xdev, struct kobj_uevent_env *env) { struct backend_info *be = dev_get_drvdata(&xdev->dev); char *val; DPRINTK("netback_uevent"); val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL); if (IS_ERR(val)) { int err = PTR_ERR(val); xenbus_dev_fatal(xdev, err, "reading script"); return err; } else { if (add_uevent_var(env, "script=%s", val)) { kfree(val); return -ENOMEM; } kfree(val); } if (be && be->netif && add_uevent_var(env, "vif=%s", be->netif->dev->name)) return -ENOMEM; return 0; }
static void connect(struct backend_info *be) { int err; struct xenbus_device *dev = be->dev; err = connect_rings(be); if (err) return; err = xen_net_read_mac(dev, be->netif->fe_dev_addr); if (err) { xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); return; } xen_net_read_rate(dev, &be->netif->credit_bytes, &be->netif->credit_usec); be->netif->remaining_credit = be->netif->credit_bytes; unregister_hotplug_status_watch(be); err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, hotplug_status_changed, "%s/%s", dev->nodename, "hotplug-status"); if (err) { /* Switch now, since we can't do a watch. */ xenbus_switch_state(dev, XenbusStateConnected); } else { be->have_hotplug_status_watch = 1; } netif_wake_queue(be->netif->dev); }
/** * Handle the creation of the hotplug script environment. We add the script * and vif variables to the environment, for the benefit of the vif-* hotplug * scripts. */ static int netback_uevent(struct xenbus_device *xdev, char **envp, int num_envp, char *buffer, int buffer_size) { struct backend_info *be = xdev->dev.driver_data; netif_t *netif = be->netif; int i = 0, length = 0; char *val; DPRINTK("netback_uevent"); val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL); if (IS_ERR(val)) { int err = PTR_ERR(val); xenbus_dev_fatal(xdev, err, "reading script"); return err; } else { add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "script=%s", val); kfree(val); } add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "vif=%s", netif->dev->name); envp[i] = NULL; return 0; }
/* * Callback received when the frontend's state changes. */ static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state) { struct backend_info *be = dev_get_drvdata(&dev->dev); int err; DPRINTK("%s", xenbus_strstate(frontend_state)); switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { pr_info(DRV_PFX "%s: prepare for reconnect\n", dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } break; case XenbusStateInitialised: case XenbusStateConnected: /* * Ensure we connect even when two watches fire in * close succession and we miss the intermediate value * of frontend_state. */ if (dev->state == XenbusStateConnected) break; /* * Enforce precondition before potential leak point. * xen_blkif_disconnect() is idempotent. */ xen_blkif_disconnect(be->blkif); err = connect_ring(be); if (err) break; xen_update_blkif_status(be->blkif); break; case XenbusStateClosing: xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: xen_blkif_disconnect(be->blkif); xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; /* fall through if not online */ case XenbusStateUnknown: /* implies xen_blkif_disconnect() via xen_blkbk_remove() */ device_unregister(&dev->dev); break; default: xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", frontend_state); break; } }
static int xen_pcibk_xenbus_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int err = 0; struct xen_pcibk_device *pdev = alloc_pdev(dev); if (pdev == NULL) { err = -ENOMEM; xenbus_dev_fatal(dev, err, "Error allocating xen_pcibk_device struct"); goto out; } /* wait for xend to configure us */ err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) goto out; /* watch the backend node for backend configuration information */ err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch, xen_pcibk_be_watch); if (err) goto out; pdev->be_watching = 1; /* We need to force a call to our callback here in case * xend already configured us! */ xen_pcibk_be_watch(&pdev->be_watch, NULL, 0); out: return err; }
static int connect_ring(struct backend_info *be) { struct xenbus_device *dev = be->dev; unsigned long ring_ref; unsigned int evtchn; char protocol[64] = ""; int err; DPRINTK("%s", dev->otherend); err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu", &ring_ref, "event-channel", "%u", &evtchn, NULL); if (err) { xenbus_dev_fatal(dev, err, "reading %s/ring-ref and event-channel", dev->otherend); return err; } be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; err = xenbus_gather(XBT_NIL, dev->otherend, "protocol", "%63s", protocol, NULL); if (err) strcpy(protocol, "unspecified, assuming native"); else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; else { xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } pr_info(DRV_PFX "ring-ref %ld, event-channel %d, protocol %d (%s)\n", ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ err = xen_blkif_map(be->blkif, ring_ref, evtchn); if (err) { xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u", ring_ref, evtchn); return err; } return 0; }
/** * Entry point to this code when a new device is created. Allocate the basic * structures and the ring buffer for communication with the backend, and * inform the backend of the appropriate details for those. Switch to * Initialised state. */ static int ixpfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int err, vdevice, i; struct ixpfront_info *info; /* FIXME: Use dynamic device id if this is not set. */ err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device", "%i", &vdevice); if (err != 1) { /* go looking in the extended area instead */ err = xenbus_scanf(XBT_NIL, dev->nodename, "virtual-device-ext", "%i", &vdevice); if (err != 1) { xenbus_dev_fatal(dev, err, "reading virtual-device"); return err; } } info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); return -ENOMEM; } info->xbdev = dev; info->vdevice = vdevice; info->connected = IXP_STATE_DISCONNECTED; for (i = 0; i < IXP_RING_SIZE; i++) info->shadow[i].req.id = i+1; info->shadow[IXP_RING_SIZE-1].req.id = 0x0fffffff; /* Front end dir is a number, which is used as the id. */ info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); dev_set_drvdata(&dev->dev, info); err = talk_to_ixpback(dev, info); if (err) { kfree(info); dev_set_drvdata(&dev->dev, NULL); return err; } return 0; }
/** * Callback received when the frontend's state changes. */ static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state) { struct backend_info *be = dev_get_drvdata(&dev->dev); pr_debug("frontend state %s", xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { printk(KERN_INFO "%s: %s: prepare for reconnect\n", __func__, dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } break; case XenbusStateInitialised: break; case XenbusStateConnected: if (dev->state == XenbusStateConnected) break; backend_create_xenvif(be); if (be->vif) connect(be); #ifdef DNP_XEN be->vif->assigned_dnpVF_ID = -1; be->vif->dnp_net_device = NULL; register_vif(be->vif); //Below only need if I want to start with bridge //switch_vif_netif(be->vif->domid,1); #endif break; case XenbusStateClosing: if (be->vif) kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); disconnect_backend(dev); xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; /* fall through if not online */ case XenbusStateUnknown: device_unregister(&dev->dev); break; default: xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", frontend_state); break; } }
static int xenkbd_connect_backend(struct xenbus_device *dev, struct xenkbd_info *info) { int ret; struct xenbus_transaction xbt; ret = bind_listening_port_to_irqhandler( dev->otherend_id, input_handler, 0, "xenkbd", info); if (ret < 0) { xenbus_dev_fatal(dev, ret, "bind_listening_port_to_irqhandler"); return ret; } info->irq = ret; again: ret = xenbus_transaction_start(&xbt); if (ret) { xenbus_dev_fatal(dev, ret, "starting transaction"); return ret; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", virt_to_mfn(info->page)); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", irq_to_evtchn_port(info->irq)); if (ret) goto error_xenbus; ret = xenbus_transaction_end(xbt, 0); if (ret) { if (ret == -EAGAIN) goto again; xenbus_dev_fatal(dev, ret, "completing transaction"); return ret; } xenbus_switch_state(dev, XenbusStateInitialised); return 0; error_xenbus: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, ret, "writing xenstore"); return ret; }
static int setup_ixpring(struct xenbus_device *dev, struct ixpfront_info *info) { struct ixp_sring *sring; int err; info->ring_ref = GRANT_INVALID_REF; sring = (struct ixp_sring *)__get_free_page(GFP_NOIO | __GFP_HIGH); if (!sring) { xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); return -ENOMEM; } SHARED_RING_INIT(sring); FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); if (err < 0) { free_page((unsigned long)sring); info->ring.sring = NULL; goto fail; } info->ring_ref = err; err = xenbus_alloc_evtchn(dev, &info->evtchn); if (err) goto fail; err = bind_evtchn_to_irqhandler(info->evtchn, ixp_interrupt, IRQF_SAMPLE_RANDOM, "ixp", info); if (err <= 0) { xenbus_dev_fatal(dev, err, "bind_evtchn_to_irqhandler failed"); goto fail; } info->irq = err; return 0; fail: ixp_free(info, 0); return err; }
int xenbus_grant_ring(struct xenbus_device *dev, paddr_t ring_pa, grant_ref_t *entryp) { int err = xengnt_grant_access(dev->xbusd_otherend_id, ring_pa, 0, entryp); if (err != 0) xenbus_dev_fatal(dev, err, "granting access to ring page"); return err; }
/* * Entry point to this code when a new device is created. Allocate the basic * structures, and watch the store waiting for the hotplug scripts to tell us * the device's physical major and minor numbers. Switch to InitWait. */ static int xen_blkbk_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int err; struct backend_info *be = kzalloc(sizeof(struct backend_info), GFP_KERNEL); if (!be) { xenbus_dev_fatal(dev, -ENOMEM, "allocating backend structure"); return -ENOMEM; } be->dev = dev; dev_set_drvdata(&dev->dev, be); be->blkif = xen_blkif_alloc(dev->otherend_id); if (IS_ERR(be->blkif)) { err = PTR_ERR(be->blkif); be->blkif = NULL; xenbus_dev_fatal(dev, err, "creating block interface"); goto fail; } /* setup back pointer */ be->blkif->be = be; err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed, "%s/%s", dev->nodename, "physical-device"); if (err) goto fail; err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) goto fail; return 0; fail: DPRINTK("failed"); xen_blkbk_remove(dev); return err; }
static int connect_ctrl_ring(struct backend_info *be) { struct xenbus_device *dev = be->dev; struct xenvif *vif = be->vif; unsigned int val; grant_ref_t ring_ref; unsigned int evtchn; int err; err = xenbus_gather(XBT_NIL, dev->otherend, "ctrl-ring-ref", "%u", &val, NULL); if (err) goto done; /* The frontend does not have a control ring */ ring_ref = val; err = xenbus_gather(XBT_NIL, dev->otherend, "event-channel-ctrl", "%u", &val, NULL); if (err) { xenbus_dev_fatal(dev, err, "reading %s/event-channel-ctrl", dev->otherend); goto fail; } evtchn = val; err = xenvif_connect_ctrl(vif, ring_ref, evtchn); if (err) { xenbus_dev_fatal(dev, err, "mapping shared-frame %u port %u", ring_ref, evtchn); goto fail; } done: return 0; fail: return err; }
static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state) { struct backend_info *be = dev_get_drvdata(&dev->dev); printk("\nxen: dom0:otherend id, frontend state: %s", xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch(frontend_state){ case XenbusStateInitialising:{ if (dev->state == XenbusStateClosed) { printk("\nxen: dom0: %s prepare for reconnect", dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } printk("\nxen: dom0: state changed to XenbusStateInitialising"); break; } case XenbusStateInitialised: printk("\nxen: dom0: front state is XenbusStateInitiallised"); if(be->chrif) connect(be); xen_chrif_thread(be->chrif); break; case XenbusStateConnected: // if (dev->state == XenbusStateConnected) // break; //map page here printk("\nxen: dom0: front state XenbusStateConnected"); break; case XenbusStateClosing: xenbus_switch_state(dev, XenbusStateClosing); printk("\nxen: dom0: state changed to XenbusStateClosing"); break; case XenbusStateClosed: //xen_chrif_disconnect(be->chrif); xenbus_switch_state(dev, XenbusStateClosed); printk("\nxen: dom0: state changed to XenbusStateClosed"); if (xenbus_dev_is_online(dev)) break; case XenbusStateUnknown: //device_unregister(&dev->dev); printk("\nxen: dom0: state Unknown"); break; default: xenbus_dev_fatal(dev, -EINVAL, "default saw state %d at frontend", frontend_state); break; } }
/** * Callback received when the frontend's state changes. */ static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state) { struct backend_info *be = dev->dev.driver_data; DPRINTK("%s", xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { printk("%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); if (be->netif) { netif_disconnect(be->netif); be->netif = NULL; } xenbus_switch_state(dev, XenbusStateInitWait); } break; case XenbusStateInitialised: break; case XenbusStateConnected: backend_create_netif(be); if (be->netif) connect(be); break; case XenbusStateClosing: xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; /* fall through if not online */ case XenbusStateUnknown: if (be->netif != NULL) kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); device_unregister(&dev->dev); break; default: xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", frontend_state); break; } }
/** * Callback received when the hotplug scripts have placed the handle node. * Read it, and create a netif structure. If the frontend is ready, connect. */ static void backend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) { int err; long handle; struct backend_info *be = container_of(watch, struct backend_info, backend_watch); struct xenbus_device *dev = be->dev; DPRINTK(""); err = xenbus_scanf(XBT_NULL, dev->nodename, "handle", "%li", &handle); if (XENBUS_EXIST_ERR(err)) { /* Since this watch will fire once immediately after it is registered, we expect this. Ignore it, and wait for the hotplug scripts. */ return; } if (err != 1) { xenbus_dev_fatal(dev, err, "reading handle"); return; } if (be->netif == NULL) { u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; be->netif = netif_alloc(dev->otherend_id, handle, be_mac); if (IS_ERR(be->netif)) { err = PTR_ERR(be->netif); be->netif = NULL; xenbus_dev_fatal(dev, err, "creating interface"); return; } kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE); maybe_connect(be); } }
static int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref, int remote_evtchn) { int err = 0; void *vaddr; dev_dbg(&pdev->xdev->dev, "Attaching to frontend resources - gnt_ref=%d evtchn=%d\n", gnt_ref, remote_evtchn); err = xenbus_map_ring_valloc(pdev->xdev, gnt_ref, &vaddr); if (err < 0) { xenbus_dev_fatal(pdev->xdev, err, "Error mapping other domain page in ours."); goto out; } spin_lock(&pdev->dev_lock); pdev->sh_info = vaddr; spin_unlock(&pdev->dev_lock); err = bind_interdomain_evtchn_to_irqhandler( pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event, 0, DRV_NAME, pdev); if (err < 0) { xenbus_dev_fatal(pdev->xdev, err, "Error binding event channel to IRQ"); goto out; } spin_lock(&pdev->dev_lock); pdev->evtchn_irq = err; spin_unlock(&pdev->dev_lock); err = 0; dev_dbg(&pdev->xdev->dev, "Attached!\n"); out: return err; }
int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, struct backend_info *be, int state) { struct xenbus_device *dev = be->dev; int err; err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache", "%d", state); if (err) xenbus_dev_fatal(dev, err, "writing feature-flush-cache"); return err; }
/** * Callback received when the frontend's state changes. */ static void frontend_changed(struct xenbus_device *dev, enum xenbus_state frontend_state) { struct backend_info *be = dev_get_drvdata(&dev->dev); pr_debug("frontend state %s", xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { // printk(KERN_INFO "%s: %s: prepare for reconnect\n", ; xenbus_switch_state(dev, XenbusStateInitWait); } break; case XenbusStateInitialised: break; case XenbusStateConnected: if (dev->state == XenbusStateConnected) break; backend_create_xenvif(be); if (be->vif) connect(be); break; case XenbusStateClosing: if (be->vif) kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); disconnect_backend(dev); xenbus_switch_state(dev, XenbusStateClosing); break; case XenbusStateClosed: xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; /* fall through if not online */ case XenbusStateUnknown: device_unregister(&dev->dev); break; default: xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", frontend_state); break; } }
int xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp) { int error; error = gnttab_grant_foreign_access( xenbus_get_otherend_id(dev), ring_mfn, 0, refp); if (error) { xenbus_dev_fatal(dev, error, "granting access to ring page"); return (error); } return (0); }
static int usbfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int err; struct usb_hcd *hcd; struct usbfront_info *info; if (usb_disabled()) return -ENODEV; hcd = create_hcd(dev); if (IS_ERR(hcd)) { err = PTR_ERR(hcd); xenbus_dev_fatal(dev, err, "fail to create usb host controller"); goto fail; } info = hcd_to_info(hcd); dev->dev.driver_data = info; err = usb_add_hcd(hcd, 0, 0); if (err != 0) { xenbus_dev_fatal(dev, err, "fail to adding USB host controller"); goto fail; } init_waitqueue_head(&info->wq); return 0; fail: usb_put_hcd(hcd); dev->dev.driver_data = NULL; return err; }
static int read_otherend_details(struct xenbus_device *xendev, char *id_node, char *path_node) { int err = xenbus_gather(XBT_NULL, xendev->nodename, id_node, "%i", &xendev->otherend_id, path_node, NULL, &xendev->otherend, NULL); if (err) { xenbus_dev_fatal(xendev, err, "reading other end details from %s", xendev->nodename); return (err); } if (strlen(xendev->otherend) == 0 || !xenbus_exists_dir(xendev->otherend, "")) { xenbus_dev_fatal(xendev, X_ENOENT, "missing other end from %s", xendev->nodename); kmem_free((void *)xendev->otherend, strlen(xendev->otherend) + 1); xendev->otherend = NULL; return (X_ENOENT); } return (0); }
/** * Write the physical details regarding the block device to the store, and * switch to Connected state. */ static void connect(struct backend_info *be) { xenbus_transaction_t xbt; int err; struct xenbus_device *dev = be->dev; DPRINTK("%s", dev->otherend); /* Supply the information about the device the frontend needs */ again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu", vbd_size(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sectors", dev->nodename); goto abort; } /* FIXME: use a typename instead */ err = xenbus_printf(xbt, dev->nodename, "info", "%u", vbd_info(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/info", dev->nodename); goto abort; } err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", vbd_secsize(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sector-size", dev->nodename); goto abort; } err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) xenbus_dev_fatal(dev, err, "ending transaction"); err = xenbus_switch_state(dev, XenbusStateConnected); if (err) xenbus_dev_fatal(dev, err, "switching to Connected state", dev->nodename); return; abort: xenbus_transaction_end(xbt, 1); }
static int read_xenbus_vif_flags(struct backend_info *be) { struct xenvif *vif = be->vif; struct xenbus_device *dev = be->dev; unsigned int rx_copy; int err; err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u", &rx_copy); if (err == -ENOENT) { err = 0; rx_copy = 0; } if (err < 0) { xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy", dev->otherend); return err; } if (!rx_copy) return -EOPNOTSUPP; if (!xenbus_read_unsigned(dev->otherend, "feature-rx-notify", 0)) { /* - Reduce drain timeout to poll more frequently for * Rx requests. * - Disable Rx stall detection. */ be->vif->drain_timeout = msecs_to_jiffies(30); be->vif->stall_timeout = 0; } vif->can_sg = !!xenbus_read_unsigned(dev->otherend, "feature-sg", 0); vif->gso_mask = 0; if (xenbus_read_unsigned(dev->otherend, "feature-gso-tcpv4", 0)) vif->gso_mask |= GSO_BIT(TCPV4); if (xenbus_read_unsigned(dev->otherend, "feature-gso-tcpv6", 0)) vif->gso_mask |= GSO_BIT(TCPV6); vif->ip_csum = !xenbus_read_unsigned(dev->otherend, "feature-no-csum-offload", 0); vif->ipv6_csum = !!xenbus_read_unsigned(dev->otherend, "feature-ipv6-csum-offload", 0); return 0; }
static int xen_pcibk_export_device(struct xen_pcibk_device *pdev, int domain, int bus, int slot, int func, int devid) { struct pci_dev *dev; int err = 0; dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n", domain, bus, slot, func); dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func); if (!dev) { err = -EINVAL; xenbus_dev_fatal(pdev->xdev, err, "Couldn't locate PCI device " "(%04x:%02x:%02x.%01x)! " "perhaps already in-use?", domain, bus, slot, func); goto out; } err = xen_pcibk_add_pci_dev(pdev, dev, devid, xen_pcibk_publish_pci_dev); if (err) goto out; dev_dbg(&dev->dev, "registering for %d\n", pdev->xdev->otherend_id); dev->dev_flags |= PCI_DEV_FLAGS_ASSIGNED; if (xen_register_device_domain_owner(dev, pdev->xdev->otherend_id) != 0) { dev_err(&dev->dev, "device has been assigned to another " \ "domain! Over-writting the ownership, but beware.\n"); xen_unregister_device_domain_owner(dev); xen_register_device_domain_owner(dev, pdev->xdev->otherend_id); } /* TODO: It'd be nice to export a bridge and have all of its children * get exported with it. This may be best done in xend (which will * have to calculate resource usage anyway) but we probably want to * put something in here to ensure that if a bridge gets given to a * driver domain, that all devices under that bridge are not given * to other driver domains (as he who controls the bridge can disable * it and stop the other devices from working). */ out: return err; }
/** * Allocate an event channel for the given xenbus_device, assigning the newly * created local port to *port. Return 0 on success, or -errno on error. On * error, the device will switch to XenbusStateClosing, and the error will be * saved in the store. */ int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) { struct evtchn_alloc_unbound alloc_unbound; int err; alloc_unbound.dom = DOMID_SELF; alloc_unbound.remote_dom = dev->otherend_id; err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc_unbound); if (err) xenbus_dev_fatal(dev, err, "allocating event channel"); else *port = alloc_unbound.port; return err; }