aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Pugliese <thomas.pugliese@gmail.com>2014-03-07 16:37:35 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-03-09 01:30:28 -0500
commit335053fe8c94f50c7f1cd7011b3088547480df3c (patch)
treed4d2cbad17637a4b8bdf9a70bdf19a4745529488
parent04a378f36d9dc9e242ff206fcad23ba258dba818 (diff)
usb: wusbcore: use multiple urbs for HWA iso transfer result frame reads
Submit multiple concurrent urbs for HWA isochronous transfer result data frame reads. This keeps the read pipeline full and significantly improves performance in cases where the frame reads cannot be combined because they are not contiguous or multiples of the max packet size. Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/wusbcore/wa-hc.c2
-rw-r--r--drivers/usb/wusbcore/wa-hc.h15
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c191
3 files changed, 134 insertions, 74 deletions
diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index 368360f9a93a..252c7bd9218a 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -75,8 +75,6 @@ void __wa_destroy(struct wahc *wa)
75 if (wa->dti_urb) { 75 if (wa->dti_urb) {
76 usb_kill_urb(wa->dti_urb); 76 usb_kill_urb(wa->dti_urb);
77 usb_put_urb(wa->dti_urb); 77 usb_put_urb(wa->dti_urb);
78 usb_kill_urb(wa->buf_in_urb);
79 usb_put_urb(wa->buf_in_urb);
80 } 78 }
81 kfree(wa->dti_buf); 79 kfree(wa->dti_buf);
82 wa_nep_destroy(wa); 80 wa_nep_destroy(wa);
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index 7510960588dc..f2a8d29e17b9 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -125,7 +125,8 @@ struct wa_rpipe {
125 125
126enum wa_dti_state { 126enum wa_dti_state {
127 WA_DTI_TRANSFER_RESULT_PENDING, 127 WA_DTI_TRANSFER_RESULT_PENDING,
128 WA_DTI_ISOC_PACKET_STATUS_PENDING 128 WA_DTI_ISOC_PACKET_STATUS_PENDING,
129 WA_DTI_BUF_IN_DATA_PENDING
129}; 130};
130 131
131enum wa_quirks { 132enum wa_quirks {
@@ -146,6 +147,8 @@ enum wa_vendor_specific_requests {
146 WA_REQ_ALEREON_FEATURE_SET = 0x01, 147 WA_REQ_ALEREON_FEATURE_SET = 0x01,
147 WA_REQ_ALEREON_FEATURE_CLEAR = 0x00, 148 WA_REQ_ALEREON_FEATURE_CLEAR = 0x00,
148}; 149};
150
151#define WA_MAX_BUF_IN_URBS 4
149/** 152/**
150 * Instance of a HWA Host Controller 153 * Instance of a HWA Host Controller
151 * 154 *
@@ -216,7 +219,9 @@ struct wahc {
216 u32 dti_isoc_xfer_in_progress; 219 u32 dti_isoc_xfer_in_progress;
217 u8 dti_isoc_xfer_seg; 220 u8 dti_isoc_xfer_seg;
218 struct urb *dti_urb; /* URB for reading xfer results */ 221 struct urb *dti_urb; /* URB for reading xfer results */
219 struct urb *buf_in_urb; /* URB for reading data in */ 222 /* URBs for reading data in */
223 struct urb buf_in_urbs[WA_MAX_BUF_IN_URBS];
224 int active_buf_in_urbs; /* number of buf_in_urbs active. */
220 struct edc dti_edc; /* DTI error density counter */ 225 struct edc dti_edc; /* DTI error density counter */
221 void *dti_buf; 226 void *dti_buf;
222 size_t dti_buf_size; 227 size_t dti_buf_size;
@@ -286,6 +291,8 @@ static inline void wa_rpipe_init(struct wahc *wa)
286 291
287static inline void wa_init(struct wahc *wa) 292static inline void wa_init(struct wahc *wa)
288{ 293{
294 int index;
295
289 edc_init(&wa->nep_edc); 296 edc_init(&wa->nep_edc);
290 atomic_set(&wa->notifs_queued, 0); 297 atomic_set(&wa->notifs_queued, 0);
291 wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING; 298 wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
@@ -299,6 +306,10 @@ static inline void wa_init(struct wahc *wa)
299 INIT_WORK(&wa->xfer_error_work, wa_process_errored_transfers_run); 306 INIT_WORK(&wa->xfer_error_work, wa_process_errored_transfers_run);
300 wa->dto_in_use = 0; 307 wa->dto_in_use = 0;
301 atomic_set(&wa->xfer_id_count, 1); 308 atomic_set(&wa->xfer_id_count, 1);
309 /* init the buf in URBs */
310 for (index = 0; index < WA_MAX_BUF_IN_URBS; ++index)
311 usb_init_urb(&(wa->buf_in_urbs[index]));
312 wa->active_buf_in_urbs = 0;
302} 313}
303 314
304/** 315/**
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index f930bbb1a0ff..c8e2a47d62a7 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -2159,9 +2159,9 @@ static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
2159 } 2159 }
2160} 2160}
2161 2161
2162/* Populate the wa->buf_in_urb based on the current isoc transfer state. */ 2162/* Populate the given urb based on the current isoc transfer state. */
2163static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer, 2163static int __wa_populate_buf_in_urb_isoc(struct wahc *wa,
2164 struct wa_seg *seg) 2164 struct urb *buf_in_urb, struct wa_xfer *xfer, struct wa_seg *seg)
2165{ 2165{
2166 int urb_start_frame = seg->isoc_frame_index + seg->isoc_frame_offset; 2166 int urb_start_frame = seg->isoc_frame_index + seg->isoc_frame_offset;
2167 int seg_index, total_len = 0, urb_frame_index = urb_start_frame; 2167 int seg_index, total_len = 0, urb_frame_index = urb_start_frame;
@@ -2171,7 +2171,7 @@ static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer,
2171 int next_frame_contiguous; 2171 int next_frame_contiguous;
2172 struct usb_iso_packet_descriptor *iso_frame; 2172 struct usb_iso_packet_descriptor *iso_frame;
2173 2173
2174 BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); 2174 BUG_ON(buf_in_urb->status == -EINPROGRESS);
2175 2175
2176 /* 2176 /*
2177 * If the current frame actual_length is contiguous with the next frame 2177 * If the current frame actual_length is contiguous with the next frame
@@ -2201,68 +2201,68 @@ static int __wa_populate_buf_in_urb_isoc(struct wahc *wa, struct wa_xfer *xfer,
2201 && ((iso_frame->actual_length % dti_packet_size) == 0)); 2201 && ((iso_frame->actual_length % dti_packet_size) == 0));
2202 2202
2203 /* this should always be 0 before a resubmit. */ 2203 /* this should always be 0 before a resubmit. */
2204 wa->buf_in_urb->num_mapped_sgs = 0; 2204 buf_in_urb->num_mapped_sgs = 0;
2205 wa->buf_in_urb->transfer_dma = xfer->urb->transfer_dma + 2205 buf_in_urb->transfer_dma = xfer->urb->transfer_dma +
2206 iso_frame_desc[urb_start_frame].offset; 2206 iso_frame_desc[urb_start_frame].offset;
2207 wa->buf_in_urb->transfer_buffer_length = total_len; 2207 buf_in_urb->transfer_buffer_length = total_len;
2208 wa->buf_in_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 2208 buf_in_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
2209 wa->buf_in_urb->transfer_buffer = NULL; 2209 buf_in_urb->transfer_buffer = NULL;
2210 wa->buf_in_urb->sg = NULL; 2210 buf_in_urb->sg = NULL;
2211 wa->buf_in_urb->num_sgs = 0; 2211 buf_in_urb->num_sgs = 0;
2212 wa->buf_in_urb->context = seg; 2212 buf_in_urb->context = seg;
2213 2213
2214 /* return the number of frames included in this URB. */ 2214 /* return the number of frames included in this URB. */
2215 return seg_index - seg->isoc_frame_index; 2215 return seg_index - seg->isoc_frame_index;
2216} 2216}
2217 2217
2218/* Populate the wa->buf_in_urb based on the current transfer state. */ 2218/* Populate the given urb based on the current transfer state. */
2219static int wa_populate_buf_in_urb(struct wahc *wa, struct wa_xfer *xfer, 2219static int wa_populate_buf_in_urb(struct urb *buf_in_urb, struct wa_xfer *xfer,
2220 unsigned int seg_idx, unsigned int bytes_transferred) 2220 unsigned int seg_idx, unsigned int bytes_transferred)
2221{ 2221{
2222 int result = 0; 2222 int result = 0;
2223 struct wa_seg *seg = xfer->seg[seg_idx]; 2223 struct wa_seg *seg = xfer->seg[seg_idx];
2224 2224
2225 BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); 2225 BUG_ON(buf_in_urb->status == -EINPROGRESS);
2226 /* this should always be 0 before a resubmit. */ 2226 /* this should always be 0 before a resubmit. */
2227 wa->buf_in_urb->num_mapped_sgs = 0; 2227 buf_in_urb->num_mapped_sgs = 0;
2228 2228
2229 if (xfer->is_dma) { 2229 if (xfer->is_dma) {
2230 wa->buf_in_urb->transfer_dma = xfer->urb->transfer_dma 2230 buf_in_urb->transfer_dma = xfer->urb->transfer_dma
2231 + (seg_idx * xfer->seg_size); 2231 + (seg_idx * xfer->seg_size);
2232 wa->buf_in_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 2232 buf_in_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
2233 wa->buf_in_urb->transfer_buffer = NULL; 2233 buf_in_urb->transfer_buffer = NULL;
2234 wa->buf_in_urb->sg = NULL; 2234 buf_in_urb->sg = NULL;
2235 wa->buf_in_urb->num_sgs = 0; 2235 buf_in_urb->num_sgs = 0;
2236 } else { 2236 } else {
2237 /* do buffer or SG processing. */ 2237 /* do buffer or SG processing. */
2238 wa->buf_in_urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP; 2238 buf_in_urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP;
2239 2239
2240 if (xfer->urb->transfer_buffer) { 2240 if (xfer->urb->transfer_buffer) {
2241 wa->buf_in_urb->transfer_buffer = 2241 buf_in_urb->transfer_buffer =
2242 xfer->urb->transfer_buffer 2242 xfer->urb->transfer_buffer
2243 + (seg_idx * xfer->seg_size); 2243 + (seg_idx * xfer->seg_size);
2244 wa->buf_in_urb->sg = NULL; 2244 buf_in_urb->sg = NULL;
2245 wa->buf_in_urb->num_sgs = 0; 2245 buf_in_urb->num_sgs = 0;
2246 } else { 2246 } else {
2247 /* allocate an SG list to store seg_size bytes 2247 /* allocate an SG list to store seg_size bytes
2248 and copy the subset of the xfer->urb->sg 2248 and copy the subset of the xfer->urb->sg
2249 that matches the buffer subset we are 2249 that matches the buffer subset we are
2250 about to read. */ 2250 about to read. */
2251 wa->buf_in_urb->sg = wa_xfer_create_subset_sg( 2251 buf_in_urb->sg = wa_xfer_create_subset_sg(
2252 xfer->urb->sg, 2252 xfer->urb->sg,
2253 seg_idx * xfer->seg_size, 2253 seg_idx * xfer->seg_size,
2254 bytes_transferred, 2254 bytes_transferred,
2255 &(wa->buf_in_urb->num_sgs)); 2255 &(buf_in_urb->num_sgs));
2256 2256
2257 if (!(wa->buf_in_urb->sg)) { 2257 if (!(buf_in_urb->sg)) {
2258 wa->buf_in_urb->num_sgs = 0; 2258 buf_in_urb->num_sgs = 0;
2259 result = -ENOMEM; 2259 result = -ENOMEM;
2260 } 2260 }
2261 wa->buf_in_urb->transfer_buffer = NULL; 2261 buf_in_urb->transfer_buffer = NULL;
2262 } 2262 }
2263 } 2263 }
2264 wa->buf_in_urb->transfer_buffer_length = bytes_transferred; 2264 buf_in_urb->transfer_buffer_length = bytes_transferred;
2265 wa->buf_in_urb->context = seg; 2265 buf_in_urb->context = seg;
2266 2266
2267 return result; 2267 return result;
2268} 2268}
@@ -2287,6 +2287,7 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
2287 u8 usb_status; 2287 u8 usb_status;
2288 unsigned rpipe_ready = 0; 2288 unsigned rpipe_ready = 0;
2289 unsigned bytes_transferred = le32_to_cpu(xfer_result->dwTransferLength); 2289 unsigned bytes_transferred = le32_to_cpu(xfer_result->dwTransferLength);
2290 struct urb *buf_in_urb = &(wa->buf_in_urbs[0]);
2290 2291
2291 spin_lock_irqsave(&xfer->lock, flags); 2292 spin_lock_irqsave(&xfer->lock, flags);
2292 seg_idx = xfer_result->bTransferSegment & 0x7f; 2293 seg_idx = xfer_result->bTransferSegment & 0x7f;
@@ -2337,13 +2338,16 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
2337 && (bytes_transferred > 0)) { 2338 && (bytes_transferred > 0)) {
2338 /* IN data phase: read to buffer */ 2339 /* IN data phase: read to buffer */
2339 seg->status = WA_SEG_DTI_PENDING; 2340 seg->status = WA_SEG_DTI_PENDING;
2340 result = wa_populate_buf_in_urb(wa, xfer, seg_idx, 2341 result = wa_populate_buf_in_urb(buf_in_urb, xfer, seg_idx,
2341 bytes_transferred); 2342 bytes_transferred);
2342 if (result < 0) 2343 if (result < 0)
2343 goto error_buf_in_populate; 2344 goto error_buf_in_populate;
2344 result = usb_submit_urb(wa->buf_in_urb, GFP_ATOMIC); 2345 ++(wa->active_buf_in_urbs);
2345 if (result < 0) 2346 result = usb_submit_urb(buf_in_urb, GFP_ATOMIC);
2347 if (result < 0) {
2348 --(wa->active_buf_in_urbs);
2346 goto error_submit_buf_in; 2349 goto error_submit_buf_in;
2350 }
2347 } else { 2351 } else {
2348 /* OUT data phase or no data, complete it -- */ 2352 /* OUT data phase or no data, complete it -- */
2349 seg->result = bytes_transferred; 2353 seg->result = bytes_transferred;
@@ -2367,8 +2371,8 @@ error_submit_buf_in:
2367 dev_err(dev, "xfer %p#%u: can't submit DTI data phase: %d\n", 2371 dev_err(dev, "xfer %p#%u: can't submit DTI data phase: %d\n",
2368 xfer, seg_idx, result); 2372 xfer, seg_idx, result);
2369 seg->result = result; 2373 seg->result = result;
2370 kfree(wa->buf_in_urb->sg); 2374 kfree(buf_in_urb->sg);
2371 wa->buf_in_urb->sg = NULL; 2375 buf_in_urb->sg = NULL;
2372error_buf_in_populate: 2376error_buf_in_populate:
2373 __wa_xfer_abort(xfer); 2377 __wa_xfer_abort(xfer);
2374 seg->status = WA_SEG_ERROR; 2378 seg->status = WA_SEG_ERROR;
@@ -2477,16 +2481,16 @@ static int wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
2477 for (seg_index = 0; seg_index < seg->isoc_frame_count; ++seg_index) { 2481 for (seg_index = 0; seg_index < seg->isoc_frame_count; ++seg_index) {
2478 struct usb_iso_packet_descriptor *iso_frame_desc = 2482 struct usb_iso_packet_descriptor *iso_frame_desc =
2479 xfer->urb->iso_frame_desc; 2483 xfer->urb->iso_frame_desc;
2480 const int urb_frame_index = 2484 const int xfer_frame_index =
2481 seg->isoc_frame_offset + seg_index; 2485 seg->isoc_frame_offset + seg_index;
2482 2486
2483 iso_frame_desc[urb_frame_index].status = 2487 iso_frame_desc[xfer_frame_index].status =
2484 wa_xfer_status_to_errno( 2488 wa_xfer_status_to_errno(
2485 le16_to_cpu(status_array[seg_index].PacketStatus)); 2489 le16_to_cpu(status_array[seg_index].PacketStatus));
2486 iso_frame_desc[urb_frame_index].actual_length = 2490 iso_frame_desc[xfer_frame_index].actual_length =
2487 le16_to_cpu(status_array[seg_index].PacketLength); 2491 le16_to_cpu(status_array[seg_index].PacketLength);
2488 /* track the number of frames successfully transferred. */ 2492 /* track the number of frames successfully transferred. */
2489 if (iso_frame_desc[urb_frame_index].actual_length > 0) { 2493 if (iso_frame_desc[xfer_frame_index].actual_length > 0) {
2490 /* save the starting frame index for buf_in_urb. */ 2494 /* save the starting frame index for buf_in_urb. */
2491 if (!data_frame_count) 2495 if (!data_frame_count)
2492 first_frame_index = seg_index; 2496 first_frame_index = seg_index;
@@ -2495,21 +2499,53 @@ static int wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
2495 } 2499 }
2496 2500
2497 if (xfer->is_inbound && data_frame_count) { 2501 if (xfer->is_inbound && data_frame_count) {
2498 int result, urb_frame_count; 2502 int result, total_frames_read = 0, urb_index = 0;
2503 struct urb *buf_in_urb;
2499 2504
2505 /* IN data phase: read to buffer */
2506 seg->status = WA_SEG_DTI_PENDING;
2507
2508 /* start with the first frame with data. */
2500 seg->isoc_frame_index = first_frame_index; 2509 seg->isoc_frame_index = first_frame_index;
2501 /* submit a read URB for the first frame with data. */ 2510 /* submit up to WA_MAX_BUF_IN_URBS read URBs. */
2502 urb_frame_count = __wa_populate_buf_in_urb_isoc(wa, xfer, seg); 2511 do {
2503 /* advance index to start of next read URB. */ 2512 int urb_frame_index, urb_frame_count;
2504 seg->isoc_frame_index += urb_frame_count; 2513 struct usb_iso_packet_descriptor *iso_frame_desc;
2514
2515 buf_in_urb = &(wa->buf_in_urbs[urb_index]);
2516 urb_frame_count = __wa_populate_buf_in_urb_isoc(wa,
2517 buf_in_urb, xfer, seg);
2518 /* advance frame index to start of next read URB. */
2519 seg->isoc_frame_index += urb_frame_count;
2520 total_frames_read += urb_frame_count;
2521
2522 ++(wa->active_buf_in_urbs);
2523 result = usb_submit_urb(buf_in_urb, GFP_ATOMIC);
2524
2525 /* skip 0-byte frames. */
2526 urb_frame_index =
2527 seg->isoc_frame_offset + seg->isoc_frame_index;
2528 iso_frame_desc =
2529 &(xfer->urb->iso_frame_desc[urb_frame_index]);
2530 while ((seg->isoc_frame_index <
2531 seg->isoc_frame_count) &&
2532 (iso_frame_desc->actual_length == 0)) {
2533 ++(seg->isoc_frame_index);
2534 ++iso_frame_desc;
2535 }
2536 ++urb_index;
2537
2538 } while ((result == 0) && (urb_index < WA_MAX_BUF_IN_URBS)
2539 && (seg->isoc_frame_index <
2540 seg->isoc_frame_count));
2505 2541
2506 result = usb_submit_urb(wa->buf_in_urb, GFP_ATOMIC);
2507 if (result < 0) { 2542 if (result < 0) {
2543 --(wa->active_buf_in_urbs);
2508 dev_err(dev, "DTI Error: Could not submit buf in URB (%d)", 2544 dev_err(dev, "DTI Error: Could not submit buf in URB (%d)",
2509 result); 2545 result);
2510 wa_reset_all(wa); 2546 wa_reset_all(wa);
2511 } else if (data_frame_count > urb_frame_count) 2547 } else if (data_frame_count > total_frames_read)
2512 /* If we need to read multiple frames, set DTI busy. */ 2548 /* If we need to read more frames, set DTI busy. */
2513 dti_busy = 1; 2549 dti_busy = 1;
2514 } else { 2550 } else {
2515 /* OUT transfer or no more IN data, complete it -- */ 2551 /* OUT transfer or no more IN data, complete it -- */
@@ -2517,7 +2553,10 @@ static int wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
2517 done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_DONE); 2553 done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_DONE);
2518 } 2554 }
2519 spin_unlock_irqrestore(&xfer->lock, flags); 2555 spin_unlock_irqrestore(&xfer->lock, flags);
2520 wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING; 2556 if (dti_busy)
2557 wa->dti_state = WA_DTI_BUF_IN_DATA_PENDING;
2558 else
2559 wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
2521 if (done) 2560 if (done)
2522 wa_xfer_completion(xfer); 2561 wa_xfer_completion(xfer);
2523 if (rpipe_ready) 2562 if (rpipe_ready)
@@ -2551,7 +2590,7 @@ static void wa_buf_in_cb(struct urb *urb)
2551 struct wa_rpipe *rpipe; 2590 struct wa_rpipe *rpipe;
2552 unsigned rpipe_ready = 0, isoc_data_frame_count = 0; 2591 unsigned rpipe_ready = 0, isoc_data_frame_count = 0;
2553 unsigned long flags; 2592 unsigned long flags;
2554 int resubmit_dti = 0; 2593 int resubmit_dti = 0, active_buf_in_urbs;
2555 u8 done = 0; 2594 u8 done = 0;
2556 2595
2557 /* free the sg if it was used. */ 2596 /* free the sg if it was used. */
@@ -2561,6 +2600,8 @@ static void wa_buf_in_cb(struct urb *urb)
2561 spin_lock_irqsave(&xfer->lock, flags); 2600 spin_lock_irqsave(&xfer->lock, flags);
2562 wa = xfer->wa; 2601 wa = xfer->wa;
2563 dev = &wa->usb_iface->dev; 2602 dev = &wa->usb_iface->dev;
2603 --(wa->active_buf_in_urbs);
2604 active_buf_in_urbs = wa->active_buf_in_urbs;
2564 2605
2565 if (usb_pipeisoc(xfer->urb->pipe)) { 2606 if (usb_pipeisoc(xfer->urb->pipe)) {
2566 struct usb_iso_packet_descriptor *iso_frame_desc = 2607 struct usb_iso_packet_descriptor *iso_frame_desc =
@@ -2596,12 +2637,14 @@ static void wa_buf_in_cb(struct urb *urb)
2596 int result, urb_frame_count; 2637 int result, urb_frame_count;
2597 2638
2598 /* submit a read URB for the next frame with data. */ 2639 /* submit a read URB for the next frame with data. */
2599 urb_frame_count = __wa_populate_buf_in_urb_isoc(wa, 2640 urb_frame_count = __wa_populate_buf_in_urb_isoc(wa, urb,
2600 xfer, seg); 2641 xfer, seg);
2601 /* advance index to start of next read URB. */ 2642 /* advance index to start of next read URB. */
2602 seg->isoc_frame_index += urb_frame_count; 2643 seg->isoc_frame_index += urb_frame_count;
2603 result = usb_submit_urb(wa->buf_in_urb, GFP_ATOMIC); 2644 ++(wa->active_buf_in_urbs);
2645 result = usb_submit_urb(urb, GFP_ATOMIC);
2604 if (result < 0) { 2646 if (result < 0) {
2647 --(wa->active_buf_in_urbs);
2605 dev_err(dev, "DTI Error: Could not submit buf in URB (%d)", 2648 dev_err(dev, "DTI Error: Could not submit buf in URB (%d)",
2606 result); 2649 result);
2607 wa_reset_all(wa); 2650 wa_reset_all(wa);
@@ -2615,7 +2658,7 @@ static void wa_buf_in_cb(struct urb *urb)
2615 */ 2658 */
2616 resubmit_dti = (isoc_data_frame_count == 2659 resubmit_dti = (isoc_data_frame_count ==
2617 urb_frame_count); 2660 urb_frame_count);
2618 } else { 2661 } else if (active_buf_in_urbs == 0) {
2619 rpipe = xfer->ep->hcpriv; 2662 rpipe = xfer->ep->hcpriv;
2620 dev_dbg(dev, 2663 dev_dbg(dev,
2621 "xfer %p 0x%08X#%u: data in done (%zu bytes)\n", 2664 "xfer %p 0x%08X#%u: data in done (%zu bytes)\n",
@@ -2635,7 +2678,12 @@ static void wa_buf_in_cb(struct urb *urb)
2635 case -ENOENT: /* as it was done by the who unlinked us */ 2678 case -ENOENT: /* as it was done by the who unlinked us */
2636 break; 2679 break;
2637 default: /* Other errors ... */ 2680 default: /* Other errors ... */
2638 resubmit_dti = 1; 2681 /*
2682 * Error on data buf read. Only resubmit DTI if it hasn't
2683 * already been done by previously hitting this error or by a
2684 * successful completion of the previous buf_in_urb.
2685 */
2686 resubmit_dti = wa->dti_state != WA_DTI_TRANSFER_RESULT_PENDING;
2639 spin_lock_irqsave(&xfer->lock, flags); 2687 spin_lock_irqsave(&xfer->lock, flags);
2640 rpipe = xfer->ep->hcpriv; 2688 rpipe = xfer->ep->hcpriv;
2641 if (printk_ratelimit()) 2689 if (printk_ratelimit())
@@ -2650,8 +2698,11 @@ static void wa_buf_in_cb(struct urb *urb)
2650 } 2698 }
2651 seg->result = urb->status; 2699 seg->result = urb->status;
2652 rpipe_ready = rpipe_avail_inc(rpipe); 2700 rpipe_ready = rpipe_avail_inc(rpipe);
2653 __wa_xfer_abort(xfer); 2701 if (active_buf_in_urbs == 0)
2654 done = __wa_xfer_mark_seg_as_done(xfer, seg, WA_SEG_ERROR); 2702 done = __wa_xfer_mark_seg_as_done(xfer, seg,
2703 WA_SEG_ERROR);
2704 else
2705 __wa_xfer_abort(xfer);
2655 spin_unlock_irqrestore(&xfer->lock, flags); 2706 spin_unlock_irqrestore(&xfer->lock, flags);
2656 if (done) 2707 if (done)
2657 wa_xfer_completion(xfer); 2708 wa_xfer_completion(xfer);
@@ -2660,7 +2711,11 @@ static void wa_buf_in_cb(struct urb *urb)
2660 } 2711 }
2661 2712
2662 if (resubmit_dti) { 2713 if (resubmit_dti) {
2663 int result = usb_submit_urb(wa->dti_urb, GFP_ATOMIC); 2714 int result;
2715
2716 wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
2717
2718 result = usb_submit_urb(wa->dti_urb, GFP_ATOMIC);
2664 if (result < 0) { 2719 if (result < 0) {
2665 dev_err(dev, "DTI Error: Could not submit DTI URB (%d)\n", 2720 dev_err(dev, "DTI Error: Could not submit DTI URB (%d)\n",
2666 result); 2721 result);
@@ -2794,7 +2849,7 @@ int wa_dti_start(struct wahc *wa)
2794{ 2849{
2795 const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd; 2850 const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd;
2796 struct device *dev = &wa->usb_iface->dev; 2851 struct device *dev = &wa->usb_iface->dev;
2797 int result = -ENOMEM; 2852 int result = -ENOMEM, index;
2798 2853
2799 if (wa->dti_urb != NULL) /* DTI URB already started */ 2854 if (wa->dti_urb != NULL) /* DTI URB already started */
2800 goto out; 2855 goto out;
@@ -2810,15 +2865,14 @@ int wa_dti_start(struct wahc *wa)
2810 wa->dti_buf, wa->dti_buf_size, 2865 wa->dti_buf, wa->dti_buf_size,
2811 wa_dti_cb, wa); 2866 wa_dti_cb, wa);
2812 2867
2813 wa->buf_in_urb = usb_alloc_urb(0, GFP_KERNEL); 2868 /* init the buf in URBs */
2814 if (wa->buf_in_urb == NULL) { 2869 for (index = 0; index < WA_MAX_BUF_IN_URBS; ++index) {
2815 dev_err(dev, "Can't allocate BUF-IN URB\n"); 2870 usb_fill_bulk_urb(
2816 goto error_buf_in_urb_alloc; 2871 &(wa->buf_in_urbs[index]), wa->usb_dev,
2872 usb_rcvbulkpipe(wa->usb_dev,
2873 0x80 | dti_epd->bEndpointAddress),
2874 NULL, 0, wa_buf_in_cb, wa);
2817 } 2875 }
2818 usb_fill_bulk_urb(
2819 wa->buf_in_urb, wa->usb_dev,
2820 usb_rcvbulkpipe(wa->usb_dev, 0x80 | dti_epd->bEndpointAddress),
2821 NULL, 0, wa_buf_in_cb, wa);
2822 result = usb_submit_urb(wa->dti_urb, GFP_KERNEL); 2876 result = usb_submit_urb(wa->dti_urb, GFP_KERNEL);
2823 if (result < 0) { 2877 if (result < 0) {
2824 dev_err(dev, "DTI Error: Could not submit DTI URB (%d) resetting\n", 2878 dev_err(dev, "DTI Error: Could not submit DTI URB (%d) resetting\n",
@@ -2829,9 +2883,6 @@ out:
2829 return 0; 2883 return 0;
2830 2884
2831error_dti_urb_submit: 2885error_dti_urb_submit:
2832 usb_put_urb(wa->buf_in_urb);
2833 wa->buf_in_urb = NULL;
2834error_buf_in_urb_alloc:
2835 usb_put_urb(wa->dti_urb); 2886 usb_put_urb(wa->dti_urb);
2836 wa->dti_urb = NULL; 2887 wa->dti_urb = NULL;
2837error_dti_urb_alloc: 2888error_dti_urb_alloc: