Loading drivers/usb/gadget/function/f_cdev.c +84 −3 Original line number Original line Diff line number Diff line Loading @@ -128,6 +128,10 @@ struct f_cdev { unsigned long nbytes_to_port_bridge; unsigned long nbytes_to_port_bridge; unsigned long nbytes_from_port_bridge; unsigned long nbytes_from_port_bridge; unsigned int single_packet_mode; unsigned int rx_buf_size; unsigned int rx_queue_size; struct dentry *debugfs_root; struct dentry *debugfs_root; /* To test remote wakeup using debugfs */ /* To test remote wakeup using debugfs */ Loading @@ -140,6 +144,7 @@ struct f_cdev_opts { char *func_name; char *func_name; u8 port_num; u8 port_num; u8 proto; u8 proto; int refcnt; }; }; static int major, minors; static int major, minors; Loading Loading @@ -406,7 +411,14 @@ static void port_complete_set_line_coding(struct usb_ep *ep, static void usb_cser_free_func(struct usb_function *f) static void usb_cser_free_func(struct usb_function *f) { { /* Do nothing as cser_alloc() doesn't alloc anything. */ unsigned long flags; struct f_cdev_opts *opts = container_of(f->fi, struct f_cdev_opts, func_inst); struct f_cdev *port = opts->port; spin_lock_irqsave(&port->port_lock, flags); opts->refcnt--; spin_unlock_irqrestore(&port->port_lock, flags); } } static int static int Loading Loading @@ -950,7 +962,7 @@ static void usb_cser_start_rx(struct f_cdev *port) req = list_entry(pool->next, struct usb_request, list); req = list_entry(pool->next, struct usb_request, list); list_del_init(&req->list); list_del_init(&req->list); req->length = BRIDGE_RX_BUF_SIZE; req->length = port->rx_buf_size; req->complete = usb_cser_read_complete; req->complete = usb_cser_read_complete; spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags); ret = usb_ep_queue(ep, req, GFP_KERNEL); ret = usb_ep_queue(ep, req, GFP_KERNEL); Loading Loading @@ -1047,7 +1059,9 @@ static void usb_cser_start_io(struct f_cdev *port) ret = usb_cser_alloc_requests(port->port_usb.out, ret = usb_cser_alloc_requests(port->port_usb.out, &port->read_pool, &port->read_pool, BRIDGE_RX_QUEUE_SIZE, BRIDGE_RX_BUF_SIZE, 0, port->rx_queue_size, port->rx_buf_size, 0, usb_cser_read_complete); usb_cser_read_complete); if (ret) { if (ret) { pr_err("unable to allocate out requests\n"); pr_err("unable to allocate out requests\n"); Loading Loading @@ -1242,6 +1256,8 @@ ssize_t f_cdev_read(struct file *file, current_rx_req = NULL; current_rx_req = NULL; current_rx_buf = NULL; current_rx_buf = NULL; } } if (port->single_packet_mode) break; } } port->pending_rx_bytes = pending_rx_bytes; port->pending_rx_bytes = pending_rx_bytes; Loading Loading @@ -1766,6 +1782,11 @@ static struct f_cdev *f_cdev_alloc(char *func_name, int portno) INIT_LIST_HEAD(&port->read_queued); INIT_LIST_HEAD(&port->read_queued); INIT_LIST_HEAD(&port->write_pool); INIT_LIST_HEAD(&port->write_pool); /* Fill rx bridge parameters */ port->rx_buf_size = BRIDGE_RX_BUF_SIZE; port->rx_queue_size = BRIDGE_RX_QUEUE_SIZE; port->single_packet_mode = 0; port->fcdev_wq = create_singlethread_workqueue(port->name); port->fcdev_wq = create_singlethread_workqueue(port->name); if (!port->fcdev_wq) { if (!port->fcdev_wq) { pr_err("Unable to create workqueue fcdev_wq for port:%s\n", pr_err("Unable to create workqueue fcdev_wq for port:%s\n", Loading Loading @@ -1932,9 +1953,64 @@ static ssize_t usb_cser_status_store(struct config_item *item, return len; return len; } } #define CDEV_BUF_ATTRIBUTE(name) \ static ssize_t usb_cser_##name##_show(struct config_item *item, \ char *page) \ { \ struct f_cdev *port = to_f_cdev_opts(item)->port; \ unsigned long flags; \ int ret; \ \ spin_lock_irqsave(&port->port_lock, flags); \ ret = scnprintf(page, PAGE_SIZE, "%u\n", \ port->name); \ spin_unlock_irqrestore(&port->port_lock, flags); \ \ return ret; \ } \ \ static ssize_t usb_cser_##name##_store(struct config_item *item, \ const char *page, size_t len) \ { \ struct f_cdev_opts *opts = to_f_cdev_opts(item); \ struct f_cdev *port = opts->port; \ unsigned long flags; \ int ret; \ unsigned int val; \ \ spin_lock_irqsave(&port->port_lock, flags); \ if (opts->refcnt) { \ ret = -EBUSY; \ goto end; \ } \ \ ret = kstrtouint(page, 0, &val); \ if (ret) \ goto end; \ \ port->name = val; \ ret = len; \ \ end: \ spin_unlock_irqrestore(&port->port_lock, flags); \ return ret; \ } \ \ CDEV_BUF_ATTRIBUTE(rx_buf_size); CDEV_BUF_ATTRIBUTE(rx_queue_size); CDEV_BUF_ATTRIBUTE(single_packet_mode); CONFIGFS_ATTR(usb_cser_, single_packet_mode); CONFIGFS_ATTR(usb_cser_, status); CONFIGFS_ATTR(usb_cser_, status); CONFIGFS_ATTR(usb_cser_, rx_buf_size); CONFIGFS_ATTR(usb_cser_, rx_queue_size); static struct configfs_attribute *cserial_attrs[] = { static struct configfs_attribute *cserial_attrs[] = { &usb_cser_attr_single_packet_mode, &usb_cser_attr_status, &usb_cser_attr_status, &usb_cser_attr_rx_buf_size, &usb_cser_attr_rx_queue_size, NULL, NULL, }; }; Loading Loading @@ -2045,6 +2121,11 @@ static struct usb_function *cser_alloc(struct usb_function_instance *fi) { { struct f_cdev_opts *opts = to_fi_cdev_opts(fi); struct f_cdev_opts *opts = to_fi_cdev_opts(fi); struct f_cdev *port = opts->port; struct f_cdev *port = opts->port; unsigned long flags; spin_lock_irqsave(&port->port_lock, flags); opts->refcnt++; spin_unlock_irqrestore(&port->port_lock, flags); port->port_usb.func.name = "cser"; port->port_usb.func.name = "cser"; port->port_usb.func.strings = usb_cser_strings; port->port_usb.func.strings = usb_cser_strings; Loading Loading
drivers/usb/gadget/function/f_cdev.c +84 −3 Original line number Original line Diff line number Diff line Loading @@ -128,6 +128,10 @@ struct f_cdev { unsigned long nbytes_to_port_bridge; unsigned long nbytes_to_port_bridge; unsigned long nbytes_from_port_bridge; unsigned long nbytes_from_port_bridge; unsigned int single_packet_mode; unsigned int rx_buf_size; unsigned int rx_queue_size; struct dentry *debugfs_root; struct dentry *debugfs_root; /* To test remote wakeup using debugfs */ /* To test remote wakeup using debugfs */ Loading @@ -140,6 +144,7 @@ struct f_cdev_opts { char *func_name; char *func_name; u8 port_num; u8 port_num; u8 proto; u8 proto; int refcnt; }; }; static int major, minors; static int major, minors; Loading Loading @@ -406,7 +411,14 @@ static void port_complete_set_line_coding(struct usb_ep *ep, static void usb_cser_free_func(struct usb_function *f) static void usb_cser_free_func(struct usb_function *f) { { /* Do nothing as cser_alloc() doesn't alloc anything. */ unsigned long flags; struct f_cdev_opts *opts = container_of(f->fi, struct f_cdev_opts, func_inst); struct f_cdev *port = opts->port; spin_lock_irqsave(&port->port_lock, flags); opts->refcnt--; spin_unlock_irqrestore(&port->port_lock, flags); } } static int static int Loading Loading @@ -950,7 +962,7 @@ static void usb_cser_start_rx(struct f_cdev *port) req = list_entry(pool->next, struct usb_request, list); req = list_entry(pool->next, struct usb_request, list); list_del_init(&req->list); list_del_init(&req->list); req->length = BRIDGE_RX_BUF_SIZE; req->length = port->rx_buf_size; req->complete = usb_cser_read_complete; req->complete = usb_cser_read_complete; spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags); ret = usb_ep_queue(ep, req, GFP_KERNEL); ret = usb_ep_queue(ep, req, GFP_KERNEL); Loading Loading @@ -1047,7 +1059,9 @@ static void usb_cser_start_io(struct f_cdev *port) ret = usb_cser_alloc_requests(port->port_usb.out, ret = usb_cser_alloc_requests(port->port_usb.out, &port->read_pool, &port->read_pool, BRIDGE_RX_QUEUE_SIZE, BRIDGE_RX_BUF_SIZE, 0, port->rx_queue_size, port->rx_buf_size, 0, usb_cser_read_complete); usb_cser_read_complete); if (ret) { if (ret) { pr_err("unable to allocate out requests\n"); pr_err("unable to allocate out requests\n"); Loading Loading @@ -1242,6 +1256,8 @@ ssize_t f_cdev_read(struct file *file, current_rx_req = NULL; current_rx_req = NULL; current_rx_buf = NULL; current_rx_buf = NULL; } } if (port->single_packet_mode) break; } } port->pending_rx_bytes = pending_rx_bytes; port->pending_rx_bytes = pending_rx_bytes; Loading Loading @@ -1766,6 +1782,11 @@ static struct f_cdev *f_cdev_alloc(char *func_name, int portno) INIT_LIST_HEAD(&port->read_queued); INIT_LIST_HEAD(&port->read_queued); INIT_LIST_HEAD(&port->write_pool); INIT_LIST_HEAD(&port->write_pool); /* Fill rx bridge parameters */ port->rx_buf_size = BRIDGE_RX_BUF_SIZE; port->rx_queue_size = BRIDGE_RX_QUEUE_SIZE; port->single_packet_mode = 0; port->fcdev_wq = create_singlethread_workqueue(port->name); port->fcdev_wq = create_singlethread_workqueue(port->name); if (!port->fcdev_wq) { if (!port->fcdev_wq) { pr_err("Unable to create workqueue fcdev_wq for port:%s\n", pr_err("Unable to create workqueue fcdev_wq for port:%s\n", Loading Loading @@ -1932,9 +1953,64 @@ static ssize_t usb_cser_status_store(struct config_item *item, return len; return len; } } #define CDEV_BUF_ATTRIBUTE(name) \ static ssize_t usb_cser_##name##_show(struct config_item *item, \ char *page) \ { \ struct f_cdev *port = to_f_cdev_opts(item)->port; \ unsigned long flags; \ int ret; \ \ spin_lock_irqsave(&port->port_lock, flags); \ ret = scnprintf(page, PAGE_SIZE, "%u\n", \ port->name); \ spin_unlock_irqrestore(&port->port_lock, flags); \ \ return ret; \ } \ \ static ssize_t usb_cser_##name##_store(struct config_item *item, \ const char *page, size_t len) \ { \ struct f_cdev_opts *opts = to_f_cdev_opts(item); \ struct f_cdev *port = opts->port; \ unsigned long flags; \ int ret; \ unsigned int val; \ \ spin_lock_irqsave(&port->port_lock, flags); \ if (opts->refcnt) { \ ret = -EBUSY; \ goto end; \ } \ \ ret = kstrtouint(page, 0, &val); \ if (ret) \ goto end; \ \ port->name = val; \ ret = len; \ \ end: \ spin_unlock_irqrestore(&port->port_lock, flags); \ return ret; \ } \ \ CDEV_BUF_ATTRIBUTE(rx_buf_size); CDEV_BUF_ATTRIBUTE(rx_queue_size); CDEV_BUF_ATTRIBUTE(single_packet_mode); CONFIGFS_ATTR(usb_cser_, single_packet_mode); CONFIGFS_ATTR(usb_cser_, status); CONFIGFS_ATTR(usb_cser_, status); CONFIGFS_ATTR(usb_cser_, rx_buf_size); CONFIGFS_ATTR(usb_cser_, rx_queue_size); static struct configfs_attribute *cserial_attrs[] = { static struct configfs_attribute *cserial_attrs[] = { &usb_cser_attr_single_packet_mode, &usb_cser_attr_status, &usb_cser_attr_status, &usb_cser_attr_rx_buf_size, &usb_cser_attr_rx_queue_size, NULL, NULL, }; }; Loading Loading @@ -2045,6 +2121,11 @@ static struct usb_function *cser_alloc(struct usb_function_instance *fi) { { struct f_cdev_opts *opts = to_fi_cdev_opts(fi); struct f_cdev_opts *opts = to_fi_cdev_opts(fi); struct f_cdev *port = opts->port; struct f_cdev *port = opts->port; unsigned long flags; spin_lock_irqsave(&port->port_lock, flags); opts->refcnt++; spin_unlock_irqrestore(&port->port_lock, flags); port->port_usb.func.name = "cser"; port->port_usb.func.name = "cser"; port->port_usb.func.strings = usb_cser_strings; port->port_usb.func.strings = usb_cser_strings; Loading