@@ -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)
{
@@ -689,7 +690,8 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
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);
+ destroy_sch_ep(udev, sch_bw, sch_ep);
+ break;
}
}
}
@@ -704,9 +706,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 +719,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 +748,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;