diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/wusbcore/wa-xfer.c | 366 |
1 files changed, 255 insertions, 111 deletions
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index f1e9a386beca..9325d27453c4 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c | |||
@@ -121,6 +121,9 @@ struct wa_seg { | |||
121 | struct list_head list_node; /* for rpipe->req_list */ | 121 | struct list_head list_node; /* for rpipe->req_list */ |
122 | struct wa_xfer *xfer; /* out xfer */ | 122 | struct wa_xfer *xfer; /* out xfer */ |
123 | u8 index; /* which segment we are */ | 123 | u8 index; /* which segment we are */ |
124 | int isoc_frame_count; /* number of isoc frames in this segment. */ | ||
125 | int isoc_frame_offset; /* starting frame offset in the xfer URB. */ | ||
126 | int isoc_size; /* size of all isoc frames sent by this seg. */ | ||
124 | enum wa_seg_status status; | 127 | enum wa_seg_status status; |
125 | ssize_t result; /* bytes xfered or error */ | 128 | ssize_t result; /* bytes xfered or error */ |
126 | struct wa_xfer_hdr xfer_hdr; | 129 | struct wa_xfer_hdr xfer_hdr; |
@@ -154,12 +157,17 @@ struct wa_xfer { | |||
154 | unsigned is_dma:1; | 157 | unsigned is_dma:1; |
155 | size_t seg_size; | 158 | size_t seg_size; |
156 | int result; | 159 | int result; |
160 | /* Isoc frame that the current transfer buffer corresponds to. */ | ||
161 | int dto_isoc_frame_index; | ||
157 | 162 | ||
158 | gfp_t gfp; /* allocation mask */ | 163 | gfp_t gfp; /* allocation mask */ |
159 | 164 | ||
160 | struct wusb_dev *wusb_dev; /* for activity timestamps */ | 165 | struct wusb_dev *wusb_dev; /* for activity timestamps */ |
161 | }; | 166 | }; |
162 | 167 | ||
168 | static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer, | ||
169 | struct wa_seg *seg, int curr_iso_frame); | ||
170 | |||
163 | static inline void wa_xfer_init(struct wa_xfer *xfer) | 171 | static inline void wa_xfer_init(struct wa_xfer *xfer) |
164 | { | 172 | { |
165 | kref_init(&xfer->refcnt); | 173 | kref_init(&xfer->refcnt); |
@@ -463,6 +471,31 @@ error_kmalloc: | |||
463 | } | 471 | } |
464 | 472 | ||
465 | /* | 473 | /* |
474 | * Calculate the number of isoc frames starting from isoc_frame_offset | ||
475 | * that will fit a in transfer segment. | ||
476 | */ | ||
477 | static int __wa_seg_calculate_isoc_frame_count(struct wa_xfer *xfer, | ||
478 | int isoc_frame_offset, int *total_size) | ||
479 | { | ||
480 | int segment_size = 0, frame_count = 0; | ||
481 | int index = isoc_frame_offset; | ||
482 | |||
483 | while ((index < xfer->urb->number_of_packets) | ||
484 | && ((segment_size + xfer->urb->iso_frame_desc[index].length) | ||
485 | <= xfer->seg_size)) { | ||
486 | /* this frame fits. count it. */ | ||
487 | ++frame_count; | ||
488 | segment_size += xfer->urb->iso_frame_desc[index].length; | ||
489 | |||
490 | /* move to the next isoc frame. */ | ||
491 | ++index; | ||
492 | } | ||
493 | |||
494 | *total_size = segment_size; | ||
495 | return frame_count; | ||
496 | } | ||
497 | |||
498 | /* | ||
466 | * | 499 | * |
467 | * @returns < 0 on error, transfer segment request size if ok | 500 | * @returns < 0 on error, transfer segment request size if ok |
468 | */ | 501 | */ |
@@ -505,8 +538,20 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, | |||
505 | 538 | ||
506 | maxpktsize = le16_to_cpu(rpipe->descr.wMaxPacketSize); | 539 | maxpktsize = le16_to_cpu(rpipe->descr.wMaxPacketSize); |
507 | if ((rpipe->descr.bmAttribute & 0x3) == USB_ENDPOINT_XFER_ISOC) { | 540 | if ((rpipe->descr.bmAttribute & 0x3) == USB_ENDPOINT_XFER_ISOC) { |
541 | int index = 0; | ||
542 | |||
508 | xfer->seg_size = maxpktsize; | 543 | xfer->seg_size = maxpktsize; |
509 | xfer->segs = urb->number_of_packets; | 544 | xfer->segs = 0; |
545 | /* | ||
546 | * loop over urb->number_of_packets to determine how many | ||
547 | * xfer segments will be needed to send the isoc frames. | ||
548 | */ | ||
549 | while (index < urb->number_of_packets) { | ||
550 | int seg_size; /* don't care. */ | ||
551 | index += __wa_seg_calculate_isoc_frame_count(xfer, | ||
552 | index, &seg_size); | ||
553 | ++xfer->segs; | ||
554 | } | ||
510 | } else { | 555 | } else { |
511 | xfer->seg_size = le16_to_cpu(rpipe->descr.wBlocks) | 556 | xfer->seg_size = le16_to_cpu(rpipe->descr.wBlocks) |
512 | * 1 << (xfer->wa->wa_descr->bRPipeBlockSize - 1); | 557 | * 1 << (xfer->wa->wa_descr->bRPipeBlockSize - 1); |
@@ -523,20 +568,43 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, | |||
523 | xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize; | 568 | xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize; |
524 | xfer->segs = DIV_ROUND_UP(urb->transfer_buffer_length, | 569 | xfer->segs = DIV_ROUND_UP(urb->transfer_buffer_length, |
525 | xfer->seg_size); | 570 | xfer->seg_size); |
526 | if (xfer->segs >= WA_SEGS_MAX) { | ||
527 | dev_err(dev, "BUG? oops, number of segments %zu bigger than %d\n", | ||
528 | (urb->transfer_buffer_length/xfer->seg_size), | ||
529 | WA_SEGS_MAX); | ||
530 | result = -EINVAL; | ||
531 | goto error; | ||
532 | } | ||
533 | if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL) | 571 | if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL) |
534 | xfer->segs = 1; | 572 | xfer->segs = 1; |
535 | } | 573 | } |
574 | |||
575 | if (xfer->segs >= WA_SEGS_MAX) { | ||
576 | dev_err(dev, "BUG? oops, number of segments %zu bigger than %d\n", | ||
577 | (urb->transfer_buffer_length/xfer->seg_size), | ||
578 | WA_SEGS_MAX); | ||
579 | result = -EINVAL; | ||
580 | goto error; | ||
581 | } | ||
536 | error: | 582 | error: |
537 | return result; | 583 | return result; |
538 | } | 584 | } |
539 | 585 | ||
586 | static void __wa_setup_isoc_packet_descr( | ||
587 | struct wa_xfer_packet_info_hwaiso *packet_desc, | ||
588 | struct wa_xfer *xfer, | ||
589 | struct wa_seg *seg) { | ||
590 | struct usb_iso_packet_descriptor *iso_frame_desc = | ||
591 | xfer->urb->iso_frame_desc; | ||
592 | int frame_index; | ||
593 | |||
594 | /* populate isoc packet descriptor. */ | ||
595 | packet_desc->bPacketType = WA_XFER_ISO_PACKET_INFO; | ||
596 | packet_desc->wLength = cpu_to_le16(sizeof(*packet_desc) + | ||
597 | (sizeof(packet_desc->PacketLength[0]) * | ||
598 | seg->isoc_frame_count)); | ||
599 | for (frame_index = 0; frame_index < seg->isoc_frame_count; | ||
600 | ++frame_index) { | ||
601 | int offset_index = frame_index + seg->isoc_frame_offset; | ||
602 | packet_desc->PacketLength[frame_index] = | ||
603 | cpu_to_le16(iso_frame_desc[offset_index].length); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | |||
540 | /* Fill in the common request header and xfer-type specific data. */ | 608 | /* Fill in the common request header and xfer-type specific data. */ |
541 | static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, | 609 | static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, |
542 | struct wa_xfer_hdr *xfer_hdr0, | 610 | struct wa_xfer_hdr *xfer_hdr0, |
@@ -544,8 +612,9 @@ static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, | |||
544 | size_t xfer_hdr_size) | 612 | size_t xfer_hdr_size) |
545 | { | 613 | { |
546 | struct wa_rpipe *rpipe = xfer->ep->hcpriv; | 614 | struct wa_rpipe *rpipe = xfer->ep->hcpriv; |
615 | struct wa_seg *seg = xfer->seg[0]; | ||
547 | 616 | ||
548 | xfer_hdr0 = &xfer->seg[0]->xfer_hdr; | 617 | xfer_hdr0 = &seg->xfer_hdr; |
549 | xfer_hdr0->bLength = xfer_hdr_size; | 618 | xfer_hdr0->bLength = xfer_hdr_size; |
550 | xfer_hdr0->bRequestType = xfer_type; | 619 | xfer_hdr0->bRequestType = xfer_type; |
551 | xfer_hdr0->wRPipe = rpipe->descr.wRPipeIndex; | 620 | xfer_hdr0->wRPipe = rpipe->descr.wRPipeIndex; |
@@ -567,19 +636,11 @@ static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer, | |||
567 | container_of(xfer_hdr0, struct wa_xfer_hwaiso, hdr); | 636 | container_of(xfer_hdr0, struct wa_xfer_hwaiso, hdr); |
568 | struct wa_xfer_packet_info_hwaiso *packet_desc = | 637 | struct wa_xfer_packet_info_hwaiso *packet_desc = |
569 | ((void *)xfer_iso) + xfer_hdr_size; | 638 | ((void *)xfer_iso) + xfer_hdr_size; |
570 | struct usb_iso_packet_descriptor *iso_frame_desc = | 639 | |
571 | &(xfer->urb->iso_frame_desc[0]); | ||
572 | /* populate the isoc section of the transfer request. */ | 640 | /* populate the isoc section of the transfer request. */ |
573 | xfer_iso->dwNumOfPackets = cpu_to_le32(1); | 641 | xfer_iso->dwNumOfPackets = cpu_to_le32(seg->isoc_frame_count); |
574 | /* | 642 | /* populate isoc packet descriptor. */ |
575 | * populate isoc packet descriptor. This assumes 1 | 643 | __wa_setup_isoc_packet_descr(packet_desc, xfer, seg); |
576 | * packet per segment. | ||
577 | */ | ||
578 | packet_desc->wLength = cpu_to_le16(sizeof(*packet_desc) + | ||
579 | sizeof(packet_desc->PacketLength[0])); | ||
580 | packet_desc->bPacketType = WA_XFER_ISO_PACKET_INFO; | ||
581 | packet_desc->PacketLength[0] = | ||
582 | cpu_to_le16(iso_frame_desc->length); | ||
583 | break; | 644 | break; |
584 | } | 645 | } |
585 | default: | 646 | default: |
@@ -608,54 +669,112 @@ static void wa_seg_dto_cb(struct urb *urb) | |||
608 | struct wa_rpipe *rpipe; | 669 | struct wa_rpipe *rpipe; |
609 | unsigned long flags; | 670 | unsigned long flags; |
610 | unsigned rpipe_ready = 0; | 671 | unsigned rpipe_ready = 0; |
672 | int data_send_done = 1, release_dto = 0, holding_dto = 0; | ||
611 | u8 done = 0; | 673 | u8 done = 0; |
674 | int result; | ||
612 | 675 | ||
613 | /* free the sg if it was used. */ | 676 | /* free the sg if it was used. */ |
614 | kfree(urb->sg); | 677 | kfree(urb->sg); |
615 | urb->sg = NULL; | 678 | urb->sg = NULL; |
616 | 679 | ||
680 | spin_lock_irqsave(&xfer->lock, flags); | ||
681 | wa = xfer->wa; | ||
682 | dev = &wa->usb_iface->dev; | ||
683 | if (usb_pipeisoc(xfer->urb->pipe)) { | ||
684 | xfer->dto_isoc_frame_index += 1; | ||
685 | if (xfer->dto_isoc_frame_index < seg->isoc_frame_count) { | ||
686 | data_send_done = 0; | ||
687 | holding_dto = 1; /* checked in error cases. */ | ||
688 | /* | ||
689 | * if this is the last isoc frame of the segment, we | ||
690 | * can release DTO after sending this frame. | ||
691 | */ | ||
692 | if ((xfer->dto_isoc_frame_index + 1) >= | ||
693 | seg->isoc_frame_count) | ||
694 | release_dto = 1; | ||
695 | } | ||
696 | dev_dbg(dev, "xfer 0x%08X#%u: isoc frame = %d, holding_dto = %d, release_dto = %d.\n", | ||
697 | wa_xfer_id(xfer), seg->index, | ||
698 | xfer->dto_isoc_frame_index, holding_dto, release_dto); | ||
699 | } | ||
700 | spin_unlock_irqrestore(&xfer->lock, flags); | ||
701 | |||
617 | switch (urb->status) { | 702 | switch (urb->status) { |
618 | case 0: | 703 | case 0: |
619 | spin_lock_irqsave(&xfer->lock, flags); | 704 | spin_lock_irqsave(&xfer->lock, flags); |
620 | wa = xfer->wa; | 705 | seg->result += urb->actual_length; |
621 | dev = &wa->usb_iface->dev; | 706 | if (data_send_done) { |
622 | dev_dbg(dev, "xfer %p#%u: data out done (%d bytes)\n", | 707 | dev_dbg(dev, "xfer 0x%08X#%u: data out done (%zu bytes)\n", |
623 | xfer, seg->index, urb->actual_length); | 708 | wa_xfer_id(xfer), seg->index, seg->result); |
624 | if (seg->status < WA_SEG_PENDING) | 709 | if (seg->status < WA_SEG_PENDING) |
625 | seg->status = WA_SEG_PENDING; | 710 | seg->status = WA_SEG_PENDING; |
626 | seg->result = urb->actual_length; | 711 | } else { |
712 | /* should only hit this for isoc xfers. */ | ||
713 | /* | ||
714 | * Populate the dto URB with the next isoc frame buffer, | ||
715 | * send the URB and release DTO if we no longer need it. | ||
716 | */ | ||
717 | __wa_populate_dto_urb_isoc(xfer, seg, | ||
718 | seg->isoc_frame_offset + | ||
719 | xfer->dto_isoc_frame_index); | ||
720 | |||
721 | /* resubmit the URB with the next isoc frame. */ | ||
722 | result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC); | ||
723 | if (result < 0) { | ||
724 | dev_err(dev, "xfer 0x%08X#%u: DTO submit failed: %d\n", | ||
725 | wa_xfer_id(xfer), seg->index, result); | ||
726 | spin_unlock_irqrestore(&xfer->lock, flags); | ||
727 | goto error_dto_submit; | ||
728 | } | ||
729 | } | ||
627 | spin_unlock_irqrestore(&xfer->lock, flags); | 730 | spin_unlock_irqrestore(&xfer->lock, flags); |
731 | if (release_dto) { | ||
732 | __wa_dto_put(wa); | ||
733 | wa_check_for_delayed_rpipes(wa); | ||
734 | } | ||
628 | break; | 735 | break; |
629 | case -ECONNRESET: /* URB unlinked; no need to do anything */ | 736 | case -ECONNRESET: /* URB unlinked; no need to do anything */ |
630 | case -ENOENT: /* as it was done by the who unlinked us */ | 737 | case -ENOENT: /* as it was done by the who unlinked us */ |
738 | if (holding_dto) { | ||
739 | __wa_dto_put(wa); | ||
740 | wa_check_for_delayed_rpipes(wa); | ||
741 | } | ||
631 | break; | 742 | break; |
632 | default: /* Other errors ... */ | 743 | default: /* Other errors ... */ |
633 | spin_lock_irqsave(&xfer->lock, flags); | 744 | dev_err(dev, "xfer 0x%08X#%u: data out error %d\n", |
634 | wa = xfer->wa; | 745 | wa_xfer_id(xfer), seg->index, urb->status); |
635 | dev = &wa->usb_iface->dev; | 746 | goto error_default; |
636 | rpipe = xfer->ep->hcpriv; | 747 | } |
637 | dev_dbg(dev, "xfer %p#%u: data out error %d\n", | 748 | |
638 | xfer, seg->index, urb->status); | 749 | return; |
639 | if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, | 750 | |
640 | EDC_ERROR_TIMEFRAME)){ | 751 | error_dto_submit: |
641 | dev_err(dev, "DTO: URB max acceptable errors " | 752 | error_default: |
642 | "exceeded, resetting device\n"); | 753 | spin_lock_irqsave(&xfer->lock, flags); |
643 | wa_reset_all(wa); | 754 | rpipe = xfer->ep->hcpriv; |
644 | } | 755 | if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, |
645 | if (seg->status != WA_SEG_ERROR) { | 756 | EDC_ERROR_TIMEFRAME)){ |
646 | seg->status = WA_SEG_ERROR; | 757 | dev_err(dev, "DTO: URB max acceptable errors exceeded, resetting device\n"); |
647 | seg->result = urb->status; | 758 | wa_reset_all(wa); |
648 | xfer->segs_done++; | 759 | } |
649 | __wa_xfer_abort(xfer); | 760 | if (seg->status != WA_SEG_ERROR) { |
650 | rpipe_ready = rpipe_avail_inc(rpipe); | 761 | seg->status = WA_SEG_ERROR; |
651 | done = __wa_xfer_is_done(xfer); | 762 | seg->result = urb->status; |
652 | } | 763 | xfer->segs_done++; |
653 | spin_unlock_irqrestore(&xfer->lock, flags); | 764 | __wa_xfer_abort(xfer); |
654 | if (done) | 765 | rpipe_ready = rpipe_avail_inc(rpipe); |
655 | wa_xfer_completion(xfer); | 766 | done = __wa_xfer_is_done(xfer); |
656 | if (rpipe_ready) | ||
657 | wa_xfer_delayed_run(rpipe); | ||
658 | } | 767 | } |
768 | spin_unlock_irqrestore(&xfer->lock, flags); | ||
769 | if (holding_dto) { | ||
770 | __wa_dto_put(wa); | ||
771 | wa_check_for_delayed_rpipes(wa); | ||
772 | } | ||
773 | if (done) | ||
774 | wa_xfer_completion(xfer); | ||
775 | if (rpipe_ready) | ||
776 | wa_xfer_delayed_run(rpipe); | ||
777 | |||
659 | } | 778 | } |
660 | 779 | ||
661 | /* | 780 | /* |
@@ -686,8 +805,8 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb) | |||
686 | spin_lock_irqsave(&xfer->lock, flags); | 805 | spin_lock_irqsave(&xfer->lock, flags); |
687 | wa = xfer->wa; | 806 | wa = xfer->wa; |
688 | dev = &wa->usb_iface->dev; | 807 | dev = &wa->usb_iface->dev; |
689 | dev_dbg(dev, "iso xfer %p#%u: packet descriptor done\n", | 808 | dev_dbg(dev, "iso xfer %08X#%u: packet descriptor done\n", |
690 | xfer, seg->index); | 809 | wa_xfer_id(xfer), seg->index); |
691 | if (xfer->is_inbound && seg->status < WA_SEG_PENDING) | 810 | if (xfer->is_inbound && seg->status < WA_SEG_PENDING) |
692 | seg->status = WA_SEG_PENDING; | 811 | seg->status = WA_SEG_PENDING; |
693 | spin_unlock_irqrestore(&xfer->lock, flags); | 812 | spin_unlock_irqrestore(&xfer->lock, flags); |
@@ -700,8 +819,8 @@ static void wa_seg_iso_pack_desc_cb(struct urb *urb) | |||
700 | wa = xfer->wa; | 819 | wa = xfer->wa; |
701 | dev = &wa->usb_iface->dev; | 820 | dev = &wa->usb_iface->dev; |
702 | rpipe = xfer->ep->hcpriv; | 821 | rpipe = xfer->ep->hcpriv; |
703 | pr_err_ratelimited("iso xfer %p#%u: packet descriptor error %d\n", | 822 | pr_err_ratelimited("iso xfer %08X#%u: packet descriptor error %d\n", |
704 | xfer, seg->index, urb->status); | 823 | wa_xfer_id(xfer), seg->index, urb->status); |
705 | if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, | 824 | if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS, |
706 | EDC_ERROR_TIMEFRAME)){ | 825 | EDC_ERROR_TIMEFRAME)){ |
707 | dev_err(dev, "DTO: URB max acceptable errors exceeded, resetting device\n"); | 826 | dev_err(dev, "DTO: URB max acceptable errors exceeded, resetting device\n"); |
@@ -885,8 +1004,8 @@ static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg, | |||
885 | /* | 1004 | /* |
886 | * Populate DMA buffer info for the isoc dto urb. | 1005 | * Populate DMA buffer info for the isoc dto urb. |
887 | */ | 1006 | */ |
888 | static void __wa_populate_dto_urb_iso(struct wa_xfer *xfer, | 1007 | static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer, |
889 | struct wa_seg *seg, int curr_iso_frame) | 1008 | struct wa_seg *seg, int curr_iso_frame) |
890 | { | 1009 | { |
891 | /* | 1010 | /* |
892 | * dto urb buffer address and size pulled from | 1011 | * dto urb buffer address and size pulled from |
@@ -960,13 +1079,14 @@ static int __wa_populate_dto_urb(struct wa_xfer *xfer, | |||
960 | */ | 1079 | */ |
961 | static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) | 1080 | static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) |
962 | { | 1081 | { |
963 | int result, cnt; | 1082 | int result, cnt, iso_frame_offset; |
964 | size_t alloc_size = sizeof(*xfer->seg[0]) | 1083 | size_t alloc_size = sizeof(*xfer->seg[0]) |
965 | - sizeof(xfer->seg[0]->xfer_hdr) + xfer_hdr_size; | 1084 | - sizeof(xfer->seg[0]->xfer_hdr) + xfer_hdr_size; |
966 | struct usb_device *usb_dev = xfer->wa->usb_dev; | 1085 | struct usb_device *usb_dev = xfer->wa->usb_dev; |
967 | const struct usb_endpoint_descriptor *dto_epd = xfer->wa->dto_epd; | 1086 | const struct usb_endpoint_descriptor *dto_epd = xfer->wa->dto_epd; |
968 | struct wa_seg *seg; | 1087 | struct wa_seg *seg; |
969 | size_t buf_itr, buf_size, buf_itr_size, iso_pkt_descr_size = 0; | 1088 | size_t buf_itr, buf_size, buf_itr_size; |
1089 | int xfer_isoc_frame_offset = 0; | ||
970 | 1090 | ||
971 | result = -ENOMEM; | 1091 | result = -ENOMEM; |
972 | xfer->seg = kcalloc(xfer->segs, sizeof(xfer->seg[0]), GFP_ATOMIC); | 1092 | xfer->seg = kcalloc(xfer->segs, sizeof(xfer->seg[0]), GFP_ATOMIC); |
@@ -974,24 +1094,30 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) | |||
974 | goto error_segs_kzalloc; | 1094 | goto error_segs_kzalloc; |
975 | buf_itr = 0; | 1095 | buf_itr = 0; |
976 | buf_size = xfer->urb->transfer_buffer_length; | 1096 | buf_size = xfer->urb->transfer_buffer_length; |
1097 | iso_frame_offset = 0; | ||
1098 | for (cnt = 0; cnt < xfer->segs; cnt++) { | ||
1099 | size_t iso_pkt_descr_size = 0; | ||
1100 | int seg_isoc_frame_count = 0, seg_isoc_size = 0; | ||
977 | 1101 | ||
978 | if (usb_pipeisoc(xfer->urb->pipe)) { | 1102 | if (usb_pipeisoc(xfer->urb->pipe)) { |
979 | /* | 1103 | seg_isoc_frame_count = |
980 | * This calculation assumes one isoc packet per xfer segment. | 1104 | __wa_seg_calculate_isoc_frame_count(xfer, |
981 | * It will need to be updated if this changes. | 1105 | xfer_isoc_frame_offset, &seg_isoc_size); |
982 | */ | ||
983 | iso_pkt_descr_size = sizeof(struct wa_xfer_packet_info_hwaiso) + | ||
984 | sizeof(__le16); | ||
985 | alloc_size += iso_pkt_descr_size; | ||
986 | } | ||
987 | 1106 | ||
988 | for (cnt = 0; cnt < xfer->segs; cnt++) { | 1107 | iso_pkt_descr_size = |
989 | seg = xfer->seg[cnt] = kmalloc(alloc_size, GFP_ATOMIC); | 1108 | sizeof(struct wa_xfer_packet_info_hwaiso) + |
1109 | (seg_isoc_frame_count * sizeof(__le16)); | ||
1110 | } | ||
1111 | seg = xfer->seg[cnt] = kmalloc(alloc_size + iso_pkt_descr_size, | ||
1112 | GFP_ATOMIC); | ||
990 | if (seg == NULL) | 1113 | if (seg == NULL) |
991 | goto error_seg_kmalloc; | 1114 | goto error_seg_kmalloc; |
992 | wa_seg_init(seg); | 1115 | wa_seg_init(seg); |
993 | seg->xfer = xfer; | 1116 | seg->xfer = xfer; |
994 | seg->index = cnt; | 1117 | seg->index = cnt; |
1118 | seg->isoc_frame_count = seg_isoc_frame_count; | ||
1119 | seg->isoc_frame_offset = xfer_isoc_frame_offset; | ||
1120 | seg->isoc_size = seg_isoc_size; | ||
995 | usb_fill_bulk_urb(&seg->tr_urb, usb_dev, | 1121 | usb_fill_bulk_urb(&seg->tr_urb, usb_dev, |
996 | usb_sndbulkpipe(usb_dev, | 1122 | usb_sndbulkpipe(usb_dev, |
997 | dto_epd->bEndpointAddress), | 1123 | dto_epd->bEndpointAddress), |
@@ -1029,8 +1155,16 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) | |||
1029 | iso_pkt_descr_size, | 1155 | iso_pkt_descr_size, |
1030 | wa_seg_iso_pack_desc_cb, seg); | 1156 | wa_seg_iso_pack_desc_cb, seg); |
1031 | 1157 | ||
1032 | /* fill in the xfer buffer information. */ | 1158 | /* |
1033 | __wa_populate_dto_urb_iso(xfer, seg, cnt); | 1159 | * Fill in the xfer buffer information for the |
1160 | * first isoc frame. Subsequent frames in this | ||
1161 | * segment will be filled in and sent from the | ||
1162 | * DTO completion routine, if needed. | ||
1163 | */ | ||
1164 | __wa_populate_dto_urb_isoc(xfer, seg, | ||
1165 | xfer_isoc_frame_offset); | ||
1166 | /* adjust starting frame offset for next seg. */ | ||
1167 | xfer_isoc_frame_offset += seg_isoc_frame_count; | ||
1034 | } else { | 1168 | } else { |
1035 | /* fill in the xfer buffer information. */ | 1169 | /* fill in the xfer buffer information. */ |
1036 | result = __wa_populate_dto_urb(xfer, seg, | 1170 | result = __wa_populate_dto_urb(xfer, seg, |
@@ -1099,28 +1233,23 @@ static int __wa_xfer_setup(struct wa_xfer *xfer, struct urb *urb) | |||
1099 | xfer_hdr = xfer_hdr0; | 1233 | xfer_hdr = xfer_hdr0; |
1100 | if (xfer_type == WA_XFER_TYPE_ISO) { | 1234 | if (xfer_type == WA_XFER_TYPE_ISO) { |
1101 | xfer_hdr0->dwTransferLength = | 1235 | xfer_hdr0->dwTransferLength = |
1102 | cpu_to_le32(xfer->urb->iso_frame_desc[0].length); | 1236 | cpu_to_le32(xfer->seg[0]->isoc_size); |
1103 | for (cnt = 1; cnt < xfer->segs; cnt++) { | 1237 | for (cnt = 1; cnt < xfer->segs; cnt++) { |
1104 | struct usb_iso_packet_descriptor *iso_frame_desc = | ||
1105 | &(xfer->urb->iso_frame_desc[cnt]); | ||
1106 | struct wa_xfer_packet_info_hwaiso *packet_desc; | 1238 | struct wa_xfer_packet_info_hwaiso *packet_desc; |
1239 | struct wa_seg *seg = xfer->seg[cnt]; | ||
1107 | 1240 | ||
1108 | xfer_hdr = &xfer->seg[cnt]->xfer_hdr; | 1241 | xfer_hdr = &seg->xfer_hdr; |
1109 | packet_desc = ((void *)xfer_hdr) + xfer_hdr_size; | 1242 | packet_desc = ((void *)xfer_hdr) + xfer_hdr_size; |
1110 | /* | 1243 | /* |
1111 | * Copy values from the 0th header and isoc packet | 1244 | * Copy values from the 0th header. Segment specific |
1112 | * descriptor. Segment specific values are set below. | 1245 | * values are set below. |
1113 | */ | 1246 | */ |
1114 | memcpy(xfer_hdr, xfer_hdr0, | 1247 | memcpy(xfer_hdr, xfer_hdr0, xfer_hdr_size); |
1115 | xfer_hdr_size + sizeof(*packet_desc)); | ||
1116 | xfer_hdr->bTransferSegment = cnt; | 1248 | xfer_hdr->bTransferSegment = cnt; |
1117 | xfer_hdr->dwTransferLength = | 1249 | xfer_hdr->dwTransferLength = |
1118 | cpu_to_le32(iso_frame_desc->length); | 1250 | cpu_to_le32(seg->isoc_size); |
1119 | /* populate isoc packet descriptor length. */ | 1251 | __wa_setup_isoc_packet_descr(packet_desc, xfer, seg); |
1120 | packet_desc->PacketLength[0] = | 1252 | seg->status = WA_SEG_READY; |
1121 | cpu_to_le16(iso_frame_desc->length); | ||
1122 | |||
1123 | xfer->seg[cnt]->status = WA_SEG_READY; | ||
1124 | } | 1253 | } |
1125 | } else { | 1254 | } else { |
1126 | transfer_size = urb->transfer_buffer_length; | 1255 | transfer_size = urb->transfer_buffer_length; |
@@ -1175,6 +1304,13 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer, | |||
1175 | __func__, xfer, seg->index, result); | 1304 | __func__, xfer, seg->index, result); |
1176 | goto error_iso_pack_desc_submit; | 1305 | goto error_iso_pack_desc_submit; |
1177 | } | 1306 | } |
1307 | xfer->dto_isoc_frame_index = 0; | ||
1308 | /* | ||
1309 | * If this segment contains more than one isoc frame, hold | ||
1310 | * onto the dto resource until we send all frames. | ||
1311 | */ | ||
1312 | if (seg->isoc_frame_count > 1) | ||
1313 | *dto_done = 0; | ||
1178 | } | 1314 | } |
1179 | /* submit the out data if this is an out request. */ | 1315 | /* submit the out data if this is an out request. */ |
1180 | if (seg->dto_urb) { | 1316 | if (seg->dto_urb) { |
@@ -1196,6 +1332,7 @@ error_iso_pack_desc_submit: | |||
1196 | error_seg_submit: | 1332 | error_seg_submit: |
1197 | seg->status = WA_SEG_ERROR; | 1333 | seg->status = WA_SEG_ERROR; |
1198 | seg->result = result; | 1334 | seg->result = result; |
1335 | *dto_done = 1; | ||
1199 | return result; | 1336 | return result; |
1200 | } | 1337 | } |
1201 | 1338 | ||
@@ -1306,9 +1443,6 @@ static int __wa_xfer_submit(struct wa_xfer *xfer) | |||
1306 | available = atomic_read(&rpipe->segs_available); | 1443 | available = atomic_read(&rpipe->segs_available); |
1307 | empty = list_empty(&rpipe->seg_list); | 1444 | empty = list_empty(&rpipe->seg_list); |
1308 | seg = xfer->seg[cnt]; | 1445 | seg = xfer->seg[cnt]; |
1309 | dev_dbg(dev, "xfer %p ID 0x%08X#%u: available %u empty %u (%s)\n", | ||
1310 | xfer, wa_xfer_id(xfer), cnt, available, empty, | ||
1311 | available == 0 || !empty ? "delayed" : "submitted"); | ||
1312 | if (available && empty) { | 1446 | if (available && empty) { |
1313 | /* | 1447 | /* |
1314 | * Only attempt to acquire DTO if we have a segment | 1448 | * Only attempt to acquire DTO if we have a segment |
@@ -1319,6 +1453,9 @@ static int __wa_xfer_submit(struct wa_xfer *xfer) | |||
1319 | delay_seg = 0; | 1453 | delay_seg = 0; |
1320 | result = __wa_seg_submit(rpipe, xfer, seg, | 1454 | result = __wa_seg_submit(rpipe, xfer, seg, |
1321 | &dto_done); | 1455 | &dto_done); |
1456 | dev_dbg(dev, "xfer %p ID 0x%08X#%u: available %u empty %u submitted\n", | ||
1457 | xfer, wa_xfer_id(xfer), cnt, available, | ||
1458 | empty); | ||
1322 | if (dto_done) | 1459 | if (dto_done) |
1323 | __wa_dto_put(rpipe->wa); | 1460 | __wa_dto_put(rpipe->wa); |
1324 | 1461 | ||
@@ -1330,6 +1467,8 @@ static int __wa_xfer_submit(struct wa_xfer *xfer) | |||
1330 | } | 1467 | } |
1331 | 1468 | ||
1332 | if (delay_seg) { | 1469 | if (delay_seg) { |
1470 | dev_dbg(dev, "xfer %p ID 0x%08X#%u: available %u empty %u delayed\n", | ||
1471 | xfer, wa_xfer_id(xfer), cnt, available, empty); | ||
1333 | seg->status = WA_SEG_DELAYED; | 1472 | seg->status = WA_SEG_DELAYED; |
1334 | list_add_tail(&seg->list_node, &rpipe->seg_list); | 1473 | list_add_tail(&seg->list_node, &rpipe->seg_list); |
1335 | } | 1474 | } |
@@ -2031,29 +2170,19 @@ static void wa_process_iso_packet_status(struct wahc *wa, struct urb *urb) | |||
2031 | { | 2170 | { |
2032 | struct device *dev = &wa->usb_iface->dev; | 2171 | struct device *dev = &wa->usb_iface->dev; |
2033 | struct wa_xfer_packet_status_hwaiso *packet_status; | 2172 | struct wa_xfer_packet_status_hwaiso *packet_status; |
2173 | struct wa_xfer_packet_status_len_hwaiso *status_array; | ||
2034 | struct wa_xfer *xfer; | 2174 | struct wa_xfer *xfer; |
2035 | unsigned long flags; | 2175 | unsigned long flags; |
2036 | struct wa_seg *seg; | 2176 | struct wa_seg *seg; |
2037 | struct wa_rpipe *rpipe; | 2177 | struct wa_rpipe *rpipe; |
2038 | unsigned done = 0; | 2178 | unsigned done = 0; |
2039 | unsigned rpipe_ready = 0; | 2179 | unsigned rpipe_ready = 0, seg_index; |
2040 | const int expected_size = sizeof(*packet_status) + | 2180 | int expected_size; |
2041 | sizeof(packet_status->PacketStatus[0]); | ||
2042 | 2181 | ||
2043 | /* We have a xfer result buffer; check it */ | 2182 | /* We have a xfer result buffer; check it */ |
2044 | dev_dbg(dev, "DTI: isoc packet status %d bytes at %p\n", | 2183 | dev_dbg(dev, "DTI: isoc packet status %d bytes at %p\n", |
2045 | urb->actual_length, urb->transfer_buffer); | 2184 | urb->actual_length, urb->transfer_buffer); |
2046 | if (urb->actual_length != expected_size) { | ||
2047 | dev_err(dev, "DTI Error: isoc packet status--bad urb length (%d bytes vs %d needed)\n", | ||
2048 | urb->actual_length, expected_size); | ||
2049 | goto error_parse_buffer; | ||
2050 | } | ||
2051 | packet_status = (struct wa_xfer_packet_status_hwaiso *)(wa->dti_buf); | 2185 | packet_status = (struct wa_xfer_packet_status_hwaiso *)(wa->dti_buf); |
2052 | if (le16_to_cpu(packet_status->wLength) != expected_size) { | ||
2053 | dev_err(dev, "DTI Error: isoc packet status--bad length %u\n", | ||
2054 | le16_to_cpu(packet_status->wLength)); | ||
2055 | goto error_parse_buffer; | ||
2056 | } | ||
2057 | if (packet_status->bPacketType != WA_XFER_ISO_PACKET_STATUS) { | 2186 | if (packet_status->bPacketType != WA_XFER_ISO_PACKET_STATUS) { |
2058 | dev_err(dev, "DTI Error: isoc packet status--bad type 0x%02x\n", | 2187 | dev_err(dev, "DTI Error: isoc packet status--bad type 0x%02x\n", |
2059 | packet_status->bPacketType); | 2188 | packet_status->bPacketType); |
@@ -2070,13 +2199,28 @@ static void wa_process_iso_packet_status(struct wahc *wa, struct urb *urb) | |||
2070 | goto error_bad_seg; | 2199 | goto error_bad_seg; |
2071 | seg = xfer->seg[wa->dti_isoc_xfer_seg]; | 2200 | seg = xfer->seg[wa->dti_isoc_xfer_seg]; |
2072 | rpipe = xfer->ep->hcpriv; | 2201 | rpipe = xfer->ep->hcpriv; |
2073 | 2202 | expected_size = sizeof(*packet_status) + | |
2074 | /* set urb isoc packet status and length. */ | 2203 | (sizeof(packet_status->PacketStatus[0]) * |
2075 | xfer->urb->iso_frame_desc[seg->index].status = | 2204 | seg->isoc_frame_count); |
2076 | wa_xfer_status_to_errno( | 2205 | if (urb->actual_length != expected_size) { |
2077 | le16_to_cpu(packet_status->PacketStatus[0].PacketStatus)); | 2206 | dev_err(dev, "DTI Error: isoc packet status--bad urb length (%d bytes vs %d needed)\n", |
2078 | xfer->urb->iso_frame_desc[seg->index].actual_length = | 2207 | urb->actual_length, expected_size); |
2079 | le16_to_cpu(packet_status->PacketStatus[0].PacketLength); | 2208 | goto error_bad_seg; |
2209 | } | ||
2210 | if (le16_to_cpu(packet_status->wLength) != expected_size) { | ||
2211 | dev_err(dev, "DTI Error: isoc packet status--bad length %u\n", | ||
2212 | le16_to_cpu(packet_status->wLength)); | ||
2213 | goto error_bad_seg; | ||
2214 | } | ||
2215 | /* isoc packet status and lengths back xfer urb. */ | ||
2216 | status_array = packet_status->PacketStatus; | ||
2217 | for (seg_index = 0; seg_index < seg->isoc_frame_count; ++seg_index) { | ||
2218 | xfer->urb->iso_frame_desc[seg->index].status = | ||
2219 | wa_xfer_status_to_errno( | ||
2220 | le16_to_cpu(status_array[seg_index].PacketStatus)); | ||
2221 | xfer->urb->iso_frame_desc[seg->index].actual_length = | ||
2222 | le16_to_cpu(status_array[seg_index].PacketLength); | ||
2223 | } | ||
2080 | 2224 | ||
2081 | if (!xfer->is_inbound) { | 2225 | if (!xfer->is_inbound) { |
2082 | /* OUT transfer, complete it -- */ | 2226 | /* OUT transfer, complete it -- */ |