diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 13 | ||||
-rw-r--r-- | drivers/usb/host/isp1362-hcd.c | 18 | ||||
-rw-r--r-- | drivers/usb/host/isp1362.h | 12 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 30 | ||||
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/whci/asl.c | 23 | ||||
-rw-r--r-- | drivers/usb/host/whci/debug.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/whci/pzl.c | 24 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hcd.c | 29 |
9 files changed, 106 insertions, 51 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 3ea05936851..b25cdea93a1 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1400,6 +1400,10 @@ iso_stream_schedule ( | |||
1400 | goto fail; | 1400 | goto fail; |
1401 | } | 1401 | } |
1402 | 1402 | ||
1403 | period = urb->interval; | ||
1404 | if (!stream->highspeed) | ||
1405 | period <<= 3; | ||
1406 | |||
1403 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; | 1407 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; |
1404 | 1408 | ||
1405 | /* when's the last uframe this urb could start? */ | 1409 | /* when's the last uframe this urb could start? */ |
@@ -1417,14 +1421,15 @@ iso_stream_schedule ( | |||
1417 | 1421 | ||
1418 | /* Fell behind (by up to twice the slop amount)? */ | 1422 | /* Fell behind (by up to twice the slop amount)? */ |
1419 | if (start >= max - 2 * 8 * SCHEDULE_SLOP) | 1423 | if (start >= max - 2 * 8 * SCHEDULE_SLOP) |
1420 | start += stream->interval * DIV_ROUND_UP( | 1424 | start += period * DIV_ROUND_UP( |
1421 | max - start, stream->interval) - mod; | 1425 | max - start, period) - mod; |
1422 | 1426 | ||
1423 | /* Tried to schedule too far into the future? */ | 1427 | /* Tried to schedule too far into the future? */ |
1424 | if (unlikely((start + sched->span) >= max)) { | 1428 | if (unlikely((start + sched->span) >= max)) { |
1425 | status = -EFBIG; | 1429 | status = -EFBIG; |
1426 | goto fail; | 1430 | goto fail; |
1427 | } | 1431 | } |
1432 | stream->next_uframe = start; | ||
1428 | goto ready; | 1433 | goto ready; |
1429 | } | 1434 | } |
1430 | 1435 | ||
@@ -1440,10 +1445,6 @@ iso_stream_schedule ( | |||
1440 | 1445 | ||
1441 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | 1446 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ |
1442 | 1447 | ||
1443 | period = urb->interval; | ||
1444 | if (!stream->highspeed) | ||
1445 | period <<= 3; | ||
1446 | |||
1447 | /* find a uframe slot with enough bandwidth */ | 1448 | /* find a uframe slot with enough bandwidth */ |
1448 | for (; start < (stream->next_uframe + period); start++) { | 1449 | for (; start < (stream->next_uframe + period); start++) { |
1449 | int enough_space; | 1450 | int enough_space; |
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index e35d82808ba..5c774ab9825 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c | |||
@@ -2284,10 +2284,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd) | |||
2284 | dev_info(hcd->self.controller, "ISP1362 Memory usage:\n"); | 2284 | dev_info(hcd->self.controller, "ISP1362 Memory usage:\n"); |
2285 | dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n", | 2285 | dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n", |
2286 | istl_size / 2, istl_size, 0, istl_size / 2); | 2286 | istl_size / 2, istl_size, 0, istl_size / 2); |
2287 | dev_info(hcd->self.controller, " INTL: %4d * (%3u+8): %4d @ $%04x\n", | 2287 | dev_info(hcd->self.controller, " INTL: %4d * (%3lu+8): %4d @ $%04x\n", |
2288 | ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE, | 2288 | ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE, |
2289 | intl_size, istl_size); | 2289 | intl_size, istl_size); |
2290 | dev_info(hcd->self.controller, " ATL : %4d * (%3u+8): %4d @ $%04x\n", | 2290 | dev_info(hcd->self.controller, " ATL : %4d * (%3lu+8): %4d @ $%04x\n", |
2291 | atl_buffers, atl_blksize - PTD_HEADER_SIZE, | 2291 | atl_buffers, atl_blksize - PTD_HEADER_SIZE, |
2292 | atl_size, istl_size + intl_size); | 2292 | atl_size, istl_size + intl_size); |
2293 | dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total, | 2293 | dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total, |
@@ -2677,12 +2677,12 @@ static int __devexit isp1362_remove(struct platform_device *pdev) | |||
2677 | DBG(0, "%s: Removing HCD\n", __func__); | 2677 | DBG(0, "%s: Removing HCD\n", __func__); |
2678 | usb_remove_hcd(hcd); | 2678 | usb_remove_hcd(hcd); |
2679 | 2679 | ||
2680 | DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, | 2680 | DBG(0, "%s: Unmapping data_reg @ %p\n", __func__, |
2681 | (u32)isp1362_hcd->data_reg); | 2681 | isp1362_hcd->data_reg); |
2682 | iounmap(isp1362_hcd->data_reg); | 2682 | iounmap(isp1362_hcd->data_reg); |
2683 | 2683 | ||
2684 | DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, | 2684 | DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, |
2685 | (u32)isp1362_hcd->addr_reg); | 2685 | isp1362_hcd->addr_reg); |
2686 | iounmap(isp1362_hcd->addr_reg); | 2686 | iounmap(isp1362_hcd->addr_reg); |
2687 | 2687 | ||
2688 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 2688 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
@@ -2810,16 +2810,16 @@ static int __init isp1362_probe(struct platform_device *pdev) | |||
2810 | return 0; | 2810 | return 0; |
2811 | 2811 | ||
2812 | err6: | 2812 | err6: |
2813 | DBG(0, "%s: Freeing dev %08x\n", __func__, (u32)isp1362_hcd); | 2813 | DBG(0, "%s: Freeing dev %p\n", __func__, isp1362_hcd); |
2814 | usb_put_hcd(hcd); | 2814 | usb_put_hcd(hcd); |
2815 | err5: | 2815 | err5: |
2816 | DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, (u32)data_reg); | 2816 | DBG(0, "%s: Unmapping data_reg @ %p\n", __func__, data_reg); |
2817 | iounmap(data_reg); | 2817 | iounmap(data_reg); |
2818 | err4: | 2818 | err4: |
2819 | DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start); | 2819 | DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start); |
2820 | release_mem_region(data->start, resource_len(data)); | 2820 | release_mem_region(data->start, resource_len(data)); |
2821 | err3: | 2821 | err3: |
2822 | DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, (u32)addr_reg); | 2822 | DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg); |
2823 | iounmap(addr_reg); | 2823 | iounmap(addr_reg); |
2824 | err2: | 2824 | err2: |
2825 | DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start); | 2825 | DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start); |
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index fe60f62a32f..1a253ebf7e5 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h | |||
@@ -580,7 +580,7 @@ static inline const char *ISP1362_INT_NAME(int n) | |||
580 | 580 | ||
581 | static inline void ALIGNSTAT(struct isp1362_hcd *isp1362_hcd, void *ptr) | 581 | static inline void ALIGNSTAT(struct isp1362_hcd *isp1362_hcd, void *ptr) |
582 | { | 582 | { |
583 | unsigned p = (unsigned)ptr; | 583 | unsigned long p = (unsigned long)ptr; |
584 | if (!(p & 0xf)) | 584 | if (!(p & 0xf)) |
585 | isp1362_hcd->stat16++; | 585 | isp1362_hcd->stat16++; |
586 | else if (!(p & 0x7)) | 586 | else if (!(p & 0x7)) |
@@ -770,7 +770,7 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l | |||
770 | if (!len) | 770 | if (!len) |
771 | return; | 771 | return; |
772 | 772 | ||
773 | if ((unsigned)dp & 0x1) { | 773 | if ((unsigned long)dp & 0x1) { |
774 | /* not aligned */ | 774 | /* not aligned */ |
775 | for (; len > 1; len -= 2) { | 775 | for (; len > 1; len -= 2) { |
776 | data = *dp++; | 776 | data = *dp++; |
@@ -962,8 +962,8 @@ static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 | |||
962 | 962 | ||
963 | isp1362_write_diraddr(isp1362_hcd, offset, len); | 963 | isp1362_write_diraddr(isp1362_hcd, offset, len); |
964 | 964 | ||
965 | DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %08x\n", __func__, | 965 | DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %p\n", |
966 | len, offset, (u32)buf); | 966 | __func__, len, offset, buf); |
967 | 967 | ||
968 | isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); | 968 | isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); |
969 | _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); | 969 | _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); |
@@ -982,8 +982,8 @@ static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 | |||
982 | 982 | ||
983 | isp1362_write_diraddr(isp1362_hcd, offset, len); | 983 | isp1362_write_diraddr(isp1362_hcd, offset, len); |
984 | 984 | ||
985 | DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %08x\n", __func__, | 985 | DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %p\n", |
986 | len, offset, (u32)buf); | 986 | __func__, len, offset, buf); |
987 | 987 | ||
988 | isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); | 988 | isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); |
989 | _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); | 989 | _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index b5294a9344d..f1c06202fdf 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -481,38 +481,47 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) | |||
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
484 | #ifdef CONFIG_PM | 484 | #ifdef CONFIG_PM |
485 | static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state) | 485 | static int ohci_hcd_pxa27x_drv_suspend(struct device *dev) |
486 | { | 486 | { |
487 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 487 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
488 | struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); | 488 | struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); |
489 | 489 | ||
490 | if (time_before(jiffies, ohci->ohci.next_statechange)) | 490 | if (time_before(jiffies, ohci->ohci.next_statechange)) |
491 | msleep(5); | 491 | msleep(5); |
492 | ohci->ohci.next_statechange = jiffies; | 492 | ohci->ohci.next_statechange = jiffies; |
493 | 493 | ||
494 | pxa27x_stop_hc(ohci, &pdev->dev); | 494 | pxa27x_stop_hc(ohci, dev); |
495 | hcd->state = HC_STATE_SUSPENDED; | 495 | hcd->state = HC_STATE_SUSPENDED; |
496 | 496 | ||
497 | return 0; | 497 | return 0; |
498 | } | 498 | } |
499 | 499 | ||
500 | static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev) | 500 | static int ohci_hcd_pxa27x_drv_resume(struct device *dev) |
501 | { | 501 | { |
502 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 502 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
503 | struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); | 503 | struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); |
504 | struct pxaohci_platform_data *inf = dev->platform_data; | ||
504 | int status; | 505 | int status; |
505 | 506 | ||
506 | if (time_before(jiffies, ohci->ohci.next_statechange)) | 507 | if (time_before(jiffies, ohci->ohci.next_statechange)) |
507 | msleep(5); | 508 | msleep(5); |
508 | ohci->ohci.next_statechange = jiffies; | 509 | ohci->ohci.next_statechange = jiffies; |
509 | 510 | ||
510 | if ((status = pxa27x_start_hc(ohci, &pdev->dev)) < 0) | 511 | if ((status = pxa27x_start_hc(ohci, dev)) < 0) |
511 | return status; | 512 | return status; |
512 | 513 | ||
514 | /* Select Power Management Mode */ | ||
515 | pxa27x_ohci_select_pmm(ohci, inf->port_mode); | ||
516 | |||
513 | ohci_finish_controller_resume(hcd); | 517 | ohci_finish_controller_resume(hcd); |
514 | return 0; | 518 | return 0; |
515 | } | 519 | } |
520 | |||
521 | static struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = { | ||
522 | .suspend = ohci_hcd_pxa27x_drv_suspend, | ||
523 | .resume = ohci_hcd_pxa27x_drv_resume, | ||
524 | }; | ||
516 | #endif | 525 | #endif |
517 | 526 | ||
518 | /* work with hotplug and coldplug */ | 527 | /* work with hotplug and coldplug */ |
@@ -522,13 +531,12 @@ static struct platform_driver ohci_hcd_pxa27x_driver = { | |||
522 | .probe = ohci_hcd_pxa27x_drv_probe, | 531 | .probe = ohci_hcd_pxa27x_drv_probe, |
523 | .remove = ohci_hcd_pxa27x_drv_remove, | 532 | .remove = ohci_hcd_pxa27x_drv_remove, |
524 | .shutdown = usb_hcd_platform_shutdown, | 533 | .shutdown = usb_hcd_platform_shutdown, |
525 | #ifdef CONFIG_PM | ||
526 | .suspend = ohci_hcd_pxa27x_drv_suspend, | ||
527 | .resume = ohci_hcd_pxa27x_drv_resume, | ||
528 | #endif | ||
529 | .driver = { | 534 | .driver = { |
530 | .name = "pxa27x-ohci", | 535 | .name = "pxa27x-ohci", |
531 | .owner = THIS_MODULE, | 536 | .owner = THIS_MODULE, |
537 | #ifdef CONFIG_PM | ||
538 | .pm = &ohci_hcd_pxa27x_pm_ops, | ||
539 | #endif | ||
532 | }, | 540 | }, |
533 | }; | 541 | }; |
534 | 542 | ||
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 23cf3bde476..83b5f9cea85 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -475,4 +475,4 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) | |||
475 | else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) | 475 | else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) |
476 | quirk_usb_handoff_xhci(pdev); | 476 | quirk_usb_handoff_xhci(pdev); |
477 | } | 477 | } |
478 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); | 478 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); |
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index c632437c764..562eba10881 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c | |||
@@ -115,6 +115,10 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset) | |||
115 | if (status & QTD_STS_HALTED) { | 115 | if (status & QTD_STS_HALTED) { |
116 | /* Ug, an error. */ | 116 | /* Ug, an error. */ |
117 | process_halted_qtd(whc, qset, td); | 117 | process_halted_qtd(whc, qset, td); |
118 | /* A halted qTD always triggers an update | ||
119 | because the qset was either removed or | ||
120 | reactivated. */ | ||
121 | update |= WHC_UPDATE_UPDATED; | ||
118 | goto done; | 122 | goto done; |
119 | } | 123 | } |
120 | 124 | ||
@@ -305,6 +309,7 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status) | |||
305 | struct whc_urb *wurb = urb->hcpriv; | 309 | struct whc_urb *wurb = urb->hcpriv; |
306 | struct whc_qset *qset = wurb->qset; | 310 | struct whc_qset *qset = wurb->qset; |
307 | struct whc_std *std, *t; | 311 | struct whc_std *std, *t; |
312 | bool has_qtd = false; | ||
308 | int ret; | 313 | int ret; |
309 | unsigned long flags; | 314 | unsigned long flags; |
310 | 315 | ||
@@ -315,17 +320,21 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status) | |||
315 | goto out; | 320 | goto out; |
316 | 321 | ||
317 | list_for_each_entry_safe(std, t, &qset->stds, list_node) { | 322 | list_for_each_entry_safe(std, t, &qset->stds, list_node) { |
318 | if (std->urb == urb) | 323 | if (std->urb == urb) { |
324 | if (std->qtd) | ||
325 | has_qtd = true; | ||
319 | qset_free_std(whc, std); | 326 | qset_free_std(whc, std); |
320 | else | 327 | } else |
321 | std->qtd = NULL; /* so this std is re-added when the qset is */ | 328 | std->qtd = NULL; /* so this std is re-added when the qset is */ |
322 | } | 329 | } |
323 | 330 | ||
324 | asl_qset_remove(whc, qset); | 331 | if (has_qtd) { |
325 | wurb->status = status; | 332 | asl_qset_remove(whc, qset); |
326 | wurb->is_async = true; | 333 | wurb->status = status; |
327 | queue_work(whc->workqueue, &wurb->dequeue_work); | 334 | wurb->is_async = true; |
328 | 335 | queue_work(whc->workqueue, &wurb->dequeue_work); | |
336 | } else | ||
337 | qset_remove_urb(whc, qset, urb, status); | ||
329 | out: | 338 | out: |
330 | spin_unlock_irqrestore(&whc->lock, flags); | 339 | spin_unlock_irqrestore(&whc->lock, flags); |
331 | 340 | ||
diff --git a/drivers/usb/host/whci/debug.c b/drivers/usb/host/whci/debug.c index cf2d45946c5..2273c815941 100644 --- a/drivers/usb/host/whci/debug.c +++ b/drivers/usb/host/whci/debug.c | |||
@@ -134,7 +134,7 @@ static int pzl_open(struct inode *inode, struct file *file) | |||
134 | return single_open(file, pzl_print, inode->i_private); | 134 | return single_open(file, pzl_print, inode->i_private); |
135 | } | 135 | } |
136 | 136 | ||
137 | static struct file_operations di_fops = { | 137 | static const struct file_operations di_fops = { |
138 | .open = di_open, | 138 | .open = di_open, |
139 | .read = seq_read, | 139 | .read = seq_read, |
140 | .llseek = seq_lseek, | 140 | .llseek = seq_lseek, |
@@ -142,7 +142,7 @@ static struct file_operations di_fops = { | |||
142 | .owner = THIS_MODULE, | 142 | .owner = THIS_MODULE, |
143 | }; | 143 | }; |
144 | 144 | ||
145 | static struct file_operations asl_fops = { | 145 | static const struct file_operations asl_fops = { |
146 | .open = asl_open, | 146 | .open = asl_open, |
147 | .read = seq_read, | 147 | .read = seq_read, |
148 | .llseek = seq_lseek, | 148 | .llseek = seq_lseek, |
@@ -150,7 +150,7 @@ static struct file_operations asl_fops = { | |||
150 | .owner = THIS_MODULE, | 150 | .owner = THIS_MODULE, |
151 | }; | 151 | }; |
152 | 152 | ||
153 | static struct file_operations pzl_fops = { | 153 | static const struct file_operations pzl_fops = { |
154 | .open = pzl_open, | 154 | .open = pzl_open, |
155 | .read = seq_read, | 155 | .read = seq_read, |
156 | .llseek = seq_lseek, | 156 | .llseek = seq_lseek, |
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index a9e05bac664..0db3fb2dc03 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c | |||
@@ -121,6 +121,10 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset) | |||
121 | if (status & QTD_STS_HALTED) { | 121 | if (status & QTD_STS_HALTED) { |
122 | /* Ug, an error. */ | 122 | /* Ug, an error. */ |
123 | process_halted_qtd(whc, qset, td); | 123 | process_halted_qtd(whc, qset, td); |
124 | /* A halted qTD always triggers an update | ||
125 | because the qset was either removed or | ||
126 | reactivated. */ | ||
127 | update |= WHC_UPDATE_UPDATED; | ||
124 | goto done; | 128 | goto done; |
125 | } | 129 | } |
126 | 130 | ||
@@ -333,6 +337,7 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status) | |||
333 | struct whc_urb *wurb = urb->hcpriv; | 337 | struct whc_urb *wurb = urb->hcpriv; |
334 | struct whc_qset *qset = wurb->qset; | 338 | struct whc_qset *qset = wurb->qset; |
335 | struct whc_std *std, *t; | 339 | struct whc_std *std, *t; |
340 | bool has_qtd = false; | ||
336 | int ret; | 341 | int ret; |
337 | unsigned long flags; | 342 | unsigned long flags; |
338 | 343 | ||
@@ -343,17 +348,22 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status) | |||
343 | goto out; | 348 | goto out; |
344 | 349 | ||
345 | list_for_each_entry_safe(std, t, &qset->stds, list_node) { | 350 | list_for_each_entry_safe(std, t, &qset->stds, list_node) { |
346 | if (std->urb == urb) | 351 | if (std->urb == urb) { |
352 | if (std->qtd) | ||
353 | has_qtd = true; | ||
347 | qset_free_std(whc, std); | 354 | qset_free_std(whc, std); |
348 | else | 355 | } else |
349 | std->qtd = NULL; /* so this std is re-added when the qset is */ | 356 | std->qtd = NULL; /* so this std is re-added when the qset is */ |
350 | } | 357 | } |
351 | 358 | ||
352 | pzl_qset_remove(whc, qset); | 359 | if (has_qtd) { |
353 | wurb->status = status; | 360 | pzl_qset_remove(whc, qset); |
354 | wurb->is_async = false; | 361 | update_pzl_hw_view(whc); |
355 | queue_work(whc->workqueue, &wurb->dequeue_work); | 362 | wurb->status = status; |
356 | 363 | wurb->is_async = false; | |
364 | queue_work(whc->workqueue, &wurb->dequeue_work); | ||
365 | } else | ||
366 | qset_remove_urb(whc, qset, urb, status); | ||
357 | out: | 367 | out: |
358 | spin_unlock_irqrestore(&whc->lock, flags); | 368 | spin_unlock_irqrestore(&whc->lock, flags); |
359 | 369 | ||
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 99911e727e0..932f9993848 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c | |||
@@ -335,6 +335,12 @@ void xhci_event_ring_work(unsigned long arg) | |||
335 | spin_lock_irqsave(&xhci->lock, flags); | 335 | spin_lock_irqsave(&xhci->lock, flags); |
336 | temp = xhci_readl(xhci, &xhci->op_regs->status); | 336 | temp = xhci_readl(xhci, &xhci->op_regs->status); |
337 | xhci_dbg(xhci, "op reg status = 0x%x\n", temp); | 337 | xhci_dbg(xhci, "op reg status = 0x%x\n", temp); |
338 | if (temp == 0xffffffff) { | ||
339 | xhci_dbg(xhci, "HW died, polling stopped.\n"); | ||
340 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
341 | return; | ||
342 | } | ||
343 | |||
338 | temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); | 344 | temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); |
339 | xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp); | 345 | xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp); |
340 | xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled); | 346 | xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled); |
@@ -776,6 +782,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
776 | { | 782 | { |
777 | unsigned long flags; | 783 | unsigned long flags; |
778 | int ret; | 784 | int ret; |
785 | u32 temp; | ||
779 | struct xhci_hcd *xhci; | 786 | struct xhci_hcd *xhci; |
780 | struct xhci_td *td; | 787 | struct xhci_td *td; |
781 | unsigned int ep_index; | 788 | unsigned int ep_index; |
@@ -788,6 +795,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
788 | ret = usb_hcd_check_unlink_urb(hcd, urb, status); | 795 | ret = usb_hcd_check_unlink_urb(hcd, urb, status); |
789 | if (ret || !urb->hcpriv) | 796 | if (ret || !urb->hcpriv) |
790 | goto done; | 797 | goto done; |
798 | temp = xhci_readl(xhci, &xhci->op_regs->status); | ||
799 | if (temp == 0xffffffff) { | ||
800 | xhci_dbg(xhci, "HW died, freeing TD.\n"); | ||
801 | td = (struct xhci_td *) urb->hcpriv; | ||
802 | |||
803 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
804 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
805 | usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN); | ||
806 | kfree(td); | ||
807 | return ret; | ||
808 | } | ||
791 | 809 | ||
792 | xhci_dbg(xhci, "Cancel URB %p\n", urb); | 810 | xhci_dbg(xhci, "Cancel URB %p\n", urb); |
793 | xhci_dbg(xhci, "Event ring:\n"); | 811 | xhci_dbg(xhci, "Event ring:\n"); |
@@ -877,7 +895,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
877 | ctrl_ctx->drop_flags |= drop_flag; | 895 | ctrl_ctx->drop_flags |= drop_flag; |
878 | new_drop_flags = ctrl_ctx->drop_flags; | 896 | new_drop_flags = ctrl_ctx->drop_flags; |
879 | 897 | ||
880 | ctrl_ctx->add_flags = ~drop_flag; | 898 | ctrl_ctx->add_flags &= ~drop_flag; |
881 | new_add_flags = ctrl_ctx->add_flags; | 899 | new_add_flags = ctrl_ctx->add_flags; |
882 | 900 | ||
883 | last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); | 901 | last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); |
@@ -1410,11 +1428,20 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
1410 | { | 1428 | { |
1411 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1429 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
1412 | unsigned long flags; | 1430 | unsigned long flags; |
1431 | u32 state; | ||
1413 | 1432 | ||
1414 | if (udev->slot_id == 0) | 1433 | if (udev->slot_id == 0) |
1415 | return; | 1434 | return; |
1416 | 1435 | ||
1417 | spin_lock_irqsave(&xhci->lock, flags); | 1436 | spin_lock_irqsave(&xhci->lock, flags); |
1437 | /* Don't disable the slot if the host controller is dead. */ | ||
1438 | state = xhci_readl(xhci, &xhci->op_regs->status); | ||
1439 | if (state == 0xffffffff) { | ||
1440 | xhci_free_virt_device(xhci, udev->slot_id); | ||
1441 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
1442 | return; | ||
1443 | } | ||
1444 | |||
1418 | if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) { | 1445 | if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) { |
1419 | spin_unlock_irqrestore(&xhci->lock, flags); | 1446 | spin_unlock_irqrestore(&xhci->lock, flags); |
1420 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); | 1447 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); |