Skip to content

Commit

Permalink
usb: gadget: f_uac2: reset wMaxPacketSize
Browse files Browse the repository at this point in the history
With commit 913e4a9 ("usb: gadget: f_uac2: finalize wMaxPacketSize according to bandwidth")
wMaxPacketSize is computed dynamically but the value is never reset.

Because of this, the actual maximum packet size can only decrease each time
the audio gadget is instantiated.

Reset the endpoint maximum packet size and mark wMaxPacketSize as dynamic
to solve the problem.

Fixes: 913e4a9 ("usb: gadget: f_uac2: finalize wMaxPacketSize according to bandwidth")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20201221173531.215169-2-jbrunet@baylibre.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Jerome Brunet authored and Greg Kroah-Hartman committed Dec 28, 2020
1 parent e5f4ca3 commit 9389044
Showing 1 changed file with 55 additions and 14 deletions.
69 changes: 55 additions & 14 deletions drivers/usb/gadget/function/f_uac2.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ static struct usb_endpoint_descriptor fs_epout_desc = {

.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1023),
/* .wMaxPacketSize = DYNAMIC */
.bInterval = 1,
};

Expand All @@ -280,7 +280,7 @@ static struct usb_endpoint_descriptor hs_epout_desc = {
.bDescriptorType = USB_DT_ENDPOINT,

.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1024),
/* .wMaxPacketSize = DYNAMIC */
.bInterval = 4,
};

Expand Down Expand Up @@ -348,7 +348,7 @@ static struct usb_endpoint_descriptor fs_epin_desc = {

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1023),
/* .wMaxPacketSize = DYNAMIC */
.bInterval = 1,
};

Expand All @@ -357,7 +357,7 @@ static struct usb_endpoint_descriptor hs_epin_desc = {
.bDescriptorType = USB_DT_ENDPOINT,

.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1024),
/* .wMaxPacketSize = DYNAMIC */
.bInterval = 4,
};

Expand Down Expand Up @@ -444,12 +444,28 @@ struct cntrl_range_lay3 {
__le32 dRES;
} __packed;

static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
struct usb_endpoint_descriptor *ep_desc,
unsigned int factor, bool is_playback)
enum usb_device_speed speed, bool is_playback)
{
int chmask, srate, ssize;
u16 max_packet_size;
u16 max_size_bw, max_size_ep;
unsigned int factor;

switch (speed) {
case USB_SPEED_FULL:
max_size_ep = 1023;
factor = 1000;
break;

case USB_SPEED_HIGH:
max_size_ep = 1024;
factor = 8000;
break;

default:
return -EINVAL;
}

if (is_playback) {
chmask = uac2_opts->p_chmask;
Expand All @@ -461,10 +477,12 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
ssize = uac2_opts->c_ssize;
}

max_packet_size = num_channels(chmask) * ssize *
max_size_bw = num_channels(chmask) * ssize *
DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size,
le16_to_cpu(ep_desc->wMaxPacketSize)));
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
max_size_ep));

return 0;
}

/* Use macro to overcome line length limitation */
Expand Down Expand Up @@ -670,10 +688,33 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}

/* Calculate wMaxPacketSize according to audio bandwidth */
set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
ret = set_ep_max_packet_size(uac2_opts, &fs_epin_desc, USB_SPEED_FULL,
true);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}

ret = set_ep_max_packet_size(uac2_opts, &fs_epout_desc, USB_SPEED_FULL,
false);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}

ret = set_ep_max_packet_size(uac2_opts, &hs_epin_desc, USB_SPEED_HIGH,
true);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}

ret = set_ep_max_packet_size(uac2_opts, &hs_epout_desc, USB_SPEED_HIGH,
false);
if (ret < 0) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}

if (EPOUT_EN(uac2_opts)) {
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
Expand Down

0 comments on commit 9389044

Please sign in to comment.