Skip to content

Commit 1d69f9d

Browse files
ikjn-crosgregkh
authored andcommitted
usb: xhci-mtk: fix unreleased bandwidth data
xhci-mtk needs XHCI_MTK_HOST quirk functions in add_endpoint() and drop_endpoint() to handle its own sw bandwidth management. It stores bandwidth data into an internal table every time add_endpoint() is called, and drops those in drop_endpoint(). But when bandwidth allocation fails at one endpoint, all earlier allocation from the same interface could still remain at the table. This patch moves bandwidth management codes to check_bandwidth() and reset_bandwidth() path. To do so, this patch also adds those functions to xhci_driver_overrides and lets mtk-xhci to release all failed endpoints in reset_bandwidth() path. Fixes: 08e469d ("usb: xhci-mtk: supports bandwidth scheduling with multi-TT") Signed-off-by: Ikjoon Jang <[email protected]> Link: https://lore.kernel.org/r/20210113180444.v6.1.Id0d31b5f3ddf5e734d2ab11161ac5821921b1e1e@changeid Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a55a9a4 commit 1d69f9d

File tree

5 files changed

+111
-39
lines changed

5 files changed

+111
-39
lines changed

drivers/usb/host/xhci-mtk-sch.c

Lines changed: 86 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
200200

201201
sch_ep->sch_tt = tt;
202202
sch_ep->ep = ep;
203+
INIT_LIST_HEAD(&sch_ep->tt_endpoint);
203204

204205
return sch_ep;
205206
}
@@ -583,6 +584,8 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)
583584

584585
mtk->sch_array = sch_array;
585586

587+
INIT_LIST_HEAD(&mtk->bw_ep_list_new);
588+
586589
return 0;
587590
}
588591
EXPORT_SYMBOL_GPL(xhci_mtk_sch_init);
@@ -601,19 +604,14 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
601604
struct xhci_ep_ctx *ep_ctx;
602605
struct xhci_slot_ctx *slot_ctx;
603606
struct xhci_virt_device *virt_dev;
604-
struct mu3h_sch_bw_info *sch_bw;
605607
struct mu3h_sch_ep_info *sch_ep;
606-
struct mu3h_sch_bw_info *sch_array;
607608
unsigned int ep_index;
608-
int bw_index;
609-
int ret = 0;
610609

611610
xhci = hcd_to_xhci(hcd);
612611
virt_dev = xhci->devs[udev->slot_id];
613612
ep_index = xhci_get_endpoint_index(&ep->desc);
614613
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
615614
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
616-
sch_array = mtk->sch_array;
617615

618616
xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
619617
__func__, usb_endpoint_type(&ep->desc), udev->speed,
@@ -632,39 +630,34 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
632630
return 0;
633631
}
634632

635-
bw_index = get_bw_index(xhci, udev, ep);
636-
sch_bw = &sch_array[bw_index];
637-
638633
sch_ep = create_sch_ep(udev, ep, ep_ctx);
639634
if (IS_ERR_OR_NULL(sch_ep))
640635
return -ENOMEM;
641636

642637
setup_sch_info(udev, ep_ctx, sch_ep);
643638

644-
ret = check_sch_bw(udev, sch_bw, sch_ep);
645-
if (ret) {
646-
xhci_err(xhci, "Not enough bandwidth!\n");
647-
if (is_fs_or_ls(udev->speed))
648-
drop_tt(udev);
649-
650-
kfree(sch_ep);
651-
return -ENOSPC;
652-
}
639+
list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_list_new);
653640

654-
list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
641+
return 0;
642+
}
643+
EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
655644

656-
ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
657-
| EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode));
658-
ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
659-
| EP_BREPEAT(sch_ep->repeat));
645+
static void xhci_mtk_drop_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
646+
struct mu3h_sch_ep_info *sch_ep)
647+
{
648+
struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
649+
int bw_index = get_bw_index(xhci, udev, sch_ep->ep);
650+
struct mu3h_sch_bw_info *sch_bw = &mtk->sch_array[bw_index];
660651

661-
xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
662-
sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
663-
sch_ep->offset, sch_ep->repeat);
652+
update_bus_bw(sch_bw, sch_ep, 0);
653+
list_del(&sch_ep->endpoint);
664654

665-
return 0;
655+
if (sch_ep->sch_tt) {
656+
list_del(&sch_ep->tt_endpoint);
657+
drop_tt(udev);
658+
}
659+
kfree(sch_ep);
666660
}
667-
EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
668661

669662
void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
670663
struct usb_host_endpoint *ep)
@@ -675,7 +668,7 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
675668
struct xhci_virt_device *virt_dev;
676669
struct mu3h_sch_bw_info *sch_array;
677670
struct mu3h_sch_bw_info *sch_bw;
678-
struct mu3h_sch_ep_info *sch_ep;
671+
struct mu3h_sch_ep_info *sch_ep, *tmp;
679672
int bw_index;
680673

681674
xhci = hcd_to_xhci(hcd);
@@ -694,17 +687,73 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
694687
bw_index = get_bw_index(xhci, udev, ep);
695688
sch_bw = &sch_array[bw_index];
696689

