in pvcalls-back.c [921:986]
static int backend_connect(struct xenbus_device *dev)
{
int err;
evtchn_port_t evtchn;
grant_ref_t ring_ref;
struct pvcalls_fedata *fedata = NULL;
fedata = kzalloc(sizeof(struct pvcalls_fedata), GFP_KERNEL);
if (!fedata)
return -ENOMEM;
fedata->irq = -1;
err = xenbus_scanf(XBT_NIL, dev->otherend, "port", "%u",
&evtchn);
if (err != 1) {
err = -EINVAL;
xenbus_dev_fatal(dev, err, "reading %s/event-channel",
dev->otherend);
goto error;
}
err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-ref", "%u", &ring_ref);
if (err != 1) {
err = -EINVAL;
xenbus_dev_fatal(dev, err, "reading %s/ring-ref",
dev->otherend);
goto error;
}
err = bind_interdomain_evtchn_to_irq_lateeoi(dev, evtchn);
if (err < 0)
goto error;
fedata->irq = err;
err = request_threaded_irq(fedata->irq, NULL, pvcalls_back_event,
IRQF_ONESHOT, "pvcalls-back", dev);
if (err < 0)
goto error;
err = xenbus_map_ring_valloc(dev, &ring_ref, 1,
(void **)&fedata->sring);
if (err < 0)
goto error;
BACK_RING_INIT(&fedata->ring, fedata->sring, XEN_PAGE_SIZE * 1);
fedata->dev = dev;
INIT_LIST_HEAD(&fedata->socket_mappings);
INIT_RADIX_TREE(&fedata->socketpass_mappings, GFP_KERNEL);
sema_init(&fedata->socket_lock, 1);
dev_set_drvdata(&dev->dev, fedata);
down(&pvcalls_back_global.frontends_lock);
list_add_tail(&fedata->list, &pvcalls_back_global.frontends);
up(&pvcalls_back_global.frontends_lock);
return 0;
error:
if (fedata->irq >= 0)
unbind_from_irqhandler(fedata->irq, dev);
if (fedata->sring != NULL)
xenbus_unmap_ring_vfree(dev, fedata->sring);
kfree(fedata);
return err;
}