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; }
/* 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); }
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); }
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; }