blob: d48f592fe2aad71fdb5e47299cdc9db4d9f4839a [file] [log] [blame]
Cho, Yu-Chen871f8472011-04-01 14:38:43 +08001#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2
Al Cho126bb032010-09-08 00:42:32 -07003#include <linux/sched.h>
4#include <linux/errno.h>
5#include <linux/slab.h>
6
7#include <scsi/scsi.h>
8#include <scsi/scsi_eh.h>
9#include <scsi/scsi_device.h>
10
11#include "usb.h"
12#include "scsiglue.h"
13#include "transport.h"
14
15/***********************************************************************
16 * Data transfer routines
17 ***********************************************************************/
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +080018/*
19 * usb_stor_blocking_completion()
20 */
Al Cho126bb032010-09-08 00:42:32 -070021static void usb_stor_blocking_completion(struct urb *urb)
22{
23 struct completion *urb_done_ptr = urb->context;
24
Cho, Yu-Chen871f8472011-04-01 14:38:43 +080025 /* pr_info("transport --- usb_stor_blocking_completion\n"); */
Al Cho126bb032010-09-08 00:42:32 -070026 complete(urb_done_ptr);
27}
28
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +080029/*
30 * usb_stor_msg_common()
31 */
Al Cho126bb032010-09-08 00:42:32 -070032static int usb_stor_msg_common(struct us_data *us, int timeout)
33{
34 struct completion urb_done;
35 long timeleft;
36 int status;
37
Cho, Yu-Chen871f8472011-04-01 14:38:43 +080038 /* pr_info("transport --- usb_stor_msg_common\n"); */
Al Cho126bb032010-09-08 00:42:32 -070039 if (test_bit(US_FLIDX_ABORTING, &us->dflags))
40 return -EIO;
41
42 init_completion(&urb_done);
43
44 us->current_urb->context = &urb_done;
45 us->current_urb->actual_length = 0;
46 us->current_urb->error_count = 0;
47 us->current_urb->status = 0;
48
Konstantin Katuev307ae1d2010-10-29 12:18:18 +110049 us->current_urb->transfer_flags = 0;
Al Cho126bb032010-09-08 00:42:32 -070050 if (us->current_urb->transfer_buffer == us->iobuf)
51 us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
52 us->current_urb->transfer_dma = us->iobuf_dma;
53 us->current_urb->setup_dma = us->cr_dma;
54
55 status = usb_submit_urb(us->current_urb, GFP_NOIO);
56 if (status)
57 return status;
58
59 set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
60
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +080061 if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
62 if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +080063 /* pr_info("-- cancelling URB\n"); */
Al Cho126bb032010-09-08 00:42:32 -070064 usb_unlink_urb(us->current_urb);
65 }
66 }
67
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +080068 timeleft = wait_for_completion_interruptible_timeout(&urb_done,
69 timeout ? : MAX_SCHEDULE_TIMEOUT);
Al Cho126bb032010-09-08 00:42:32 -070070 clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
71
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +080072 if (timeleft <= 0) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +080073 /* pr_info("%s -- cancelling URB\n",
74 timeleft == 0 ? "Timeout" : "Signal"); */
Al Cho126bb032010-09-08 00:42:32 -070075 usb_kill_urb(us->current_urb);
76 }
77
78 return us->current_urb->status;
79}
80
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +080081/*
82 * usb_stor_control_msg()
83 */
Al Cho126bb032010-09-08 00:42:32 -070084int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
85 u8 request, u8 requesttype, u16 value, u16 index,
86 void *data, u16 size, int timeout)
87{
88 int status;
89
Cho, Yu-Chen871f8472011-04-01 14:38:43 +080090 /* pr_info("transport --- usb_stor_control_msg\n"); */
Al Cho126bb032010-09-08 00:42:32 -070091
92 /* fill in the devrequest structure */
93 us->cr->bRequestType = requesttype;
94 us->cr->bRequest = request;
95 us->cr->wValue = cpu_to_le16(value);
96 us->cr->wIndex = cpu_to_le16(index);
97 us->cr->wLength = cpu_to_le16(size);
98
99 /* fill and submit the URB */
100 usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800101 (unsigned char *) us->cr, data, size,
Al Cho126bb032010-09-08 00:42:32 -0700102 usb_stor_blocking_completion, NULL);
103 status = usb_stor_msg_common(us, timeout);
104
105 /* return the actual length of the data transferred if no error */
106 if (status == 0)
107 status = us->current_urb->actual_length;
108 return status;
109}
110
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800111/*
112 * usb_stor_clear_halt()
113 */
Al Cho126bb032010-09-08 00:42:32 -0700114int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
115{
116 int result;
117 int endp = usb_pipeendpoint(pipe);
118
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800119 /* pr_info("transport --- usb_stor_clear_halt\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800120 if (usb_pipein(pipe))
Al Cho126bb032010-09-08 00:42:32 -0700121 endp |= USB_DIR_IN;
122
123 result = usb_stor_control_msg(us, us->send_ctrl_pipe,
124 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
125 USB_ENDPOINT_HALT, endp,
126 NULL, 0, 3*HZ);
127
128 /* reset the endpoint toggle */
129 if (result >= 0)
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800130 /* usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
131 usb_pipeout(pipe), 0); */
132 usb_reset_endpoint(us->pusb_dev, endp);
Al Cho126bb032010-09-08 00:42:32 -0700133
134 return result;
135}
136
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800137/*
138 * interpret_urb_result()
139 */
Al Cho126bb032010-09-08 00:42:32 -0700140static int interpret_urb_result(struct us_data *us, unsigned int pipe,
141 unsigned int length, int result, unsigned int partial)
142{
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800143 /* pr_info("transport --- interpret_urb_result\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700144 switch (result) {
145 /* no error code; did we send all the data? */
146 case 0:
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800147 if (partial != length) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800148 /* pr_info("-- short transfer\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700149 return USB_STOR_XFER_SHORT;
150 }
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800151 /* pr_info("-- transfer complete\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700152 return USB_STOR_XFER_GOOD;
153 case -EPIPE:
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800154 if (usb_pipecontrol(pipe)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800155 /* pr_info("-- stall on control pipe\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700156 return USB_STOR_XFER_STALLED;
157 }
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800158 /* pr_info("clearing endpoint halt for pipe 0x%x\n", pipe); */
Al Cho126bb032010-09-08 00:42:32 -0700159 if (usb_stor_clear_halt(us, pipe) < 0)
160 return USB_STOR_XFER_ERROR;
161 return USB_STOR_XFER_STALLED;
162 case -EOVERFLOW:
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800163 /* pr_info("-- babble\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700164 return USB_STOR_XFER_LONG;
165 case -ECONNRESET:
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800166 /* pr_info("-- transfer cancelled\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700167 return USB_STOR_XFER_ERROR;
168 case -EREMOTEIO:
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800169 /* pr_info("-- short read transfer\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700170 return USB_STOR_XFER_SHORT;
171 case -EIO:
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800172 /* pr_info("-- abort or disconnect in progress\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700173 return USB_STOR_XFER_ERROR;
174 default:
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800175 /* pr_info("-- unknown error\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700176 return USB_STOR_XFER_ERROR;
177 }
178}
179
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800180/*
181 * usb_stor_bulk_transfer_buf()
182 */
Al Cho126bb032010-09-08 00:42:32 -0700183int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
184 void *buf, unsigned int length, unsigned int *act_len)
185{
186 int result;
187
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800188 /* pr_info("transport --- usb_stor_bulk_transfer_buf\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700189
190 /* fill and submit the URB */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800191 usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf,
192 length, usb_stor_blocking_completion, NULL);
Al Cho126bb032010-09-08 00:42:32 -0700193 result = usb_stor_msg_common(us, 0);
194
195 /* store the actual length of the data transferred */
196 if (act_len)
197 *act_len = us->current_urb->actual_length;
198
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800199 return interpret_urb_result(us, pipe, length, result,
200 us->current_urb->actual_length);
Al Cho126bb032010-09-08 00:42:32 -0700201}
202
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800203/*
204 * usb_stor_bulk_transfer_sglist()
205 */
Al Cho126bb032010-09-08 00:42:32 -0700206static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
207 struct scatterlist *sg, int num_sg, unsigned int length,
208 unsigned int *act_len)
209{
210 int result;
211
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800212 /* pr_info("transport --- usb_stor_bulk_transfer_sglist\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700213 if (test_bit(US_FLIDX_ABORTING, &us->dflags))
214 return USB_STOR_XFER_ERROR;
215
216 /* initialize the scatter-gather request block */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800217 result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
218 sg, num_sg, length, GFP_NOIO);
219 if (result) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800220 /* pr_info("usb_sg_init returned %d\n", result); */
Al Cho126bb032010-09-08 00:42:32 -0700221 return USB_STOR_XFER_ERROR;
222 }
223
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800224 /* since the block has been initialized successfully,
225 it's now okay to cancel it */
Al Cho126bb032010-09-08 00:42:32 -0700226 set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
227
228 /* did an abort/disconnect occur during the submission? */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800229 if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
Al Cho126bb032010-09-08 00:42:32 -0700230 /* cancel the request, if it hasn't been cancelled already */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800231 if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800232 /* pr_info("-- cancelling sg request\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700233 usb_sg_cancel(&us->current_sg);
234 }
235 }
236
237 /* wait for the completion of the transfer */
238 usb_sg_wait(&us->current_sg);
239 clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
240
241 result = us->current_sg.status;
242 if (act_len)
243 *act_len = us->current_sg.bytes;
244
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800245 return interpret_urb_result(us, pipe, length,
246 result, us->current_sg.bytes);
Al Cho126bb032010-09-08 00:42:32 -0700247}
248
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800249/*
250 * usb_stor_bulk_srb()
251 */
252int usb_stor_bulk_srb(struct us_data *us, unsigned int pipe,
253 struct scsi_cmnd *srb)
Al Cho126bb032010-09-08 00:42:32 -0700254{
255 unsigned int partial;
256 int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb),
257 scsi_sg_count(srb), scsi_bufflen(srb),
258 &partial);
259
260 scsi_set_resid(srb, scsi_bufflen(srb) - partial);
261 return result;
262}
263
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800264/*
265 * usb_stor_bulk_transfer_sg()
266 */
267int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
Al Cho126bb032010-09-08 00:42:32 -0700268 void *buf, unsigned int length_left, int use_sg, int *residual)
269{
270 int result;
271 unsigned int partial;
272
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800273 /* pr_info("transport --- usb_stor_bulk_transfer_sg\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700274 /* are we scatter-gathering? */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800275 if (use_sg) {
Al Cho126bb032010-09-08 00:42:32 -0700276 /* use the usb core scatter-gather primitives */
277 result = usb_stor_bulk_transfer_sglist(us, pipe,
278 (struct scatterlist *) buf, use_sg,
279 length_left, &partial);
280 length_left -= partial;
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800281 } else {
Al Cho126bb032010-09-08 00:42:32 -0700282 /* no scatter-gather, just make the request */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800283 result = usb_stor_bulk_transfer_buf(us, pipe, buf,
284 length_left, &partial);
Al Cho126bb032010-09-08 00:42:32 -0700285 length_left -= partial;
286 }
287
288 /* store the residual and return the error code */
289 if (residual)
290 *residual = length_left;
291 return result;
292}
293
294/***********************************************************************
295 * Transport routines
296 ***********************************************************************/
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800297/*
298 * usb_stor_invoke_transport()
299 */
Al Cho126bb032010-09-08 00:42:32 -0700300void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
301{
302 int need_auto_sense;
303 int result;
304
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800305 /* pr_info("transport --- usb_stor_invoke_transport\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700306 usb_stor_print_cmd(srb);
307 /* send the command to the transport layer */
308 scsi_set_resid(srb, 0);
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800309 result = us->transport(srb, us); /* usb_stor_Bulk_transport; */
310
311 /* if the command gets aborted by the higher layers,
312 we need to short-circuit all other processing */
313 if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800314 /* pr_info("-- command was aborted\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700315 srb->result = DID_ABORT << 16;
316 goto Handle_Errors;
317 }
318
319 /* if there is a transport error, reset and don't auto-sense */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800320 if (result == USB_STOR_TRANSPORT_ERROR) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800321 /* pr_info("-- transport indicates error, resetting\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700322 srb->result = DID_ERROR << 16;
323 goto Handle_Errors;
324 }
325
326 /* if the transport provided its own sense data, don't auto-sense */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800327 if (result == USB_STOR_TRANSPORT_NO_SENSE) {
Al Cho126bb032010-09-08 00:42:32 -0700328 srb->result = SAM_STAT_CHECK_CONDITION;
329 return;
330 }
331
332 srb->result = SAM_STAT_GOOD;
333
334 /* Determine if we need to auto-sense */
335 need_auto_sense = 0;
336
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800337 if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
338 srb->sc_data_direction != DMA_FROM_DEVICE) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800339 /* pr_info("-- CB transport device requiring auto-sense\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700340 need_auto_sense = 1;
341 }
342
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800343 if (result == USB_STOR_TRANSPORT_FAILED) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800344 /* pr_info("-- transport indicates command failure\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700345 need_auto_sense = 1;
346 }
347
348 /* Now, if we need to do the auto-sense, let's do it */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800349 if (need_auto_sense) {
Al Cho126bb032010-09-08 00:42:32 -0700350 int temp_result;
351 struct scsi_eh_save ses;
352
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800353 pr_info("Issuing auto-REQUEST_SENSE\n");
Al Cho126bb032010-09-08 00:42:32 -0700354
355 scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE);
356
357 /* we must do the protocol translation here */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800358 if (us->subclass == USB_SC_RBC ||
359 us->subclass == USB_SC_SCSI ||
360 us->subclass == USB_SC_CYP_ATACB) {
Al Cho126bb032010-09-08 00:42:32 -0700361 srb->cmd_len = 6;
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800362 } else {
Al Cho126bb032010-09-08 00:42:32 -0700363 srb->cmd_len = 12;
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800364 }
Al Cho126bb032010-09-08 00:42:32 -0700365 /* issue the auto-sense command */
366 scsi_set_resid(srb, 0);
367 temp_result = us->transport(us->srb, us);
368
369 /* let's clean up right away */
370 scsi_eh_restore_cmnd(srb, &ses);
371
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800372 if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800373 /* pr_info("-- auto-sense aborted\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700374 srb->result = DID_ABORT << 16;
375 goto Handle_Errors;
376 }
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800377 if (temp_result != USB_STOR_TRANSPORT_GOOD) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800378 /* pr_info("-- auto-sense failure\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700379 srb->result = DID_ERROR << 16;
380 if (!(us->fflags & US_FL_SCM_MULT_TARG))
381 goto Handle_Errors;
382 return;
383 }
384
385 /* set the result so the higher layers expect this data */
386 srb->result = SAM_STAT_CHECK_CONDITION;
387
388 if (result == USB_STOR_TRANSPORT_GOOD &&
389 (srb->sense_buffer[2] & 0xaf) == 0 &&
390 srb->sense_buffer[12] == 0 &&
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800391 srb->sense_buffer[13] == 0) {
Al Cho126bb032010-09-08 00:42:32 -0700392 srb->result = SAM_STAT_GOOD;
393 srb->sense_buffer[0] = 0x0;
394 }
395 }
396
397 /* Did we transfer less than the minimum amount required? */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800398 if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) -
399 scsi_get_resid(srb) < srb->underflow)
400 srb->result = (DID_ERROR << 16);
401 /* v02 | (SUGGEST_RETRY << 24); */
Al Cho126bb032010-09-08 00:42:32 -0700402
403 return;
404
405Handle_Errors:
406 scsi_lock(us_to_host(us));
407 set_bit(US_FLIDX_RESETTING, &us->dflags);
408 clear_bit(US_FLIDX_ABORTING, &us->dflags);
409 scsi_unlock(us_to_host(us));
410
411 mutex_unlock(&us->dev_mutex);
412 result = usb_stor_port_reset(us);
413 mutex_lock(&us->dev_mutex);
414
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800415 if (result < 0) {
Al Cho126bb032010-09-08 00:42:32 -0700416 scsi_lock(us_to_host(us));
417 usb_stor_report_device_reset(us);
418 scsi_unlock(us_to_host(us));
419 us->transport_reset(us);
420 }
421 clear_bit(US_FLIDX_RESETTING, &us->dflags);
422}
423
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800424/*
425 * ENE_stor_invoke_transport()
426 */
Al Cho126bb032010-09-08 00:42:32 -0700427void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
428{
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800429 int result = 0;
Al Cho126bb032010-09-08 00:42:32 -0700430
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800431 /* pr_info("transport --- ENE_stor_invoke_transport\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700432 usb_stor_print_cmd(srb);
433 /* send the command to the transport layer */
434 scsi_set_resid(srb, 0);
huajun li41e568d2011-03-04 10:56:18 +0800435 if (!(us->MS_Status.Ready || us->SM_Status.Ready))
Al Cho126bb032010-09-08 00:42:32 -0700436 result = ENE_InitMedia(us);
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800437
Al Cho126bb032010-09-08 00:42:32 -0700438 if (us->Power_IsResum == true) {
439 result = ENE_InitMedia(us);
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800440 us->Power_IsResum = false;
441 }
Al Cho126bb032010-09-08 00:42:32 -0700442
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800443 if (us->MS_Status.Ready)
444 result = MS_SCSIIrp(us, srb);
445 if (us->SM_Status.Ready)
446 result = SM_SCSIIrp(us, srb);
447
448 /* if the command gets aborted by the higher layers,
449 we need to short-circuit all other processing */
450 if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800451 /* pr_info("-- command was aborted\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700452 srb->result = DID_ABORT << 16;
453 goto Handle_Errors;
454 }
455
456 /* if there is a transport error, reset and don't auto-sense */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800457 if (result == USB_STOR_TRANSPORT_ERROR) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800458 /* pr_info("-- transport indicates error, resetting\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700459 srb->result = DID_ERROR << 16;
460 goto Handle_Errors;
461 }
462
463 /* if the transport provided its own sense data, don't auto-sense */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800464 if (result == USB_STOR_TRANSPORT_NO_SENSE) {
Al Cho126bb032010-09-08 00:42:32 -0700465 srb->result = SAM_STAT_CHECK_CONDITION;
466 return;
467 }
468
469 srb->result = SAM_STAT_GOOD;
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800470 if (result == USB_STOR_TRANSPORT_FAILED) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800471 /* pr_info("-- transport indicates command failure\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800472 /* need_auto_sense = 1; */
Al Cho126bb032010-09-08 00:42:32 -0700473 BuildSenseBuffer(srb, us->SrbStatus);
474 srb->result = SAM_STAT_CHECK_CONDITION;
475 }
476
477 /* Did we transfer less than the minimum amount required? */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800478 if (srb->result == SAM_STAT_GOOD && scsi_bufflen(srb) -
479 scsi_get_resid(srb) < srb->underflow)
480 srb->result = (DID_ERROR << 16);
481 /* v02 | (SUGGEST_RETRY << 24); */
Al Cho126bb032010-09-08 00:42:32 -0700482
483 return;
484
485Handle_Errors:
486 scsi_lock(us_to_host(us));
487 set_bit(US_FLIDX_RESETTING, &us->dflags);
488 clear_bit(US_FLIDX_ABORTING, &us->dflags);
489 scsi_unlock(us_to_host(us));
490
491 mutex_unlock(&us->dev_mutex);
492 result = usb_stor_port_reset(us);
493 mutex_lock(&us->dev_mutex);
494
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800495 if (result < 0) {
Al Cho126bb032010-09-08 00:42:32 -0700496 scsi_lock(us_to_host(us));
497 usb_stor_report_device_reset(us);
498 scsi_unlock(us_to_host(us));
499 us->transport_reset(us);
500 }
501 clear_bit(US_FLIDX_RESETTING, &us->dflags);
502}
503
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800504/*
505 * BuildSenseBuffer()
506 */
Al Cho126bb032010-09-08 00:42:32 -0700507void BuildSenseBuffer(struct scsi_cmnd *srb, int SrbStatus)
508{
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800509 BYTE *buf = srb->sense_buffer;
510 BYTE asc;
Al Cho126bb032010-09-08 00:42:32 -0700511
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800512 pr_info("transport --- BuildSenseBuffer\n");
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800513 switch (SrbStatus) {
514 case SS_NOT_READY:
515 asc = 0x3a;
516 break; /* sense key = 0x02 */
517 case SS_MEDIUM_ERR:
518 asc = 0x0c;
519 break; /* sense key = 0x03 */
520 case SS_ILLEGAL_REQUEST:
521 asc = 0x20;
522 break; /* sense key = 0x05 */
523 default:
524 asc = 0x00;
525 break; /* ?? */
526 }
Al Cho126bb032010-09-08 00:42:32 -0700527
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800528 memset(buf, 0, 18);
529 buf[0x00] = 0xf0;
530 buf[0x02] = SrbStatus;
531 buf[0x07] = 0x0b;
532 buf[0x0c] = asc;
Al Cho126bb032010-09-08 00:42:32 -0700533}
534
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800535/*
536 * usb_stor_stop_transport()
537 */
Al Cho126bb032010-09-08 00:42:32 -0700538void usb_stor_stop_transport(struct us_data *us)
539{
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800540 /* pr_info("transport --- usb_stor_stop_transport\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700541
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800542 if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800543 /* pr_info("-- cancelling URB\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700544 usb_unlink_urb(us->current_urb);
545 }
546
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800547 if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800548 /* pr_info("-- cancelling sg request\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700549 usb_sg_cancel(&us->current_sg);
550 }
551}
552
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800553/*
554 * usb_stor_Bulk_max_lun()
555 */
Al Cho126bb032010-09-08 00:42:32 -0700556int usb_stor_Bulk_max_lun(struct us_data *us)
557{
558 int result;
559
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800560 /* pr_info("transport --- usb_stor_Bulk_max_lun\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700561 /* issue the command */
562 us->iobuf[0] = 0;
563 result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
564 US_BULK_GET_MAX_LUN,
565 USB_DIR_IN | USB_TYPE_CLASS |
566 USB_RECIP_INTERFACE,
567 0, us->ifnum, us->iobuf, 1, HZ);
568
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800569 /* pr_info("GetMaxLUN command result is %d, data is %d\n",
570 result, us->iobuf[0]); */
Al Cho126bb032010-09-08 00:42:32 -0700571
572 /* if we have a successful request, return the result */
573 if (result > 0)
574 return us->iobuf[0];
575
576 return 0;
577}
578
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800579/*
580 * usb_stor_Bulk_transport()
581 */
Al Cho126bb032010-09-08 00:42:32 -0700582int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
583{
584 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
585 struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
586 unsigned int transfer_length = scsi_bufflen(srb);
587 unsigned int residue;
588 int result;
589 int fake_sense = 0;
590 unsigned int cswlen;
591 unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
592
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800593 /* pr_info("transport --- usb_stor_Bulk_transport\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700594 /* Take care of BULK32 devices; set extra byte to 0 */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800595 if (unlikely(us->fflags & US_FL_BULK32)) {
Al Cho126bb032010-09-08 00:42:32 -0700596 cbwlen = 32;
597 us->iobuf[31] = 0;
598 }
599
600 /* set up the command wrapper */
601 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
602 bcb->DataTransferLength = cpu_to_le32(transfer_length);
603 bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
604 bcb->Tag = ++us->tag;
605 bcb->Lun = srb->device->lun;
606 if (us->fflags & US_FL_SCM_MULT_TARG)
607 bcb->Lun |= srb->device->id << 4;
608 bcb->Length = srb->cmd_len;
609
610 /* copy the command payload */
611 memset(bcb->CDB, 0, sizeof(bcb->CDB));
612 memcpy(bcb->CDB, srb->cmnd, bcb->Length);
613
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800614 /* send command */
Al Cho126bb032010-09-08 00:42:32 -0700615 /* send it to out endpoint */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800616 /* pr_info("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
Al Cho126bb032010-09-08 00:42:32 -0700617 le32_to_cpu(bcb->Signature), bcb->Tag,
618 le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
619 (bcb->Lun >> 4), (bcb->Lun & 0x0F),
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800620 bcb->Length); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800621 result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
622 bcb, cbwlen, NULL);
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800623 /* pr_info("Bulk command transfer result=%d\n", result); */
Al Cho126bb032010-09-08 00:42:32 -0700624 if (result != USB_STOR_XFER_GOOD)
625 return USB_STOR_TRANSPORT_ERROR;
626
627 if (unlikely(us->fflags & US_FL_GO_SLOW))
628 udelay(125);
629
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800630 /* R/W data */
631 if (transfer_length) {
632 unsigned int pipe = srb->sc_data_direction ==
633 DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe;
Al Cho126bb032010-09-08 00:42:32 -0700634 result = usb_stor_bulk_srb(us, pipe, srb);
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800635 /* pr_info("Bulk data transfer result 0x%x\n", result); */
Al Cho126bb032010-09-08 00:42:32 -0700636 if (result == USB_STOR_XFER_ERROR)
637 return USB_STOR_TRANSPORT_ERROR;
638
639 if (result == USB_STOR_XFER_LONG)
640 fake_sense = 1;
641 }
642
643 /* get CSW for device status */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800644 /* pr_info("Attempting to get CSW...\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800645 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
646 US_BULK_CS_WRAP_LEN, &cswlen);
Al Cho126bb032010-09-08 00:42:32 -0700647
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800648 if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800649 /* pr_info("Received 0-length CSW; retrying...\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800650 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
651 US_BULK_CS_WRAP_LEN, &cswlen);
Al Cho126bb032010-09-08 00:42:32 -0700652 }
653
654 /* did the attempt to read the CSW fail? */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800655 if (result == USB_STOR_XFER_STALLED) {
Al Cho126bb032010-09-08 00:42:32 -0700656 /* get the status again */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800657 /* pr_info("Attempting to get CSW (2nd try)...\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800658 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
659 US_BULK_CS_WRAP_LEN, NULL);
Al Cho126bb032010-09-08 00:42:32 -0700660 }
661
662 /* if we still have a failure at this point, we're in trouble */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800663 /* pr_info("Bulk status result = %d\n", result); */
Al Cho126bb032010-09-08 00:42:32 -0700664 if (result != USB_STOR_XFER_GOOD)
665 return USB_STOR_TRANSPORT_ERROR;
666
667 /* check bulk status */
668 residue = le32_to_cpu(bcs->Residue);
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800669 /* pr_info("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
670 le32_to_cpu(bcs->Signature),
671 bcs->Tag, residue, bcs->Status); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800672 if (!(bcs->Tag == us->tag ||
673 (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
674 bcs->Status > US_BULK_STAT_PHASE) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800675 /* pr_info("Bulk logical error\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700676 return USB_STOR_TRANSPORT_ERROR;
677 }
678
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800679 if (!us->bcs_signature) {
Al Cho126bb032010-09-08 00:42:32 -0700680 us->bcs_signature = bcs->Signature;
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800681 /* if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN)) */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800682 /* pr_info("Learnt BCS signature 0x%08X\n",
683 le32_to_cpu(us->bcs_signature)); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800684 } else if (bcs->Signature != us->bcs_signature) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800685 /* pr_info("Signature mismatch: got %08X, expecting %08X\n",
Al Cho126bb032010-09-08 00:42:32 -0700686 le32_to_cpu(bcs->Signature),
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800687 le32_to_cpu(us->bcs_signature)); */
Al Cho126bb032010-09-08 00:42:32 -0700688 return USB_STOR_TRANSPORT_ERROR;
689 }
690
691 /* try to compute the actual residue, based on how much data
692 * was really transferred and what the device tells us */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800693 if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
Al Cho126bb032010-09-08 00:42:32 -0700694
695 /* Heuristically detect devices that generate bogus residues
696 * by seeing what happens with INQUIRY and READ CAPACITY
697 * commands.
698 */
699 if (bcs->Status == US_BULK_STAT_OK &&
700 scsi_get_resid(srb) == 0 &&
701 ((srb->cmnd[0] == INQUIRY &&
702 transfer_length == 36) ||
703 (srb->cmnd[0] == READ_CAPACITY &&
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800704 transfer_length == 8))) {
Al Cho126bb032010-09-08 00:42:32 -0700705 us->fflags |= US_FL_IGNORE_RESIDUE;
706
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800707 } else {
Al Cho126bb032010-09-08 00:42:32 -0700708 residue = min(residue, transfer_length);
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800709 scsi_set_resid(srb, max(scsi_get_resid(srb),
710 (int) residue));
Al Cho126bb032010-09-08 00:42:32 -0700711 }
712 }
713
714 /* based on the status code, we report good or bad */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800715 switch (bcs->Status) {
716 case US_BULK_STAT_OK:
717 if (fake_sense) {
718 memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB,
719 sizeof(usb_stor_sense_invalidCDB));
720 return USB_STOR_TRANSPORT_NO_SENSE;
721 }
722 return USB_STOR_TRANSPORT_GOOD;
Al Cho126bb032010-09-08 00:42:32 -0700723
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800724 case US_BULK_STAT_FAIL:
725 return USB_STOR_TRANSPORT_FAILED;
Al Cho126bb032010-09-08 00:42:32 -0700726
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800727 case US_BULK_STAT_PHASE:
728 return USB_STOR_TRANSPORT_ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700729 }
730 return USB_STOR_TRANSPORT_ERROR;
731}
732
733/***********************************************************************
734 * Reset routines
735 ***********************************************************************/
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800736/*
737 * usb_stor_reset_common()
738 */
Al Cho126bb032010-09-08 00:42:32 -0700739static int usb_stor_reset_common(struct us_data *us,
740 u8 request, u8 requesttype,
741 u16 value, u16 index, void *data, u16 size)
742{
743 int result;
744 int result2;
745
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800746 /* pr_info("transport --- usb_stor_reset_common\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800747 if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800748 /* pr_info("No reset during disconnect\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700749 return -EIO;
750 }
751
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800752 result = usb_stor_control_msg(us, us->send_ctrl_pipe,
753 request, requesttype, value, index, data, size, 5*HZ);
754
755 if (result < 0) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800756 /* pr_info("Soft reset failed: %d\n", result); */
Al Cho126bb032010-09-08 00:42:32 -0700757 return result;
758 }
759
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800760 wait_event_interruptible_timeout(us->delay_wait,
761 test_bit(US_FLIDX_DISCONNECTING, &us->dflags), HZ*6);
762
763 if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800764 /* pr_info("Reset interrupted by disconnect\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700765 return -EIO;
766 }
767
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800768 /* pr_info("Soft reset: clearing bulk-in endpoint halt\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700769 result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
770
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800771 /* pr_info("Soft reset: clearing bulk-out endpoint halt\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700772 result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
773
774 /* return a result code based on the result of the clear-halts */
775 if (result >= 0)
776 result = result2;
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800777 /* if (result < 0) */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800778 /* pr_info("Soft reset failed\n"); */
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800779 /* else */
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800780 /* pr_info("Soft reset done\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700781 return result;
782}
783
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800784/*
785 * usb_stor_Bulk_reset()
786 */
Al Cho126bb032010-09-08 00:42:32 -0700787int usb_stor_Bulk_reset(struct us_data *us)
788{
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800789 /* pr_info("transport --- usb_stor_Bulk_reset\n"); */
Al Cho126bb032010-09-08 00:42:32 -0700790 return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
791 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
792 0, us->ifnum, NULL, 0);
793}
794
Cho, Yu-Chen3aa4fc52011-05-18 18:40:14 +0800795/*
796 * usb_stor_port_reset()
797 */
Al Cho126bb032010-09-08 00:42:32 -0700798int usb_stor_port_reset(struct us_data *us)
799{
Greg Kroah-Hartmana200adb2010-09-30 04:34:26 -0700800 int result;
Al Cho126bb032010-09-08 00:42:32 -0700801
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800802 /* pr_info("transport --- usb_stor_port_reset\n"); */
Al Choe1049602010-09-24 18:50:11 +0800803 result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
Al Cho126bb032010-09-08 00:42:32 -0700804 if (result < 0)
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800805 pr_info("unable to lock device for reset: %d\n", result);
Al Choe1049602010-09-24 18:50:11 +0800806 else {
Al Cho126bb032010-09-08 00:42:32 -0700807 /* Were we disconnected while waiting for the lock? */
Al Choe1049602010-09-24 18:50:11 +0800808 if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
Al Cho126bb032010-09-08 00:42:32 -0700809 result = -EIO;
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800810 /* pr_info("No reset during disconnect\n"); */
Al Choe1049602010-09-24 18:50:11 +0800811 } else {
Al Cho126bb032010-09-08 00:42:32 -0700812 result = usb_reset_device(us->pusb_dev);
Cho, Yu-Chen871f8472011-04-01 14:38:43 +0800813 /* pr_info("usb_reset_composite_device returns %d\n",
814 result); */
Al Cho126bb032010-09-08 00:42:32 -0700815 }
Al Choe1049602010-09-24 18:50:11 +0800816 usb_unlock_device(us->pusb_dev);
Al Cho126bb032010-09-08 00:42:32 -0700817 }
818 return result;
819}
820
821