Example #1
0
static int xenkbd_connect_backend(struct xenbus_device *dev,
				  struct xenkbd_info *info)
{
	int ret, evtchn;
	struct xenbus_transaction xbt;

	ret = xenbus_alloc_evtchn(dev, &evtchn);
	if (ret)
		return ret;
	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
					0, dev->devicetype, info);
	if (ret < 0) {
		xenbus_free_evtchn(dev, evtchn);
		xenbus_dev_fatal(dev, ret, "bind_evtchn_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",
			    evtchn);
	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;
}
Example #2
0
/* Release a reference to a pcifront device */
static void
put_pdev(struct pcifront_device *pdev)
{
	if (--pdev->ref_cnt > 0)
		return;

	DPRINTF("freeing pdev @ 0x%p (ref_cnt=%d)\n", pdev, pdev->ref_cnt);

	if (pdev->evtchn != INVALID_EVTCHN)
		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);

	if (pdev->gnt_ref != INVALID_GRANT_REF)
		gnttab_end_foreign_access(pdev->gnt_ref, 0, (void *)pdev->sh_info);

	pdev->xdev->data = NULL;

	free(pdev, M_DEVBUF);
}
Example #3
0
static void free_pdev(struct pcifront_device *pdev)
{
	dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);

	pcifront_free_roots(pdev);

	/*For PCIE_AER error handling job*/
	flush_scheduled_work();
	unbind_from_irqhandler(pdev->evtchn, pdev);

	if (pdev->evtchn != INVALID_EVTCHN)
		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);

	if (pdev->gnt_ref != INVALID_GRANT_REF)
		gnttab_end_foreign_access(pdev->gnt_ref,
					  (unsigned long)pdev->sh_info);

	dev_set_drvdata(&pdev->xdev->dev, NULL);

	kfree(pdev);
}
Example #4
0
static int xenkbd_connect_backend(struct xenbus_device *dev,
				  struct xenkbd_info *info)
{
	int ret, evtchn;
	struct xenbus_transaction xbt;

	ret = gnttab_grant_foreign_access(dev->otherend_id,
	                                  virt_to_gfn(info->page), 0);
	if (ret < 0)
		return ret;
	info->gref = ret;

	ret = xenbus_alloc_evtchn(dev, &evtchn);
	if (ret)
		goto error_grant;
	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
					0, dev->devicetype, info);
	if (ret < 0) {
		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
		goto error_evtchan;
	}
	info->irq = ret;

 again:
	ret = xenbus_transaction_start(&xbt);
	if (ret) {
		xenbus_dev_fatal(dev, ret, "starting transaction");
		goto error_irqh;
	}
	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
			    virt_to_gfn(info->page));
	if (ret)
		goto error_xenbus;
	ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref);
	if (ret)
		goto error_xenbus;
	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
			    evtchn);
	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");
		goto error_irqh;
	}

	xenbus_switch_state(dev, XenbusStateInitialised);
	return 0;

 error_xenbus:
	xenbus_transaction_end(xbt, 1);
	xenbus_dev_fatal(dev, ret, "writing xenstore");
 error_irqh:
	unbind_from_irqhandler(info->irq, info);
	info->irq = -1;
 error_evtchan:
	xenbus_free_evtchn(dev, evtchn);
 error_grant:
	gnttab_end_foreign_access(info->gref, 0, 0UL);
	info->gref = -1;
	return ret;
}
/**
 * Connect the OpenXT input device to the corresponding backend.
 *
 * @param dev The device to be connected.
 * @param info The information structure that corresponds to the given device.
 *
 * @return int Zero on success, or an error code on failure.
 */
static int oxtkbd_connect_backend(struct xenbus_device *dev,
                  struct openxt_kbd_info *info)
{
    int ret, evtchn;
    struct xenbus_transaction xbt;

    //To communicate with the backend, we'll share a single page of memory
    //We'll start this process by granting out our "shared page".
    ret = gnttab_grant_foreign_access(dev->otherend_id, virt_to_mfn(info->page), 0);
    if (ret < 0)
        return ret;

    info->gref = ret;

    //Next, we'll need to create an event channel we can use to signal that data
    //has changed in our shared page.
    ret = xenbus_alloc_evtchn(dev, &evtchn);
    if (ret)
        goto error_grant;

    //Bind our input handler to our event channel-- ensuring we're recieve any
    //"new data" notifications.
    ret = bind_evtchn_to_irqhandler(evtchn, input_handler, 0, dev->devicetype, info);
    if (ret < 0) {
        xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
        goto error_evtchan;
    }

    info->irq = ret;

 again:

    //Now that we've set up our shared assets, we'll need to communicate them
    //to the backend. First, we'll start a xenbus transaction, so we can dump
    //all of our data into the XenStore simultaneously.
    ret = xenbus_transaction_start(&xbt);
    if (ret) {
        xenbus_dev_fatal(dev, ret, "starting transaction");
        goto error_irqh;
    }

    //Provide a direct reference to the page. This allows backends that want
    //to use foreign mappings (i.e. legacy backends) to map in the shared page
    //without touching grants.
    ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", virt_to_mfn(info->page));
    if (ret)
        goto error_xenbus;

    //And provide our grant reference. This is the preferred way of getting the
    //shared page.
    ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref);
    if (ret)
        goto error_xenbus;

    //Provide the number for our event channel, so the backend can signal
    //new informatino to us.
    ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", evtchn);
    if (ret)
        goto error_xenbus;

    //Attempt to apply all of our changes at once.
    ret = xenbus_transaction_end(xbt, 0);

    //If our transaction failed...
    if (ret) {

        //... it may have been because the XenStore was busy. If this is the case,
        //repeat out transaction until we succeed, or hit an error.
        if (ret == -EAGAIN)
            goto again;

        //Otherwise, we couldn't connect. Bail out!
        xenbus_dev_fatal(dev, ret, "completing transaction");
        goto error_irqh;
    }

    //Finally, switch our state to "intialized", hopefully cueing the backend
    //to connect.
    xenbus_switch_state(dev, XenbusStateInitialised);
    return 0;

 error_xenbus:
    xenbus_transaction_end(xbt, 1);
    xenbus_dev_fatal(dev, ret, "writing xenstore");
 error_irqh:
    unbind_from_irqhandler(info->irq, info);
    info->irq = -1;
 error_evtchan:
    xenbus_free_evtchn(dev, evtchn);
 error_grant:
    gnttab_end_foreign_access(info->gref, 0, 0UL);
    info->gref = -1;
    return ret;
}