1 // SPDX-License-Identifier: GPL-2.0+
3 * trans_usbg.c - USB peripheral usb9pfs configuration driver and transport.
5 * Copyright (C) 2024 Michael Grzeschik <m.grzeschik@pengutronix.de>
8 /* Gadget usb9pfs only needs two bulk endpoints, and will use the usb9pfs
9 * transport to mount host exported filesystem via usb gadget.
12 /* +--------------------------+ | +--------------------------+
13 * | 9PFS mounting client | | | 9PFS exporting server |
15 * | (this:trans_usbg) | | |(e.g. diod or nfs-ganesha)|
16 * +-------------^------------+ | +-------------^------------+
18 * ------------------|------------------------------------|-------------
20 * +-------------v------------+ | +-------------v------------+
22 * HW | USB Device Controller <---------> USB Host Controller |
24 * +--------------------------+ | +--------------------------+
27 #include <linux/cleanup.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/usb/composite.h>
31 #include <linux/usb/func_utils.h>
33 #include <net/9p/9p.h>
34 #include <net/9p/client.h>
35 #include <net/9p/transport.h>
37 #define DEFAULT_BUFLEN 16384
40 struct p9_client
*client
;
42 /* 9p request lock for en/dequeue */
45 struct usb_request
*in_req
;
46 struct usb_request
*out_req
;
49 struct usb_ep
*out_ep
;
51 struct completion send
;
52 struct completion received
;
56 struct usb_function function
;
59 static inline struct f_usb9pfs
*func_to_usb9pfs(struct usb_function
*f
)
61 return container_of(f
, struct f_usb9pfs
, function
);
64 struct f_usb9pfs_opts
{
65 struct usb_function_instance func_inst
;
68 struct f_usb9pfs_dev
*dev
;
70 /* Read/write access to configfs attributes is handled by configfs.
72 * This is to protect the data from concurrent access by read/write
73 * and create symlink/remove symlink.
79 struct f_usb9pfs_dev
{
80 struct f_usb9pfs
*usb9pfs
;
81 struct f_usb9pfs_opts
*opts
;
85 struct list_head usb9pfs_instance
;
88 static DEFINE_MUTEX(usb9pfs_lock
);
89 static struct list_head usbg_instance_list
;
91 static int usb9pfs_queue_tx(struct f_usb9pfs
*usb9pfs
, struct p9_req_t
*p9_tx_req
,
94 struct usb_composite_dev
*cdev
= usb9pfs
->function
.config
->cdev
;
95 struct usb_request
*req
= usb9pfs
->in_req
;
98 if (!(p9_tx_req
->tc
.size
% usb9pfs
->in_ep
->maxpacket
))
101 req
->buf
= p9_tx_req
->tc
.sdata
;
102 req
->length
= p9_tx_req
->tc
.size
;
103 req
->context
= p9_tx_req
;
105 dev_dbg(&cdev
->gadget
->dev
, "%s usb9pfs send --> %d/%d, zero: %d\n",
106 usb9pfs
->in_ep
->name
, req
->actual
, req
->length
, req
->zero
);
108 ret
= usb_ep_queue(usb9pfs
->in_ep
, req
, gfp_flags
);
112 dev_dbg(&cdev
->gadget
->dev
, "tx submit --> %d\n", ret
);
117 static int usb9pfs_queue_rx(struct f_usb9pfs
*usb9pfs
, struct usb_request
*req
,
120 struct usb_composite_dev
*cdev
= usb9pfs
->function
.config
->cdev
;
123 ret
= usb_ep_queue(usb9pfs
->out_ep
, req
, gfp_flags
);
125 dev_dbg(&cdev
->gadget
->dev
, "rx submit --> %d\n", ret
);
130 static int usb9pfs_transmit(struct f_usb9pfs
*usb9pfs
, struct p9_req_t
*p9_req
)
134 guard(spinlock_irqsave
)(&usb9pfs
->lock
);
136 ret
= usb9pfs_queue_tx(usb9pfs
, p9_req
, GFP_ATOMIC
);
140 list_del(&p9_req
->req_list
);
147 static void usb9pfs_tx_complete(struct usb_ep
*ep
, struct usb_request
*req
)
149 struct f_usb9pfs
*usb9pfs
= ep
->driver_data
;
150 struct usb_composite_dev
*cdev
= usb9pfs
->function
.config
->cdev
;
151 struct p9_req_t
*p9_tx_req
= req
->context
;
154 /* reset zero packages */
158 dev_err(&cdev
->gadget
->dev
, "%s usb9pfs complete --> %d, %d/%d\n",
159 ep
->name
, req
->status
, req
->actual
, req
->length
);
163 dev_dbg(&cdev
->gadget
->dev
, "%s usb9pfs complete --> %d, %d/%d\n",
164 ep
->name
, req
->status
, req
->actual
, req
->length
);
166 spin_lock_irqsave(&usb9pfs
->lock
, flags
);
167 WRITE_ONCE(p9_tx_req
->status
, REQ_STATUS_SENT
);
169 p9_req_put(usb9pfs
->client
, p9_tx_req
);
173 spin_unlock_irqrestore(&usb9pfs
->lock
, flags
);
175 complete(&usb9pfs
->send
);
178 static struct p9_req_t
*usb9pfs_rx_header(struct f_usb9pfs
*usb9pfs
, void *buf
)
180 struct p9_req_t
*p9_rx_req
;
184 /* start by reading header */
187 rc
.capacity
= P9_HDRSZ
;
190 p9_debug(P9_DEBUG_TRANS
, "mux %p got %zu bytes\n", usb9pfs
,
191 rc
.capacity
- rc
.offset
);
193 ret
= p9_parse_header(&rc
, &rc
.size
, NULL
, NULL
, 0);
195 p9_debug(P9_DEBUG_ERROR
,
196 "error parsing header: %d\n", ret
);
200 p9_debug(P9_DEBUG_TRANS
,
201 "mux %p pkt: size: %d bytes tag: %d\n",
202 usb9pfs
, rc
.size
, rc
.tag
);
204 p9_rx_req
= p9_tag_lookup(usb9pfs
->client
, rc
.tag
);
205 if (!p9_rx_req
|| p9_rx_req
->status
!= REQ_STATUS_SENT
) {
206 p9_debug(P9_DEBUG_ERROR
, "Unexpected packet tag %d\n", rc
.tag
);
210 if (rc
.size
> p9_rx_req
->rc
.capacity
) {
211 p9_debug(P9_DEBUG_ERROR
,
212 "requested packet size too big: %d for tag %d with capacity %zd\n",
213 rc
.size
, rc
.tag
, p9_rx_req
->rc
.capacity
);
214 p9_req_put(usb9pfs
->client
, p9_rx_req
);
218 if (!p9_rx_req
->rc
.sdata
) {
219 p9_debug(P9_DEBUG_ERROR
,
220 "No recv fcall for tag %d (req %p), disconnecting!\n",
222 p9_req_put(usb9pfs
->client
, p9_rx_req
);
229 static void usb9pfs_rx_complete(struct usb_ep
*ep
, struct usb_request
*req
)
231 struct f_usb9pfs
*usb9pfs
= ep
->driver_data
;
232 struct usb_composite_dev
*cdev
= usb9pfs
->function
.config
->cdev
;
233 struct p9_req_t
*p9_rx_req
;
236 dev_err(&cdev
->gadget
->dev
, "%s usb9pfs complete --> %d, %d/%d\n",
237 ep
->name
, req
->status
, req
->actual
, req
->length
);
241 p9_rx_req
= usb9pfs_rx_header(usb9pfs
, req
->buf
);
245 memcpy(p9_rx_req
->rc
.sdata
, req
->buf
, req
->actual
);
247 p9_rx_req
->rc
.size
= req
->actual
;
249 p9_client_cb(usb9pfs
->client
, p9_rx_req
, REQ_STATUS_RCVD
);
250 p9_req_put(usb9pfs
->client
, p9_rx_req
);
252 complete(&usb9pfs
->received
);
255 static void disable_ep(struct usb_composite_dev
*cdev
, struct usb_ep
*ep
)
259 value
= usb_ep_disable(ep
);
261 dev_info(&cdev
->gadget
->dev
,
262 "disable %s --> %d\n", ep
->name
, value
);
265 static void disable_usb9pfs(struct f_usb9pfs
*usb9pfs
)
267 struct usb_composite_dev
*cdev
=
268 usb9pfs
->function
.config
->cdev
;
270 if (usb9pfs
->in_req
) {
271 usb_ep_free_request(usb9pfs
->in_ep
, usb9pfs
->in_req
);
272 usb9pfs
->in_req
= NULL
;
275 if (usb9pfs
->out_req
) {
276 usb_ep_free_request(usb9pfs
->out_ep
, usb9pfs
->out_req
);
277 usb9pfs
->out_req
= NULL
;
280 disable_ep(cdev
, usb9pfs
->in_ep
);
281 disable_ep(cdev
, usb9pfs
->out_ep
);
282 dev_dbg(&cdev
->gadget
->dev
, "%s disabled\n",
283 usb9pfs
->function
.name
);
286 static int alloc_requests(struct usb_composite_dev
*cdev
,
287 struct f_usb9pfs
*usb9pfs
)
291 usb9pfs
->in_req
= usb_ep_alloc_request(usb9pfs
->in_ep
, GFP_ATOMIC
);
292 if (!usb9pfs
->in_req
) {
297 usb9pfs
->out_req
= alloc_ep_req(usb9pfs
->out_ep
, usb9pfs
->buflen
);
298 if (!usb9pfs
->out_req
) {
303 usb9pfs
->in_req
->complete
= usb9pfs_tx_complete
;
304 usb9pfs
->out_req
->complete
= usb9pfs_rx_complete
;
306 /* length will be set in complete routine */
307 usb9pfs
->in_req
->context
= usb9pfs
;
308 usb9pfs
->out_req
->context
= usb9pfs
;
313 usb_ep_free_request(usb9pfs
->in_ep
, usb9pfs
->in_req
);
318 static int enable_endpoint(struct usb_composite_dev
*cdev
,
319 struct f_usb9pfs
*usb9pfs
, struct usb_ep
*ep
)
323 ret
= config_ep_by_speed(cdev
->gadget
, &usb9pfs
->function
, ep
);
327 ret
= usb_ep_enable(ep
);
331 ep
->driver_data
= usb9pfs
;
337 enable_usb9pfs(struct usb_composite_dev
*cdev
, struct f_usb9pfs
*usb9pfs
)
339 struct p9_client
*client
;
342 ret
= enable_endpoint(cdev
, usb9pfs
, usb9pfs
->in_ep
);
346 ret
= enable_endpoint(cdev
, usb9pfs
, usb9pfs
->out_ep
);
350 ret
= alloc_requests(cdev
, usb9pfs
);
354 client
= usb9pfs
->client
;
356 client
->status
= Connected
;
358 dev_dbg(&cdev
->gadget
->dev
, "%s enabled\n", usb9pfs
->function
.name
);
362 usb_ep_disable(usb9pfs
->out_ep
);
364 usb_ep_disable(usb9pfs
->in_ep
);
369 static int p9_usbg_create(struct p9_client
*client
, const char *devname
, char *args
)
371 struct f_usb9pfs_dev
*dev
;
372 struct f_usb9pfs
*usb9pfs
;
379 guard(mutex
)(&usb9pfs_lock
);
381 list_for_each_entry(dev
, &usbg_instance_list
, usb9pfs_instance
) {
382 if (!strncmp(devname
, dev
->tag
, strlen(devname
))) {
394 pr_err("no channels available for device %s\n", devname
);
398 usb9pfs
= dev
->usb9pfs
;
402 client
->trans
= (void *)usb9pfs
;
403 if (!usb9pfs
->in_req
)
404 client
->status
= Disconnected
;
406 client
->status
= Connected
;
407 usb9pfs
->client
= client
;
409 client
->trans_mod
->maxsize
= usb9pfs
->buflen
;
411 complete(&usb9pfs
->received
);
416 static void usb9pfs_clear_tx(struct f_usb9pfs
*usb9pfs
)
418 struct p9_req_t
*req
;
420 guard(spinlock_irqsave
)(&usb9pfs
->lock
);
422 req
= usb9pfs
->in_req
->context
;
427 req
->t_err
= -ECONNRESET
;
429 p9_client_cb(usb9pfs
->client
, req
, REQ_STATUS_ERROR
);
432 static void p9_usbg_close(struct p9_client
*client
)
434 struct f_usb9pfs
*usb9pfs
;
435 struct f_usb9pfs_dev
*dev
;
436 struct f_usb9pfs_opts
*opts
;
441 usb9pfs
= client
->trans
;
445 client
->status
= Disconnected
;
447 usb9pfs_clear_tx(usb9pfs
);
449 opts
= container_of(usb9pfs
->function
.fi
,
450 struct f_usb9pfs_opts
, func_inst
);
454 mutex_lock(&usb9pfs_lock
);
456 mutex_unlock(&usb9pfs_lock
);
459 static int p9_usbg_request(struct p9_client
*client
, struct p9_req_t
*p9_req
)
461 struct f_usb9pfs
*usb9pfs
= client
->trans
;
464 if (client
->status
!= Connected
)
467 ret
= wait_for_completion_killable(&usb9pfs
->received
);
471 ret
= usb9pfs_transmit(usb9pfs
, p9_req
);
475 ret
= wait_for_completion_killable(&usb9pfs
->send
);
479 return usb9pfs_queue_rx(usb9pfs
, usb9pfs
->out_req
, GFP_ATOMIC
);
482 static int p9_usbg_cancel(struct p9_client
*client
, struct p9_req_t
*req
)
484 struct f_usb9pfs
*usb9pfs
= client
->trans
;
487 p9_debug(P9_DEBUG_TRANS
, "client %p req %p\n", client
, req
);
489 guard(spinlock_irqsave
)(&usb9pfs
->lock
);
491 if (req
->status
== REQ_STATUS_UNSENT
) {
492 list_del(&req
->req_list
);
493 WRITE_ONCE(req
->status
, REQ_STATUS_FLSHD
);
494 p9_req_put(client
, req
);
501 static struct p9_trans_module p9_usbg_trans
= {
503 .create
= p9_usbg_create
,
504 .close
= p9_usbg_close
,
505 .request
= p9_usbg_request
,
506 .cancel
= p9_usbg_cancel
,
507 .owner
= THIS_MODULE
,
510 /*-------------------------------------------------------------------------*/
512 #define USB_PROTOCOL_9PFS 0x09
514 static struct usb_interface_descriptor usb9pfs_intf
= {
515 .bLength
= sizeof(usb9pfs_intf
),
516 .bDescriptorType
= USB_DT_INTERFACE
,
519 .bInterfaceClass
= USB_CLASS_VENDOR_SPEC
,
520 .bInterfaceSubClass
= USB_SUBCLASS_VENDOR_SPEC
,
521 .bInterfaceProtocol
= USB_PROTOCOL_9PFS
,
523 /* .iInterface = DYNAMIC */
526 /* full speed support: */
528 static struct usb_endpoint_descriptor fs_usb9pfs_source_desc
= {
529 .bLength
= USB_DT_ENDPOINT_SIZE
,
530 .bDescriptorType
= USB_DT_ENDPOINT
,
532 .bEndpointAddress
= USB_DIR_IN
,
533 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
536 static struct usb_endpoint_descriptor fs_usb9pfs_sink_desc
= {
537 .bLength
= USB_DT_ENDPOINT_SIZE
,
538 .bDescriptorType
= USB_DT_ENDPOINT
,
540 .bEndpointAddress
= USB_DIR_OUT
,
541 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
544 static struct usb_descriptor_header
*fs_usb9pfs_descs
[] = {
545 (struct usb_descriptor_header
*)&usb9pfs_intf
,
546 (struct usb_descriptor_header
*)&fs_usb9pfs_sink_desc
,
547 (struct usb_descriptor_header
*)&fs_usb9pfs_source_desc
,
551 /* high speed support: */
553 static struct usb_endpoint_descriptor hs_usb9pfs_source_desc
= {
554 .bLength
= USB_DT_ENDPOINT_SIZE
,
555 .bDescriptorType
= USB_DT_ENDPOINT
,
557 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
558 .wMaxPacketSize
= cpu_to_le16(512),
561 static struct usb_endpoint_descriptor hs_usb9pfs_sink_desc
= {
562 .bLength
= USB_DT_ENDPOINT_SIZE
,
563 .bDescriptorType
= USB_DT_ENDPOINT
,
565 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
566 .wMaxPacketSize
= cpu_to_le16(512),
569 static struct usb_descriptor_header
*hs_usb9pfs_descs
[] = {
570 (struct usb_descriptor_header
*)&usb9pfs_intf
,
571 (struct usb_descriptor_header
*)&hs_usb9pfs_source_desc
,
572 (struct usb_descriptor_header
*)&hs_usb9pfs_sink_desc
,
576 /* super speed support: */
578 static struct usb_endpoint_descriptor ss_usb9pfs_source_desc
= {
579 .bLength
= USB_DT_ENDPOINT_SIZE
,
580 .bDescriptorType
= USB_DT_ENDPOINT
,
582 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
583 .wMaxPacketSize
= cpu_to_le16(1024),
586 static struct usb_ss_ep_comp_descriptor ss_usb9pfs_source_comp_desc
= {
587 .bLength
= USB_DT_SS_EP_COMP_SIZE
,
588 .bDescriptorType
= USB_DT_SS_ENDPOINT_COMP
,
591 .wBytesPerInterval
= 0,
594 static struct usb_endpoint_descriptor ss_usb9pfs_sink_desc
= {
595 .bLength
= USB_DT_ENDPOINT_SIZE
,
596 .bDescriptorType
= USB_DT_ENDPOINT
,
598 .bmAttributes
= USB_ENDPOINT_XFER_BULK
,
599 .wMaxPacketSize
= cpu_to_le16(1024),
602 static struct usb_ss_ep_comp_descriptor ss_usb9pfs_sink_comp_desc
= {
603 .bLength
= USB_DT_SS_EP_COMP_SIZE
,
604 .bDescriptorType
= USB_DT_SS_ENDPOINT_COMP
,
607 .wBytesPerInterval
= 0,
610 static struct usb_descriptor_header
*ss_usb9pfs_descs
[] = {
611 (struct usb_descriptor_header
*)&usb9pfs_intf
,
612 (struct usb_descriptor_header
*)&ss_usb9pfs_source_desc
,
613 (struct usb_descriptor_header
*)&ss_usb9pfs_source_comp_desc
,
614 (struct usb_descriptor_header
*)&ss_usb9pfs_sink_desc
,
615 (struct usb_descriptor_header
*)&ss_usb9pfs_sink_comp_desc
,
619 /* function-specific strings: */
620 static struct usb_string strings_usb9pfs
[] = {
621 [0].s
= "usb9pfs input to output",
622 { } /* end of list */
625 static struct usb_gadget_strings stringtab_usb9pfs
= {
626 .language
= 0x0409, /* en-us */
627 .strings
= strings_usb9pfs
,
630 static struct usb_gadget_strings
*usb9pfs_strings
[] = {
635 /*-------------------------------------------------------------------------*/
637 static int usb9pfs_func_bind(struct usb_configuration
*c
,
638 struct usb_function
*f
)
640 struct f_usb9pfs
*usb9pfs
= func_to_usb9pfs(f
);
641 struct f_usb9pfs_opts
*opts
;
642 struct usb_composite_dev
*cdev
= c
->cdev
;
646 /* allocate interface ID(s) */
647 id
= usb_interface_id(c
, f
);
650 usb9pfs_intf
.bInterfaceNumber
= id
;
652 id
= usb_string_id(cdev
);
655 strings_usb9pfs
[0].id
= id
;
656 usb9pfs_intf
.iInterface
= id
;
658 /* allocate endpoints */
659 usb9pfs
->in_ep
= usb_ep_autoconfig(cdev
->gadget
,
660 &fs_usb9pfs_source_desc
);
664 usb9pfs
->out_ep
= usb_ep_autoconfig(cdev
->gadget
,
665 &fs_usb9pfs_sink_desc
);
666 if (!usb9pfs
->out_ep
)
669 /* support high speed hardware */
670 hs_usb9pfs_source_desc
.bEndpointAddress
=
671 fs_usb9pfs_source_desc
.bEndpointAddress
;
672 hs_usb9pfs_sink_desc
.bEndpointAddress
=
673 fs_usb9pfs_sink_desc
.bEndpointAddress
;
675 /* support super speed hardware */
676 ss_usb9pfs_source_desc
.bEndpointAddress
=
677 fs_usb9pfs_source_desc
.bEndpointAddress
;
678 ss_usb9pfs_sink_desc
.bEndpointAddress
=
679 fs_usb9pfs_sink_desc
.bEndpointAddress
;
681 ret
= usb_assign_descriptors(f
, fs_usb9pfs_descs
, hs_usb9pfs_descs
,
682 ss_usb9pfs_descs
, ss_usb9pfs_descs
);
686 opts
= container_of(f
->fi
, struct f_usb9pfs_opts
, func_inst
);
687 opts
->dev
->usb9pfs
= usb9pfs
;
689 dev_dbg(&cdev
->gadget
->dev
, "%s speed %s: IN/%s, OUT/%s\n",
690 (gadget_is_superspeed(c
->cdev
->gadget
) ? "super" :
691 (gadget_is_dualspeed(c
->cdev
->gadget
) ? "dual" : "full")),
692 f
->name
, usb9pfs
->in_ep
->name
, usb9pfs
->out_ep
->name
);
697 ERROR(cdev
, "%s: can't autoconfigure on %s\n",
698 f
->name
, cdev
->gadget
->name
);
702 static void usb9pfs_func_unbind(struct usb_configuration
*c
,
703 struct usb_function
*f
)
705 struct f_usb9pfs
*usb9pfs
= func_to_usb9pfs(f
);
707 disable_usb9pfs(usb9pfs
);
710 static void usb9pfs_free_func(struct usb_function
*f
)
712 struct f_usb9pfs
*usb9pfs
= func_to_usb9pfs(f
);
713 struct f_usb9pfs_opts
*opts
;
717 opts
= container_of(f
->fi
, struct f_usb9pfs_opts
, func_inst
);
719 mutex_lock(&opts
->lock
);
721 mutex_unlock(&opts
->lock
);
723 usb_free_all_descriptors(f
);
726 static int usb9pfs_set_alt(struct usb_function
*f
,
727 unsigned int intf
, unsigned int alt
)
729 struct f_usb9pfs
*usb9pfs
= func_to_usb9pfs(f
);
730 struct usb_composite_dev
*cdev
= f
->config
->cdev
;
732 return enable_usb9pfs(cdev
, usb9pfs
);
735 static void usb9pfs_disable(struct usb_function
*f
)
737 struct f_usb9pfs
*usb9pfs
= func_to_usb9pfs(f
);
739 usb9pfs_clear_tx(usb9pfs
);
742 static struct usb_function
*usb9pfs_alloc(struct usb_function_instance
*fi
)
744 struct f_usb9pfs_opts
*usb9pfs_opts
;
745 struct f_usb9pfs
*usb9pfs
;
747 usb9pfs
= kzalloc(sizeof(*usb9pfs
), GFP_KERNEL
);
749 return ERR_PTR(-ENOMEM
);
751 spin_lock_init(&usb9pfs
->lock
);
753 init_completion(&usb9pfs
->send
);
754 init_completion(&usb9pfs
->received
);
756 usb9pfs_opts
= container_of(fi
, struct f_usb9pfs_opts
, func_inst
);
758 mutex_lock(&usb9pfs_opts
->lock
);
759 usb9pfs_opts
->refcnt
++;
760 mutex_unlock(&usb9pfs_opts
->lock
);
762 usb9pfs
->buflen
= usb9pfs_opts
->buflen
;
764 usb9pfs
->function
.name
= "usb9pfs";
765 usb9pfs
->function
.bind
= usb9pfs_func_bind
;
766 usb9pfs
->function
.unbind
= usb9pfs_func_unbind
;
767 usb9pfs
->function
.set_alt
= usb9pfs_set_alt
;
768 usb9pfs
->function
.disable
= usb9pfs_disable
;
769 usb9pfs
->function
.strings
= usb9pfs_strings
;
771 usb9pfs
->function
.free_func
= usb9pfs_free_func
;
773 return &usb9pfs
->function
;
776 static inline struct f_usb9pfs_opts
*to_f_usb9pfs_opts(struct config_item
*item
)
778 return container_of(to_config_group(item
), struct f_usb9pfs_opts
,
782 static inline struct f_usb9pfs_opts
*fi_to_f_usb9pfs_opts(struct usb_function_instance
*fi
)
784 return container_of(fi
, struct f_usb9pfs_opts
, func_inst
);
787 static void usb9pfs_attr_release(struct config_item
*item
)
789 struct f_usb9pfs_opts
*usb9pfs_opts
= to_f_usb9pfs_opts(item
);
791 usb_put_function_instance(&usb9pfs_opts
->func_inst
);
794 static struct configfs_item_operations usb9pfs_item_ops
= {
795 .release
= usb9pfs_attr_release
,
798 static ssize_t
f_usb9pfs_opts_buflen_show(struct config_item
*item
, char *page
)
800 struct f_usb9pfs_opts
*opts
= to_f_usb9pfs_opts(item
);
803 mutex_lock(&opts
->lock
);
804 ret
= sysfs_emit(page
, "%d\n", opts
->buflen
);
805 mutex_unlock(&opts
->lock
);
810 static ssize_t
f_usb9pfs_opts_buflen_store(struct config_item
*item
,
811 const char *page
, size_t len
)
813 struct f_usb9pfs_opts
*opts
= to_f_usb9pfs_opts(item
);
817 guard(mutex
)(&opts
->lock
);
822 ret
= kstrtou32(page
, 0, &num
);
831 CONFIGFS_ATTR(f_usb9pfs_opts_
, buflen
);
833 static struct configfs_attribute
*usb9pfs_attrs
[] = {
834 &f_usb9pfs_opts_attr_buflen
,
838 static const struct config_item_type usb9pfs_func_type
= {
839 .ct_item_ops
= &usb9pfs_item_ops
,
840 .ct_attrs
= usb9pfs_attrs
,
841 .ct_owner
= THIS_MODULE
,
844 static struct f_usb9pfs_dev
*_usb9pfs_do_find_dev(const char *tag
)
846 struct f_usb9pfs_dev
*usb9pfs_dev
;
851 list_for_each_entry(usb9pfs_dev
, &usbg_instance_list
, usb9pfs_instance
) {
852 if (strcmp(usb9pfs_dev
->tag
, tag
) == 0)
859 static int usb9pfs_tag_instance(struct f_usb9pfs_dev
*dev
, const char *tag
)
861 struct f_usb9pfs_dev
*existing
;
864 guard(mutex
)(&usb9pfs_lock
);
866 existing
= _usb9pfs_do_find_dev(tag
);
868 strscpy(dev
->tag
, tag
, ARRAY_SIZE(dev
->tag
));
869 else if (existing
!= dev
)
875 static int usb9pfs_set_inst_tag(struct usb_function_instance
*fi
, const char *tag
)
877 if (strlen(tag
) >= sizeof_field(struct f_usb9pfs_dev
, tag
))
878 return -ENAMETOOLONG
;
879 return usb9pfs_tag_instance(fi_to_f_usb9pfs_opts(fi
)->dev
, tag
);
882 static void usb9pfs_free_instance(struct usb_function_instance
*fi
)
884 struct f_usb9pfs_opts
*usb9pfs_opts
=
885 container_of(fi
, struct f_usb9pfs_opts
, func_inst
);
886 struct f_usb9pfs_dev
*dev
= usb9pfs_opts
->dev
;
888 mutex_lock(&usb9pfs_lock
);
889 list_del(&dev
->usb9pfs_instance
);
890 mutex_unlock(&usb9pfs_lock
);
895 static struct usb_function_instance
*usb9pfs_alloc_instance(void)
897 struct f_usb9pfs_opts
*usb9pfs_opts
;
898 struct f_usb9pfs_dev
*dev
;
900 usb9pfs_opts
= kzalloc(sizeof(*usb9pfs_opts
), GFP_KERNEL
);
902 return ERR_PTR(-ENOMEM
);
904 mutex_init(&usb9pfs_opts
->lock
);
906 usb9pfs_opts
->func_inst
.set_inst_name
= usb9pfs_set_inst_tag
;
907 usb9pfs_opts
->func_inst
.free_func_inst
= usb9pfs_free_instance
;
909 usb9pfs_opts
->buflen
= DEFAULT_BUFLEN
;
911 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
914 return ERR_PTR(-ENOMEM
);
917 usb9pfs_opts
->dev
= dev
;
918 dev
->opts
= usb9pfs_opts
;
920 config_group_init_type_name(&usb9pfs_opts
->func_inst
.group
, "",
923 mutex_lock(&usb9pfs_lock
);
924 list_add_tail(&dev
->usb9pfs_instance
, &usbg_instance_list
);
925 mutex_unlock(&usb9pfs_lock
);
927 return &usb9pfs_opts
->func_inst
;
929 DECLARE_USB_FUNCTION(usb9pfs
, usb9pfs_alloc_instance
, usb9pfs_alloc
);
931 static int __init
usb9pfs_modinit(void)
935 INIT_LIST_HEAD(&usbg_instance_list
);
937 ret
= usb_function_register(&usb9pfsusb_func
);
939 v9fs_register_trans(&p9_usbg_trans
);
944 static void __exit
usb9pfs_modexit(void)
946 usb_function_unregister(&usb9pfsusb_func
);
947 v9fs_unregister_trans(&p9_usbg_trans
);
950 module_init(usb9pfs_modinit
);
951 module_exit(usb9pfs_modexit
);
953 MODULE_ALIAS_9P("usbg");
954 MODULE_LICENSE("GPL");
955 MODULE_DESCRIPTION("USB gadget 9pfs transport");
956 MODULE_AUTHOR("Michael Grzeschik");