summaryrefslogtreecommitdiffstats
path: root/sys/dev/arcmsr/arcmsr.c
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2007-03-06 01:12:15 +0000
committerscottl <scottl@FreeBSD.org>2007-03-06 01:12:15 +0000
commit2af792b8915a6aab423f7f69284ebc8498a1fdda (patch)
tree35989b1717c9a78ad667671116c6f65440ae88d9 /sys/dev/arcmsr/arcmsr.c
parentde1068910187cc59c6ffea68b3b754da87651362 (diff)
downloadFreeBSD-src-2af792b8915a6aab423f7f69284ebc8498a1fdda.zip
FreeBSD-src-2af792b8915a6aab423f7f69284ebc8498a1fdda.tar.gz
Better fix for the errors under high load. Returning CAM_SCSI_BUSY is almost
never correct as CAM has no real understanding of it, and will just immediately retry the command. This leads to undesirable cycling of the camisr as well as a high possibility for the command to exhaust its retries before the driver can get around to servicing it. The better fix, as demonstrated here, is to freeze the simq and mark the command as needing to be tried. Then when driver can service the command, the simq gets unfrozen. This is correct, and documented here to help reduce the mystery. However, it also points out a shortcoming in CAM error handling that makes writing drivers harder. Submitted by: Erich Chen
Diffstat (limited to 'sys/dev/arcmsr/arcmsr.c')
-rw-r--r--sys/dev/arcmsr/arcmsr.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
index 185e0da..5e2bb86 100644
--- a/sys/dev/arcmsr/arcmsr.c
+++ b/sys/dev/arcmsr/arcmsr.c
@@ -417,7 +417,12 @@ static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
}
ARCMSR_LOCK_ACQUIRE(&acb->workingQ_done_lock);
if(stand_flag==1) {
- atomic_subtract_int(&acb->srboutstandingcount, 1);
+ atomic_subtract_int(&acb->srboutstandingcount, 1);
+ if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
+ acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) {
+ acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
+ pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+ }
}
srb->startdone=ARCMSR_SRB_DONE;
srb->srb_flags=0;
@@ -1303,7 +1308,8 @@ static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, i
pccb->ccb_h.status |= CAM_SIM_QUEUED;
if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) {
pccb->ccb_h.status &= ~CAM_STATUS_MASK;
- pccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ pccb->ccb_h.status |= (CAM_REQUEUE_REQ|CAM_DEV_QFRZN);
+ acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
arcmsr_srb_complete(srb, 0);
return;
}
OpenPOWER on IntegriCloud