2 * linux/fs/9p/trans_xen
6 * Copyright (C) 2017 by Stefano Stabellini <stefano@aporeto.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 #include <xen/events.h>
34 #include <xen/grant_table.h>
36 #include <xen/xenbus.h>
37 #include <xen/interface/io/9pfs.h>
39 #include <linux/module.h>
40 #include <linux/spinlock.h>
41 #include <net/9p/9p.h>
42 #include <net/9p/client.h>
43 #include <net/9p/transport.h>
45 #define XEN_9PFS_NUM_RINGS 2
46 #define XEN_9PFS_RING_ORDER 6
47 #define XEN_9PFS_RING_SIZE XEN_FLEX_RING_SIZE(XEN_9PFS_RING_ORDER)
49 struct xen_9pfs_header
{
54 /* uint8_t sdata[]; */
55 } __attribute__((packed
));
57 /* One per ring, more than one per 9pfs share */
58 struct xen_9pfs_dataring
{
59 struct xen_9pfs_front_priv
*priv
;
61 struct xen_9pfs_data_intf
*intf
;
65 /* protect a ring from concurrent accesses */
68 struct xen_9pfs_data data
;
70 struct work_struct work
;
73 /* One per 9pfs share */
74 struct xen_9pfs_front_priv
{
75 struct list_head list
;
76 struct xenbus_device
*dev
;
78 struct p9_client
*client
;
81 struct xen_9pfs_dataring
*rings
;
84 static LIST_HEAD(xen_9pfs_devs
);
85 static DEFINE_RWLOCK(xen_9pfs_lock
);
87 /* We don't currently allow canceling of requests */
88 static int p9_xen_cancel(struct p9_client
*client
, struct p9_req_t
*req
)
93 static int p9_xen_create(struct p9_client
*client
, const char *addr
, char *args
)
95 struct xen_9pfs_front_priv
*priv
;
100 read_lock(&xen_9pfs_lock
);
101 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
102 if (!strcmp(priv
->tag
, addr
)) {
103 priv
->client
= client
;
104 read_unlock(&xen_9pfs_lock
);
108 read_unlock(&xen_9pfs_lock
);
112 static void p9_xen_close(struct p9_client
*client
)
114 struct xen_9pfs_front_priv
*priv
;
116 read_lock(&xen_9pfs_lock
);
117 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
118 if (priv
->client
== client
) {
120 read_unlock(&xen_9pfs_lock
);
124 read_unlock(&xen_9pfs_lock
);
127 static bool p9_xen_write_todo(struct xen_9pfs_dataring
*ring
, RING_IDX size
)
131 cons
= ring
->intf
->out_cons
;
132 prod
= ring
->intf
->out_prod
;
135 return XEN_9PFS_RING_SIZE
-
136 xen_9pfs_queued(prod
, cons
, XEN_9PFS_RING_SIZE
) >= size
;
139 static int p9_xen_request(struct p9_client
*client
, struct p9_req_t
*p9_req
)
141 struct xen_9pfs_front_priv
*priv
= NULL
;
142 RING_IDX cons
, prod
, masked_cons
, masked_prod
;
144 u32 size
= p9_req
->tc
.size
;
145 struct xen_9pfs_dataring
*ring
;
148 read_lock(&xen_9pfs_lock
);
149 list_for_each_entry(priv
, &xen_9pfs_devs
, list
) {
150 if (priv
->client
== client
)
153 read_unlock(&xen_9pfs_lock
);
154 if (!priv
|| priv
->client
!= client
)
157 num
= p9_req
->tc
.tag
% priv
->num_rings
;
158 ring
= &priv
->rings
[num
];
161 while (wait_event_killable(ring
->wq
,
162 p9_xen_write_todo(ring
, size
)) != 0)
165 spin_lock_irqsave(&ring
->lock
, flags
);
166 cons
= ring
->intf
->out_cons
;
167 prod
= ring
->intf
->out_prod
;
170 if (XEN_9PFS_RING_SIZE
- xen_9pfs_queued(prod
, cons
,
171 XEN_9PFS_RING_SIZE
) < size
) {
172 spin_unlock_irqrestore(&ring
->lock
, flags
);
176 masked_prod
= xen_9pfs_mask(prod
, XEN_9PFS_RING_SIZE
);
177 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
179 xen_9pfs_write_packet(ring
->data
.out
, p9_req
->tc
.sdata
, size
,
180 &masked_prod
, masked_cons
, XEN_9PFS_RING_SIZE
);
182 p9_req
->status
= REQ_STATUS_SENT
;
183 virt_wmb(); /* write ring before updating pointer */
185 ring
->intf
->out_prod
= prod
;
186 spin_unlock_irqrestore(&ring
->lock
, flags
);
187 notify_remote_via_irq(ring
->irq
);
193 static void p9_xen_response(struct work_struct
*work
)
195 struct xen_9pfs_front_priv
*priv
;
196 struct xen_9pfs_dataring
*ring
;
197 RING_IDX cons
, prod
, masked_cons
, masked_prod
;
198 struct xen_9pfs_header h
;
199 struct p9_req_t
*req
;
202 ring
= container_of(work
, struct xen_9pfs_dataring
, work
);
206 cons
= ring
->intf
->in_cons
;
207 prod
= ring
->intf
->in_prod
;
210 if (xen_9pfs_queued(prod
, cons
, XEN_9PFS_RING_SIZE
) <
212 notify_remote_via_irq(ring
->irq
);
216 masked_prod
= xen_9pfs_mask(prod
, XEN_9PFS_RING_SIZE
);
217 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
219 /* First, read just the header */
220 xen_9pfs_read_packet(&h
, ring
->data
.in
, sizeof(h
),
221 masked_prod
, &masked_cons
,
224 req
= p9_tag_lookup(priv
->client
, h
.tag
);
225 if (!req
|| req
->status
!= REQ_STATUS_SENT
) {
226 dev_warn(&priv
->dev
->dev
, "Wrong req tag=%x\n", h
.tag
);
229 ring
->intf
->in_cons
= cons
;
233 memcpy(&req
->rc
, &h
, sizeof(h
));
236 masked_cons
= xen_9pfs_mask(cons
, XEN_9PFS_RING_SIZE
);
237 /* Then, read the whole packet (including the header) */
238 xen_9pfs_read_packet(req
->rc
.sdata
, ring
->data
.in
, h
.size
,
239 masked_prod
, &masked_cons
,
244 ring
->intf
->in_cons
= cons
;
246 status
= (req
->status
!= REQ_STATUS_ERROR
) ?
247 REQ_STATUS_RCVD
: REQ_STATUS_ERROR
;
249 p9_client_cb(priv
->client
, req
, status
);
253 static irqreturn_t
xen_9pfs_front_event_handler(int irq
, void *r
)
255 struct xen_9pfs_dataring
*ring
= r
;
257 if (!ring
|| !ring
->priv
->client
) {
258 /* ignore spurious interrupt */
262 wake_up_interruptible(&ring
->wq
);
263 schedule_work(&ring
->work
);
268 static struct p9_trans_module p9_xen_trans
= {
270 .maxsize
= 1 << (XEN_9PFS_RING_ORDER
+ XEN_PAGE_SHIFT
),
272 .create
= p9_xen_create
,
273 .close
= p9_xen_close
,
274 .request
= p9_xen_request
,
275 .cancel
= p9_xen_cancel
,
276 .owner
= THIS_MODULE
,
279 static const struct xenbus_device_id xen_9pfs_front_ids
[] = {
284 static void xen_9pfs_front_free(struct xen_9pfs_front_priv
*priv
)
288 write_lock(&xen_9pfs_lock
);
289 list_del(&priv
->list
);
290 write_unlock(&xen_9pfs_lock
);
292 for (i
= 0; i
< priv
->num_rings
; i
++) {
293 if (!priv
->rings
[i
].intf
)
295 if (priv
->rings
[i
].irq
> 0)
296 unbind_from_irqhandler(priv
->rings
[i
].irq
, priv
->dev
);
297 if (priv
->rings
[i
].data
.in
) {
298 for (j
= 0; j
< (1 << XEN_9PFS_RING_ORDER
); j
++) {
301 ref
= priv
->rings
[i
].intf
->ref
[j
];
302 gnttab_end_foreign_access(ref
, 0, 0);
304 free_pages((unsigned long)priv
->rings
[i
].data
.in
,
305 XEN_9PFS_RING_ORDER
-
306 (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
308 gnttab_end_foreign_access(priv
->rings
[i
].ref
, 0, 0);
309 free_page((unsigned long)priv
->rings
[i
].intf
);
316 static int xen_9pfs_front_remove(struct xenbus_device
*dev
)
318 struct xen_9pfs_front_priv
*priv
= dev_get_drvdata(&dev
->dev
);
320 dev_set_drvdata(&dev
->dev
, NULL
);
321 xen_9pfs_front_free(priv
);
325 static int xen_9pfs_front_alloc_dataring(struct xenbus_device
*dev
,
326 struct xen_9pfs_dataring
*ring
)
332 init_waitqueue_head(&ring
->wq
);
333 spin_lock_init(&ring
->lock
);
334 INIT_WORK(&ring
->work
, p9_xen_response
);
336 ring
->intf
= (struct xen_9pfs_data_intf
*)get_zeroed_page(GFP_KERNEL
);
339 ret
= gnttab_grant_foreign_access(dev
->otherend_id
,
340 virt_to_gfn(ring
->intf
), 0);
344 bytes
= (void *)__get_free_pages(GFP_KERNEL
| __GFP_ZERO
,
345 XEN_9PFS_RING_ORDER
- (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
350 for (; i
< (1 << XEN_9PFS_RING_ORDER
); i
++) {
351 ret
= gnttab_grant_foreign_access(
352 dev
->otherend_id
, virt_to_gfn(bytes
) + i
, 0);
355 ring
->intf
->ref
[i
] = ret
;
357 ring
->intf
->ring_order
= XEN_9PFS_RING_ORDER
;
358 ring
->data
.in
= bytes
;
359 ring
->data
.out
= bytes
+ XEN_9PFS_RING_SIZE
;
361 ret
= xenbus_alloc_evtchn(dev
, &ring
->evtchn
);
364 ring
->irq
= bind_evtchn_to_irqhandler(ring
->evtchn
,
365 xen_9pfs_front_event_handler
,
366 0, "xen_9pfs-frontend", ring
);
370 xenbus_free_evtchn(dev
, ring
->evtchn
);
374 for (i
--; i
>= 0; i
--)
375 gnttab_end_foreign_access(ring
->intf
->ref
[i
], 0, 0);
376 free_pages((unsigned long)bytes
,
377 XEN_9PFS_RING_ORDER
-
378 (PAGE_SHIFT
- XEN_PAGE_SHIFT
));
380 gnttab_end_foreign_access(ring
->ref
, 0, 0);
381 free_page((unsigned long)ring
->intf
);
385 static int xen_9pfs_front_probe(struct xenbus_device
*dev
,
386 const struct xenbus_device_id
*id
)
389 struct xenbus_transaction xbt
;
390 struct xen_9pfs_front_priv
*priv
= NULL
;
392 unsigned int max_rings
, max_ring_order
, len
= 0;
394 versions
= xenbus_read(XBT_NIL
, dev
->otherend
, "versions", &len
);
395 if (IS_ERR(versions
))
396 return PTR_ERR(versions
);
397 if (strcmp(versions
, "1")) {
402 max_rings
= xenbus_read_unsigned(dev
->otherend
, "max-rings", 0);
403 if (max_rings
< XEN_9PFS_NUM_RINGS
)
405 max_ring_order
= xenbus_read_unsigned(dev
->otherend
,
406 "max-ring-page-order", 0);
407 if (max_ring_order
< XEN_9PFS_RING_ORDER
)
410 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
415 priv
->num_rings
= XEN_9PFS_NUM_RINGS
;
416 priv
->rings
= kcalloc(priv
->num_rings
, sizeof(*priv
->rings
),
423 for (i
= 0; i
< priv
->num_rings
; i
++) {
424 priv
->rings
[i
].priv
= priv
;
425 ret
= xen_9pfs_front_alloc_dataring(dev
, &priv
->rings
[i
]);
431 ret
= xenbus_transaction_start(&xbt
);
433 xenbus_dev_fatal(dev
, ret
, "starting transaction");
436 ret
= xenbus_printf(xbt
, dev
->nodename
, "version", "%u", 1);
439 ret
= xenbus_printf(xbt
, dev
->nodename
, "num-rings", "%u",
443 for (i
= 0; i
< priv
->num_rings
; i
++) {
446 BUILD_BUG_ON(XEN_9PFS_NUM_RINGS
> 9);
447 sprintf(str
, "ring-ref%u", i
);
448 ret
= xenbus_printf(xbt
, dev
->nodename
, str
, "%d",
453 sprintf(str
, "event-channel-%u", i
);
454 ret
= xenbus_printf(xbt
, dev
->nodename
, str
, "%u",
455 priv
->rings
[i
].evtchn
);
459 priv
->tag
= xenbus_read(xbt
, dev
->nodename
, "tag", NULL
);
460 if (IS_ERR(priv
->tag
)) {
461 ret
= PTR_ERR(priv
->tag
);
464 ret
= xenbus_transaction_end(xbt
, 0);
468 xenbus_dev_fatal(dev
, ret
, "completing transaction");
472 write_lock(&xen_9pfs_lock
);
473 list_add_tail(&priv
->list
, &xen_9pfs_devs
);
474 write_unlock(&xen_9pfs_lock
);
475 dev_set_drvdata(&dev
->dev
, priv
);
476 xenbus_switch_state(dev
, XenbusStateInitialised
);
481 xenbus_transaction_end(xbt
, 1);
482 xenbus_dev_fatal(dev
, ret
, "writing xenstore");
484 dev_set_drvdata(&dev
->dev
, NULL
);
485 xen_9pfs_front_free(priv
);
489 static int xen_9pfs_front_resume(struct xenbus_device
*dev
)
491 dev_warn(&dev
->dev
, "suspend/resume unsupported\n");
495 static void xen_9pfs_front_changed(struct xenbus_device
*dev
,
496 enum xenbus_state backend_state
)
498 switch (backend_state
) {
499 case XenbusStateReconfiguring
:
500 case XenbusStateReconfigured
:
501 case XenbusStateInitialising
:
502 case XenbusStateInitialised
:
503 case XenbusStateUnknown
:
506 case XenbusStateInitWait
:
509 case XenbusStateConnected
:
510 xenbus_switch_state(dev
, XenbusStateConnected
);
513 case XenbusStateClosed
:
514 if (dev
->state
== XenbusStateClosed
)
516 /* Missed the backend's CLOSING state -- fallthrough */
517 case XenbusStateClosing
:
518 xenbus_frontend_closed(dev
);
523 static struct xenbus_driver xen_9pfs_front_driver
= {
524 .ids
= xen_9pfs_front_ids
,
525 .probe
= xen_9pfs_front_probe
,
526 .remove
= xen_9pfs_front_remove
,
527 .resume
= xen_9pfs_front_resume
,
528 .otherend_changed
= xen_9pfs_front_changed
,
531 static int p9_trans_xen_init(void)
536 pr_info("Initialising Xen transport for 9pfs\n");
538 v9fs_register_trans(&p9_xen_trans
);
539 return xenbus_register_frontend(&xen_9pfs_front_driver
);
541 module_init(p9_trans_xen_init
);
543 static void p9_trans_xen_exit(void)
545 v9fs_unregister_trans(&p9_xen_trans
);
546 return xenbus_unregister_driver(&xen_9pfs_front_driver
);
548 module_exit(p9_trans_xen_exit
);
550 MODULE_AUTHOR("Stefano Stabellini <stefano@aporeto.com>");
551 MODULE_DESCRIPTION("Xen Transport for 9P");
552 MODULE_LICENSE("GPL");