Commit 54f6a8af authored by Chunfeng Yun's avatar Chunfeng Yun Committed by Greg Kroah-Hartman

usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints

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: 1d69f9d9 ("usb: xhci-mtk: fix unreleased bandwidth data")
Cc: stable <stable@vger.kernel.org>
Reviewed-and-tested-by: default avatarIkjoon Jang <ikjn@chromium.org>
Signed-off-by: default avatarChunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/1612159064-28413-1-git-send-email-chunfeng.yun@mediatek.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9917f0e3
......@@ -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;
......@@ -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,
......@@ -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)
{
......@@ -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;
}
......@@ -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)
{
......@@ -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);
......@@ -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];
......@@ -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);
......@@ -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);
......
......@@ -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
......@@ -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
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment