aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2014-05-28 23:51:13 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-06-11 12:03:24 -0700
commit6e9a86e1e78b462d38e74ad47a8d32a3e0abe6bd (patch)
treec58d439193cad51bf45c47c51ba5e5bddbd54e99
parent88580b125ac63b24bbba7f71bd235f27c65f5baa (diff)
xhci: delete endpoints from bandwidth list before freeing whole device
commit 5dc2808c4729bf080487e61b80ee04e0fdb12a37 upstream. Lists of endpoints are stored for bandwidth calculation for roothub ports. Make sure we remove all endpoints from the list before the whole device, containing its endpoints list_head stuctures, is freed. This used to be done in the wrong order in xhci_mem_cleanup(), and triggered an oops in resume from S4 (hibernate). Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/xhci-mem.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index f2e57a1112c9..d007f0920126 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1794,6 +1794,16 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
kfree(cur_cd);
}
+ num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
+ for (i = 0; i < num_ports; i++) {
+ struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
+ for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
+ struct list_head *ep = &bwt->interval_bw[j].endpoints;
+ while (!list_empty(ep))
+ list_del_init(ep->next);
+ }
+ }
+
for (i = 1; i < MAX_HC_SLOTS; ++i)
xhci_free_virt_device(xhci, i);
@@ -1834,16 +1844,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
if (!xhci->rh_bw)
goto no_bw;
- num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
- for (i = 0; i < num_ports; i++) {
- struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
- for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
- struct list_head *ep = &bwt->interval_bw[j].endpoints;
- while (!list_empty(ep))
- list_del_init(ep->next);
- }
- }
-
for (i = 0; i < num_ports; i++) {
struct xhci_tt_bw_info *tt, *n;
list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) {