aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r--drivers/usb/storage/scsiglue.c54
-rw-r--r--drivers/usb/storage/scsiglue.h1
-rw-r--r--drivers/usb/storage/transport.c116
-rw-r--r--drivers/usb/storage/transport.h1
4 files changed, 99 insertions, 73 deletions
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index e43eddc3d44b..af294bb68c35 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -155,6 +155,15 @@ static int slave_configure(struct scsi_device *sdev)
155 * If this device makes that mistake, tell the sd driver. */ 155 * If this device makes that mistake, tell the sd driver. */
156 if (us->flags & US_FL_FIX_CAPACITY) 156 if (us->flags & US_FL_FIX_CAPACITY)
157 sdev->fix_capacity = 1; 157 sdev->fix_capacity = 1;
158
159 /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
160 * Hardware Error) when any low-level error occurs,
161 * recoverable or not. Setting this flag tells the SCSI
162 * midlayer to retry such commands, which frequently will
163 * succeed and fix the error. The worst this can lead to
164 * is an occasional series of retries that will all fail. */
165 sdev->retry_hwerror = 1;
166
158 } else { 167 } else {
159 168
160 /* Non-disk-type devices don't need to blacklist any pages 169 /* Non-disk-type devices don't need to blacklist any pages
@@ -255,50 +264,23 @@ static int device_reset(struct scsi_cmnd *srb)
255 264
256 /* lock the device pointers and do the reset */ 265 /* lock the device pointers and do the reset */
257 down(&(us->dev_semaphore)); 266 down(&(us->dev_semaphore));
258 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { 267 result = us->transport_reset(us);
259 result = FAILED;
260 US_DEBUGP("No reset during disconnect\n");
261 } else
262 result = us->transport_reset(us);
263 up(&(us->dev_semaphore)); 268 up(&(us->dev_semaphore));
264 269
265 return result; 270 return result < 0 ? FAILED : SUCCESS;
266} 271}
267 272
268/* This resets the device's USB port. */ 273/* Simulate a SCSI bus reset by resetting the device's USB port. */
269/* It refuses to work if there's more than one interface in
270 * the device, so that other users are not affected. */
271/* This is always called with scsi_lock(host) held */ 274/* This is always called with scsi_lock(host) held */
272static int bus_reset(struct scsi_cmnd *srb) 275static int bus_reset(struct scsi_cmnd *srb)
273{ 276{
274 struct us_data *us = host_to_us(srb->device->host); 277 struct us_data *us = host_to_us(srb->device->host);
275 int result, rc; 278 int result;
276 279
277 US_DEBUGP("%s called\n", __FUNCTION__); 280 US_DEBUGP("%s called\n", __FUNCTION__);
278 281
279 /* The USB subsystem doesn't handle synchronisation between
280 * a device's several drivers. Therefore we reset only devices
281 * with just one interface, which we of course own. */
282
283 down(&(us->dev_semaphore)); 282 down(&(us->dev_semaphore));
284 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { 283 result = usb_stor_port_reset(us);
285 result = -EIO;
286 US_DEBUGP("No reset during disconnect\n");
287 } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
288 result = -EBUSY;
289 US_DEBUGP("Refusing to reset a multi-interface device\n");
290 } else {
291 rc = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
292 if (rc < 0) {
293 US_DEBUGP("unable to lock device for reset: %d\n", rc);
294 result = rc;
295 } else {
296 result = usb_reset_device(us->pusb_dev);
297 if (rc)
298 usb_unlock_device(us->pusb_dev);
299 US_DEBUGP("usb_reset_device returns %d\n", result);
300 }
301 }
302 up(&(us->dev_semaphore)); 284 up(&(us->dev_semaphore));
303 285
304 /* lock the host for the return */ 286 /* lock the host for the return */
@@ -320,6 +302,14 @@ void usb_stor_report_device_reset(struct us_data *us)
320 } 302 }
321} 303}
322 304
305/* Report a driver-initiated bus reset to the SCSI layer.
306 * Calling this for a SCSI-initiated reset is unnecessary but harmless.
307 * The caller must own the SCSI host lock. */
308void usb_stor_report_bus_reset(struct us_data *us)
309{
310 scsi_report_bus_reset(us_to_host(us), 0);
311}
312
323/*********************************************************************** 313/***********************************************************************
324 * /proc/scsi/ functions 314 * /proc/scsi/ functions
325 ***********************************************************************/ 315 ***********************************************************************/
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index d0a49af026c4..737e4fa6045f 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -42,6 +42,7 @@
42#define _SCSIGLUE_H_ 42#define _SCSIGLUE_H_
43 43
44extern void usb_stor_report_device_reset(struct us_data *us); 44extern void usb_stor_report_device_reset(struct us_data *us);
45extern void usb_stor_report_bus_reset(struct us_data *us);
45 46
46extern unsigned char usb_stor_sense_invalidCDB[18]; 47extern unsigned char usb_stor_sense_invalidCDB[18];
47extern struct scsi_host_template usb_stor_host_template; 48extern struct scsi_host_template usb_stor_host_template;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 9743e289cd3b..e6b1c6cf07f2 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -266,8 +266,9 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
266 NULL, 0, 3*HZ); 266 NULL, 0, 3*HZ);
267 267
268 /* reset the endpoint toggle */ 268 /* reset the endpoint toggle */
269 usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), 269 if (result >= 0)
270 usb_pipeout(pipe), 0); 270 usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
271 usb_pipeout(pipe), 0);
271 272
272 US_DEBUGP("%s: result = %d\n", __FUNCTION__, result); 273 US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
273 return result; 274 return result;
@@ -540,15 +541,15 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
540 */ 541 */
541 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { 542 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
542 US_DEBUGP("-- command was aborted\n"); 543 US_DEBUGP("-- command was aborted\n");
543 goto Handle_Abort; 544 srb->result = DID_ABORT << 16;
545 goto Handle_Errors;
544 } 546 }
545 547
546 /* if there is a transport error, reset and don't auto-sense */ 548 /* if there is a transport error, reset and don't auto-sense */
547 if (result == USB_STOR_TRANSPORT_ERROR) { 549 if (result == USB_STOR_TRANSPORT_ERROR) {
548 US_DEBUGP("-- transport indicates error, resetting\n"); 550 US_DEBUGP("-- transport indicates error, resetting\n");
549 us->transport_reset(us);
550 srb->result = DID_ERROR << 16; 551 srb->result = DID_ERROR << 16;
551 return; 552 goto Handle_Errors;
552 } 553 }
553 554
554 /* if the transport provided its own sense data, don't auto-sense */ 555 /* if the transport provided its own sense data, don't auto-sense */
@@ -668,7 +669,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
668 669
669 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { 670 if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
670 US_DEBUGP("-- auto-sense aborted\n"); 671 US_DEBUGP("-- auto-sense aborted\n");
671 goto Handle_Abort; 672 srb->result = DID_ABORT << 16;
673 goto Handle_Errors;
672 } 674 }
673 if (temp_result != USB_STOR_TRANSPORT_GOOD) { 675 if (temp_result != USB_STOR_TRANSPORT_GOOD) {
674 US_DEBUGP("-- auto-sense failure\n"); 676 US_DEBUGP("-- auto-sense failure\n");
@@ -677,9 +679,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
677 * multi-target device, since failure of an 679 * multi-target device, since failure of an
678 * auto-sense is perfectly valid 680 * auto-sense is perfectly valid
679 */ 681 */
680 if (!(us->flags & US_FL_SCM_MULT_TARG))
681 us->transport_reset(us);
682 srb->result = DID_ERROR << 16; 682 srb->result = DID_ERROR << 16;
683 if (!(us->flags & US_FL_SCM_MULT_TARG))
684 goto Handle_Errors;
683 return; 685 return;
684 } 686 }
685 687
@@ -720,12 +722,28 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
720 722
721 return; 723 return;
722 724
723 /* abort processing: the bulk-only transport requires a reset 725 /* Error and abort processing: try to resynchronize with the device
724 * following an abort */ 726 * by issuing a port reset. If that fails, try a class-specific
725 Handle_Abort: 727 * device reset. */
726 srb->result = DID_ABORT << 16; 728 Handle_Errors:
727 if (us->protocol == US_PR_BULK) 729
730 /* Let the SCSI layer know we are doing a reset, set the
731 * RESETTING bit, and clear the ABORTING bit so that the reset
732 * may proceed. */
733 scsi_lock(us_to_host(us));
734 usb_stor_report_bus_reset(us);
735 set_bit(US_FLIDX_RESETTING, &us->flags);
736 clear_bit(US_FLIDX_ABORTING, &us->flags);
737 scsi_unlock(us_to_host(us));
738
739 result = usb_stor_port_reset(us);
740 if (result < 0) {
741 scsi_lock(us_to_host(us));
742 usb_stor_report_device_reset(us);
743 scsi_unlock(us_to_host(us));
728 us->transport_reset(us); 744 us->transport_reset(us);
745 }
746 clear_bit(US_FLIDX_RESETTING, &us->flags);
729} 747}
730 748
731/* Stop the current URB transfer */ 749/* Stop the current URB transfer */
@@ -1124,7 +1142,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
1124 * It's handy that every transport mechanism uses the control endpoint for 1142 * It's handy that every transport mechanism uses the control endpoint for
1125 * resets. 1143 * resets.
1126 * 1144 *
1127 * Basically, we send a reset with a 20-second timeout, so we don't get 1145 * Basically, we send a reset with a 5-second timeout, so we don't get
1128 * jammed attempting to do the reset. 1146 * jammed attempting to do the reset.
1129 */ 1147 */
1130static int usb_stor_reset_common(struct us_data *us, 1148static int usb_stor_reset_common(struct us_data *us,
@@ -1133,28 +1151,18 @@ static int usb_stor_reset_common(struct us_data *us,
1133{ 1151{
1134 int result; 1152 int result;
1135 int result2; 1153 int result2;
1136 int rc = FAILED;
1137 1154
1138 /* Let the SCSI layer know we are doing a reset, set the 1155 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
1139 * RESETTING bit, and clear the ABORTING bit so that the reset 1156 US_DEBUGP("No reset during disconnect\n");
1140 * may proceed. 1157 return -EIO;
1141 */ 1158 }
1142 scsi_lock(us_to_host(us));
1143 usb_stor_report_device_reset(us);
1144 set_bit(US_FLIDX_RESETTING, &us->flags);
1145 clear_bit(US_FLIDX_ABORTING, &us->flags);
1146 scsi_unlock(us_to_host(us));
1147 1159
1148 /* A 20-second timeout may seem rather long, but a LaCie
1149 * StudioDrive USB2 device takes 16+ seconds to get going
1150 * following a powerup or USB attach event.
1151 */
1152 result = usb_stor_control_msg(us, us->send_ctrl_pipe, 1160 result = usb_stor_control_msg(us, us->send_ctrl_pipe,
1153 request, requesttype, value, index, data, size, 1161 request, requesttype, value, index, data, size,
1154 20*HZ); 1162 5*HZ);
1155 if (result < 0) { 1163 if (result < 0) {
1156 US_DEBUGP("Soft reset failed: %d\n", result); 1164 US_DEBUGP("Soft reset failed: %d\n", result);
1157 goto Done; 1165 return result;
1158 } 1166 }
1159 1167
1160 /* Give the device some time to recover from the reset, 1168 /* Give the device some time to recover from the reset,
@@ -1164,7 +1172,7 @@ static int usb_stor_reset_common(struct us_data *us,
1164 HZ*6); 1172 HZ*6);
1165 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { 1173 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
1166 US_DEBUGP("Reset interrupted by disconnect\n"); 1174 US_DEBUGP("Reset interrupted by disconnect\n");
1167 goto Done; 1175 return -EIO;
1168 } 1176 }
1169 1177
1170 US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); 1178 US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
@@ -1173,17 +1181,14 @@ static int usb_stor_reset_common(struct us_data *us,
1173 US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); 1181 US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
1174 result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); 1182 result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
1175 1183
1176 /* return a result code based on the result of the control message */ 1184 /* return a result code based on the result of the clear-halts */
1177 if (result < 0 || result2 < 0) { 1185 if (result >= 0)
1186 result = result2;
1187 if (result < 0)
1178 US_DEBUGP("Soft reset failed\n"); 1188 US_DEBUGP("Soft reset failed\n");
1179 goto Done; 1189 else
1180 } 1190 US_DEBUGP("Soft reset done\n");
1181 US_DEBUGP("Soft reset done\n"); 1191 return result;
1182 rc = SUCCESS;
1183
1184 Done:
1185 clear_bit(US_FLIDX_RESETTING, &us->flags);
1186 return rc;
1187} 1192}
1188 1193
1189/* This issues a CB[I] Reset to the device in question 1194/* This issues a CB[I] Reset to the device in question
@@ -1213,3 +1218,32 @@ int usb_stor_Bulk_reset(struct us_data *us)
1213 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 1218 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1214 0, us->ifnum, NULL, 0); 1219 0, us->ifnum, NULL, 0);
1215} 1220}
1221
1222/* Issue a USB port reset to the device. But don't do anything if
1223 * there's more than one interface in the device, so that other users
1224 * are not affected. */
1225int usb_stor_port_reset(struct us_data *us)
1226{
1227 int result, rc;
1228
1229 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
1230 result = -EIO;
1231 US_DEBUGP("No reset during disconnect\n");
1232 } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
1233 result = -EBUSY;
1234 US_DEBUGP("Refusing to reset a multi-interface device\n");
1235 } else {
1236 result = rc =
1237 usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
1238 if (result < 0) {
1239 US_DEBUGP("unable to lock device for reset: %d\n",
1240 result);
1241 } else {
1242 result = usb_reset_device(us->pusb_dev);
1243 if (rc)
1244 usb_unlock_device(us->pusb_dev);
1245 US_DEBUGP("usb_reset_device returns %d\n", result);
1246 }
1247 }
1248 return result;
1249}
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index e25f8d8fc741..8d9e0663f8fe 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -171,4 +171,5 @@ extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
171extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, 171extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
172 void *buf, unsigned int length, int use_sg, int *residual); 172 void *buf, unsigned int length, int use_sg, int *residual);
173 173
174extern int usb_stor_port_reset(struct us_data *us);
174#endif 175#endif