aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2011-04-11 08:23:27 +0000
committerAlexander Motin <mav@FreeBSD.org>2011-04-11 08:23:27 +0000
commit669d9046a932e070a7e83b671a4d484ca6c1a11e (patch)
tree86287cce7f730c32e59fc733155aea235aae67cf /sys
parent6b3664c018521138d81d439930c3dd3258ef13f4 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/storage/umass.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 208616ee9dffb..de6ad9da9a922 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -1849,9 +1849,23 @@ umass_t_cbi_command_callback(struct usb_xfer *xfer, usb_error_t error)
break;
default: /* Error */
- umass_tr_error(xfer, error);
- /* skip reset */
- sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
+ /*
+ * STALL on the control pipe can be result of the command error.
+ * Attempt to clear this STALL same as for bulk pipe also
+ * results in command completion interrupt, but ASC/ASCQ there
+ * look like not always valid, so don't bother about it.
+ */
+ if ((error == USB_ERR_STALLED) ||
+ (sc->sc_transfer.callback == &umass_cam_cb)) {
+ sc->sc_transfer.ccb = NULL;
+ (sc->sc_transfer.callback)
+ (sc, ccb, sc->sc_transfer.data_len,
+ STATUS_CMD_UNKNOWN);
+ } else {
+ umass_tr_error(xfer, error);
+ /* skip reset */
+ sc->sc_last_xfer_index = UMASS_T_CBI_COMMAND;
+ }
break;
}
}
@@ -2605,17 +2619,9 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/*
* The wire protocol failed and will hopefully have
* recovered. We return an error to CAM and let CAM
- * retry the command if necessary. In case of SCSI IO
- * commands we ask the CAM layer to check the
- * condition first. This is a quick hack to make
- * certain devices work.
+ * retry the command if necessary.
*/
- if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
- } else {
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- }
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
break;
}