aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage/transport.c')
-rw-r--r--drivers/usb/storage/transport.c116
1 files changed, 75 insertions, 41 deletions
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}