Skip to content

Commit

Permalink
usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints
Browse files Browse the repository at this point in the history
For those unchecked endpoints, we don't allocate bandwidth for
them, so no need free the bandwidth, otherwise will decrease
the allocated bandwidth.
Meanwhile use xhci_dbg() instead of dev_dbg() to print logs and
rename bw_ep_list_new as bw_ep_chk_list.

Fixes: 1d69f9d ("usb: xhci-mtk: fix unreleased bandwidth data")
Cc: stable <stable@vger.kernel.org>
Reviewed-and-tested-by: Ikjoon Jang <ikjn@chromium.org>
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/1612159064-28413-1-git-send-email-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Chunfeng Yun authored and gregkh committed Feb 1, 2021
1 parent 9917f0e commit 54f6a8a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 29 deletions.
61 changes: 33 additions & 28 deletions drivers/usb/host/xhci-mtk-sch.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,

sch_ep->sch_tt = tt;
sch_ep->ep = ep;
INIT_LIST_HEAD(&sch_ep->endpoint);
INIT_LIST_HEAD(&sch_ep->tt_endpoint);

return sch_ep;
Expand Down Expand Up @@ -374,6 +375,7 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
sch_ep->bw_budget_table[j];
}
}
sch_ep->allocated = used;
}

static int check_sch_tt(struct usb_device *udev,
Expand Down Expand Up @@ -542,6 +544,22 @@ static int check_sch_bw(struct usb_device *udev,
return 0;
}

static void destroy_sch_ep(struct usb_device *udev,
struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
{
/* only release ep bw check passed by check_sch_bw() */
if (sch_ep->allocated)
update_bus_bw(sch_bw, sch_ep, 0);

list_del(&sch_ep->endpoint);

if (sch_ep->sch_tt) {
list_del(&sch_ep->tt_endpoint);
drop_tt(udev);
}
kfree(sch_ep);
}

static bool need_bw_sch(struct usb_host_endpoint *ep,
enum usb_device_speed speed, int has_tt)
{
Expand Down Expand Up @@ -584,7 +602,7 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)

mtk->sch_array = sch_array;

INIT_LIST_HEAD(&mtk->bw_ep_list_new);
INIT_LIST_HEAD(&mtk->bw_ep_chk_list);

return 0;
}
Expand Down Expand Up @@ -636,29 +654,12 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,

setup_sch_info(udev, ep_ctx, sch_ep);

list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_list_new);
list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list);

return 0;
}
EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);

static void xhci_mtk_drop_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
struct mu3h_sch_ep_info *sch_ep)
{
struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
int bw_index = get_bw_index(xhci, udev, sch_ep->ep);
struct mu3h_sch_bw_info *sch_bw = &mtk->sch_array[bw_index];

update_bus_bw(sch_bw, sch_ep, 0);
list_del(&sch_ep->endpoint);

if (sch_ep->sch_tt) {
list_del(&sch_ep->tt_endpoint);
drop_tt(udev);
}
kfree(sch_ep);
}

void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint *ep)
{
Expand Down Expand Up @@ -688,9 +689,8 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
sch_bw = &sch_array[bw_index];

list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
if (sch_ep->ep == ep) {
xhci_mtk_drop_ep(mtk, udev, sch_ep);
}
if (sch_ep->ep == ep)
destroy_sch_ep(udev, sch_bw, sch_ep);
}
}
EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);
Expand All @@ -704,9 +704,9 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
struct mu3h_sch_ep_info *sch_ep, *tmp;
int bw_index, ret;

dev_dbg(&udev->dev, "%s\n", __func__);
xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));

list_for_each_entry(sch_ep, &mtk->bw_ep_list_new, endpoint) {
list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) {
bw_index = get_bw_index(xhci, udev, sch_ep->ep);
sch_bw = &mtk->sch_array[bw_index];

Expand All @@ -717,7 +717,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
}
}

list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, 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);
Expand Down Expand Up @@ -746,12 +746,17 @@ 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 xhci_hcd *xhci = hcd_to_xhci(hcd);
struct mu3h_sch_bw_info *sch_bw;
struct mu3h_sch_ep_info *sch_ep, *tmp;
int bw_index;

dev_dbg(&udev->dev, "%s\n", __func__);
xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));

list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
xhci_mtk_drop_ep(mtk, udev, sch_ep);
list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) {
bw_index = get_bw_index(xhci, udev, sch_ep->ep);
sch_bw = &mtk->sch_array[bw_index];
destroy_sch_ep(udev, sch_bw, sch_ep);
}

xhci_reset_bandwidth(hcd, udev);
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/host/xhci-mtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct mu3h_sch_bw_info {
* @ep_type: endpoint type
* @maxpkt: max packet size of endpoint
* @ep: address of usb_host_endpoint struct
* @allocated: the bandwidth is aready allocated from bus_bw
* @offset: which uframe of the interval that transfer should be
* scheduled first time within the interval
* @repeat: the time gap between two uframes that transfers are
Expand Down Expand Up @@ -86,6 +87,7 @@ struct mu3h_sch_ep_info {
u32 ep_type;
u32 maxpkt;
void *ep;
bool allocated;
/*
* mtk xHCI scheduling information put into reserved DWs
* in ep context
Expand Down Expand Up @@ -130,8 +132,8 @@ struct mu3c_ippc_regs {
struct xhci_hcd_mtk {
struct device *dev;
struct usb_hcd *hcd;
struct list_head bw_ep_list_new;
struct mu3h_sch_bw_info *sch_array;
struct list_head bw_ep_chk_list;
struct mu3c_ippc_regs __iomem *ippc_regs;
bool has_ippc;
int num_u2_ports;
Expand Down

0 comments on commit 54f6a8a

Please sign in to comment.