Skip to content

Commit d0e4d56

Browse files
sstabelliniBoris Ostrovsky
authored andcommitted
xen/pvcalls: connect to a frontend
Introduce a per-frontend data structure named pvcalls_fedata. It contains pointers to the command ring, its event channel, a list of active sockets and a tree of passive sockets (passing sockets need to be looked up from the id on listen, accept and poll commands, while active sockets only on release). It also has an unbound workqueue to schedule the work of parsing and executing commands on the command ring. socket_lock protects the two lists. In pvcalls_back_global, keep a list of connected frontends. [ boris: fixed whitespaces/long lines ] Signed-off-by: Stefano Stabellini <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Reviewed-by: Juergen Gross <[email protected]> CC: [email protected] CC: [email protected] Signed-off-by: Boris Ostrovsky <[email protected]>
1 parent 0a9c75c commit d0e4d56

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

drivers/xen/pvcalls-back.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,91 @@ struct pvcalls_back_global {
3333
struct semaphore frontends_lock;
3434
} pvcalls_back_global;
3535

36+
/*
37+
* Per-frontend data structure. It contains pointers to the command
38+
* ring, its event channel, a list of active sockets and a tree of
39+
* passive sockets.
40+
*/
41+
struct pvcalls_fedata {
42+
struct list_head list;
43+
struct xenbus_device *dev;
44+
struct xen_pvcalls_sring *sring;
45+
struct xen_pvcalls_back_ring ring;
46+
int irq;
47+
struct list_head socket_mappings;
48+
struct radix_tree_root socketpass_mappings;
49+
struct semaphore socket_lock;
50+
};
51+
52+
static irqreturn_t pvcalls_back_event(int irq, void *dev_id)
53+
{
54+
return IRQ_HANDLED;
55+
}
56+
3657
static int backend_connect(struct xenbus_device *dev)
3758
{
59+
int err, evtchn;
60+
grant_ref_t ring_ref;
61+
struct pvcalls_fedata *fedata = NULL;
62+
63+
fedata = kzalloc(sizeof(struct pvcalls_fedata), GFP_KERNEL);
64+
if (!fedata)
65+
return -ENOMEM;
66+
67+
fedata->irq = -1;
68+
err = xenbus_scanf(XBT_NIL, dev->otherend, "port", "%u",
69+
&evtchn);
70+
if (err != 1) {
71+
err = -EINVAL;
72+
xenbus_dev_fatal(dev, err, "reading %s/event-channel",
73+
dev->otherend);
74+
goto error;
75+
}
76+
77+
err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-ref", "%u", &ring_ref);
78+
if (err != 1) {
79+
err = -EINVAL;
80+
xenbus_dev_fatal(dev, err, "reading %s/ring-ref",
81+
dev->otherend);
82+
goto error;
83+
}
84+
85+
err = bind_interdomain_evtchn_to_irq(dev->otherend_id, evtchn);
86+
if (err < 0)
87+
goto error;
88+
fedata->irq = err;
89+
90+
err = request_threaded_irq(fedata->irq, NULL, pvcalls_back_event,
91+
IRQF_ONESHOT, "pvcalls-back", dev);
92+
if (err < 0)
93+
goto error;
94+
95+
err = xenbus_map_ring_valloc(dev, &ring_ref, 1,
96+
(void **)&fedata->sring);
97+
if (err < 0)
98+
goto error;
99+
100+
BACK_RING_INIT(&fedata->ring, fedata->sring, XEN_PAGE_SIZE * 1);
101+
fedata->dev = dev;
102+
103+
INIT_LIST_HEAD(&fedata->socket_mappings);
104+
INIT_RADIX_TREE(&fedata->socketpass_mappings, GFP_KERNEL);
105+
sema_init(&fedata->socket_lock, 1);
106+
dev_set_drvdata(&dev->dev, fedata);
107+
108+
down(&pvcalls_back_global.frontends_lock);
109+
list_add_tail(&fedata->list, &pvcalls_back_global.frontends);
110+
up(&pvcalls_back_global.frontends_lock);
111+
38112
return 0;
113+
114+
error:
115+
if (fedata->irq >= 0)
116+
unbind_from_irqhandler(fedata->irq, dev);
117+
if (fedata->sring != NULL)
118+
xenbus_unmap_ring_vfree(dev, fedata->sring);
119+
kfree(fedata);
120+
return err;
39121
}
40122

41123
static int backend_disconnect(struct xenbus_device *dev)

0 commit comments

Comments
 (0)