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/cam_periph.c | |
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/cam_periph.c')
-rw-r--r-- | sys/cam/cam_periph.c | 59 |
1 files changed, 36 insertions, 23 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); + } + } } /* |