Don't arbitrarily set SCSI_NOSLEEP. It is now handled correctly by the

higher level scsi code.

Spls should never be conditionalized, so don't do so here.

Restructure the get_scb routine so that we can't get into an infinite
loop if the ccbs are exhausted and we are are called with SCSI_NOSLEEP set.

Other driver maintainer's that based their scb allocation routines on Julian's
code should look at these changes and implement them for their driver.

The aic7xxx driver inspired these changes because early revs of the
aic7770 chips have so few SCBs that you can actually run out.  If you
have a rev C or aic7770 (as is reported by the driver probe) and had more
than 2 drives, you could get into an infinite loop when using up all of
the SCBs.  Since the driver will only allow two SCBs per device and I
only had two devices, I never saw this problem on my Rev C card.

Bzero only 19 bytes of the scb instead of 2k (ack!).  This was a hold
over from when a struct SCB only contained the information downloaded
to the board, but we now store kernel driver data in there as well.  This
greatly lowers the overhead for small transactions (I get ~1MB/sec for
dds with a 512 byte block size).

Submitted by: John Dyson with the aic7xxx specific optimization by me
This commit is contained in:
Justin T. Gibbs 1995-04-23 22:04:58 +00:00
parent 12930dab88
commit c6baec432a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=8032
2 changed files with 39 additions and 22 deletions

View File

@ -24,7 +24,7 @@
*
* commenced: Sun Sep 27 18:14:01 PDT 1992
*
* $Id: aic7xxx.c,v 1.20 1995/04/09 06:39:01 gibbs Exp $
* $Id: aic7xxx.c,v 1.21 1995/04/15 21:37:32 gibbs Exp $
*/
/*
* TODO:
@ -1081,6 +1081,7 @@ ahcintr(unit)
sg->addr = KVTOPHYS(&xs->sense);
sg->len = sizeof(struct scsi_sense_data);
scb->target_channel_lun = tcl;
scb->SG_segment_count = 1;
scb->SG_list_pointer = KVTOPHYS(sg);
@ -1144,6 +1145,9 @@ ahcintr(unit)
scb->xs->resid = (inb(iobase+SCBARRAY+17) << 16) |
(inb(iobase+SCBARRAY+16) << 8) |
inb(iobase+SCBARRAY+15);
#ifdef AHC_DEBUG
printf("ahc: Handled Residual\n");
#endif
break;
}
case ABORT_TAG:
@ -1675,8 +1679,6 @@ ahc_scsi_cmd(xs)
* then we can't allow it to sleep
*/
flags = xs->flags;
if (xs->bp)
flags |= (SCSI_NOSLEEP); /* just to be sure */
if (flags & ITSDONE) {
printf("ahc%d: Already done?", unit);
xs->flags &= ~ITSDONE;
@ -1844,15 +1846,17 @@ ahc_free_scb(unit, scb, flags)
int unit, flags;
struct scb *scb;
{
unsigned int opri = 0;
unsigned int opri;
struct ahc_data *ahc = ahcdata[unit];
if (!(flags & SCSI_NOMASK))
opri = splbio();
opri = splbio();
scb->flags = SCB_FREE;
scb->next = ahc->free_scb;
ahc->free_scb = scb;
#ifdef AHC_DEBUG
ahc->activescbs--;
#endif
/*
* If there were none, wake abybody waiting for
* one to come free, starting with queued entries
@ -1860,8 +1864,7 @@ ahc_free_scb(unit, scb, flags)
if (!scb->next) {
wakeup((caddr_t)&ahc->free_scb);
}
if (!(flags & SCSI_NOMASK))
splx(opri);
splx(opri);
}
/*
@ -1874,12 +1877,10 @@ ahc_get_scb(unit, flags)
int unit, flags;
{
struct ahc_data *ahc = ahcdata[unit];
unsigned opri = 0;
unsigned opri;
struct scb *scbp;
int position;
if (!(flags & SCSI_NOMASK))
opri = splbio();
opri = splbio();
/*
* If we can and have to, sleep waiting for one to come free
* but only if we can't allocate a new one.
@ -1925,24 +1926,32 @@ ahc_get_scb(unit, flags)
} else {
printf("ahc%d: Can't malloc SCB\n", unit);
} goto gottit;
}
break;
} else {
if (!(flags & SCSI_NOSLEEP)) {
tsleep((caddr_t)&ahc->free_scb, PRIBIO,
"ahcscb", 0);
continue;
}
break;
}
} if (scbp) {
}
if (scbp) {
/* Get SCB from from free list */
ahc->free_scb = scbp->next;
/* preserve the position */
position = scbp->position;
bzero(scbp, sizeof(struct scb));
bzero(scbp, SCB_BZERO_SIZE);
scbp->flags = SCB_ACTIVE;
scbp->position = position;
#ifdef AHC_DEBUG
ahc->activescbs++;
if( ahc->activescbs == ahc->maxscbs )
printf("ahc%d: Max SCBs active\n", unit);
#endif
}
gottit: if (!(flags & SCSI_NOMASK))
splx(opri);
gottit:
splx(opri);
return (scbp);
}

View File

@ -20,7 +20,7 @@
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
* $Id: aic7xxx.h,v 1.4 1995/02/22 01:43:25 gibbs Exp $
* $Id: aic7xxx.h,v 1.5 1995/03/31 13:54:41 gibbs Exp $
*/
#ifndef _AIC7XXX_H_
@ -88,9 +88,16 @@ struct scb {
/*18*/ u_char residual_data_count[3];
/*19*/ u_char residual_SG_segment_count;
#define SCB_DOWN_SIZE 19 /* amount to actually download */
#define SCB_BZERO_SIZE 19 /*
* amount we need to clear between
* commands
*/
/*23*/ physaddr data __attribute__ ((packed));
/*26*/ u_char datalen[3];
#define SCB_UP_SIZE 26 /* amount to actually upload */
#define SCB_UP_SIZE 26 /*
* amount we need to upload to perform
* a request sense.
*/
/*30*/ physaddr host_scb __attribute__ ((packed));
#if 0
/*
@ -136,6 +143,7 @@ struct ahc_data {
u_short wdtrpending; /* Pending WDTR to these targets */
u_short tagenable; /* Targets that can handle tagqueing */
int numscbs;
int activescbs;
u_char maxscbs;
u_char unpause;
u_char pause;