Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01f96ccc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: cdev: Add single packet and dynamic buffer support for Rx path"

parents 82146398 8c6a54ca
Loading
Loading
Loading
Loading
+84 −3
Original line number Original line Diff line number Diff line
@@ -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 */
@@ -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;
@@ -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
@@ -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);
@@ -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");
@@ -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;
@@ -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",
@@ -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,
};
};


@@ -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;