diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 23 | ||||
-rw-r--r-- | drivers/usb/host/whci/asl.c | 23 | ||||
-rw-r--r-- | drivers/usb/host/whci/pzl.c | 24 |
4 files changed, 52 insertions, 30 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 3efa59b18044..b25cdea93a1f 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,8 +1421,8 @@ 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)) { |
@@ -1441,10 +1445,6 @@ iso_stream_schedule ( | |||
1441 | 1445 | ||
1442 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | 1446 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ |
1443 | 1447 | ||
1444 | period = urb->interval; | ||
1445 | if (!stream->highspeed) | ||
1446 | period <<= 3; | ||
1447 | |||
1448 | /* find a uframe slot with enough bandwidth */ | 1448 | /* find a uframe slot with enough bandwidth */ |
1449 | for (; start < (stream->next_uframe + period); start++) { | 1449 | for (; start < (stream->next_uframe + period); start++) { |
1450 | int enough_space; | 1450 | int enough_space; |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 749b53742828..e33d36256350 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -1003,19 +1003,20 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | |||
1003 | if (syssts == SE0) { | 1003 | if (syssts == SE0) { |
1004 | r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); | 1004 | r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); |
1005 | r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port)); | 1005 | r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port)); |
1006 | return; | 1006 | } else { |
1007 | } | 1007 | if (syssts == FS_JSTS) |
1008 | r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); | ||
1009 | else if (syssts == LS_JSTS) | ||
1010 | r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); | ||
1008 | 1011 | ||
1009 | if (syssts == FS_JSTS) | 1012 | r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); |
1010 | r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); | 1013 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); |
1011 | else if (syssts == LS_JSTS) | ||
1012 | r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); | ||
1013 | 1014 | ||
1014 | r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); | 1015 | if (r8a66597->bus_suspended) |
1015 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); | 1016 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); |
1017 | } | ||
1016 | 1018 | ||
1017 | if (r8a66597->bus_suspended) | 1019 | usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); |
1018 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | ||
1019 | } | 1020 | } |
1020 | 1021 | ||
1021 | /* this function must be called with interrupt disabled */ | 1022 | /* this function must be called with interrupt disabled */ |
@@ -1024,6 +1025,8 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port) | |||
1024 | u16 speed = get_rh_usb_speed(r8a66597, port); | 1025 | u16 speed = get_rh_usb_speed(r8a66597, port); |
1025 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | 1026 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; |
1026 | 1027 | ||
1028 | rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) | | ||
1029 | (1 << USB_PORT_FEAT_LOWSPEED)); | ||
1027 | if (speed == HSMODE) | 1030 | if (speed == HSMODE) |
1028 | rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED); | 1031 | rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED); |
1029 | else if (speed == LSMODE) | 1032 | else if (speed == LSMODE) |
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index c632437c7649..562eba108816 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/pzl.c b/drivers/usb/host/whci/pzl.c index a9e05bac6646..0db3fb2dc03a 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 | ||