@@ -98,6 +98,8 @@ struct uas_dev_info {
98
98
unsigned cmd_pipe , status_pipe , data_in_pipe , data_out_pipe ;
99
99
unsigned use_streams :1 ;
100
100
unsigned uas_sense_old :1 ;
101
+ struct scsi_cmnd * cmnd ;
102
+ struct urb * status_urb ; /* used only if stream support is available */
101
103
};
102
104
103
105
enum {
@@ -116,6 +118,7 @@ struct uas_cmd_info {
116
118
unsigned int state ;
117
119
unsigned int stream ;
118
120
struct urb * cmd_urb ;
121
+ /* status_urb is used only if stream support isn't available */
119
122
struct urb * status_urb ;
120
123
struct urb * data_in_urb ;
121
124
struct urb * data_out_urb ;
@@ -125,29 +128,38 @@ struct uas_cmd_info {
125
128
/* I hate forward declarations, but I actually have a loop */
126
129
static int uas_submit_urbs (struct scsi_cmnd * cmnd ,
127
130
struct uas_dev_info * devinfo , gfp_t gfp );
131
+ static void uas_do_work (struct work_struct * work );
128
132
133
+ static DECLARE_WORK (uas_work , uas_do_work ) ;
129
134
static DEFINE_SPINLOCK (uas_work_lock );
130
135
static LIST_HEAD (uas_work_list );
131
136
132
137
static void uas_do_work (struct work_struct * work )
133
138
{
134
139
struct uas_cmd_info * cmdinfo ;
140
+ struct uas_cmd_info * temp ;
135
141
struct list_head list ;
142
+ int err ;
136
143
137
144
spin_lock_irq (& uas_work_lock );
138
145
list_replace_init (& uas_work_list , & list );
139
146
spin_unlock_irq (& uas_work_lock );
140
147
141
- list_for_each_entry (cmdinfo , & list , list ) {
148
+ list_for_each_entry_safe (cmdinfo , temp , & list , list ) {
142
149
struct scsi_pointer * scp = (void * )cmdinfo ;
143
150
struct scsi_cmnd * cmnd = container_of (scp ,
144
151
struct scsi_cmnd , SCp );
145
- uas_submit_urbs (cmnd , cmnd -> device -> hostdata , GFP_NOIO );
152
+ err = uas_submit_urbs (cmnd , cmnd -> device -> hostdata , GFP_NOIO );
153
+ if (err ) {
154
+ list_del (& cmdinfo -> list );
155
+ spin_lock_irq (& uas_work_lock );
156
+ list_add_tail (& cmdinfo -> list , & uas_work_list );
157
+ spin_unlock_irq (& uas_work_lock );
158
+ schedule_work (& uas_work );
159
+ }
146
160
}
147
161
}
148
162
149
- static DECLARE_WORK (uas_work , uas_do_work ) ;
150
-
151
163
static void uas_sense (struct urb * urb , struct scsi_cmnd * cmnd )
152
164
{
153
165
struct sense_iu * sense_iu = urb -> transfer_buffer ;
@@ -169,10 +181,7 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
169
181
}
170
182
171
183
cmnd -> result = sense_iu -> status ;
172
- if (sdev -> current_cmnd )
173
- sdev -> current_cmnd = NULL ;
174
184
cmnd -> scsi_done (cmnd );
175
- usb_free_urb (urb );
176
185
}
177
186
178
187
static void uas_sense_old (struct urb * urb , struct scsi_cmnd * cmnd )
@@ -196,10 +205,7 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
196
205
}
197
206
198
207
cmnd -> result = sense_iu -> status ;
199
- if (sdev -> current_cmnd )
200
- sdev -> current_cmnd = NULL ;
201
208
cmnd -> scsi_done (cmnd );
202
- usb_free_urb (urb );
203
209
}
204
210
205
211
static void uas_xfer_data (struct urb * urb , struct scsi_cmnd * cmnd ,
@@ -208,7 +214,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
208
214
struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
209
215
int err ;
210
216
211
- cmdinfo -> state = direction | SUBMIT_STATUS_URB ;
217
+ cmdinfo -> state = direction ;
212
218
err = uas_submit_urbs (cmnd , cmnd -> device -> hostdata , GFP_ATOMIC );
213
219
if (err ) {
214
220
spin_lock (& uas_work_lock );
@@ -221,27 +227,40 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
221
227
static void uas_stat_cmplt (struct urb * urb )
222
228
{
223
229
struct iu * iu = urb -> transfer_buffer ;
224
- struct scsi_device * sdev = urb -> context ;
225
- struct uas_dev_info * devinfo = sdev -> hostdata ;
230
+ struct Scsi_Host * shost = urb -> context ;
231
+ struct uas_dev_info * devinfo = ( void * ) shost -> hostdata [ 0 ] ;
226
232
struct scsi_cmnd * cmnd ;
227
233
u16 tag ;
234
+ int ret ;
228
235
229
236
if (urb -> status ) {
230
237
dev_err (& urb -> dev -> dev , "URB BAD STATUS %d\n" , urb -> status );
231
- usb_free_urb (urb );
238
+ if (devinfo -> use_streams )
239
+ usb_free_urb (urb );
232
240
return ;
233
241
}
234
242
235
243
tag = be16_to_cpup (& iu -> tag ) - 1 ;
236
- if (sdev -> current_cmnd )
237
- cmnd = sdev -> current_cmnd ;
244
+ if (tag == 0 )
245
+ cmnd = devinfo -> cmnd ;
238
246
else
239
- cmnd = scsi_find_tag (sdev , tag );
240
- if (!cmnd )
247
+ cmnd = scsi_host_find_tag (shost , tag - 1 );
248
+ if (!cmnd ) {
249
+ if (devinfo -> use_streams ) {
250
+ usb_free_urb (urb );
251
+ return ;
252
+ }
253
+ ret = usb_submit_urb (urb , GFP_ATOMIC );
254
+ if (ret )
255
+ dev_err (& urb -> dev -> dev , "failed submit status urb\n" );
241
256
return ;
257
+ }
242
258
243
259
switch (iu -> iu_id ) {
244
260
case IU_ID_STATUS :
261
+ if (devinfo -> cmnd == cmnd )
262
+ devinfo -> cmnd = NULL ;
263
+
245
264
if (urb -> actual_length < 16 )
246
265
devinfo -> uas_sense_old = 1 ;
247
266
if (devinfo -> uas_sense_old )
@@ -259,6 +278,15 @@ static void uas_stat_cmplt(struct urb *urb)
259
278
scmd_printk (KERN_ERR , cmnd ,
260
279
"Bogus IU (%d) received on status pipe\n" , iu -> iu_id );
261
280
}
281
+
282
+ if (devinfo -> use_streams ) {
283
+ usb_free_urb (urb );
284
+ return ;
285
+ }
286
+
287
+ ret = usb_submit_urb (urb , GFP_ATOMIC );
288
+ if (ret )
289
+ dev_err (& urb -> dev -> dev , "failed submit status urb\n" );
262
290
}
263
291
264
292
static void uas_data_cmplt (struct urb * urb )
@@ -289,7 +317,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
289
317
}
290
318
291
319
static struct urb * uas_alloc_sense_urb (struct uas_dev_info * devinfo , gfp_t gfp ,
292
- struct scsi_cmnd * cmnd , u16 stream_id )
320
+ struct Scsi_Host * shost , u16 stream_id )
293
321
{
294
322
struct usb_device * udev = devinfo -> udev ;
295
323
struct urb * urb = usb_alloc_urb (0 , gfp );
@@ -303,7 +331,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
303
331
goto free ;
304
332
305
333
usb_fill_bulk_urb (urb , udev , devinfo -> status_pipe , iu , sizeof (* iu ),
306
- uas_stat_cmplt , cmnd -> device );
334
+ uas_stat_cmplt , shost );
307
335
urb -> stream_id = stream_id ;
308
336
urb -> transfer_flags |= URB_FREE_BUFFER ;
309
337
out :
@@ -334,7 +362,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
334
362
goto free ;
335
363
336
364
iu -> iu_id = IU_ID_COMMAND ;
337
- iu -> tag = cpu_to_be16 (stream_id );
365
+ if (blk_rq_tagged (cmnd -> request ))
366
+ iu -> tag = cpu_to_be16 (cmnd -> request -> tag + 2 );
367
+ else
368
+ iu -> tag = cpu_to_be16 (1 );
338
369
iu -> prio_attr = UAS_SIMPLE_TAG ;
339
370
iu -> len = len ;
340
371
int_to_scsilun (sdev -> lun , & iu -> lun );
@@ -362,8 +393,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
362
393
struct uas_cmd_info * cmdinfo = (void * )& cmnd -> SCp ;
363
394
364
395
if (cmdinfo -> state & ALLOC_STATUS_URB ) {
365
- cmdinfo -> status_urb = uas_alloc_sense_urb (devinfo , gfp , cmnd ,
366
- cmdinfo -> stream );
396
+ cmdinfo -> status_urb = uas_alloc_sense_urb (devinfo , gfp ,
397
+ cmnd -> device -> host , cmdinfo -> stream );
367
398
if (!cmdinfo -> status_urb )
368
399
return SCSI_MLQUEUE_DEVICE_BUSY ;
369
400
cmdinfo -> state &= ~ALLOC_STATUS_URB ;
@@ -444,13 +475,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
444
475
445
476
BUILD_BUG_ON (sizeof (struct uas_cmd_info ) > sizeof (struct scsi_pointer ));
446
477
447
- if (! cmdinfo -> status_urb && sdev -> current_cmnd )
478
+ if (devinfo -> cmnd )
448
479
return SCSI_MLQUEUE_DEVICE_BUSY ;
449
480
450
481
if (blk_rq_tagged (cmnd -> request )) {
451
- cmdinfo -> stream = cmnd -> request -> tag + 1 ;
482
+ cmdinfo -> stream = cmnd -> request -> tag + 2 ;
452
483
} else {
453
- sdev -> current_cmnd = cmnd ;
484
+ devinfo -> cmnd = cmnd ;
454
485
cmdinfo -> stream = 1 ;
455
486
}
456
487
@@ -472,7 +503,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
472
503
}
473
504
474
505
if (!devinfo -> use_streams ) {
475
- cmdinfo -> state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB );
506
+ cmdinfo -> state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB |
507
+ ALLOC_STATUS_URB | SUBMIT_STATUS_URB );
476
508
cmdinfo -> stream = 0 ;
477
509
}
478
510
@@ -551,7 +583,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
551
583
{
552
584
struct uas_dev_info * devinfo = sdev -> hostdata ;
553
585
scsi_set_tag_type (sdev , MSG_ORDERED_TAG );
554
- scsi_activate_tcq (sdev , devinfo -> qdepth - 1 );
586
+ scsi_activate_tcq (sdev , devinfo -> qdepth - 2 );
555
587
return 0 ;
556
588
}
557
589
@@ -619,6 +651,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
619
651
unsigned i , n_endpoints = intf -> cur_altsetting -> desc .bNumEndpoints ;
620
652
621
653
devinfo -> uas_sense_old = 0 ;
654
+ devinfo -> cmnd = NULL ;
622
655
623
656
for (i = 0 ; i < n_endpoints ; i ++ ) {
624
657
unsigned char * extra = endpoint [i ].extra ;
@@ -670,6 +703,40 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
670
703
}
671
704
}
672
705
706
+ static int uas_alloc_status_urb (struct uas_dev_info * devinfo ,
707
+ struct Scsi_Host * shost )
708
+ {
709
+ if (devinfo -> use_streams ) {
710
+ devinfo -> status_urb = NULL ;
711
+ return 0 ;
712
+ }
713
+
714
+ devinfo -> status_urb = uas_alloc_sense_urb (devinfo , GFP_KERNEL ,
715
+ shost , 0 );
716
+ if (!devinfo -> status_urb )
717
+ goto err_s_urb ;
718
+
719
+ if (usb_submit_urb (devinfo -> status_urb , GFP_KERNEL ))
720
+ goto err_submit_urb ;
721
+
722
+ return 0 ;
723
+ err_submit_urb :
724
+ usb_free_urb (devinfo -> status_urb );
725
+ err_s_urb :
726
+ return - ENOMEM ;
727
+ }
728
+
729
+ static void uas_free_streams (struct uas_dev_info * devinfo )
730
+ {
731
+ struct usb_device * udev = devinfo -> udev ;
732
+ struct usb_host_endpoint * eps [3 ];
733
+
734
+ eps [0 ] = usb_pipe_endpoint (udev , devinfo -> status_pipe );
735
+ eps [1 ] = usb_pipe_endpoint (udev , devinfo -> data_in_pipe );
736
+ eps [2 ] = usb_pipe_endpoint (udev , devinfo -> data_out_pipe );
737
+ usb_free_streams (devinfo -> intf , eps , 3 , GFP_KERNEL );
738
+ }
739
+
673
740
/*
674
741
* XXX: What I'd like to do here is register a SCSI host for each USB host in
675
742
* the system. Follow usb-storage's design of registering a SCSI host for
@@ -699,18 +766,33 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
699
766
shost -> max_id = 1 ;
700
767
shost -> sg_tablesize = udev -> bus -> sg_tablesize ;
701
768
702
- result = scsi_add_host (shost , & intf -> dev );
769
+ devinfo -> intf = intf ;
770
+ devinfo -> udev = udev ;
771
+ uas_configure_endpoints (devinfo );
772
+
773
+ result = scsi_init_shared_tag_map (shost , devinfo -> qdepth - 2 );
703
774
if (result )
704
775
goto free ;
776
+
777
+ result = scsi_add_host (shost , & intf -> dev );
778
+ if (result )
779
+ goto deconfig_eps ;
780
+
705
781
shost -> hostdata [0 ] = (unsigned long )devinfo ;
706
782
707
- devinfo -> intf = intf ;
708
- devinfo -> udev = udev ;
709
- uas_configure_endpoints ( devinfo ) ;
783
+ result = uas_alloc_status_urb ( devinfo , shost ) ;
784
+ if ( result )
785
+ goto err_alloc_status ;
710
786
711
787
scsi_scan_host (shost );
712
788
usb_set_intfdata (intf , shost );
713
789
return result ;
790
+
791
+ err_alloc_status :
792
+ scsi_remove_host (shost );
793
+ shost = NULL ;
794
+ deconfig_eps :
795
+ uas_free_streams (devinfo );
714
796
free :
715
797
kfree (devinfo );
716
798
if (shost )
@@ -732,18 +814,13 @@ static int uas_post_reset(struct usb_interface *intf)
732
814
733
815
static void uas_disconnect (struct usb_interface * intf )
734
816
{
735
- struct usb_device * udev = interface_to_usbdev (intf );
736
- struct usb_host_endpoint * eps [3 ];
737
817
struct Scsi_Host * shost = usb_get_intfdata (intf );
738
818
struct uas_dev_info * devinfo = (void * )shost -> hostdata [0 ];
739
819
740
820
scsi_remove_host (shost );
741
-
742
- eps [0 ] = usb_pipe_endpoint (udev , devinfo -> status_pipe );
743
- eps [1 ] = usb_pipe_endpoint (udev , devinfo -> data_in_pipe );
744
- eps [2 ] = usb_pipe_endpoint (udev , devinfo -> data_out_pipe );
745
- usb_free_streams (intf , eps , 3 , GFP_KERNEL );
746
-
821
+ usb_kill_urb (devinfo -> status_urb );
822
+ usb_free_urb (devinfo -> status_urb );
823
+ uas_free_streams (devinfo );
747
824
kfree (devinfo );
748
825
}
749
826
0 commit comments