diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-06-01 04:06:24 -0400 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2012-06-13 19:37:30 -0400 |
commit | 32f1d2c536d0c26c5814cb0e6a0606c42d02fac1 (patch) | |
tree | 76f9d51f81cf29d07a988b0283e2ea4d874a0971 /drivers/usb/host/xhci-mem.c | |
parent | 46ed8f00d8982e49f8fe2c1a9cea192f640cb3ba (diff) |
xhci: Don't free endpoints in xhci_mem_cleanup()
This patch fixes a few issues introduced in the recent fix
[f8a9e72d: USB: fix resource leak in xhci power loss path]
- The endpoints listed in bw table are just links and each entry is an
array member of dev->eps[]. But the commit above adds a kfree() call
to these instances, and thus it results in memory corruption.
- It clears only the first entry of rh_bw[], but there can be multiple
ports.
- It'd be safer to clear the list_head of ep as well, not only
removing from the list, as it's checked in
xhci_discover_or_reset_device().
This patch should be backported to kernels as old as 3.2, that contain
the commit 839c817ce67178ca3c7c7ad534c571bba1e69ebe "xhci: Store
information about roothubs and TTs."
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Reviewed-by: Oliver Neukum <oneukum@suse.de>
Cc: <stable@vger.kernel.org>
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 898dfc8bc520..77689bd64cac 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1772,17 +1772,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
1772 | { | 1772 | { |
1773 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | 1773 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
1774 | struct dev_info *dev_info, *next; | 1774 | struct dev_info *dev_info, *next; |
1775 | struct list_head *tt_list_head; | ||
1776 | struct list_head *tt; | ||
1777 | struct list_head *endpoints; | ||
1778 | struct list_head *ep, *q; | ||
1779 | struct xhci_tt_bw_info *tt_info; | ||
1780 | struct xhci_interval_bw_table *bwt; | ||
1781 | struct xhci_virt_ep *virt_ep; | ||
1782 | |||
1783 | unsigned long flags; | 1775 | unsigned long flags; |
1784 | int size; | 1776 | int size; |
1785 | int i; | 1777 | int i, j, num_ports; |
1786 | 1778 | ||
1787 | /* Free the Event Ring Segment Table and the actual Event Ring */ | 1779 | /* Free the Event Ring Segment Table and the actual Event Ring */ |
1788 | size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); | 1780 | size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); |
@@ -1841,21 +1833,22 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
1841 | } | 1833 | } |
1842 | spin_unlock_irqrestore(&xhci->lock, flags); | 1834 | spin_unlock_irqrestore(&xhci->lock, flags); |
1843 | 1835 | ||
1844 | bwt = &xhci->rh_bw->bw_table; | 1836 | num_ports = HCS_MAX_PORTS(xhci->hcs_params1); |
1845 | for (i = 0; i < XHCI_MAX_INTERVAL; i++) { | 1837 | for (i = 0; i < num_ports; i++) { |
1846 | endpoints = &bwt->interval_bw[i].endpoints; | 1838 | struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; |
1847 | list_for_each_safe(ep, q, endpoints) { | 1839 | for (j = 0; j < XHCI_MAX_INTERVAL; j++) { |
1848 | virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); | 1840 | struct list_head *ep = &bwt->interval_bw[j].endpoints; |
1849 | list_del(&virt_ep->bw_endpoint_list); | 1841 | while (!list_empty(ep)) |
1850 | kfree(virt_ep); | 1842 | list_del_init(ep->next); |
1851 | } | 1843 | } |
1852 | } | 1844 | } |
1853 | 1845 | ||
1854 | tt_list_head = &xhci->rh_bw->tts; | 1846 | for (i = 0; i < num_ports; i++) { |
1855 | list_for_each_safe(tt, q, tt_list_head) { | 1847 | struct xhci_tt_bw_info *tt, *n; |
1856 | tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); | 1848 | list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) { |
1857 | list_del(tt); | 1849 | list_del(&tt->tt_list); |
1858 | kfree(tt_info); | 1850 | kfree(tt); |
1851 | } | ||
1859 | } | 1852 | } |
1860 | 1853 | ||
1861 | xhci->num_usb2_ports = 0; | 1854 | xhci->num_usb2_ports = 0; |