diff options
author | mav <mav@FreeBSD.org> | 2009-11-14 20:13:38 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2009-11-14 20:13:38 +0000 |
commit | 2f5418e2b9f72a27fd6515faa265998fda9f1d0b (patch) | |
tree | 352bf63383ab97b930ea51f43c617d5cf95be212 /sys/cam | |
parent | 65ae6957dab32b28124a7f314768cb788541ec8c (diff) | |
download | FreeBSD-src-2f5418e2b9f72a27fd6515faa265998fda9f1d0b.zip FreeBSD-src-2f5418e2b9f72a27fd6515faa265998fda9f1d0b.tar.gz |
MFp4:
Fix several device freeze counting bugs.
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/cam_periph.c | 59 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_cd.c | 6 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_ch.c | 3 |
3 files changed, 42 insertions, 26 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 70764c6..63cc2c6 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -981,16 +981,21 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb) { union ccb *saved_ccb; cam_status status; - int frozen; + int frozen = 0; int sense; struct scsi_start_stop_unit *scsi_cmd; u_int32_t relsim_flags, timeout; - u_int32_t qfrozen_cnt; - int xpt_done_ccb; + int xpt_done_ccb = FALSE; - xpt_done_ccb = FALSE; status = done_ccb->ccb_h.status; - frozen = (status & CAM_DEV_QFRZN) != 0; + if (status & CAM_DEV_QFRZN) { + frozen = 1; + /* + * Clear freeze flag now for case of retry, + * freeze will be dropped later. + */ + done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; + } sense = (status & CAM_AUTOSNS_VALID) != 0; status &= CAM_STATUS_MASK; @@ -998,17 +1003,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb) relsim_flags = 0; saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr; - /* - * Unfreeze the queue once if it is already frozen.. - */ - if (frozen != 0) { - qfrozen_cnt = cam_release_devq(done_ccb->ccb_h.path, - /*relsim_flags*/0, - /*openings*/0, - /*timeout*/0, - /*getcount_only*/0); - } - switch (status) { case CAM_REQ_CMP: { @@ -1185,14 +1179,33 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb) */ if (done_ccb->ccb_h.retry_count > 0) done_ccb->ccb_h.retry_count--; - - qfrozen_cnt = cam_release_devq(done_ccb->ccb_h.path, - /*relsim_flags*/relsim_flags, - /*openings*/0, - /*timeout*/timeout, - /*getcount_only*/0); - if (xpt_done_ccb == TRUE) + /* + * Drop freeze taken due to CAM_DEV_QFREEZE flag set on recovery + * request. + */ + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/relsim_flags, + /*openings*/0, + /*timeout*/timeout, + /*getcount_only*/0); + if (xpt_done_ccb == TRUE) { + /* + * Copy frozen flag from recovery request if it is set there + * for some reason. + */ + if (frozen != 0) + done_ccb->ccb_h.status |= CAM_DEV_QFRZN; (*done_ccb->ccb_h.cbfcnp)(periph, done_ccb); + } else { + /* Drop freeze taken, if this recovery request got error. */ + if (frozen != 0) { + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*openings*/0, + /*timeout*/0, + /*getcount_only*/0); + } + } } /* diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index f2a612b..7bd6158 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -1570,7 +1570,8 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) bp->bio_resid = bp->bio_bcount; bp->bio_error = error; bp->bio_flags |= BIO_ERROR; - cam_release_devq(done_ccb->ccb_h.path, + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(done_ccb->ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, @@ -1658,7 +1659,8 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) struct ccb_getdev cgd; /* Don't wedge this device's queue */ - cam_release_devq(done_ccb->ccb_h.path, + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(done_ccb->ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c index 781245a..2829a15 100644 --- a/sys/cam/scsi/scsi_ch.c +++ b/sys/cam/scsi/scsi_ch.c @@ -606,7 +606,8 @@ chdone(struct cam_periph *periph, union ccb *done_ccb) retry_scheduled = 0; /* Don't wedge this device's queue */ - cam_release_devq(done_ccb->ccb_h.path, + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(done_ccb->ccb_h.path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, |