aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Anderson <dianders@chromium.org>2019-05-31 16:04:12 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2019-06-06 06:51:41 -0400
commitbabd183915e91a64e976b9e8ab682bb56624df76 (patch)
treeab678ec74fbcb6ec20ddd1fee34208c71c743a21
parentf2c7c76c5d0a443053e94adb9f0918fa2fb85c3a (diff)
usb: dwc2: host: Fix wMaxPacketSize handling (fix webcam regression)
In commit abb621844f6a ("usb: ch9: make usb_endpoint_maxp() return only packet size") the API to usb_endpoint_maxp() changed. It used to just return wMaxPacketSize but after that commit it returned wMaxPacketSize with the high bits (the multiplier) masked off. If you wanted to get the multiplier it was now up to your code to call the new usb_endpoint_maxp_mult() which was introduced in commit 541b6fe63023 ("usb: add helper to extract bits 12:11 of wMaxPacketSize"). Prior to the API change most host drivers were updated, but no update was made to dwc2. Presumably it was assumed that dwc2 was too simplistic to use the multiplier and thus just didn't support a certain class of USB devices. However, it turns out that dwc2 did use the multiplier and many devices using it were working quite nicely. That means that many USB devices have been broken since the API change. One such device is a Logitech HD Pro Webcam C920. Specifically, though dwc2 didn't directly call usb_endpoint_maxp(), it did call usb_maxpacket() which in turn called usb_endpoint_maxp(). Let's update dwc2 to work properly with the new API. Fixes: abb621844f6a ("usb: ch9: make usb_endpoint_maxp() return only packet size") Cc: stable@vger.kernel.org Acked-by: Minas Harutyunyan <hminas@synopsys.com> Reviewed-by: Matthias Kaehlcke <mka@chromium.org> Signed-off-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc2/hcd.c29
-rw-r--r--drivers/usb/dwc2/hcd.h20
-rw-r--r--drivers/usb/dwc2/hcd_intr.c5
-rw-r--r--drivers/usb/dwc2/hcd_queue.c10
4 files changed, 37 insertions, 27 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index b50ec3714fd8..5c51bf5506d1 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2608,7 +2608,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
2608 chan->dev_addr = dwc2_hcd_get_dev_addr(&urb->pipe_info); 2608 chan->dev_addr = dwc2_hcd_get_dev_addr(&urb->pipe_info);
2609 chan->ep_num = dwc2_hcd_get_ep_num(&urb->pipe_info); 2609 chan->ep_num = dwc2_hcd_get_ep_num(&urb->pipe_info);
2610 chan->speed = qh->dev_speed; 2610 chan->speed = qh->dev_speed;
2611 chan->max_packet = dwc2_max_packet(qh->maxp); 2611 chan->max_packet = qh->maxp;
2612 2612
2613 chan->xfer_started = 0; 2613 chan->xfer_started = 0;
2614 chan->halt_status = DWC2_HC_XFER_NO_HALT_STATUS; 2614 chan->halt_status = DWC2_HC_XFER_NO_HALT_STATUS;
@@ -2686,7 +2686,7 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
2686 * This value may be modified when the transfer is started 2686 * This value may be modified when the transfer is started
2687 * to reflect the actual transfer length 2687 * to reflect the actual transfer length
2688 */ 2688 */
2689 chan->multi_count = dwc2_hb_mult(qh->maxp); 2689 chan->multi_count = qh->maxp_mult;
2690 2690
2691 if (hsotg->params.dma_desc_enable) { 2691 if (hsotg->params.dma_desc_enable) {
2692 chan->desc_list_addr = qh->desc_list_dma; 2692 chan->desc_list_addr = qh->desc_list_dma;
@@ -3806,19 +3806,21 @@ static struct dwc2_hcd_urb *dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg,
3806 3806
3807static void dwc2_hcd_urb_set_pipeinfo(struct dwc2_hsotg *hsotg, 3807static void dwc2_hcd_urb_set_pipeinfo(struct dwc2_hsotg *hsotg,
3808 struct dwc2_hcd_urb *urb, u8 dev_addr, 3808 struct dwc2_hcd_urb *urb, u8 dev_addr,
3809 u8 ep_num, u8 ep_type, u8 ep_dir, u16 mps) 3809 u8 ep_num, u8 ep_type, u8 ep_dir,
3810 u16 maxp, u16 maxp_mult)
3810{ 3811{
3811 if (dbg_perio() || 3812 if (dbg_perio() ||
3812 ep_type == USB_ENDPOINT_XFER_BULK || 3813 ep_type == USB_ENDPOINT_XFER_BULK ||
3813 ep_type == USB_ENDPOINT_XFER_CONTROL) 3814 ep_type == USB_ENDPOINT_XFER_CONTROL)
3814 dev_vdbg(hsotg->dev, 3815 dev_vdbg(hsotg->dev,
3815 "addr=%d, ep_num=%d, ep_dir=%1x, ep_type=%1x, mps=%d\n", 3816 "addr=%d, ep_num=%d, ep_dir=%1x, ep_type=%1x, maxp=%d (%d mult)\n",
3816 dev_addr, ep_num, ep_dir, ep_type, mps); 3817 dev_addr, ep_num, ep_dir, ep_type, maxp, maxp_mult);
3817 urb->pipe_info.dev_addr = dev_addr; 3818 urb->pipe_info.dev_addr = dev_addr;
3818 urb->pipe_info.ep_num = ep_num; 3819 urb->pipe_info.ep_num = ep_num;
3819 urb->pipe_info.pipe_type = ep_type; 3820 urb->pipe_info.pipe_type = ep_type;
3820 urb->pipe_info.pipe_dir = ep_dir; 3821 urb->pipe_info.pipe_dir = ep_dir;
3821 urb->pipe_info.mps = mps; 3822 urb->pipe_info.maxp = maxp;
3823 urb->pipe_info.maxp_mult = maxp_mult;
3822} 3824}
3823 3825
3824/* 3826/*
@@ -3909,8 +3911,9 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
3909 dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 3911 dwc2_hcd_is_pipe_in(&urb->pipe_info) ?
3910 "IN" : "OUT"); 3912 "IN" : "OUT");
3911 dev_dbg(hsotg->dev, 3913 dev_dbg(hsotg->dev,
3912 " Max packet size: %d\n", 3914 " Max packet size: %d (%d mult)\n",
3913 dwc2_hcd_get_mps(&urb->pipe_info)); 3915 dwc2_hcd_get_maxp(&urb->pipe_info),
3916 dwc2_hcd_get_maxp_mult(&urb->pipe_info));
3914 dev_dbg(hsotg->dev, 3917 dev_dbg(hsotg->dev,
3915 " transfer_buffer: %p\n", 3918 " transfer_buffer: %p\n",
3916 urb->buf); 3919 urb->buf);
@@ -4510,8 +4513,10 @@ static void dwc2_dump_urb_info(struct usb_hcd *hcd, struct urb *urb,
4510 } 4513 }
4511 4514
4512 dev_vdbg(hsotg->dev, " Speed: %s\n", speed); 4515 dev_vdbg(hsotg->dev, " Speed: %s\n", speed);
4513 dev_vdbg(hsotg->dev, " Max packet size: %d\n", 4516 dev_vdbg(hsotg->dev, " Max packet size: %d (%d mult)\n",
4514 usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); 4517 usb_endpoint_maxp(&urb->ep->desc),
4518 usb_endpoint_maxp_mult(&urb->ep->desc));
4519
4515 dev_vdbg(hsotg->dev, " Data buffer length: %d\n", 4520 dev_vdbg(hsotg->dev, " Data buffer length: %d\n",
4516 urb->transfer_buffer_length); 4521 urb->transfer_buffer_length);
4517 dev_vdbg(hsotg->dev, " Transfer buffer: %p, Transfer DMA: %08lx\n", 4522 dev_vdbg(hsotg->dev, " Transfer buffer: %p, Transfer DMA: %08lx\n",
@@ -4594,8 +4599,8 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
4594 dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, usb_pipedevice(urb->pipe), 4599 dwc2_hcd_urb_set_pipeinfo(hsotg, dwc2_urb, usb_pipedevice(urb->pipe),
4595 usb_pipeendpoint(urb->pipe), ep_type, 4600 usb_pipeendpoint(urb->pipe), ep_type,
4596 usb_pipein(urb->pipe), 4601 usb_pipein(urb->pipe),
4597 usb_maxpacket(urb->dev, urb->pipe, 4602 usb_endpoint_maxp(&ep->desc),
4598 !(usb_pipein(urb->pipe)))); 4603 usb_endpoint_maxp_mult(&ep->desc));
4599 4604
4600 buf = urb->transfer_buffer; 4605 buf = urb->transfer_buffer;
4601 4606
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index c089ffa1f0a8..ce6445a06588 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -171,7 +171,8 @@ struct dwc2_hcd_pipe_info {
171 u8 ep_num; 171 u8 ep_num;
172 u8 pipe_type; 172 u8 pipe_type;
173 u8 pipe_dir; 173 u8 pipe_dir;
174 u16 mps; 174 u16 maxp;
175 u16 maxp_mult;
175}; 176};
176 177
177struct dwc2_hcd_iso_packet_desc { 178struct dwc2_hcd_iso_packet_desc {
@@ -264,6 +265,7 @@ struct dwc2_hs_transfer_time {
264 * - USB_ENDPOINT_XFER_ISOC 265 * - USB_ENDPOINT_XFER_ISOC
265 * @ep_is_in: Endpoint direction 266 * @ep_is_in: Endpoint direction
266 * @maxp: Value from wMaxPacketSize field of Endpoint Descriptor 267 * @maxp: Value from wMaxPacketSize field of Endpoint Descriptor
268 * @maxp_mult: Multiplier for maxp
267 * @dev_speed: Device speed. One of the following values: 269 * @dev_speed: Device speed. One of the following values:
268 * - USB_SPEED_LOW 270 * - USB_SPEED_LOW
269 * - USB_SPEED_FULL 271 * - USB_SPEED_FULL
@@ -340,6 +342,7 @@ struct dwc2_qh {
340 u8 ep_type; 342 u8 ep_type;
341 u8 ep_is_in; 343 u8 ep_is_in;
342 u16 maxp; 344 u16 maxp;
345 u16 maxp_mult;
343 u8 dev_speed; 346 u8 dev_speed;
344 u8 data_toggle; 347 u8 data_toggle;
345 u8 ping_state; 348 u8 ping_state;
@@ -503,9 +506,14 @@ static inline u8 dwc2_hcd_get_pipe_type(struct dwc2_hcd_pipe_info *pipe)
503 return pipe->pipe_type; 506 return pipe->pipe_type;
504} 507}
505 508
506static inline u16 dwc2_hcd_get_mps(struct dwc2_hcd_pipe_info *pipe) 509static inline u16 dwc2_hcd_get_maxp(struct dwc2_hcd_pipe_info *pipe)
510{
511 return pipe->maxp;
512}
513
514static inline u16 dwc2_hcd_get_maxp_mult(struct dwc2_hcd_pipe_info *pipe)
507{ 515{
508 return pipe->mps; 516 return pipe->maxp_mult;
509} 517}
510 518
511static inline u8 dwc2_hcd_get_dev_addr(struct dwc2_hcd_pipe_info *pipe) 519static inline u8 dwc2_hcd_get_dev_addr(struct dwc2_hcd_pipe_info *pipe)
@@ -620,12 +628,6 @@ static inline bool dbg_urb(struct urb *urb)
620static inline bool dbg_perio(void) { return false; } 628static inline bool dbg_perio(void) { return false; }
621#endif 629#endif
622 630
623/* High bandwidth multiplier as encoded in highspeed endpoint descriptors */
624#define dwc2_hb_mult(wmaxpacketsize) (1 + (((wmaxpacketsize) >> 11) & 0x03))
625
626/* Packet size for any kind of endpoint descriptor */
627#define dwc2_max_packet(wmaxpacketsize) ((wmaxpacketsize) & 0x07ff)
628
629/* 631/*
630 * Returns true if frame1 index is greater than frame2 index. The comparison 632 * Returns true if frame1 index is greater than frame2 index. The comparison
631 * is done modulo FRLISTEN_64_SIZE. This accounts for the rollover of the 633 * is done modulo FRLISTEN_64_SIZE. This accounts for the rollover of the
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 88b5dcf3aefc..a052d39b4375 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -1617,8 +1617,9 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
1617 1617
1618 dev_err(hsotg->dev, " Speed: %s\n", speed); 1618 dev_err(hsotg->dev, " Speed: %s\n", speed);
1619 1619
1620 dev_err(hsotg->dev, " Max packet size: %d\n", 1620 dev_err(hsotg->dev, " Max packet size: %d (mult %d)\n",
1621 dwc2_hcd_get_mps(&urb->pipe_info)); 1621 dwc2_hcd_get_maxp(&urb->pipe_info),
1622 dwc2_hcd_get_maxp_mult(&urb->pipe_info));
1622 dev_err(hsotg->dev, " Data buffer length: %d\n", urb->length); 1623 dev_err(hsotg->dev, " Data buffer length: %d\n", urb->length);
1623 dev_err(hsotg->dev, " Transfer buffer: %p, Transfer DMA: %08lx\n", 1624 dev_err(hsotg->dev, " Transfer buffer: %p, Transfer DMA: %08lx\n",
1624 urb->buf, (unsigned long)urb->dma); 1625 urb->buf, (unsigned long)urb->dma);
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index ea3aa640c15c..68bbac64b753 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -708,7 +708,7 @@ static void dwc2_hs_pmap_unschedule(struct dwc2_hsotg *hsotg,
708static int dwc2_uframe_schedule_split(struct dwc2_hsotg *hsotg, 708static int dwc2_uframe_schedule_split(struct dwc2_hsotg *hsotg,
709 struct dwc2_qh *qh) 709 struct dwc2_qh *qh)
710{ 710{
711 int bytecount = dwc2_hb_mult(qh->maxp) * dwc2_max_packet(qh->maxp); 711 int bytecount = qh->maxp_mult * qh->maxp;
712 int ls_search_slice; 712 int ls_search_slice;
713 int err = 0; 713 int err = 0;
714 int host_interval_in_sched; 714 int host_interval_in_sched;
@@ -1332,7 +1332,7 @@ static int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg,
1332 u32 max_channel_xfer_size; 1332 u32 max_channel_xfer_size;
1333 int status = 0; 1333 int status = 0;
1334 1334
1335 max_xfer_size = dwc2_max_packet(qh->maxp) * dwc2_hb_mult(qh->maxp); 1335 max_xfer_size = qh->maxp * qh->maxp_mult;
1336 max_channel_xfer_size = hsotg->params.max_transfer_size; 1336 max_channel_xfer_size = hsotg->params.max_transfer_size;
1337 1337
1338 if (max_xfer_size > max_channel_xfer_size) { 1338 if (max_xfer_size > max_channel_xfer_size) {
@@ -1517,8 +1517,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
1517 u32 prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; 1517 u32 prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
1518 bool do_split = (prtspd == HPRT0_SPD_HIGH_SPEED && 1518 bool do_split = (prtspd == HPRT0_SPD_HIGH_SPEED &&
1519 dev_speed != USB_SPEED_HIGH); 1519 dev_speed != USB_SPEED_HIGH);
1520 int maxp = dwc2_hcd_get_mps(&urb->pipe_info); 1520 int maxp = dwc2_hcd_get_maxp(&urb->pipe_info);
1521 int bytecount = dwc2_hb_mult(maxp) * dwc2_max_packet(maxp); 1521 int maxp_mult = dwc2_hcd_get_maxp_mult(&urb->pipe_info);
1522 int bytecount = maxp_mult * maxp;
1522 char *speed, *type; 1523 char *speed, *type;
1523 1524
1524 /* Initialize QH */ 1525 /* Initialize QH */
@@ -1531,6 +1532,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
1531 1532
1532 qh->data_toggle = DWC2_HC_PID_DATA0; 1533 qh->data_toggle = DWC2_HC_PID_DATA0;
1533 qh->maxp = maxp; 1534 qh->maxp = maxp;
1535 qh->maxp_mult = maxp_mult;
1534 INIT_LIST_HEAD(&qh->qtd_list); 1536 INIT_LIST_HEAD(&qh->qtd_list);
1535 INIT_LIST_HEAD(&qh->qh_list_entry); 1537 INIT_LIST_HEAD(&qh->qh_list_entry);
1536 1538