mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 01:01:52 +00:00
xhci: Bug fixes for 3.5
Hi Greg, Here's five bug fixes for 3.5. They fix some memory leaks in the bandwidth calculation code, fix a couple bugs in the USB3 Link PM patchset, and make system suspend and resume work on platforms with the AsMedia ASM1042 xHCI host controller. Sarah Sharp -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJP2SkLAAoJEBMGWMLi1Gc5J08P/3+jxbPAC49miW8QXau993Ud Ng8glY9hSavl06mLzf63Eke2SnQNJ9cq+FaqVyYOX5AVcNRCcgsyqJpllF2Eu8iU e6Icomst4m1Jmk/38CSEo+eL3fBME4cfhT9zhzmR2dhJnzGx4HnCmAh8I+TqvGSy osXWq0RQ6k6yUSBLH+nKeeCY1Nn4QYyBI1Ix4jKDKiZQSAfd1ppzh8bszOTFSE9b y9BoB6lWVO7xnbofOlD+SqSSd8TLg9nyTekp2iVRLzY9Df83Xn8+Vu2YYJCJGB4V 1bLemY4hwP//TBAf45/KLDluIJb+JJ/Dzwa+W0YiogeD8munL8G21biXayB4G/11 rLnbHxmvBn/DC7s+aT2ie++Cn97ZV+WJW4p9x2hYnMJayukzV9+GqF4F+uD55NP7 WtfvIgmc4H4qAX2wEAYyJRUAL+tfGsBDjr/ItKiKaj15xsN2YPEE3fFx0s8Ht46M aRQN1AJghK1MD/pQHRm9uP4GB3lZtcKwMgpkT7cYsXaBtf1Fn3VfHExpuZ4bvFNB I+6B+WVF5PE//h+fdB1GGvLKv2FTR1DjvU6+tVv5KnBAm4Vmfnw+vrqMhG8KMZpF NEVmiTN53tMyLC9ez7uBgzwVARE4RbqdiWHJIjj8CEjkbknDe0+keYBZ2egoQW6d olNSuH3khQ/hoRYutqcK =oodF -----END PGP SIGNATURE----- Merge tag 'for-usb-linus-2012-06-13' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus xhci: Bug fixes for 3.5 Hi Greg, Here's five bug fixes for 3.5. They fix some memory leaks in the bandwidth calculation code, fix a couple bugs in the USB3 Link PM patchset, and make system suspend and resume work on platforms with the AsMedia ASM1042 xHCI host controller. Sarah Sharp
This commit is contained in:
commit
57e04bdb3e
@ -3379,7 +3379,7 @@ int usb_disable_lpm(struct usb_device *udev)
|
||||
return 0;
|
||||
|
||||
udev->lpm_disable_count++;
|
||||
if ((udev->u1_params.timeout == 0 && udev->u1_params.timeout == 0))
|
||||
if ((udev->u1_params.timeout == 0 && udev->u2_params.timeout == 0))
|
||||
return 0;
|
||||
|
||||
/* If LPM is enabled, attempt to disable it. */
|
||||
|
@ -793,10 +793,9 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci,
|
||||
struct xhci_virt_device *virt_dev,
|
||||
int slot_id)
|
||||
{
|
||||
struct list_head *tt;
|
||||
struct list_head *tt_list_head;
|
||||
struct list_head *tt_next;
|
||||
struct xhci_tt_bw_info *tt_info;
|
||||
struct xhci_tt_bw_info *tt_info, *next;
|
||||
bool slot_found = false;
|
||||
|
||||
/* If the device never made it past the Set Address stage,
|
||||
* it may not have the real_port set correctly.
|
||||
@ -808,34 +807,16 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci,
|
||||
}
|
||||
|
||||
tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts);
|
||||
if (list_empty(tt_list_head))
|
||||
return;
|
||||
|
||||
list_for_each(tt, tt_list_head) {
|
||||
tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list);
|
||||
if (tt_info->slot_id == slot_id)
|
||||
list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) {
|
||||
/* Multi-TT hubs will have more than one entry */
|
||||
if (tt_info->slot_id == slot_id) {
|
||||
slot_found = true;
|
||||
list_del(&tt_info->tt_list);
|
||||
kfree(tt_info);
|
||||
} else if (slot_found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Cautionary measure in case the hub was disconnected before we
|
||||
* stored the TT information.
|
||||
*/
|
||||
if (tt_info->slot_id != slot_id)
|
||||
return;
|
||||
|
||||
tt_next = tt->next;
|
||||
tt_info = list_entry(tt, struct xhci_tt_bw_info,
|
||||
tt_list);
|
||||
/* Multi-TT hubs will have more than one entry */
|
||||
do {
|
||||
list_del(tt);
|
||||
kfree(tt_info);
|
||||
tt = tt_next;
|
||||
if (list_empty(tt_list_head))
|
||||
break;
|
||||
tt_next = tt->next;
|
||||
tt_info = list_entry(tt, struct xhci_tt_bw_info,
|
||||
tt_list);
|
||||
} while (tt_info->slot_id == slot_id);
|
||||
}
|
||||
|
||||
int xhci_alloc_tt_info(struct xhci_hcd *xhci,
|
||||
@ -1791,17 +1772,9 @@ 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;
|
||||
int i, j, num_ports;
|
||||
|
||||
/* Free the Event Ring Segment Table and the actual Event Ring */
|
||||
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
|
||||
@ -1860,21 +1833,22 @@ 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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) {
|
||||
list_del(&tt->tt_list);
|
||||
kfree(tt);
|
||||
}
|
||||
}
|
||||
|
||||
xhci->num_usb2_ports = 0;
|
||||
|
@ -795,8 +795,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
command |= CMD_CSS;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) {
|
||||
xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n");
|
||||
if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
|
||||
xhci_warn(xhci, "WARN: xHC save state timeout\n");
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -848,8 +848,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
||||
command |= CMD_CRS;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
if (handshake(xhci, &xhci->op_regs->status,
|
||||
STS_RESTORE, 0, 10*100)) {
|
||||
xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n");
|
||||
STS_RESTORE, 0, 10 * 1000)) {
|
||||
xhci_warn(xhci, "WARN: xHC restore state timeout\n");
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -3906,7 +3906,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
|
||||
default:
|
||||
dev_warn(&udev->dev, "%s: Can't get timeout for non-U1 or U2 state.\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
return USB3_LPM_DISABLED;
|
||||
}
|
||||
|
||||
if (sel <= max_sel_pel && pel <= max_sel_pel)
|
||||
|
Loading…
Reference in New Issue
Block a user