aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Stabellini <sstabellini@kernel.org>2017-07-06 13:59:29 -0400
committerBoris Ostrovsky <boris.ostrovsky@oracle.com>2017-08-31 09:45:55 -0400
commitd0e4d560c2433d29d11219567958b12bfe596d22 (patch)
treef5ddbf208aa06f1a7c0d0cbd3d8c0a12298c33e2
parent0a9c75c2c7258f2c50d2c62430ccca3eec9f866f (diff)
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 <stefano@aporeto.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Reviewed-by: Juergen Gross <jgross@suse.com> CC: boris.ostrovsky@oracle.com CC: jgross@suse.com Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
-rw-r--r--drivers/xen/pvcalls-back.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c
index 72d2fce27a34..48b71236192d 100644
--- a/drivers/xen/pvcalls-back.c
+++ b/drivers/xen/pvcalls-back.c
@@ -33,9 +33,91 @@ struct pvcalls_back_global {
33 struct semaphore frontends_lock; 33 struct semaphore frontends_lock;
34} pvcalls_back_global; 34} pvcalls_back_global;
35 35
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 */
41struct 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
52static irqreturn_t pvcalls_back_event(int irq, void *dev_id)
53{
54 return IRQ_HANDLED;
55}
56
36static int backend_connect(struct xenbus_device *dev) 57static int backend_connect(struct xenbus_device *dev)
37{ 58{
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
38 return 0; 112 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;
39} 121}
40 122
41static int backend_disconnect(struct xenbus_device *dev) 123static int backend_disconnect(struct xenbus_device *dev)