aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp116x-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/isp116x-hcd.c')
-rw-r--r--drivers/usb/host/isp116x-hcd.c187
1 files changed, 86 insertions, 101 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 46873f2534b5..5c851a36de72 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -228,7 +228,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
228 struct urb, urb_list); 228 struct urb, urb_list);
229 ptd = &ep->ptd; 229 ptd = &ep->ptd;
230 len = ep->length; 230 len = ep->length;
231 spin_lock(&urb->lock);
232 ep->data = (unsigned char *)urb->transfer_buffer 231 ep->data = (unsigned char *)urb->transfer_buffer
233 + urb->actual_length; 232 + urb->actual_length;
234 233
@@ -264,7 +263,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
264 | PTD_EP(ep->epnum); 263 | PTD_EP(ep->epnum);
265 ptd->len = PTD_LEN(len) | PTD_DIR(dir); 264 ptd->len = PTD_LEN(len) | PTD_DIR(dir);
266 ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); 265 ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe));
267 spin_unlock(&urb->lock);
268 if (!ep->active) { 266 if (!ep->active) {
269 ptd->mps |= PTD_LAST_MSK; 267 ptd->mps |= PTD_LAST_MSK;
270 isp116x->atl_last_dir = dir; 268 isp116x->atl_last_dir = dir;
@@ -275,6 +273,61 @@ static void preproc_atl_queue(struct isp116x *isp116x)
275} 273}
276 274
277/* 275/*
276 Take done or failed requests out of schedule. Give back
277 processed urbs.
278*/
279static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
280 struct urb *urb)
281__releases(isp116x->lock) __acquires(isp116x->lock)
282{
283 unsigned i;
284
285 urb->hcpriv = NULL;
286 ep->error_count = 0;
287
288 if (usb_pipecontrol(urb->pipe))
289 ep->nextpid = USB_PID_SETUP;
290
291 urb_dbg(urb, "Finish");
292
293 spin_unlock(&isp116x->lock);
294 usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
295 spin_lock(&isp116x->lock);
296
297 /* take idle endpoints out of the schedule */
298 if (!list_empty(&ep->hep->urb_list))
299 return;
300
301 /* async deschedule */
302 if (!list_empty(&ep->schedule)) {
303 list_del_init(&ep->schedule);
304 return;
305 }
306
307 /* periodic deschedule */
308 DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
309 for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
310 struct isp116x_ep *temp;
311 struct isp116x_ep **prev = &isp116x->periodic[i];
312
313 while (*prev && ((temp = *prev) != ep))
314 prev = &temp->next;
315 if (*prev)
316 *prev = ep->next;
317 isp116x->load[i] -= ep->load;
318 }
319 ep->branch = PERIODIC_SIZE;
320 isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
321 ep->load / ep->period;
322
323 /* switch irq type? */
324 if (!--isp116x->periodic_count) {
325 isp116x->irqenb &= ~HCuPINT_SOF;
326 isp116x->irqenb |= HCuPINT_ATL;
327 }
328}
329
330/*
278 Analyze transfer results, handle partial transfers and errors 331 Analyze transfer results, handle partial transfers and errors
279*/ 332*/
280static void postproc_atl_queue(struct isp116x *isp116x) 333static void postproc_atl_queue(struct isp116x *isp116x)
@@ -284,6 +337,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
284 struct usb_device *udev; 337 struct usb_device *udev;
285 struct ptd *ptd; 338 struct ptd *ptd;
286 int short_not_ok; 339 int short_not_ok;
340 int status;
287 u8 cc; 341 u8 cc;
288 342
289 for (ep = isp116x->atl_active; ep; ep = ep->active) { 343 for (ep = isp116x->atl_active; ep; ep = ep->active) {
@@ -294,7 +348,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
294 ptd = &ep->ptd; 348 ptd = &ep->ptd;
295 cc = PTD_GET_CC(ptd); 349 cc = PTD_GET_CC(ptd);
296 short_not_ok = 1; 350 short_not_ok = 1;
297 spin_lock(&urb->lock); 351 status = -EINPROGRESS;
298 352
299 /* Data underrun is special. For allowed underrun 353 /* Data underrun is special. For allowed underrun
300 we clear the error and continue as normal. For 354 we clear the error and continue as normal. For
@@ -302,47 +356,36 @@ static void postproc_atl_queue(struct isp116x *isp116x)
302 immediately while for control transfer, 356 immediately while for control transfer,
303 we do a STATUS stage. */ 357 we do a STATUS stage. */
304 if (cc == TD_DATAUNDERRUN) { 358 if (cc == TD_DATAUNDERRUN) {
305 if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) { 359 if (!(urb->transfer_flags & URB_SHORT_NOT_OK) ||
306 DBG("Allowed data underrun\n"); 360 usb_pipecontrol(urb->pipe)) {
361 DBG("Allowed or control data underrun\n");
307 cc = TD_CC_NOERROR; 362 cc = TD_CC_NOERROR;
308 short_not_ok = 0; 363 short_not_ok = 0;
309 } else { 364 } else {
310 ep->error_count = 1; 365 ep->error_count = 1;
311 if (usb_pipecontrol(urb->pipe)) 366 usb_settoggle(udev, ep->epnum,
312 ep->nextpid = USB_PID_ACK; 367 ep->nextpid == USB_PID_OUT,
313 else 368 PTD_GET_TOGGLE(ptd));
314 usb_settoggle(udev, ep->epnum,
315 ep->nextpid ==
316 USB_PID_OUT,
317 PTD_GET_TOGGLE(ptd));
318 urb->actual_length += PTD_GET_COUNT(ptd); 369 urb->actual_length += PTD_GET_COUNT(ptd);
319 urb->status = cc_to_error[TD_DATAUNDERRUN]; 370 status = cc_to_error[TD_DATAUNDERRUN];
320 spin_unlock(&urb->lock); 371 goto done;
321 continue;
322 } 372 }
323 } 373 }
324 /* Keep underrun error through the STATUS stage */
325 if (urb->status == cc_to_error[TD_DATAUNDERRUN])
326 cc = TD_DATAUNDERRUN;
327 374
328 if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED 375 if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED
329 && (++ep->error_count >= 3 || cc == TD_CC_STALL 376 && (++ep->error_count >= 3 || cc == TD_CC_STALL
330 || cc == TD_DATAOVERRUN)) { 377 || cc == TD_DATAOVERRUN)) {
331 if (urb->status == -EINPROGRESS) 378 status = cc_to_error[cc];
332 urb->status = cc_to_error[cc];
333 if (ep->nextpid == USB_PID_ACK) 379 if (ep->nextpid == USB_PID_ACK)
334 ep->nextpid = 0; 380 ep->nextpid = 0;
335 spin_unlock(&urb->lock); 381 goto done;
336 continue;
337 } 382 }
338 /* According to usb spec, zero-length Int transfer signals 383 /* According to usb spec, zero-length Int transfer signals
339 finishing of the urb. Hey, does this apply only 384 finishing of the urb. Hey, does this apply only
340 for IN endpoints? */ 385 for IN endpoints? */
341 if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) { 386 if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) {
342 if (urb->status == -EINPROGRESS) 387 status = 0;
343 urb->status = 0; 388 goto done;
344 spin_unlock(&urb->lock);
345 continue;
346 } 389 }
347 390
348 /* Relax after previously failed, but later succeeded 391 /* Relax after previously failed, but later succeeded
@@ -381,8 +424,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
381 /* All data for this URB is transferred, let's finish */ 424 /* All data for this URB is transferred, let's finish */
382 if (usb_pipecontrol(urb->pipe)) 425 if (usb_pipecontrol(urb->pipe))
383 ep->nextpid = USB_PID_ACK; 426 ep->nextpid = USB_PID_ACK;
384 else if (urb->status == -EINPROGRESS) 427 else
385 urb->status = 0; 428 status = 0;
386 break; 429 break;
387 case USB_PID_SETUP: 430 case USB_PID_SETUP:
388 if (PTD_GET_ACTIVE(ptd) 431 if (PTD_GET_ACTIVE(ptd)
@@ -402,69 +445,27 @@ static void postproc_atl_queue(struct isp116x *isp116x)
402 if (PTD_GET_ACTIVE(ptd) 445 if (PTD_GET_ACTIVE(ptd)
403 || (cc != TD_CC_NOERROR && cc < 0x0E)) 446 || (cc != TD_CC_NOERROR && cc < 0x0E))
404 break; 447 break;
405 if (urb->status == -EINPROGRESS) 448 if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
406 urb->status = 0; 449 urb->actual_length <
450 urb->transfer_buffer_length)
451 status = -EREMOTEIO;
452 else
453 status = 0;
407 ep->nextpid = 0; 454 ep->nextpid = 0;
408 break; 455 break;
409 default: 456 default:
410 BUG(); 457 BUG();
411 } 458 }
412 spin_unlock(&urb->lock);
413 }
414}
415
416/*
417 Take done or failed requests out of schedule. Give back
418 processed urbs.
419*/
420static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
421 struct urb *urb)
422__releases(isp116x->lock) __acquires(isp116x->lock)
423{
424 unsigned i;
425
426 urb->hcpriv = NULL;
427 ep->error_count = 0;
428
429 if (usb_pipecontrol(urb->pipe))
430 ep->nextpid = USB_PID_SETUP;
431
432 urb_dbg(urb, "Finish");
433
434 spin_unlock(&isp116x->lock);
435 usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb);
436 spin_lock(&isp116x->lock);
437
438 /* take idle endpoints out of the schedule */
439 if (!list_empty(&ep->hep->urb_list))
440 return;
441
442 /* async deschedule */
443 if (!list_empty(&ep->schedule)) {
444 list_del_init(&ep->schedule);
445 return;
446 }
447 459
448 /* periodic deschedule */ 460 done:
449 DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); 461 if (status != -EINPROGRESS) {
450 for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { 462 spin_lock(&urb->lock);
451 struct isp116x_ep *temp; 463 if (urb->status == -EINPROGRESS)
452 struct isp116x_ep **prev = &isp116x->periodic[i]; 464 urb->status = status;
453 465 spin_unlock(&urb->lock);
454 while (*prev && ((temp = *prev) != ep)) 466 }
455 prev = &temp->next; 467 if (urb->status != -EINPROGRESS)
456 if (*prev) 468 finish_request(isp116x, ep, urb);
457 *prev = ep->next;
458 isp116x->load[i] -= ep->load;
459 }
460 ep->branch = PERIODIC_SIZE;
461 isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
462 ep->load / ep->period;
463
464 /* switch irq type? */
465 if (!--isp116x->periodic_count) {
466 isp116x->irqenb &= ~HCuPINT_SOF;
467 isp116x->irqenb |= HCuPINT_ATL;
468 } 469 }
469} 470}
470 471
@@ -570,9 +571,6 @@ static void start_atl_transfers(struct isp116x *isp116x)
570*/ 571*/
571static void finish_atl_transfers(struct isp116x *isp116x) 572static void finish_atl_transfers(struct isp116x *isp116x)
572{ 573{
573 struct isp116x_ep *ep;
574 struct urb *urb;
575
576 if (!isp116x->atl_active) 574 if (!isp116x->atl_active)
577 return; 575 return;
578 /* Fifo not ready? */ 576 /* Fifo not ready? */
@@ -582,16 +580,6 @@ static void finish_atl_transfers(struct isp116x *isp116x)
582 atomic_inc(&isp116x->atl_finishing); 580 atomic_inc(&isp116x->atl_finishing);
583 unpack_fifo(isp116x); 581 unpack_fifo(isp116x);
584 postproc_atl_queue(isp116x); 582 postproc_atl_queue(isp116x);
585 for (ep = isp116x->atl_active; ep; ep = ep->active) {
586 urb =
587 container_of(ep->hep->urb_list.next, struct urb, urb_list);
588 /* USB_PID_ACK check here avoids finishing of
589 control transfers, for which TD_DATAUNDERRUN
590 occured, while URB_SHORT_NOT_OK was set */
591 if (urb && urb->status != -EINPROGRESS
592 && ep->nextpid != USB_PID_ACK)
593 finish_request(isp116x, ep, urb);
594 }
595 atomic_dec(&isp116x->atl_finishing); 583 atomic_dec(&isp116x->atl_finishing);
596} 584}
597 585
@@ -821,15 +809,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
821 } 809 }
822 810
823 /* in case of unlink-during-submit */ 811 /* in case of unlink-during-submit */
824 spin_lock(&urb->lock);
825 if (urb->status != -EINPROGRESS) { 812 if (urb->status != -EINPROGRESS) {
826 spin_unlock(&urb->lock);
827 finish_request(isp116x, ep, urb); 813 finish_request(isp116x, ep, urb);
828 ret = 0; 814 ret = 0;
829 goto fail; 815 goto fail;
830 } 816 }
831 urb->hcpriv = hep; 817 urb->hcpriv = hep;
832 spin_unlock(&urb->lock);
833 start_atl_transfers(isp116x); 818 start_atl_transfers(isp116x);
834 819
835 fail: 820 fail: