Fix some more problems in the recovery code.
Cleanup of the disconnected list was broken in the SCB paging case (confusion of NULLand SCB_LIST_NULL) Implement a clean mechanism for determining that we have exited the timeout state and test for this in ahc_done instead of all over the place. Bring back the use of AAP (Auto Access Pause) I don't think it was the true cause of the bus hangs people were reporting. We want to reset the bus if we've been through an Abort action, not if we are a recovery SCB (one implies the other, but not vice-versa).
This commit is contained in:
parent
78b845fbdb
commit
87dca7091f
@ -1545,13 +1545,6 @@ ahc_handle_scsiint(ahc, intstat)
|
|||||||
ahc_run_done_queue(ahc);
|
ahc_run_done_queue(ahc);
|
||||||
scb = NULL;
|
scb = NULL;
|
||||||
printerror = 0;
|
printerror = 0;
|
||||||
/*
|
|
||||||
* We only send these for
|
|
||||||
* error recovery, so if it
|
|
||||||
* worked, we're no longer in
|
|
||||||
* a timeout.
|
|
||||||
*/
|
|
||||||
ahc->in_timeout = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1727,7 +1720,6 @@ ahc_handle_devreset(ahc, scb)
|
|||||||
XS_NOERROR);
|
XS_NOERROR);
|
||||||
sc_print_addr(scb->xs->sc_link);
|
sc_print_addr(scb->xs->sc_link);
|
||||||
printf("Bus Device Reset delivered. %d SCBs aborted\n", found);
|
printf("Bus Device Reset delivered. %d SCBs aborted\n", found);
|
||||||
ahc->in_timeout = FALSE;
|
|
||||||
ahc_run_done_queue(ahc);
|
ahc_run_done_queue(ahc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1754,7 +1746,8 @@ ahc_done(ahc, scb)
|
|||||||
xs->error = XS_TIMEOUT;
|
xs->error = XS_TIMEOUT;
|
||||||
} else if (scb->flags & SCB_SENSE)
|
} else if (scb->flags & SCB_SENSE)
|
||||||
xs->error = XS_SENSE;
|
xs->error = XS_SENSE;
|
||||||
if (scb->flags & SCB_SENTORDEREDTAG)
|
|
||||||
|
if (scb->flags & SCB_RECOVERY_SCB)
|
||||||
ahc->in_timeout = FALSE;
|
ahc->in_timeout = FALSE;
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
if ((xs->flags & SCSI_ERR_OK) && !(xs->error == XS_SENSE)) {
|
if ((xs->flags & SCSI_ERR_OK) && !(xs->error == XS_SENSE)) {
|
||||||
@ -2454,7 +2447,12 @@ ahc_run_waiting_queue(ahc)
|
|||||||
{
|
{
|
||||||
struct scb *scb;
|
struct scb *scb;
|
||||||
|
|
||||||
pause_sequencer(ahc);
|
/*
|
||||||
|
* On aic78X0 chips, we rely on Auto Access Pause (AAP)
|
||||||
|
* instead of doing an explicit pause/unpause.
|
||||||
|
*/
|
||||||
|
if ((ahc->type & AHC_AIC78X0) == 0)
|
||||||
|
pause_sequencer(ahc);
|
||||||
|
|
||||||
while ((scb = ahc->waiting_scbs.stqh_first) != NULL) {
|
while ((scb = ahc->waiting_scbs.stqh_first) != NULL) {
|
||||||
|
|
||||||
@ -2475,7 +2473,8 @@ ahc_run_waiting_queue(ahc)
|
|||||||
*/
|
*/
|
||||||
ahc->curqincnt++;
|
ahc->curqincnt++;
|
||||||
}
|
}
|
||||||
unpause_sequencer(ahc, /*Unpause always*/FALSE);
|
if ((ahc->type & AHC_AIC78X0) == 0)
|
||||||
|
unpause_sequencer(ahc, /*Unpause always*/FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2781,7 +2780,7 @@ ahc_timeout(arg)
|
|||||||
/* Decide our course of action */
|
/* Decide our course of action */
|
||||||
|
|
||||||
channel = (scb->hscb->tcl & SELBUSB) ? 'B': 'A';
|
channel = (scb->hscb->tcl & SELBUSB) ? 'B': 'A';
|
||||||
if (scb->flags & SCB_RECOVERY_SCB) {
|
if (scb->flags & SCB_ABORT) {
|
||||||
/*
|
/*
|
||||||
* Been down this road before.
|
* Been down this road before.
|
||||||
* Do a full bus reset.
|
* Do a full bus reset.
|
||||||
@ -2790,7 +2789,6 @@ ahc_timeout(arg)
|
|||||||
/*Initiate Reset*/TRUE);
|
/*Initiate Reset*/TRUE);
|
||||||
printf("%s: Issued Channel %c Bus Reset. "
|
printf("%s: Issued Channel %c Bus Reset. "
|
||||||
"%d SCBs aborted\n", ahc_name(ahc), channel, found);
|
"%d SCBs aborted\n", ahc_name(ahc), channel, found);
|
||||||
ahc->in_timeout = FALSE;
|
|
||||||
} else if ((scb->hscb->control & TAG_ENB) != 0
|
} else if ((scb->hscb->control & TAG_ENB) != 0
|
||||||
&& (scb->flags & SCB_SENTORDEREDTAG) == 0) {
|
&& (scb->flags & SCB_SENTORDEREDTAG) == 0) {
|
||||||
/*
|
/*
|
||||||
@ -2898,7 +2896,7 @@ ahc_timeout(arg)
|
|||||||
STAILQ_INSERT_HEAD(&ahc->waiting_scbs, scb,
|
STAILQ_INSERT_HEAD(&ahc->waiting_scbs, scb,
|
||||||
links);
|
links);
|
||||||
timeout(ahc_timeout, (caddr_t)scb,
|
timeout(ahc_timeout, (caddr_t)scb,
|
||||||
(100 * hz) / 1000);
|
(200 * hz) / 1000);
|
||||||
ahc_run_waiting_queue(ahc);
|
ahc_run_waiting_queue(ahc);
|
||||||
}
|
}
|
||||||
ahc_outb(ahc, SCBPTR, saved_scbptr);
|
ahc_outb(ahc, SCBPTR, saved_scbptr);
|
||||||
@ -2968,7 +2966,8 @@ ahc_search_qinfifo(ahc, target, channel, tag, flags, xs_error, requeue)
|
|||||||
if (requeue) {
|
if (requeue) {
|
||||||
STAILQ_INSERT_TAIL(&removed_scbs, scbp, links);
|
STAILQ_INSERT_TAIL(&removed_scbs, scbp, links);
|
||||||
} else {
|
} else {
|
||||||
scbp->flags = flags;
|
scbp->flags |= flags;
|
||||||
|
scbp->flags &= ~SCB_ACTIVE;
|
||||||
scbp->xs->error = xs_error;
|
scbp->xs->error = xs_error;
|
||||||
untimeout(ahc_timeout, (caddr_t)scbp);
|
untimeout(ahc_timeout, (caddr_t)scbp);
|
||||||
}
|
}
|
||||||
@ -3028,8 +3027,16 @@ ahc_reset_device(ahc, target, channel, tag, xs_error)
|
|||||||
prev = SCB_LIST_NULL;
|
prev = SCB_LIST_NULL;
|
||||||
|
|
||||||
while (next != SCB_LIST_NULL) {
|
while (next != SCB_LIST_NULL) {
|
||||||
|
u_int8_t scb_index;
|
||||||
|
|
||||||
ahc_outb(ahc, SCBPTR, next);
|
ahc_outb(ahc, SCBPTR, next);
|
||||||
scbp = ahc->scb_data->scbarray[ahc_inb(ahc, SCB_TAG)];
|
scb_index = ahc_inb(ahc, SCB_TAG);
|
||||||
|
if (scb_index >= ahc->scb_data->numscbs) {
|
||||||
|
panic("Waiting List inconsistency. "
|
||||||
|
"SCB index == 0x%d, yet numscbs = 0x%d",
|
||||||
|
scb_index, ahc->scb_data->numscbs);
|
||||||
|
}
|
||||||
|
scbp = ahc->scb_data->scbarray[scb_index];
|
||||||
if (ahc_match_scb(scbp, target, channel, tag)) {
|
if (ahc_match_scb(scbp, target, channel, tag)) {
|
||||||
next = ahc_abort_wscb(ahc, scbp, next, prev,
|
next = ahc_abort_wscb(ahc, scbp, next, prev,
|
||||||
xs_error);
|
xs_error);
|
||||||
@ -3054,7 +3061,8 @@ ahc_reset_device(ahc, target, channel, tag, xs_error)
|
|||||||
ahc_unbusy_target(ahc, target,
|
ahc_unbusy_target(ahc, target,
|
||||||
(scbp->hscb->tcl & SELBUSB) ?
|
(scbp->hscb->tcl & SELBUSB) ?
|
||||||
'B' : 'A');
|
'B' : 'A');
|
||||||
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
|
scbp->flags |= SCB_ABORTED|SCB_QUEUED_FOR_DONE;
|
||||||
|
scbp->flags &= ~SCB_ACTIVE;
|
||||||
scbp->xs->error = xs_error;
|
scbp->xs->error = xs_error;
|
||||||
untimeout(ahc_timeout, (caddr_t)scbp);
|
untimeout(ahc_timeout, (caddr_t)scbp);
|
||||||
found++;
|
found++;
|
||||||
@ -3072,7 +3080,15 @@ ahc_reset_device(ahc, target, channel, tag, xs_error)
|
|||||||
prev = SCB_LIST_NULL;
|
prev = SCB_LIST_NULL;
|
||||||
|
|
||||||
while (next != SCB_LIST_NULL) {
|
while (next != SCB_LIST_NULL) {
|
||||||
|
u_int8_t scb_index;
|
||||||
|
|
||||||
ahc_outb(ahc, SCBPTR, next);
|
ahc_outb(ahc, SCBPTR, next);
|
||||||
|
scb_index = ahc_inb(ahc, SCB_TAG);
|
||||||
|
if (scb_index >= ahc->scb_data->numscbs) {
|
||||||
|
panic("Disconnected List inconsistency. "
|
||||||
|
"SCB index == 0x%d, yet numscbs = 0x%d",
|
||||||
|
scb_index, ahc->scb_data->numscbs);
|
||||||
|
}
|
||||||
scbp = ahc->scb_data->scbarray[ahc_inb(ahc, SCB_TAG)];
|
scbp = ahc->scb_data->scbarray[ahc_inb(ahc, SCB_TAG)];
|
||||||
if (ahc_match_scb(scbp, target, channel, tag)) {
|
if (ahc_match_scb(scbp, target, channel, tag)) {
|
||||||
u_int8_t curpos;
|
u_int8_t curpos;
|
||||||
@ -3086,13 +3102,13 @@ ahc_reset_device(ahc, target, channel, tag, xs_error)
|
|||||||
ahc_inb(ahc, FREE_SCBH));
|
ahc_inb(ahc, FREE_SCBH));
|
||||||
ahc_outb(ahc, FREE_SCBH, curpos);
|
ahc_outb(ahc, FREE_SCBH, curpos);
|
||||||
|
|
||||||
if (prev != NULL) {
|
if (prev != SCB_LIST_NULL) {
|
||||||
ahc_outb(ahc, SCBPTR, prev);
|
ahc_outb(ahc, SCBPTR, prev);
|
||||||
ahc_outb(ahc, SCB_NEXT, next);
|
ahc_outb(ahc, SCB_NEXT, next);
|
||||||
} else
|
} else
|
||||||
ahc_outb(ahc, DISCONNECTED_SCBH, next);
|
ahc_outb(ahc, DISCONNECTED_SCBH, next);
|
||||||
|
|
||||||
if (next != NULL) {
|
if (next != SCB_LIST_NULL) {
|
||||||
ahc_outb(ahc, SCBPTR, next);
|
ahc_outb(ahc, SCBPTR, next);
|
||||||
ahc_outb(ahc, SCB_NEXT, prev);
|
ahc_outb(ahc, SCB_NEXT, prev);
|
||||||
}
|
}
|
||||||
@ -3157,7 +3173,8 @@ ahc_abort_wscb (ahc, scbp, scbpos, prev, xs_error)
|
|||||||
* has been aborted.
|
* has been aborted.
|
||||||
*/
|
*/
|
||||||
ahc_outb(ahc, SCBPTR, curscb);
|
ahc_outb(ahc, SCBPTR, curscb);
|
||||||
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
|
scbp->flags |= SCB_ABORTED|SCB_QUEUED_FOR_DONE;
|
||||||
|
scbp->flags &= ~SCB_ACTIVE;
|
||||||
scbp->xs->error = xs_error;
|
scbp->xs->error = xs_error;
|
||||||
untimeout(ahc_timeout, (caddr_t)scbp);
|
untimeout(ahc_timeout, (caddr_t)scbp);
|
||||||
return next;
|
return next;
|
||||||
|
Loading…
Reference in New Issue
Block a user