diff options
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
| -rw-r--r-- | drivers/usb/host/xhci-mem.c | 39 | 
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 68eaa908ac8..ec4338eec82 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1791,6 +1791,14 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)  {  	struct pci_dev	*pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);  	struct dev_info	*dev_info, *next; +	struct list_head *tt_list_head; +	struct list_head *tt; +	struct list_head *endpoints; +	struct list_head *ep, *q; +	struct xhci_tt_bw_info *tt_info; +	struct xhci_interval_bw_table *bwt; +	struct xhci_virt_ep *virt_ep; +  	unsigned long	flags;  	int size;  	int i; @@ -1807,6 +1815,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)  	xhci->event_ring = NULL;  	xhci_dbg(xhci, "Freed event ring\n"); +	if (xhci->lpm_command) +		xhci_free_command(xhci, xhci->lpm_command); +	xhci->cmd_ring_reserved_trbs = 0;  	if (xhci->cmd_ring)  		xhci_ring_free(xhci, xhci->cmd_ring);  	xhci->cmd_ring = NULL; @@ -1849,8 +1860,26 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)  	}  	spin_unlock_irqrestore(&xhci->lock, flags); +	bwt = &xhci->rh_bw->bw_table; +	for (i = 0; i < XHCI_MAX_INTERVAL; i++) { +		endpoints = &bwt->interval_bw[i].endpoints; +		list_for_each_safe(ep, q, endpoints) { +			virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); +			list_del(&virt_ep->bw_endpoint_list); +			kfree(virt_ep); +		} +	} + +	tt_list_head = &xhci->rh_bw->tts; +	list_for_each_safe(tt, q, tt_list_head) { +		tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); +		list_del(tt); +		kfree(tt_info); +	} +  	xhci->num_usb2_ports = 0;  	xhci->num_usb3_ports = 0; +	xhci->num_active_eps = 0;  	kfree(xhci->usb2_ports);  	kfree(xhci->usb3_ports);  	kfree(xhci->port_array); @@ -2350,6 +2379,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)  	xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);  	xhci_dbg_cmd_ptrs(xhci); +	xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags); +	if (!xhci->lpm_command) +		goto fail; + +	/* Reserve one command ring TRB for disabling LPM. +	 * Since the USB core grabs the shared usb_bus bandwidth mutex before +	 * disabling LPM, we only need to reserve one TRB for all devices. +	 */ +	xhci->cmd_ring_reserved_trbs++; +  	val = xhci_readl(xhci, &xhci->cap_regs->db_off);  	val &= DBOFF_MASK;  	xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x"  |