58
58
SUBMIT_DATA_OUT_URB = (1 << 5 ),
59
59
ALLOC_CMD_URB = (1 << 6 ),
60
60
SUBMIT_CMD_URB = (1 << 7 ),
61
+ COMPLETED_DATA_IN = (1 << 8 ),
62
+ COMPLETED_DATA_OUT = (1 << 9 ),
63
+ DATA_COMPLETES_CMD = (1 << 10 ),
61
64
};
62
65
63
66
/* Overrides scsi_pointer */
@@ -111,6 +114,7 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
111
114
{
112
115
struct sense_iu * sense_iu = urb -> transfer_buffer ;
113
116
struct scsi_device * sdev = cmnd -> device ;
117
+ struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
114
118
115
119
if (urb -> actual_length > 16 ) {
116
120
unsigned len = be16_to_cpup (& sense_iu -> len );
@@ -128,13 +132,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
128
132
}
129
133
130
134
cmnd -> result = sense_iu -> status ;
131
- cmnd -> scsi_done (cmnd );
135
+ if (!(cmdinfo -> state & DATA_COMPLETES_CMD ))
136
+ cmnd -> scsi_done (cmnd );
132
137
}
133
138
134
139
static void uas_sense_old (struct urb * urb , struct scsi_cmnd * cmnd )
135
140
{
136
141
struct sense_iu_old * sense_iu = urb -> transfer_buffer ;
137
142
struct scsi_device * sdev = cmnd -> device ;
143
+ struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
138
144
139
145
if (urb -> actual_length > 8 ) {
140
146
unsigned len = be16_to_cpup (& sense_iu -> len ) - 2 ;
@@ -152,7 +158,8 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
152
158
}
153
159
154
160
cmnd -> result = sense_iu -> status ;
155
- cmnd -> scsi_done (cmnd );
161
+ if (!(cmdinfo -> state & DATA_COMPLETES_CMD ))
162
+ cmnd -> scsi_done (cmnd );
156
163
}
157
164
158
165
static void uas_xfer_data (struct urb * urb , struct scsi_cmnd * cmnd ,
@@ -177,6 +184,7 @@ static void uas_stat_cmplt(struct urb *urb)
177
184
struct Scsi_Host * shost = urb -> context ;
178
185
struct uas_dev_info * devinfo = (void * )shost -> hostdata [0 ];
179
186
struct scsi_cmnd * cmnd ;
187
+ struct uas_cmd_info * cmdinfo ;
180
188
u16 tag ;
181
189
int ret ;
182
190
@@ -202,12 +210,32 @@ static void uas_stat_cmplt(struct urb *urb)
202
210
dev_err (& urb -> dev -> dev , "failed submit status urb\n" );
203
211
return ;
204
212
}
213
+ cmdinfo = (void * )& cmnd -> SCp ;
205
214
206
215
switch (iu -> iu_id ) {
207
216
case IU_ID_STATUS :
208
217
if (devinfo -> cmnd == cmnd )
209
218
devinfo -> cmnd = NULL ;
210
219
220
+ if (!(cmdinfo -> state & COMPLETED_DATA_IN ) &&
221
+ cmdinfo -> data_in_urb ) {
222
+ if (devinfo -> use_streams ) {
223
+ cmdinfo -> state |= DATA_COMPLETES_CMD ;
224
+ usb_unlink_urb (cmdinfo -> data_in_urb );
225
+ } else {
226
+ usb_free_urb (cmdinfo -> data_in_urb );
227
+ }
228
+ }
229
+ if (!(cmdinfo -> state & COMPLETED_DATA_OUT ) &&
230
+ cmdinfo -> data_out_urb ) {
231
+ if (devinfo -> use_streams ) {
232
+ cmdinfo -> state |= DATA_COMPLETES_CMD ;
233
+ usb_unlink_urb (cmdinfo -> data_in_urb );
234
+ } else {
235
+ usb_free_urb (cmdinfo -> data_out_urb );
236
+ }
237
+ }
238
+
211
239
if (urb -> actual_length < 16 )
212
240
devinfo -> uas_sense_old = 1 ;
213
241
if (devinfo -> uas_sense_old )
@@ -236,27 +264,59 @@ static void uas_stat_cmplt(struct urb *urb)
236
264
dev_err (& urb -> dev -> dev , "failed submit status urb\n" );
237
265
}
238
266
239
- static void uas_data_cmplt (struct urb * urb )
267
+ static void uas_data_out_cmplt (struct urb * urb )
268
+ {
269
+ struct scsi_cmnd * cmnd = urb -> context ;
270
+ struct scsi_data_buffer * sdb = scsi_out (cmnd );
271
+ struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
272
+
273
+ cmdinfo -> state |= COMPLETED_DATA_OUT ;
274
+
275
+ sdb -> resid = sdb -> length - urb -> actual_length ;
276
+ usb_free_urb (urb );
277
+
278
+ if (cmdinfo -> state & DATA_COMPLETES_CMD )
279
+ cmnd -> scsi_done (cmnd );
280
+ }
281
+
282
+ static void uas_data_in_cmplt (struct urb * urb )
240
283
{
241
- struct scsi_data_buffer * sdb = urb -> context ;
284
+ struct scsi_cmnd * cmnd = urb -> context ;
285
+ struct scsi_data_buffer * sdb = scsi_in (cmnd );
286
+ struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
287
+
288
+ cmdinfo -> state |= COMPLETED_DATA_IN ;
289
+
242
290
sdb -> resid = sdb -> length - urb -> actual_length ;
243
291
usb_free_urb (urb );
292
+
293
+ if (cmdinfo -> state & DATA_COMPLETES_CMD )
294
+ cmnd -> scsi_done (cmnd );
244
295
}
245
296
246
297
static struct urb * uas_alloc_data_urb (struct uas_dev_info * devinfo , gfp_t gfp ,
247
- unsigned int pipe , u16 stream_id ,
248
- struct scsi_data_buffer * sdb ,
249
- enum dma_data_direction dir )
298
+ unsigned int pipe , struct scsi_cmnd * cmnd ,
299
+ enum dma_data_direction dir )
250
300
{
301
+ struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
251
302
struct usb_device * udev = devinfo -> udev ;
252
303
struct urb * urb = usb_alloc_urb (0 , gfp );
304
+ struct scsi_data_buffer * sdb ;
305
+ usb_complete_t complete_fn ;
306
+ u16 stream_id = cmdinfo -> stream ;
253
307
254
308
if (!urb )
255
309
goto out ;
256
- usb_fill_bulk_urb (urb , udev , pipe , NULL , sdb -> length , uas_data_cmplt ,
257
- sdb );
258
- if (devinfo -> use_streams )
259
- urb -> stream_id = stream_id ;
310
+ if (dir == DMA_FROM_DEVICE ) {
311
+ sdb = scsi_in (cmnd );
312
+ complete_fn = uas_data_in_cmplt ;
313
+ } else {
314
+ sdb = scsi_out (cmnd );
315
+ complete_fn = uas_data_out_cmplt ;
316
+ }
317
+ usb_fill_bulk_urb (urb , udev , pipe , NULL , sdb -> length ,
318
+ complete_fn , cmnd );
319
+ urb -> stream_id = stream_id ;
260
320
urb -> num_sgs = udev -> bus -> sg_tablesize ? sdb -> table .nents : 0 ;
261
321
urb -> sg = sdb -> table .sgl ;
262
322
out :
@@ -358,8 +418,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
358
418
359
419
if (cmdinfo -> state & ALLOC_DATA_IN_URB ) {
360
420
cmdinfo -> data_in_urb = uas_alloc_data_urb (devinfo , gfp ,
361
- devinfo -> data_in_pipe , cmdinfo -> stream ,
362
- scsi_in ( cmnd ), DMA_FROM_DEVICE );
421
+ devinfo -> data_in_pipe , cmnd ,
422
+ DMA_FROM_DEVICE );
363
423
if (!cmdinfo -> data_in_urb )
364
424
return SCSI_MLQUEUE_DEVICE_BUSY ;
365
425
cmdinfo -> state &= ~ALLOC_DATA_IN_URB ;
@@ -376,8 +436,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
376
436
377
437
if (cmdinfo -> state & ALLOC_DATA_OUT_URB ) {
378
438
cmdinfo -> data_out_urb = uas_alloc_data_urb (devinfo , gfp ,
379
- devinfo -> data_out_pipe , cmdinfo -> stream ,
380
- scsi_out ( cmnd ), DMA_TO_DEVICE );
439
+ devinfo -> data_out_pipe , cmnd ,
440
+ DMA_TO_DEVICE );
381
441
if (!cmdinfo -> data_out_urb )
382
442
return SCSI_MLQUEUE_DEVICE_BUSY ;
383
443
cmdinfo -> state &= ~ALLOC_DATA_OUT_URB ;
0 commit comments