static void backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { switch (backend_state) { case XenbusStateInitialised: case XenbusStateConnected: if (dev->state == XenbusStateConnected) break; if (!xenbus_read_unsigned(dev->otherend, "feature-protocol-v2", 0)) { 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; } }
static void xenkbd_backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { struct xenkbd_info *info = dev_get_drvdata(&dev->dev); int ret, val; switch (backend_state) { case XenbusStateInitialising: case XenbusStateInitialised: case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: break; case XenbusStateInitWait: InitWait: if (xenbus_read_unsigned(info->xbdev->otherend, "feature-abs-pointer", 0)) { ret = xenbus_write(XBT_NIL, info->xbdev->nodename, "request-abs-pointer", "1"); if (ret) pr_warning("xenkbd: can't request abs-pointer"); } xenbus_switch_state(dev, XenbusStateConnected); break; case XenbusStateConnected: /* * Work around xenbus race condition: If backend goes * through InitWait to Connected fast enough, we can * get Connected twice here. */ if (dev->state != XenbusStateConnected) goto InitWait; /* no InitWait seen yet, fudge it */ /* Set input abs params to match backend screen res */ if (xenbus_scanf(XBT_NIL, info->xbdev->otherend, "width", "%d", &val) > 0) input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0); if (xenbus_scanf(XBT_NIL, info->xbdev->otherend, "height", "%d", &val) > 0) input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0); break; case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; } }
static void xen_mcast_ctrl_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) { struct xenvif *vif = container_of(watch, struct xenvif, mcast_ctrl_watch); struct xenbus_device *dev = xenvif_to_xenbus_device(vif); vif->multicast_control = !!xenbus_read_unsigned(dev->otherend, "request-multicast-control", 0); }
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 xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i; unsigned int abs; struct xenkbd_info *info; struct input_dev *kbd, *ptr; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure"); return -ENOMEM; } dev_set_drvdata(&dev->dev, info); info->xbdev = dev; info->irq = -1; info->gref = -1; snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); if (!info->page) goto error_nomem; abs = xenbus_read_unsigned(dev->otherend, "feature-abs-pointer", 0); if (abs) { ret = xenbus_write(XBT_NIL, dev->nodename, "request-abs-pointer", "1"); if (ret) { pr_warning("xenkbd: can't request abs-pointer"); abs = 0; } } /* keyboard */ kbd = input_allocate_device(); if (!kbd) goto error_nomem; kbd->name = "Xen Virtual Keyboard"; kbd->phys = info->phys; kbd->id.bustype = BUS_PCI; kbd->id.vendor = 0x5853; kbd->id.product = 0xffff; __set_bit(EV_KEY, kbd->evbit); for (i = KEY_ESC; i < KEY_UNKNOWN; i++) __set_bit(i, kbd->keybit); for (i = KEY_OK; i < KEY_MAX; i++) __set_bit(i, kbd->keybit); ret = input_register_device(kbd); if (ret) { input_free_device(kbd); xenbus_dev_fatal(dev, ret, "input_register_device(kbd)"); goto error; } info->kbd = kbd; /* pointing device */ ptr = input_allocate_device(); if (!ptr) goto error_nomem; ptr->name = "Xen Virtual Pointer"; ptr->phys = info->phys; ptr->id.bustype = BUS_PCI; ptr->id.vendor = 0x5853; ptr->id.product = 0xfffe; if (abs) { __set_bit(EV_ABS, ptr->evbit); input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); } else { input_set_capability(ptr, EV_REL, REL_X); input_set_capability(ptr, EV_REL, REL_Y); } input_set_capability(ptr, EV_REL, REL_WHEEL); __set_bit(EV_KEY, ptr->evbit); for (i = BTN_LEFT; i <= BTN_TASK; i++) __set_bit(i, ptr->keybit); ret = input_register_device(ptr); if (ret) { input_free_device(ptr); xenbus_dev_fatal(dev, ret, "input_register_device(ptr)"); goto error; } info->ptr = ptr; ret = xenkbd_connect_backend(dev, info); if (ret < 0) goto error; return 0; error_nomem: ret = -ENOMEM; xenbus_dev_fatal(dev, ret, "allocating device memory"); error: xenkbd_remove(dev); return ret; }
static void connect(struct backend_info *be) { int err; struct xenbus_device *dev = be->dev; unsigned long credit_bytes, credit_usec; unsigned int queue_index; unsigned int requested_num_queues; struct xenvif_queue *queue; /* Check whether the frontend requested multiple queues * and read the number requested. */ requested_num_queues = xenbus_read_unsigned(dev->otherend, "multi-queue-num-queues", 1); if (requested_num_queues > xenvif_max_queues) { /* buggy or malicious guest */ xenbus_dev_fatal(dev, -EINVAL, "guest requested %u queues, exceeding the maximum of %u.", requested_num_queues, xenvif_max_queues); return; } err = xen_net_read_mac(dev, be->vif->fe_dev_addr); if (err) { xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); return; } xen_net_read_rate(dev, &credit_bytes, &credit_usec); xen_unregister_watchers(be->vif); xen_register_watchers(dev, be->vif); read_xenbus_vif_flags(be); err = connect_ctrl_ring(be); if (err) { xenbus_dev_fatal(dev, err, "connecting control ring"); return; } /* Use the number of queues requested by the frontend */ be->vif->queues = vzalloc(requested_num_queues * sizeof(struct xenvif_queue)); if (!be->vif->queues) { xenbus_dev_fatal(dev, -ENOMEM, "allocating queues"); return; } be->vif->num_queues = requested_num_queues; be->vif->stalled_queues = requested_num_queues; for (queue_index = 0; queue_index < requested_num_queues; ++queue_index) { queue = &be->vif->queues[queue_index]; queue->vif = be->vif; queue->id = queue_index; snprintf(queue->name, sizeof(queue->name), "%s-q%u", be->vif->dev->name, queue->id); err = xenvif_init_queue(queue); if (err) { /* xenvif_init_queue() cleans up after itself on * failure, but we need to clean up any previously * initialised queues. Set num_queues to i so that * earlier queues can be destroyed using the regular * disconnect logic. */ be->vif->num_queues = queue_index; goto err; } queue->credit_bytes = credit_bytes; queue->remaining_credit = credit_bytes; queue->credit_usec = credit_usec; err = connect_data_rings(be, queue); if (err) { /* connect_data_rings() cleans up after itself on * failure, but we need to clean up after * xenvif_init_queue() here, and also clean up any * previously initialised queues. */ xenvif_deinit_queue(queue); be->vif->num_queues = queue_index; goto err; } } #ifdef CONFIG_DEBUG_FS xenvif_debugfs_addif(be->vif); #endif /* CONFIG_DEBUG_FS */ /* Initialisation completed, tell core driver the number of * active queues. */ rtnl_lock(); netif_set_real_num_tx_queues(be->vif->dev, requested_num_queues); netif_set_real_num_rx_queues(be->vif->dev, requested_num_queues); rtnl_unlock(); xenvif_carrier_on(be->vif); 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) be->have_hotplug_status_watch = 1; netif_tx_wake_all_queues(be->vif->dev); return; err: if (be->vif->num_queues > 0) xenvif_disconnect_data(be->vif); /* Clean up existing queues */ vfree(be->vif->queues); be->vif->queues = NULL; be->vif->num_queues = 0; xenvif_disconnect_ctrl(be->vif); return; }
int xenbus_dev_is_online(struct xenbus_device *dev) { return !!xenbus_read_unsigned(dev->nodename, "online", 0); }