Пример #1
0
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();
}
Пример #2
0
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;
}
Пример #3
0
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;
	}
}
Пример #4
0
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;
}
Пример #5
0
/**
 * 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;
}
Пример #6
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);
}
Пример #7
0
/**
 * 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;
}
Пример #8
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;
	}
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
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;
}
Пример #12
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;
	}
}
Пример #13
0
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;
}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #16
0
/*
 * 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;
}
Пример #17
0
Файл: xenbus.c Проект: gxt/linux
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;
}
Пример #18
0
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;
    }
}
Пример #19
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->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;
	}
}
Пример #20
0
/**
 * 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);
	}
}
Пример #21
0
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;
}
Пример #22
0
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;
}
Пример #23
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",
;
			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;
	}
}
Пример #24
0
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);
}
Пример #25
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;
}
Пример #26
0
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);
}
Пример #27
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);
}
Пример #28
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;
}
Пример #29
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;
}
Пример #30
0
/**
 * 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;
}