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 68eaa908ac8e..ec4338eec826 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) | |||
1791 | { | 1791 | { |
1792 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | 1792 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
1793 | struct dev_info *dev_info, *next; | 1793 | struct dev_info *dev_info, *next; |
1794 | struct list_head *tt_list_head; | ||
1795 | struct list_head *tt; | ||
1796 | struct list_head *endpoints; | ||
1797 | struct list_head *ep, *q; | ||
1798 | struct xhci_tt_bw_info *tt_info; | ||
1799 | struct xhci_interval_bw_table *bwt; | ||
1800 | struct xhci_virt_ep *virt_ep; | ||
1801 | |||
1794 | unsigned long flags; | 1802 | unsigned long flags; |
1795 | int size; | 1803 | int size; |
1796 | int i; | 1804 | int i; |
@@ -1807,6 +1815,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
1807 | xhci->event_ring = NULL; | 1815 | xhci->event_ring = NULL; |
1808 | xhci_dbg(xhci, "Freed event ring\n"); | 1816 | xhci_dbg(xhci, "Freed event ring\n"); |
1809 | 1817 | ||
1818 | if (xhci->lpm_command) | ||
1819 | xhci_free_command(xhci, xhci->lpm_command); | ||
1820 | xhci->cmd_ring_reserved_trbs = 0; | ||
1810 | if (xhci->cmd_ring) | 1821 | if (xhci->cmd_ring) |
1811 | xhci_ring_free(xhci, xhci->cmd_ring); | 1822 | xhci_ring_free(xhci, xhci->cmd_ring); |
1812 | xhci->cmd_ring = NULL; | 1823 | xhci->cmd_ring = NULL; |
@@ -1849,8 +1860,26 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
1849 | } | 1860 | } |
1850 | spin_unlock_irqrestore(&xhci->lock, flags); | 1861 | spin_unlock_irqrestore(&xhci->lock, flags); |
1851 | 1862 | ||
1863 | bwt = &xhci->rh_bw->bw_table; | ||
1864 | for (i = 0; i < XHCI_MAX_INTERVAL; i++) { | ||
1865 | endpoints = &bwt->interval_bw[i].endpoints; | ||
1866 | list_for_each_safe(ep, q, endpoints) { | ||
1867 | virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); | ||
1868 | list_del(&virt_ep->bw_endpoint_list); | ||
1869 | kfree(virt_ep); | ||
1870 | } | ||
1871 | } | ||
1872 | |||
1873 | tt_list_head = &xhci->rh_bw->tts; | ||
1874 | list_for_each_safe(tt, q, tt_list_head) { | ||
1875 | tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); | ||
1876 | list_del(tt); | ||
1877 | kfree(tt_info); | ||
1878 | } | ||
1879 | |||
1852 | xhci->num_usb2_ports = 0; | 1880 | xhci->num_usb2_ports = 0; |
1853 | xhci->num_usb3_ports = 0; | 1881 | xhci->num_usb3_ports = 0; |
1882 | xhci->num_active_eps = 0; | ||
1854 | kfree(xhci->usb2_ports); | 1883 | kfree(xhci->usb2_ports); |
1855 | kfree(xhci->usb3_ports); | 1884 | kfree(xhci->usb3_ports); |
1856 | kfree(xhci->port_array); | 1885 | kfree(xhci->port_array); |
@@ -2350,6 +2379,16 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2350 | xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); | 2379 | xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); |
2351 | xhci_dbg_cmd_ptrs(xhci); | 2380 | xhci_dbg_cmd_ptrs(xhci); |
2352 | 2381 | ||
2382 | xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags); | ||
2383 | if (!xhci->lpm_command) | ||
2384 | goto fail; | ||
2385 | |||
2386 | /* Reserve one command ring TRB for disabling LPM. | ||
2387 | * Since the USB core grabs the shared usb_bus bandwidth mutex before | ||
2388 | * disabling LPM, we only need to reserve one TRB for all devices. | ||
2389 | */ | ||
2390 | xhci->cmd_ring_reserved_trbs++; | ||
2391 | |||
2353 | val = xhci_readl(xhci, &xhci->cap_regs->db_off); | 2392 | val = xhci_readl(xhci, &xhci->cap_regs->db_off); |
2354 | val &= DBOFF_MASK; | 2393 | val &= DBOFF_MASK; |
2355 | xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x" | 2394 | xhci_dbg(xhci, "// Doorbell array is located at offset 0x%x" |