mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 20:02:17 +00:00
USB: fixes for v5.6-rc1
DWC3 learned that we can't always depend on Event Status bits. A problem was solved which would only surface with scatter list on IN endpoints. DWC2 got a fix for feature requests (both set and clear) and GetStatus request. The serial gadget got a fix for a TX stall bug. Composite framework now works better for SSP devices. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEElLzh7wn96CXwjh2IzL64meEamQYFAl5FdDQRHGJhbGJpQGtl cm5lbC5vcmcACgkQzL64meEamQZ7bhAArOr7eVWligWztFcCRj1WjgeXBARK+oIZ MZGHwV3jTbmvEwlv5rAb13d3R5rkIIQshvk0dU+J0n9kiUPJntlwu41vSd5/JyqR V70oYJPuJqDbI1HpkUnzha9SgiZcKXtA1NhjQmk/NmfYXQmQq5M7lDgug8BuFBDX EbrFp8ScJZ4TExgseaOOmGNS5d2GpQCLxBc0Rqmou7/1lHfplUXU3d9tdMYjR2g3 XJucNDNV/CfN0TlThlcnyYifH7B1AWMgs9uxVA1DxRFC6IsU4SsKIEyrtU7Lf5qO jSUBsLawiuGOPdbfwxi0LwKuzWSvrs9ZAIshHL9Gkw9v/kAoWPzrbewymi06Voql H2MmjPSzynV1I5syPJPZeNxjPYNJmuMusmYuhXa+zE2alRYRDQeIk8/2goTDzcdJ 7WIPCH7NwMDxPA/KCI74lgrIdViaDN12KZUNwi54UL6IppwQHXx/zR4tes4eCSVU /1RIiD9eL7OysKmrUMLf4vofEkA0Mc3tZ88Uel7hUuIOKN/T+O+eHqWAhY1KM6nT QCa0Ko+Vq8ZqW5CKhyO6K+nG73Dbhf4vWIaEmGY+Hg1GG6wRVDTOeBfaQXbA2L8h q8Vqb+wVsE0BmvyIMrWlc/sHmYsCFMtbOOIyHqq7BjcLPbUcjrKA+gDbxaXFBJWd KDcnaUHATNE= =n8Hd -----END PGP SIGNATURE----- Merge tag 'fixes-for-v5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus Felipe writes: USB: fixes for v5.6-rc1 DWC3 learned that we can't always depend on Event Status bits. A problem was solved which would only surface with scatter list on IN endpoints. DWC2 got a fix for feature requests (both set and clear) and GetStatus request. The serial gadget got a fix for a TX stall bug. Composite framework now works better for SSP devices. * tag 'fixes-for-v5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: usb: dwc3: debug: fix string position formatting mixup with ret and len usb: gadget: serial: fix Tx stall after buffer overflow usb: gadget: ffs: ffs_aio_cancel(): Save/restore IRQ flags usb: dwc2: Fix SET/CLEAR_FEATURE and GET_STATUS flows usb: dwc2: Fix in ISOC request length checking usb: gadget: composite: Support more than 500mA MaxPower usb: gadget: composite: Fix bMaxPower for SuperSpeedPlus usb: gadget: u_audio: Fix high-speed max packet size usb: dwc3: gadget: Check for IOC/LST bit in TRB->ctrl fields
This commit is contained in:
commit
450c52c784
6 changed files with 56 additions and 36 deletions
|
@ -1083,11 +1083,6 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
|
|||
else
|
||||
packets = 1; /* send one packet if length is zero. */
|
||||
|
||||
if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
|
||||
dev_err(hsotg->dev, "req length > maxpacket*mc\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir_in && index != 0)
|
||||
if (hs_ep->isochronous)
|
||||
epsize = DXEPTSIZ_MC(packets);
|
||||
|
@ -1391,6 +1386,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
|
|||
req->actual = 0;
|
||||
req->status = -EINPROGRESS;
|
||||
|
||||
/* Don't queue ISOC request if length greater than mps*mc */
|
||||
if (hs_ep->isochronous &&
|
||||
req->length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
|
||||
dev_err(hs->dev, "req length > maxpacket*mc\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* In DDMA mode for ISOC's don't queue request if length greater
|
||||
* than descriptor limits.
|
||||
*/
|
||||
|
@ -1632,6 +1634,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
|
|||
struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
|
||||
struct dwc2_hsotg_ep *ep;
|
||||
__le16 reply;
|
||||
u16 status;
|
||||
int ret;
|
||||
|
||||
dev_dbg(hsotg->dev, "%s: USB_REQ_GET_STATUS\n", __func__);
|
||||
|
@ -1643,11 +1646,10 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
|
|||
|
||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||
case USB_RECIP_DEVICE:
|
||||
/*
|
||||
* bit 0 => self powered
|
||||
* bit 1 => remote wakeup
|
||||
*/
|
||||
reply = cpu_to_le16(0);
|
||||
status = 1 << USB_DEVICE_SELF_POWERED;
|
||||
status |= hsotg->remote_wakeup_allowed <<
|
||||
USB_DEVICE_REMOTE_WAKEUP;
|
||||
reply = cpu_to_le16(status);
|
||||
break;
|
||||
|
||||
case USB_RECIP_INTERFACE:
|
||||
|
@ -1758,7 +1760,10 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
|
|||
case USB_RECIP_DEVICE:
|
||||
switch (wValue) {
|
||||
case USB_DEVICE_REMOTE_WAKEUP:
|
||||
hsotg->remote_wakeup_allowed = 1;
|
||||
if (set)
|
||||
hsotg->remote_wakeup_allowed = 1;
|
||||
else
|
||||
hsotg->remote_wakeup_allowed = 0;
|
||||
break;
|
||||
|
||||
case USB_DEVICE_TEST_MODE:
|
||||
|
@ -1768,16 +1773,17 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
|
|||
return -EINVAL;
|
||||
|
||||
hsotg->test_mode = wIndex >> 8;
|
||||
ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(hsotg->dev,
|
||||
"%s: failed to send reply\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(hsotg->dev,
|
||||
"%s: failed to send reply\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_RECIP_ENDPOINT:
|
||||
|
|
|
@ -2429,7 +2429,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
|
|||
if (event->status & DEPEVT_STATUS_SHORT && !chain)
|
||||
return 1;
|
||||
|
||||
if (event->status & DEPEVT_STATUS_IOC)
|
||||
if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
|
||||
(trb->ctrl & DWC3_TRB_CTRL_LST))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -437,12 +437,14 @@ static u8 encode_bMaxPower(enum usb_device_speed speed,
|
|||
val = CONFIG_USB_GADGET_VBUS_DRAW;
|
||||
if (!val)
|
||||
return 0;
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
return DIV_ROUND_UP(val, 8);
|
||||
default:
|
||||
return DIV_ROUND_UP(val, 2);
|
||||
}
|
||||
if (speed < USB_SPEED_SUPER)
|
||||
return min(val, 500U) / 2;
|
||||
else
|
||||
/*
|
||||
* USB 3.x supports up to 900mA, but since 900 isn't divisible
|
||||
* by 8 the integral division will effectively cap to 896mA.
|
||||
*/
|
||||
return min(val, 900U) / 8;
|
||||
}
|
||||
|
||||
static int config_buf(struct usb_configuration *config,
|
||||
|
@ -854,6 +856,10 @@ static int set_config(struct usb_composite_dev *cdev,
|
|||
|
||||
/* when we return, be sure our power usage is valid */
|
||||
power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
|
||||
if (gadget->speed < USB_SPEED_SUPER)
|
||||
power = min(power, 500U);
|
||||
else
|
||||
power = min(power, 900U);
|
||||
done:
|
||||
usb_gadget_vbus_draw(gadget, power);
|
||||
if (result >= 0 && cdev->delayed_status)
|
||||
|
@ -2280,7 +2286,7 @@ void composite_resume(struct usb_gadget *gadget)
|
|||
{
|
||||
struct usb_composite_dev *cdev = get_gadget_data(gadget);
|
||||
struct usb_function *f;
|
||||
u16 maxpower;
|
||||
unsigned maxpower;
|
||||
|
||||
/* REVISIT: should we have config level
|
||||
* suspend/resume callbacks?
|
||||
|
@ -2294,10 +2300,14 @@ void composite_resume(struct usb_gadget *gadget)
|
|||
f->resume(f);
|
||||
}
|
||||
|
||||
maxpower = cdev->config->MaxPower;
|
||||
maxpower = cdev->config->MaxPower ?
|
||||
cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
|
||||
if (gadget->speed < USB_SPEED_SUPER)
|
||||
maxpower = min(maxpower, 500U);
|
||||
else
|
||||
maxpower = min(maxpower, 900U);
|
||||
|
||||
usb_gadget_vbus_draw(gadget, maxpower ?
|
||||
maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
|
||||
usb_gadget_vbus_draw(gadget, maxpower);
|
||||
}
|
||||
|
||||
cdev->suspended = 0;
|
||||
|
|
|
@ -1162,18 +1162,19 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
|
|||
{
|
||||
struct ffs_io_data *io_data = kiocb->private;
|
||||
struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
|
||||
unsigned long flags;
|
||||
int value;
|
||||
|
||||
ENTER();
|
||||
|
||||
spin_lock_irq(&epfile->ffs->eps_lock);
|
||||
spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
|
||||
|
||||
if (likely(io_data && io_data->ep && io_data->req))
|
||||
value = usb_ep_dequeue(io_data->ep, io_data->req);
|
||||
else
|
||||
value = -EINVAL;
|
||||
|
||||
spin_unlock_irq(&epfile->ffs->eps_lock);
|
||||
spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -361,7 +361,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
|||
ep = audio_dev->out_ep;
|
||||
prm = &uac->c_prm;
|
||||
config_ep_by_speed(gadget, &audio_dev->func, ep);
|
||||
req_len = prm->max_psize;
|
||||
req_len = ep->maxpacket;
|
||||
|
||||
prm->ep_enabled = true;
|
||||
usb_ep_enable(ep);
|
||||
|
@ -379,7 +379,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
|||
req->context = &prm->ureq[i];
|
||||
req->length = req_len;
|
||||
req->complete = u_audio_iso_complete;
|
||||
req->buf = prm->rbuf + i * prm->max_psize;
|
||||
req->buf = prm->rbuf + i * ep->maxpacket;
|
||||
}
|
||||
|
||||
if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
|
||||
|
@ -430,9 +430,9 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
|||
uac->p_pktsize = min_t(unsigned int,
|
||||
uac->p_framesize *
|
||||
(params->p_srate / uac->p_interval),
|
||||
prm->max_psize);
|
||||
ep->maxpacket);
|
||||
|
||||
if (uac->p_pktsize < prm->max_psize)
|
||||
if (uac->p_pktsize < ep->maxpacket)
|
||||
uac->p_pktsize_residue = uac->p_framesize *
|
||||
(params->p_srate % uac->p_interval);
|
||||
else
|
||||
|
@ -457,7 +457,7 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
|||
req->context = &prm->ureq[i];
|
||||
req->length = req_len;
|
||||
req->complete = u_audio_iso_complete;
|
||||
req->buf = prm->rbuf + i * prm->max_psize;
|
||||
req->buf = prm->rbuf + i * ep->maxpacket;
|
||||
}
|
||||
|
||||
if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
|
||||
|
|
|
@ -561,8 +561,10 @@ static int gs_start_io(struct gs_port *port)
|
|||
port->n_read = 0;
|
||||
started = gs_start_rx(port);
|
||||
|
||||
/* unblock any pending writes into our circular buffer */
|
||||
if (started) {
|
||||
gs_start_tx(port);
|
||||
/* Unblock any pending writes into our circular buffer, in case
|
||||
* we didn't in gs_start_tx() */
|
||||
tty_wakeup(port->port.tty);
|
||||
} else {
|
||||
gs_free_requests(ep, head, &port->read_allocated);
|
||||
|
|
Loading…
Reference in a new issue