Freeze device queue before returning errors to CAM. This is required

for proper error recovery, including keeping original request order.

Reviewed by:	hselasky
This commit is contained in:
mav 2013-01-12 11:36:23 +00:00
parent 769d01b2aa
commit b58b763008

View File

@ -2251,8 +2251,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
/*ascq*/ 0x00, /*ascq*/ 0x00,
/*extra args*/ SSD_ELEM_NONE); /*extra args*/ SSD_ELEM_NONE);
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | ccb->ccb_h.status =
CAM_AUTOSNS_VALID; CAM_SCSI_STATUS_ERROR |
CAM_AUTOSNS_VALID |
CAM_DEV_QFRZN;
xpt_freeze_devq(ccb->ccb_h.path, 1);
xpt_done(ccb); xpt_done(ccb);
goto done; goto done;
} }
@ -2512,7 +2515,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* recovered. We return an error to CAM and let CAM * recovered. We return an error to CAM and let CAM
* retry the command if necessary. * retry the command if necessary.
*/ */
ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
xpt_done(ccb); xpt_done(ccb);
break; break;
} }
@ -2575,8 +2579,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* usual. * usual.
*/ */
xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID; | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
#if 0 #if 0
@ -2587,17 +2592,18 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/* the rest of the command was filled in at attach */ /* the rest of the command was filled in at attach */
if (umass_std_transform(sc, ccb, if ((sc->sc_transform)(sc,
&sc->cam_scsi_test_unit_ready.opcode, &sc->cam_scsi_test_unit_ready.opcode,
sizeof(sc->cam_scsi_test_unit_ready))) { sizeof(sc->cam_scsi_test_unit_ready)) == 1) {
umass_command_start(sc, DIR_NONE, NULL, 0, umass_command_start(sc, DIR_NONE, NULL, 0,
ccb->ccb_h.timeout, ccb->ccb_h.timeout,
&umass_cam_quirk_cb, ccb); &umass_cam_quirk_cb, ccb);
break;
} }
break;
} else { } else {
xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID; | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
} }
xpt_done(ccb); xpt_done(ccb);
@ -2606,15 +2612,16 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
default: default:
DPRINTF(sc, UDMASS_SCSI, "Autosense failed, " DPRINTF(sc, UDMASS_SCSI, "Autosense failed, "
"status %d\n", status); "status %d\n", status);
ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN;
xpt_done(ccb); xpt_done(ccb);
} }
} }
/* /*
* This completion code just handles the fact that we sent a test-unit-ready * This completion code just handles the fact that we sent a test-unit-ready
* after having previously failed a READ CAPACITY with CHECK_COND. Even * after having previously failed a READ CAPACITY with CHECK_COND. The CCB
* though this command succeeded, we have to tell CAM to retry. * status for CAM is already set earlier.
*/ */
static void static void
umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue, umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
@ -2623,9 +2630,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
DPRINTF(sc, UDMASS_SCSI, "Test unit ready " DPRINTF(sc, UDMASS_SCSI, "Test unit ready "
"returned status %d\n", status); "returned status %d\n", status);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
xpt_done(ccb); xpt_done(ccb);
} }
@ -2914,7 +2918,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb,
xpt_done(ccb); xpt_done(ccb);
return (0); return (0);
} else if (retval == 0) { } else if (retval == 0) {
ccb->ccb_h.status = CAM_REQ_INVALID; xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN;
xpt_done(ccb); xpt_done(ccb);
return (0); return (0);
} }