usb: xhci-mtk: fix in-ep's start-split check failure
authorChunfeng Yun <chunfeng.yun@mediatek.com>
Sat, 18 Nov 2023 03:30:11 +0000 (11:30 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Nov 2023 14:31:25 +0000 (15:31 +0100)
It's wrong to use the data length in a CS (in uframe x) to check whether
there is a SS (in uframe x-2), because for a isoc-in ep, it may need some
CS to receive data;
Save the count of SS in a uframe for isoc/intr in-eps to fix the issue.

Fixes: 5c954e030f55 ("usb: xhci-mtk: improve split scheduling by separate IN/OUT budget")
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/20231118033011.22033-1-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-mtk-sch.c
drivers/usb/host/xhci-mtk.h

index 5b3cd455adecc21bd3fcc70316cb4ceab8e51609..61f3f8bbdcead3f325b60128c8bf648acf32dc2b 100644 (file)
@@ -650,9 +650,8 @@ static int check_isoc_ss_overlap(struct mu3h_sch_ep_info *sch_ep, u32 offset)
 
                if (sch_ep->ep_type == ISOC_OUT_EP) {
                        for (j = 0; j < sch_ep->num_budget_microframes; j++) {
-                               k = XHCI_MTK_BW_INDEX(base + j + CS_OFFSET);
-                               /* use cs to indicate existence of in-ss @(base+j) */
-                               if (tt->fs_bus_bw_in[k])
+                               k = XHCI_MTK_BW_INDEX(base + j);
+                               if (tt->in_ss_cnt[k])
                                        return -ESCH_SS_OVERLAP;
                        }
                } else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
@@ -769,6 +768,14 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
                                tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j];
                        }
                }
+
+               if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
+                       k = XHCI_MTK_BW_INDEX(base);
+                       if (used)
+                               tt->in_ss_cnt[k]++;
+                       else
+                               tt->in_ss_cnt[k]--;
+               }
        }
 
        if (used)
index 865b55e23b15948f68ec933395077df1f7d71960..39f7ae7d30871d074e832a44fcd6dc9708d971c0 100644 (file)
@@ -38,6 +38,7 @@
  * @fs_bus_bw_in: save bandwidth used by FS/LS IN eps in each uframes
  * @ls_bus_bw: save bandwidth used by LS eps in each uframes
  * @fs_frame_bw: save bandwidth used by FS/LS eps in each FS frames
+ * @in_ss_cnt: the count of Start-Split for IN eps
  * @ep_list: Endpoints using this TT
  */
 struct mu3h_sch_tt {
@@ -45,6 +46,7 @@ struct mu3h_sch_tt {
        u16 fs_bus_bw_in[XHCI_MTK_MAX_ESIT];
        u8 ls_bus_bw[XHCI_MTK_MAX_ESIT];
        u16 fs_frame_bw[XHCI_MTK_FRAMES_CNT];
+       u8 in_ss_cnt[XHCI_MTK_MAX_ESIT];
        struct list_head ep_list;
 };