[PATCH v6] usb: xhci-mtk: fix unreleased bandwidth data
Chunfeng Yun
chunfeng.yun at mediatek.com
Fri Jan 29 04:18:23 EST 2021
Hi Ikjoon,
On Wed, 2021-01-13 at 18:05 +0800, Ikjoon Jang wrote:
> 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: 08e469de87a2 ("usb: xhci-mtk: supports bandwidth scheduling with multi-TT")
> Signed-off-by: Ikjoon Jang <ikjn at chromium.org>
>
> ---
>
> Changes in v6:
> - use xhci overrides instead of quirk functions for
> {check|reset}_bandwidth().
>
> Changes in v5:
> - Fix a wrong commit id in Fixes tag
>
> Changes in v4:
> - bugfix in v3, check_bandwidth() return uninitialized value
> when no new endpoints were added.
> - change Fixes tag to keep dependency
>
> Changes in v3:
> - drop unrelated code cleanups
> - change Fixes tag to keep dependency
>
> Changes in v2:
> - fix a 0-day warning from unused variable
> - split one big patch into three patches
> - fix wrong offset in mediatek hw flags
>
> drivers/usb/host/xhci-mtk-sch.c | 123 ++++++++++++++++++++++----------
> drivers/usb/host/xhci-mtk.c | 2 +
> drivers/usb/host/xhci-mtk.h | 13 ++++
> drivers/usb/host/xhci.c | 8 ++-
> drivers/usb/host/xhci.h | 4 ++
> 5 files changed, 111 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
> index 45c54d56ecbd..a313e75ff1c6 100644
> --- a/drivers/usb/host/xhci-mtk-sch.c
> +++ b/drivers/usb/host/xhci-mtk-sch.c
> @@ -200,6 +200,7 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
> [...]
> +
> +int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
> +{
> + struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
> + struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> + struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
> + struct mu3h_sch_bw_info *sch_bw;
> + struct mu3h_sch_ep_info *sch_ep, *tmp;
> + int bw_index, ret;
> +
> + dev_dbg(&udev->dev, "%s\n", __func__);
> +
> + list_for_each_entry(sch_ep, &mtk->bw_ep_list_new, endpoint) {
> + bw_index = get_bw_index(xhci, udev, sch_ep->ep);
> + sch_bw = &mtk->sch_array[bw_index];
> +
> + ret = check_sch_bw(udev, sch_bw, sch_ep);
> + if (ret) {
> + xhci_err(xhci, "Not enough bandwidth!\n");
> + return -ENOSPC;
> + }
> + }
> +
> + list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
> + struct xhci_ep_ctx *ep_ctx;
> + struct usb_host_endpoint *ep = sch_ep->ep;
> + unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
> +
> + bw_index = get_bw_index(xhci, udev, ep);
> + sch_bw = &mtk->sch_array[bw_index];
> +
> + list_move_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
> +
> + ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
> + ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
> + | EP_BCSCOUNT(sch_ep->cs_count)
> + | EP_BBM(sch_ep->burst_mode));
> + ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
> + | EP_BREPEAT(sch_ep->repeat));
> +
> + xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
> + sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
> + sch_ep->offset, sch_ep->repeat);
> + }
> +
> + return xhci_check_bandwidth(hcd, udev);
> +}
> +EXPORT_SYMBOL_GPL(xhci_mtk_check_bandwidth);
> +
> +void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
> +{
> + struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
> + struct mu3h_sch_ep_info *sch_ep, *tmp;
> +
> + dev_dbg(&udev->dev, "%s\n", __func__);
> +
> + list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
> + xhci_mtk_drop_ep(mtk, udev, sch_ep);
This need skip endpoint not allocated bandwidth; e.g.
If add 3 eps, the second on is checked fail, only need drop first ep,
and skip second & third ones.
I'll send out a v7 patch, thanks
> + }
> +
> + xhci_reset_bandwidth(hcd, udev);
> +}
> +EXPORT_SYMBOL_GPL(xhci_mtk_reset_bandwidth);
[...]
More information about the Linux-mediatek
mailing list