697-
list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) {
690+
list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
698691
if (sch_ep->ep == ep) {
699-
update_bus_bw(sch_bw, sch_ep, 0);
700-
list_del(&sch_ep->endpoint);
701-
if (is_fs_or_ls(udev->speed)) {
702-
list_del(&sch_ep->tt_endpoint);
703-
drop_tt(udev);
704-
}
705-
kfree(sch_ep);
706-
break;
692+
xhci_mtk_drop_ep(mtk, udev, sch_ep);
707693
}
708694
}
709695
}
710696
EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);
697+
698+
int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
699+
{
700+
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
701+
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
702+
struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
703+
struct mu3h_sch_bw_info *sch_bw;
704+
struct mu3h_sch_ep_info *sch_ep, *tmp;
705+
int bw_index, ret;
706+
707+
dev_dbg(&udev->dev, "%s\n", __func__);
708+
709+
list_for_each_entry(sch_ep, &mtk->bw_ep_list_new, endpoint) {
710+
bw_index = get_bw_index(xhci, udev, sch_ep->ep);
711+
sch_bw = &mtk->sch_array[bw_index];
712+
713+
ret = check_sch_bw(udev, sch_bw, sch_ep);
714+
if (ret) {
715+
xhci_err(xhci, "Not enough bandwidth!\n");
716+
return -ENOSPC;
717+
}
718+
}
719+
720+
list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
721+
struct xhci_ep_ctx *ep_ctx;
722+
struct usb_host_endpoint *ep = sch_ep->ep;
723+
unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
724+
725+
bw_index = get_bw_index(xhci, udev, ep);
726+
sch_bw = &mtk->sch_array[bw_index];
727+
728+
list_move_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
729+
730+
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
731+
ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
732+
| EP_BCSCOUNT(sch_ep->cs_count)
733+
| EP_BBM(sch_ep->burst_mode));
734+
ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
735+
| EP_BREPEAT(sch_ep->repeat));
736+
737+
xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
738+
sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
739+
sch_ep->offset, sch_ep->repeat);
740+
}
741+
742+
return xhci_check_bandwidth(hcd, udev);
743+
}
744+
EXPORT_SYMBOL_GPL(xhci_mtk_check_bandwidth);
745+
746+
void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
747+
{
748+
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
749+
struct mu3h_sch_ep_info *sch_ep, *tmp;
750+
751+
dev_dbg(&udev->dev, "%s\n", __func__);
752+
753+
list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
754+
xhci_mtk_drop_ep(mtk, udev, sch_ep);
755+
}
756+
757+
xhci_reset_bandwidth(hcd, udev);
758+
}
759+
EXPORT_SYMBOL_GPL(xhci_mtk_reset_bandwidth);

drivers/usb/host/xhci-mtk.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ static void usb_wakeup_set(struct xhci_hcd_mtk *mtk, bool enable)
347347
static int xhci_mtk_setup(struct usb_hcd *hcd);
348348
static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
349349
.reset = xhci_mtk_setup,
350+
.check_bandwidth = xhci_mtk_check_bandwidth,
351+
.reset_bandwidth = xhci_mtk_reset_bandwidth,
350352
};
351353

352354
static struct hc_driver __read_mostly xhci_mtk_hc_driver;

drivers/usb/host/xhci-mtk.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct mu3c_ippc_regs {
130130
struct xhci_hcd_mtk {
131131
struct device *dev;
132132
struct usb_hcd *hcd;
133+
struct list_head bw_ep_list_new;
133134
struct mu3h_sch_bw_info *sch_array;
134135
struct mu3c_ippc_regs __iomem *ippc_regs;
135136
bool has_ippc;
@@ -166,6 +167,8 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
166167
struct usb_host_endpoint *ep);
167168
void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
168169
struct usb_host_endpoint *ep);
170+
int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
171+
void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
169172

170173
#else
171174
static inline int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd,
@@ -179,6 +182,16 @@ static inline void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd,
179182
{
180183
}
181184

185+
static inline int xhci_mtk_check_bandwidth(struct usb_hcd *hcd,
186+
struct usb_device *udev)
187+
{
188+
return 0;
189+
}
190+
191+
static inline void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd,
192+
struct usb_device *udev)
193+
{
194+
}
182195
#endif
183196

184197
#endif /* _XHCI_MTK_H_ */

drivers/usb/host/xhci.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,7 +2985,7 @@ static void xhci_check_bw_drop_ep_streams(struct xhci_hcd *xhci,
29852985
* else should be touching the xhci->devs[slot_id] structure, so we
29862986
* don't need to take the xhci->lock for manipulating that.
29872987
*/
2988-
static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
2988+
int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
29892989
{
29902990
int i;
29912991
int ret = 0;
@@ -3083,7 +3083,7 @@ static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
30833083
return ret;
30843084
}
30853085

3086-
static void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
3086+
void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
30873087
{
30883088
struct xhci_hcd *xhci;
30893089
struct xhci_virt_device *virt_dev;
@@ -5510,6 +5510,10 @@ void xhci_init_driver(struct hc_driver *drv,
55105510
drv->reset = over->reset;
55115511
if (over->start)
55125512
drv->start = over->start;
5513+
if (over->check_bandwidth)
5514+
drv->check_bandwidth = over->check_bandwidth;
5515+
if (over->reset_bandwidth)
5516+
drv->reset_bandwidth = over->reset_bandwidth;
55135517
}
55145518
}
55155519
EXPORT_SYMBOL_GPL(xhci_init_driver);

drivers/usb/host/xhci.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1920,6 +1920,8 @@ struct xhci_driver_overrides {
19201920
size_t extra_priv_size;
19211921
int (*reset)(struct usb_hcd *hcd);
19221922
int (*start)(struct usb_hcd *hcd);
1923+
int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
1924+
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
19231925
};
19241926

19251927
#define XHCI_CFC_DELAY 10
@@ -2074,6 +2076,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
20742076
void xhci_shutdown(struct usb_hcd *hcd);
20752077
void xhci_init_driver(struct hc_driver *drv,
20762078
const struct xhci_driver_overrides *over);
2079+
int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
2080+
void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
20772081
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
20782082
int xhci_ext_cap_init(struct xhci_hcd *xhci);
20792083

0 commit comments

Comments
 (0)