Add a spin lock that prevents the sequencer from attempting to add an
entry to the QOUTFIFO when it is full. This should eliminate the "Timed out while idle" problems that many have reported. In truth, this is somewhat of a hack. Although are interrupt latency is low enough that we should be able to always service the queue in time, since each entry must be passed up to the higher SCSI layer for what can be a large amount of processing (perhaps even resulting in a new command being queued) with interrupts disabled, we need this mechanism to avoid overflow. In the future, these additional tasks will be offloaded to a software interrupt handler which should make this hack unnecessary.
This commit is contained in:
parent
696a50cd5d
commit
083bc8b2cc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=28169
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.reg,v 1.3 1997/04/24 16:52:16 gibbs Exp $
|
||||
* $Id: aic7xxx.reg,v 1.4 1997/06/27 19:38:39 gibbs Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -1079,6 +1079,21 @@ scratch_ram {
|
||||
CUR_SCBID {
|
||||
size 1
|
||||
}
|
||||
/*
|
||||
* Running count of commands placed in
|
||||
* the QOUTFIFO. This is cleared by the
|
||||
* kernel driver every FIFODEPTH commands.
|
||||
*/
|
||||
CMDOUTCNT {
|
||||
size 1
|
||||
}
|
||||
/*
|
||||
* Maximum number of entries allowed in
|
||||
* the QOUT/INFIFO.
|
||||
*/
|
||||
FIFODEPTH {
|
||||
size 1
|
||||
}
|
||||
ARG_1 {
|
||||
size 1
|
||||
mask SEND_MSG 0x80
|
||||
|
@ -35,7 +35,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.seq,v 1.73 1997/04/24 16:52:18 gibbs Exp $
|
||||
* $Id: aic7xxx.seq,v 1.74 1997/06/27 19:38:42 gibbs Exp $
|
||||
*/
|
||||
|
||||
#include <dev/aic7xxx/aic7xxx.reg>
|
||||
@ -643,6 +643,15 @@ status_ok:
|
||||
|
||||
complete:
|
||||
/* Post the SCB and issue an interrupt */
|
||||
.if ( SCB_PAGING )
|
||||
/*
|
||||
* Spin loop until there is space
|
||||
* in the QOUTFIFO.
|
||||
*/
|
||||
mov A, FIFODEPTH;
|
||||
cmp CMDOUTCNT, A je .;
|
||||
inc CMDOUTCNT;
|
||||
.endif
|
||||
mov QOUTFIFO,SCB_TAG;
|
||||
mvi INTSTAT,CMDCMPLT;
|
||||
test SCB_CONTROL, ABORT_SCB jz dma_next_scb;
|
||||
|
@ -39,7 +39,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.119 1997/06/27 19:39:18 gibbs Exp $
|
||||
* $Id: aic7xxx.c,v 1.120 1997/07/20 16:21:34 bde Exp $
|
||||
*/
|
||||
/*
|
||||
* TODO:
|
||||
@ -479,6 +479,7 @@ ahc_construct(ahc, bc, ioh, maddr, type, flags)
|
||||
} else
|
||||
ahc->scb_data = scb_data;
|
||||
STAILQ_INIT(&ahc->waiting_scbs);
|
||||
STAILQ_INIT(&ahc->cmplete_scbs);
|
||||
#if defined(__FreeBSD__)
|
||||
ahc->unit = unit;
|
||||
#endif
|
||||
@ -784,6 +785,7 @@ ahc_intr(arg)
|
||||
|
||||
int_cleared = 0;
|
||||
while (qoutcnt = (ahc_inb(ahc, QOUTCNT) & ahc->qcntmask)) {
|
||||
ahc->cmdoutcnt += qoutcnt;
|
||||
for (; qoutcnt > 0; qoutcnt--) {
|
||||
scb_index = ahc_inb(ahc, QOUTFIFO);
|
||||
scb = ahc->scb_data->scbarray[scb_index];
|
||||
@ -795,6 +797,23 @@ ahc_intr(arg)
|
||||
qoutcnt);
|
||||
continue;
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&ahc->cmplete_scbs, scb,
|
||||
links);
|
||||
}
|
||||
if ((ahc->flags & AHC_PAGESCBS) != 0) {
|
||||
if (ahc->cmdoutcnt >= ahc->qfullcount) {
|
||||
/*
|
||||
* Since paging only occurs on
|
||||
* aic78X0 chips, we can use
|
||||
* Auto Access Pause to clear
|
||||
* the command count.
|
||||
*/
|
||||
ahc_outb(ahc, CMDOUTCNT, 0);
|
||||
ahc->cmdoutcnt = 0;
|
||||
}
|
||||
}
|
||||
while((scb = ahc->cmplete_scbs.stqh_first) != NULL) {
|
||||
STAILQ_REMOVE_HEAD(&ahc->cmplete_scbs, links);
|
||||
/*
|
||||
* Save off the residual if there is one.
|
||||
*/
|
||||
@ -2306,6 +2325,9 @@ ahc_init(ahc)
|
||||
*/
|
||||
ahc_outb(ahc, QCNTMASK, ahc->qcntmask);
|
||||
|
||||
ahc_outb(ahc, FIFODEPTH, ahc->qfullcount);
|
||||
ahc_outb(ahc, CMDOUTCNT, 0);
|
||||
|
||||
/* We don't have any waiting selections */
|
||||
ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);
|
||||
|
||||
@ -2581,14 +2603,13 @@ ahc_run_waiting_queue(ahc)
|
||||
|
||||
pause_sequencer(ahc);
|
||||
|
||||
while ((scb = ahc->waiting_scbs.stqh_first) != NULL) {
|
||||
if (ahc->curqincnt >= ahc->qfullcount) {
|
||||
ahc->curqincnt = ahc_inb(ahc, QINCNT) & ahc->qcntmask;
|
||||
}
|
||||
|
||||
while ((scb = ahc->waiting_scbs.stqh_first) != NULL
|
||||
&& (ahc->curqincnt < ahc->qfullcount)) {
|
||||
|
||||
if (ahc->curqincnt >= ahc->qfullcount) {
|
||||
ahc->curqincnt = ahc_inb(ahc, QINCNT) & ahc->qcntmask;
|
||||
if (ahc->curqincnt >= ahc->qfullcount)
|
||||
/* Still no space */
|
||||
break;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
|
||||
scb->flags &= ~SCB_WAITINGQ;
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: aic7xxx.h,v 1.40 1997/02/25 03:05:35 gibbs Exp $
|
||||
* $Id: aic7xxx.h,v 1.41 1997/06/27 19:39:20 gibbs Exp $
|
||||
*/
|
||||
|
||||
#ifndef _AIC7XXX_H_
|
||||
@ -264,7 +264,12 @@ struct ahc_softc {
|
||||
* SCBs waiting ready to go but
|
||||
* waiting for space in the QINFIFO.
|
||||
*/
|
||||
STAILQ_HEAD(, scb) cmplete_scbs;/*
|
||||
* SCBs out of the QOUTFIFO, waiting
|
||||
* to be ahc_done'd.
|
||||
*/
|
||||
u_int8_t activescbs;
|
||||
u_int8_t cmdoutcnt;
|
||||
u_int16_t needsdtr_orig; /* Targets we initiate sync neg with */
|
||||
u_int16_t needwdtr_orig; /* Targets we initiate wide neg with */
|
||||
u_int16_t needsdtr; /* Current list of negotiated targets */
|
||||
|
Loading…
Reference in New Issue
Block a user