[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-arm-kernel mailing list