mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 21:44:06 +08:00
usb: gadget: f_sourcesink: add queue depth
Add queue depth for both iso and bulk transfer, with more queues, we can do performance and stress test using sourcesink, and update g_zero accordingly. Reviewed-by: Krzysztof Opasiak <k.opasiak@samsung.com> Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
b084662776
commit
0d6c3d9667
@ -34,13 +34,6 @@
|
||||
* plus two that support control-OUT tests. If the optional "autoresume"
|
||||
* mode is enabled, it provides good functional coverage for the "USBCV"
|
||||
* test harness from USB-IF.
|
||||
*
|
||||
* Note that because this doesn't queue more than one request at a time,
|
||||
* some other function must be used to test queueing logic. The network
|
||||
* link (g_ether) is the best overall option for that, since its TX and RX
|
||||
* queues are relatively independent, will receive a range of packet sizes,
|
||||
* and can often be made to run out completely. Those issues are important
|
||||
* when stress testing peripheral controller drivers.
|
||||
*/
|
||||
struct f_sourcesink {
|
||||
struct usb_function function;
|
||||
@ -57,6 +50,8 @@ struct f_sourcesink {
|
||||
unsigned isoc_mult;
|
||||
unsigned isoc_maxburst;
|
||||
unsigned buflen;
|
||||
unsigned bulk_qlen;
|
||||
unsigned iso_qlen;
|
||||
};
|
||||
|
||||
static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
|
||||
@ -595,31 +590,33 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
struct usb_request *req;
|
||||
int i, size, status;
|
||||
int i, size, qlen, status = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (is_iso) {
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
size = ss->isoc_maxpacket *
|
||||
(ss->isoc_mult + 1) *
|
||||
(ss->isoc_maxburst + 1);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
size = ss->isoc_maxpacket * (ss->isoc_mult + 1);
|
||||
break;
|
||||
default:
|
||||
size = ss->isoc_maxpacket > 1023 ?
|
||||
1023 : ss->isoc_maxpacket;
|
||||
break;
|
||||
}
|
||||
ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
|
||||
req = ss_alloc_ep_req(ep, size);
|
||||
} else {
|
||||
ep = is_in ? ss->in_ep : ss->out_ep;
|
||||
req = ss_alloc_ep_req(ep, 0);
|
||||
if (is_iso) {
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
size = ss->isoc_maxpacket *
|
||||
(ss->isoc_mult + 1) *
|
||||
(ss->isoc_maxburst + 1);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
size = ss->isoc_maxpacket * (ss->isoc_mult + 1);
|
||||
break;
|
||||
default:
|
||||
size = ss->isoc_maxpacket > 1023 ?
|
||||
1023 : ss->isoc_maxpacket;
|
||||
break;
|
||||
}
|
||||
ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
|
||||
qlen = ss->iso_qlen;
|
||||
} else {
|
||||
ep = is_in ? ss->in_ep : ss->out_ep;
|
||||
qlen = ss->bulk_qlen;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < qlen; i++) {
|
||||
req = ss_alloc_ep_req(ep, size);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -639,9 +636,6 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
|
||||
ep->name, status);
|
||||
free_ep_req(ep, req);
|
||||
}
|
||||
|
||||
if (!is_iso)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -869,6 +863,8 @@ static struct usb_function *source_sink_alloc_func(
|
||||
ss->isoc_mult = ss_opts->isoc_mult;
|
||||
ss->isoc_maxburst = ss_opts->isoc_maxburst;
|
||||
ss->buflen = ss_opts->bulk_buflen;
|
||||
ss->bulk_qlen = ss_opts->bulk_qlen;
|
||||
ss->iso_qlen = ss_opts->iso_qlen;
|
||||
|
||||
ss->function.name = "source/sink";
|
||||
ss->function.bind = sourcesink_bind;
|
||||
@ -1153,6 +1149,82 @@ end:
|
||||
|
||||
CONFIGFS_ATTR(f_ss_opts_, bulk_buflen);
|
||||
|
||||
static ssize_t f_ss_opts_bulk_qlen_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct f_ss_opts *opts = to_f_ss_opts(item);
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%u\n", opts->bulk_qlen);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_bulk_qlen_store(struct config_item *item,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
struct f_ss_opts *opts = to_f_ss_opts(item);
|
||||
int ret;
|
||||
u32 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou32(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
opts->bulk_qlen = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(f_ss_opts_, bulk_qlen);
|
||||
|
||||
static ssize_t f_ss_opts_iso_qlen_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct f_ss_opts *opts = to_f_ss_opts(item);
|
||||
int result;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
result = sprintf(page, "%u\n", opts->iso_qlen);
|
||||
mutex_unlock(&opts->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ssize_t f_ss_opts_iso_qlen_store(struct config_item *item,
|
||||
const char *page, size_t len)
|
||||
{
|
||||
struct f_ss_opts *opts = to_f_ss_opts(item);
|
||||
int ret;
|
||||
u32 num;
|
||||
|
||||
mutex_lock(&opts->lock);
|
||||
if (opts->refcnt) {
|
||||
ret = -EBUSY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = kstrtou32(page, 0, &num);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
opts->iso_qlen = num;
|
||||
ret = len;
|
||||
end:
|
||||
mutex_unlock(&opts->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(f_ss_opts_, iso_qlen);
|
||||
|
||||
static struct configfs_attribute *ss_attrs[] = {
|
||||
&f_ss_opts_attr_pattern,
|
||||
&f_ss_opts_attr_isoc_interval,
|
||||
@ -1160,6 +1232,8 @@ static struct configfs_attribute *ss_attrs[] = {
|
||||
&f_ss_opts_attr_isoc_mult,
|
||||
&f_ss_opts_attr_isoc_maxburst,
|
||||
&f_ss_opts_attr_bulk_buflen,
|
||||
&f_ss_opts_attr_bulk_qlen,
|
||||
&f_ss_opts_attr_iso_qlen,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -1189,6 +1263,8 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
|
||||
ss_opts->isoc_interval = GZERO_ISOC_INTERVAL;
|
||||
ss_opts->isoc_maxpacket = GZERO_ISOC_MAXPACKET;
|
||||
ss_opts->bulk_buflen = GZERO_BULK_BUFLEN;
|
||||
ss_opts->bulk_qlen = GZERO_SS_BULK_QLEN;
|
||||
ss_opts->iso_qlen = GZERO_SS_ISO_QLEN;
|
||||
|
||||
config_group_init_type_name(&ss_opts->func_inst.group, "",
|
||||
&ss_func_type);
|
||||
|
@ -10,6 +10,8 @@
|
||||
#define GZERO_QLEN 32
|
||||
#define GZERO_ISOC_INTERVAL 4
|
||||
#define GZERO_ISOC_MAXPACKET 1024
|
||||
#define GZERO_SS_BULK_QLEN 1
|
||||
#define GZERO_SS_ISO_QLEN 8
|
||||
|
||||
struct usb_zero_options {
|
||||
unsigned pattern;
|
||||
@ -19,6 +21,8 @@ struct usb_zero_options {
|
||||
unsigned isoc_maxburst;
|
||||
unsigned bulk_buflen;
|
||||
unsigned qlen;
|
||||
unsigned ss_bulk_qlen;
|
||||
unsigned ss_iso_qlen;
|
||||
};
|
||||
|
||||
struct f_ss_opts {
|
||||
@ -29,6 +33,8 @@ struct f_ss_opts {
|
||||
unsigned isoc_mult;
|
||||
unsigned isoc_maxburst;
|
||||
unsigned bulk_buflen;
|
||||
unsigned bulk_qlen;
|
||||
unsigned iso_qlen;
|
||||
|
||||
/*
|
||||
* Read/write access to configfs attributes is handled by configfs.
|
||||
|
@ -68,6 +68,8 @@ static struct usb_zero_options gzero_options = {
|
||||
.isoc_maxpacket = GZERO_ISOC_MAXPACKET,
|
||||
.bulk_buflen = GZERO_BULK_BUFLEN,
|
||||
.qlen = GZERO_QLEN,
|
||||
.ss_bulk_qlen = GZERO_SS_BULK_QLEN,
|
||||
.ss_iso_qlen = GZERO_SS_ISO_QLEN,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -255,6 +257,14 @@ static struct usb_function_instance *func_inst_lb;
|
||||
module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(qlen, "depth of loopback queue");
|
||||
|
||||
module_param_named(ss_bulk_qlen, gzero_options.ss_bulk_qlen, uint,
|
||||
S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(bulk_qlen, "depth of sourcesink queue for bulk transfer");
|
||||
|
||||
module_param_named(ss_iso_qlen, gzero_options.ss_iso_qlen, uint,
|
||||
S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(iso_qlen, "depth of sourcesink queue for iso transfer");
|
||||
|
||||
static int zero_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
struct f_ss_opts *ss_opts;
|
||||
@ -285,6 +295,8 @@ static int zero_bind(struct usb_composite_dev *cdev)
|
||||
ss_opts->isoc_mult = gzero_options.isoc_mult;
|
||||
ss_opts->isoc_maxburst = gzero_options.isoc_maxburst;
|
||||
ss_opts->bulk_buflen = gzero_options.bulk_buflen;
|
||||
ss_opts->bulk_qlen = gzero_options.ss_bulk_qlen;
|
||||
ss_opts->iso_qlen = gzero_options.ss_iso_qlen;
|
||||
|
||||
func_ss = usb_get_function(func_inst_ss);
|
||||
if (IS_ERR(func_ss)) {
|
||||
|
Loading…
Reference in New Issue
Block a user