aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/hcd_intr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc2/hcd_intr.c')
-rw-r--r--drivers/usb/dwc2/hcd_intr.c174
1 files changed, 96 insertions, 78 deletions
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index cadba8b13c48..906f223542ee 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -55,12 +55,16 @@
55/* This function is for debug only */ 55/* This function is for debug only */
56static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) 56static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
57{ 57{
58#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
59 u16 curr_frame_number = hsotg->frame_number; 58 u16 curr_frame_number = hsotg->frame_number;
59 u16 expected = dwc2_frame_num_inc(hsotg->last_frame_num, 1);
60
61 if (expected != curr_frame_number)
62 dwc2_sch_vdbg(hsotg, "MISSED SOF %04x != %04x\n",
63 expected, curr_frame_number);
60 64
65#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
61 if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) { 66 if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
62 if (((hsotg->last_frame_num + 1) & HFNUM_MAX_FRNUM) != 67 if (expected != curr_frame_number) {
63 curr_frame_number) {
64 hsotg->frame_num_array[hsotg->frame_num_idx] = 68 hsotg->frame_num_array[hsotg->frame_num_idx] =
65 curr_frame_number; 69 curr_frame_number;
66 hsotg->last_frame_num_array[hsotg->frame_num_idx] = 70 hsotg->last_frame_num_array[hsotg->frame_num_idx] =
@@ -79,14 +83,15 @@ static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
79 } 83 }
80 hsotg->dumped_frame_num_array = 1; 84 hsotg->dumped_frame_num_array = 1;
81 } 85 }
82 hsotg->last_frame_num = curr_frame_number;
83#endif 86#endif
87 hsotg->last_frame_num = curr_frame_number;
84} 88}
85 89
86static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, 90static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg,
87 struct dwc2_host_chan *chan, 91 struct dwc2_host_chan *chan,
88 struct dwc2_qtd *qtd) 92 struct dwc2_qtd *qtd)
89{ 93{
94 struct usb_device *root_hub = dwc2_hsotg_to_hcd(hsotg)->self.root_hub;
90 struct urb *usb_urb; 95 struct urb *usb_urb;
91 96
92 if (!chan->qh) 97 if (!chan->qh)
@@ -102,6 +107,15 @@ static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg,
102 if (!usb_urb || !usb_urb->dev || !usb_urb->dev->tt) 107 if (!usb_urb || !usb_urb->dev || !usb_urb->dev->tt)
103 return; 108 return;
104 109
110 /*
111 * The root hub doesn't really have a TT, but Linux thinks it
112 * does because how could you have a "high speed hub" that
113 * directly talks directly to low speed devices without a TT?
114 * It's all lies. Lies, I tell you.
115 */
116 if (usb_urb->dev->tt->hub == root_hub)
117 return;
118
105 if (qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { 119 if (qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) {
106 chan->qh->tt_buffer_dirty = 1; 120 chan->qh->tt_buffer_dirty = 1;
107 if (usb_hub_clear_tt_buffer(usb_urb)) 121 if (usb_hub_clear_tt_buffer(usb_urb))
@@ -138,13 +152,19 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg)
138 while (qh_entry != &hsotg->periodic_sched_inactive) { 152 while (qh_entry != &hsotg->periodic_sched_inactive) {
139 qh = list_entry(qh_entry, struct dwc2_qh, qh_list_entry); 153 qh = list_entry(qh_entry, struct dwc2_qh, qh_list_entry);
140 qh_entry = qh_entry->next; 154 qh_entry = qh_entry->next;
141 if (dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number)) 155 if (dwc2_frame_num_le(qh->next_active_frame,
156 hsotg->frame_number)) {
157 dwc2_sch_vdbg(hsotg, "QH=%p ready fn=%04x, nxt=%04x\n",
158 qh, hsotg->frame_number,
159 qh->next_active_frame);
160
142 /* 161 /*
143 * Move QH to the ready list to be executed next 162 * Move QH to the ready list to be executed next
144 * (micro)frame 163 * (micro)frame
145 */ 164 */
146 list_move(&qh->qh_list_entry, 165 list_move_tail(&qh->qh_list_entry,
147 &hsotg->periodic_sched_ready); 166 &hsotg->periodic_sched_ready);
167 }
148 } 168 }
149 tr_type = dwc2_hcd_select_transactions(hsotg); 169 tr_type = dwc2_hcd_select_transactions(hsotg);
150 if (tr_type != DWC2_TRANSACTION_NONE) 170 if (tr_type != DWC2_TRANSACTION_NONE)
@@ -472,18 +492,6 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
472 xfer_length = urb->length - urb->actual_length; 492 xfer_length = urb->length - urb->actual_length;
473 } 493 }
474 494
475 /* Non DWORD-aligned buffer case handling */
476 if (chan->align_buf && xfer_length) {
477 dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
478 dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
479 chan->qh->dw_align_buf_size,
480 chan->ep_is_in ?
481 DMA_FROM_DEVICE : DMA_TO_DEVICE);
482 if (chan->ep_is_in)
483 memcpy(urb->buf + urb->actual_length,
484 chan->qh->dw_align_buf, xfer_length);
485 }
486
487 dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n", 495 dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n",
488 urb->actual_length, xfer_length); 496 urb->actual_length, xfer_length);
489 urb->actual_length += xfer_length; 497 urb->actual_length += xfer_length;
@@ -573,21 +581,6 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
573 frame_desc->status = 0; 581 frame_desc->status = 0;
574 frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg, 582 frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
575 chan, chnum, qtd, halt_status, NULL); 583 chan, chnum, qtd, halt_status, NULL);
576
577 /* Non DWORD-aligned buffer case handling */
578 if (chan->align_buf && frame_desc->actual_length) {
579 dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
580 __func__);
581 dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
582 chan->qh->dw_align_buf_size,
583 chan->ep_is_in ?
584 DMA_FROM_DEVICE : DMA_TO_DEVICE);
585 if (chan->ep_is_in)
586 memcpy(urb->buf + frame_desc->offset +
587 qtd->isoc_split_offset,
588 chan->qh->dw_align_buf,
589 frame_desc->actual_length);
590 }
591 break; 584 break;
592 case DWC2_HC_XFER_FRAME_OVERRUN: 585 case DWC2_HC_XFER_FRAME_OVERRUN:
593 urb->error_count++; 586 urb->error_count++;
@@ -608,21 +601,6 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
608 frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg, 601 frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
609 chan, chnum, qtd, halt_status, NULL); 602 chan, chnum, qtd, halt_status, NULL);
610 603
611 /* Non DWORD-aligned buffer case handling */
612 if (chan->align_buf && frame_desc->actual_length) {
613 dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
614 __func__);
615 dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
616 chan->qh->dw_align_buf_size,
617 chan->ep_is_in ?
618 DMA_FROM_DEVICE : DMA_TO_DEVICE);
619 if (chan->ep_is_in)
620 memcpy(urb->buf + frame_desc->offset +
621 qtd->isoc_split_offset,
622 chan->qh->dw_align_buf,
623 frame_desc->actual_length);
624 }
625
626 /* Skip whole frame */ 604 /* Skip whole frame */
627 if (chan->qh->do_split && 605 if (chan->qh->do_split &&
628 chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in && 606 chan->ep_type == USB_ENDPOINT_XFER_ISOC && chan->ep_is_in &&
@@ -688,8 +666,6 @@ static void dwc2_deactivate_qh(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
688 } 666 }
689 667
690no_qtd: 668no_qtd:
691 if (qh->channel)
692 qh->channel->align_buf = 0;
693 qh->channel = NULL; 669 qh->channel = NULL;
694 dwc2_hcd_qh_deactivate(hsotg, qh, continue_split); 670 dwc2_hcd_qh_deactivate(hsotg, qh, continue_split);
695} 671}
@@ -846,7 +822,7 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
846 * halt to be queued when the periodic schedule is 822 * halt to be queued when the periodic schedule is
847 * processed. 823 * processed.
848 */ 824 */
849 list_move(&chan->qh->qh_list_entry, 825 list_move_tail(&chan->qh->qh_list_entry,
850 &hsotg->periodic_sched_assigned); 826 &hsotg->periodic_sched_assigned);
851 827
852 /* 828 /*
@@ -954,14 +930,6 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg,
954 930
955 frame_desc->actual_length += len; 931 frame_desc->actual_length += len;
956 932
957 if (chan->align_buf) {
958 dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
959 dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
960 chan->qh->dw_align_buf_size, DMA_FROM_DEVICE);
961 memcpy(qtd->urb->buf + frame_desc->offset +
962 qtd->isoc_split_offset, chan->qh->dw_align_buf, len);
963 }
964
965 qtd->isoc_split_offset += len; 933 qtd->isoc_split_offset += len;
966 934
967 if (frame_desc->actual_length >= frame_desc->length) { 935 if (frame_desc->actual_length >= frame_desc->length) {
@@ -1184,19 +1152,6 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
1184 xfer_length = urb->length - urb->actual_length; 1152 xfer_length = urb->length - urb->actual_length;
1185 } 1153 }
1186 1154
1187 /* Non DWORD-aligned buffer case handling */
1188 if (chan->align_buf && xfer_length && chan->ep_is_in) {
1189 dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
1190 dma_unmap_single(hsotg->dev, chan->qh->dw_align_buf_dma,
1191 chan->qh->dw_align_buf_size,
1192 chan->ep_is_in ?
1193 DMA_FROM_DEVICE : DMA_TO_DEVICE);
1194 if (chan->ep_is_in)
1195 memcpy(urb->buf + urb->actual_length,
1196 chan->qh->dw_align_buf,
1197 xfer_length);
1198 }
1199
1200 urb->actual_length += xfer_length; 1155 urb->actual_length += xfer_length;
1201 1156
1202 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum)); 1157 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
@@ -1416,14 +1371,50 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg,
1416 1371
1417 if (chan->ep_type == USB_ENDPOINT_XFER_INT || 1372 if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
1418 chan->ep_type == USB_ENDPOINT_XFER_ISOC) { 1373 chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
1419 int frnum = dwc2_hcd_get_frame_number(hsotg); 1374 struct dwc2_qh *qh = chan->qh;
1375 bool past_end;
1376
1377 if (hsotg->core_params->uframe_sched <= 0) {
1378 int frnum = dwc2_hcd_get_frame_number(hsotg);
1379
1380 /* Don't have num_hs_transfers; simple logic */
1381 past_end = dwc2_full_frame_num(frnum) !=
1382 dwc2_full_frame_num(qh->next_active_frame);
1383 } else {
1384 int end_frnum;
1420 1385
1421 if (dwc2_full_frame_num(frnum) !=
1422 dwc2_full_frame_num(chan->qh->sched_frame)) {
1423 /* 1386 /*
1424 * No longer in the same full speed frame. 1387 * Figure out the end frame based on schedule.
1425 * Treat this as a transaction error. 1388 *
1426 */ 1389 * We don't want to go on trying again and again
1390 * forever. Let's stop when we've done all the
1391 * transfers that were scheduled.
1392 *
1393 * We're going to be comparing start_active_frame
1394 * and next_active_frame, both of which are 1
1395 * before the time the packet goes on the wire,
1396 * so that cancels out. Basically if had 1
1397 * transfer and we saw 1 NYET then we're done.
1398 * We're getting a NYET here so if next >=
1399 * (start + num_transfers) we're done. The
1400 * complexity is that for all but ISOC_OUT we
1401 * skip one slot.
1402 */
1403 end_frnum = dwc2_frame_num_inc(
1404 qh->start_active_frame,
1405 qh->num_hs_transfers);
1406
1407 if (qh->ep_type != USB_ENDPOINT_XFER_ISOC ||
1408 qh->ep_is_in)
1409 end_frnum =
1410 dwc2_frame_num_inc(end_frnum, 1);
1411
1412 past_end = dwc2_frame_num_le(
1413 end_frnum, qh->next_active_frame);
1414 }
1415
1416 if (past_end) {
1417 /* Treat this as a transaction error. */
1427#if 0 1418#if 0
1428 /* 1419 /*
1429 * Todo: Fix system performance so this can 1420 * Todo: Fix system performance so this can
@@ -2008,6 +1999,16 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
2008 } 1999 }
2009 2000
2010 dwc2_writel(hcint, hsotg->regs + HCINT(chnum)); 2001 dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
2002
2003 /*
2004 * If we got an interrupt after someone called
2005 * dwc2_hcd_endpoint_disable() we don't want to crash below
2006 */
2007 if (!chan->qh) {
2008 dev_warn(hsotg->dev, "Interrupt on disabled channel\n");
2009 return;
2010 }
2011
2011 chan->hcint = hcint; 2012 chan->hcint = hcint;
2012 hcint &= hcintmsk; 2013 hcint &= hcintmsk;
2013 2014
@@ -2130,6 +2131,7 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg)
2130{ 2131{
2131 u32 haint; 2132 u32 haint;
2132 int i; 2133 int i;
2134 struct dwc2_host_chan *chan, *chan_tmp;
2133 2135
2134 haint = dwc2_readl(hsotg->regs + HAINT); 2136 haint = dwc2_readl(hsotg->regs + HAINT);
2135 if (dbg_perio()) { 2137 if (dbg_perio()) {
@@ -2138,6 +2140,22 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg)
2138 dev_vdbg(hsotg->dev, "HAINT=%08x\n", haint); 2140 dev_vdbg(hsotg->dev, "HAINT=%08x\n", haint);
2139 } 2141 }
2140 2142
2143 /*
2144 * According to USB 2.0 spec section 11.18.8, a host must
2145 * issue complete-split transactions in a microframe for a
2146 * set of full-/low-speed endpoints in the same relative
2147 * order as the start-splits were issued in a microframe for.
2148 */
2149 list_for_each_entry_safe(chan, chan_tmp, &hsotg->split_order,
2150 split_order_list_entry) {
2151 int hc_num = chan->hc_num;
2152
2153 if (haint & (1 << hc_num)) {
2154 dwc2_hc_n_intr(hsotg, hc_num);
2155 haint &= ~(1 << hc_num);
2156 }
2157 }
2158
2141 for (i = 0; i < hsotg->core_params->host_channels; i++) { 2159 for (i = 0; i < hsotg->core_params->host_channels; i++) {
2142 if (haint & (1 << i)) 2160 if (haint & (1 << i))
2143 dwc2_hc_n_intr(hsotg, i); 2161 dwc2_hc_n_intr(hsotg, i);