summaryrefslogtreecommitdiffstats
path: root/sys/cam/cam_periph.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2009-11-14 20:13:38 +0000
committermav <mav@FreeBSD.org>2009-11-14 20:13:38 +0000
commit2f5418e2b9f72a27fd6515faa265998fda9f1d0b (patch)
tree352bf63383ab97b930ea51f43c617d5cf95be212 /sys/cam/cam_periph.c
parent65ae6957dab32b28124a7f314768cb788541ec8c (diff)
downloadFreeBSD-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.c59
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);
+ }
+ }
}
/*
OpenPOWER on IntegriCloud