Move some hardware-related items to the hardware-related header.

Shift to using the same queueing strategy that the amr driver uses.
Some simple tests indicate that we use about 2% of the CPU at around
500tps with the controller completely saturated with I/O.
This commit is contained in:
Mike Smith 1999-10-26 23:20:43 +00:00
parent ba2ace5164
commit 4b006d7bb7
5 changed files with 185 additions and 168 deletions

View File

@ -278,7 +278,7 @@ mlx_attach(struct mlx_softc *sc)
/*
* Initialise per-controller queues.
*/
TAILQ_INIT(&sc->mlx_donecmd);
TAILQ_INIT(&sc->mlx_work);
TAILQ_INIT(&sc->mlx_freecmds);
bufq_init(&sc->mlx_bufq);
@ -379,7 +379,7 @@ mlx_attach(struct mlx_softc *sc)
sc->mlx_hwid = me2->me_hardware_id;
/* print a little information about the controller and ourselves */
device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%d, %dMB RAM\n",
device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%02d, %dMB RAM\n",
mlx_name_controller(sc->mlx_hwid), sc->mlx_fwmajor, sc->mlx_fwminor,
me2->me_mem_size / (1024 * 1024));
free(me2, M_DEVBUF);
@ -390,16 +390,16 @@ mlx_attach(struct mlx_softc *sc)
switch(sc->mlx_iftype) {
case MLX_IFTYPE_3:
/* XXX certify 3.52? */
if (sc->mlx_fwminor != 51) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is NOT SUPPORTED\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 only\n");
if (sc->mlx_fwminor < 51) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
}
break;
case MLX_IFTYPE_4:
/* XXX certify firmware versions? */
if (sc->mlx_fwminor != 6) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is NOT SUPPORTED\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.6 only\n");
if (sc->mlx_fwminor < 6) {
device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
}
break;
default:
@ -653,10 +653,14 @@ mlx_intr(void *arg)
int
mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
{
int s;
debug("called");
s = splbio();
bufq_insert_tail(&sc->mlx_bufq, bp);
sc->mlx_waitbufs++;
splx(s);
mlx_startio(sc);
return(0);
}
@ -1557,7 +1561,7 @@ mlx_poll_command(struct mlx_command *mc)
} while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000));
if (mc->mc_status != MLX_STATUS_BUSY) {
s = splbio();
TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link);
TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
splx(s);
return(0);
}
@ -1581,8 +1585,10 @@ mlx_startio(struct mlx_softc *sc)
int blkcount;
int driveno;
int cmd;
int s;
/* spin until something prevents us from doing any work */
s = splbio();
for (;;) {
/* see if there's work to be done */
@ -1599,6 +1605,7 @@ mlx_startio(struct mlx_softc *sc)
/* get the buf containing our work */
bufq_remove(&sc->mlx_bufq, bp);
sc->mlx_waitbufs--;
splx(s);
/* connect the buf to the command */
mc->mc_complete = mlx_completeio;
@ -1643,7 +1650,9 @@ mlx_startio(struct mlx_softc *sc)
mc->mc_status = MLX_STATUS_WEDGED;
mlx_completeio(mc);
}
s = splbio();
}
splx(s);
}
/********************************************************************************
@ -1881,7 +1890,7 @@ mlx_start(struct mlx_command *mc)
/* save the slot number as ident so we can handle this command when complete */
mc->mc_mailbox[0x1] = mc->mc_slot;
/* set impossible status so that a woken sleeper can tell the command is in progress */
/* mark the command as currently being processed */
mc->mc_status = MLX_STATUS_BUSY;
/* assume we don't collect any completed commands */
@ -1890,7 +1899,11 @@ mlx_start(struct mlx_command *mc)
/* spin waiting for the mailbox */
for (i = 100000, done = 0; (i > 0) && !done; i--) {
s = splbio();
done = sc->mlx_tryqueue(sc, mc);
if (sc->mlx_tryqueue(sc, mc)) {
done = 1;
/* move command to work queue */
TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
}
splx(s);
/* check for command completion while we're at it */
if (mlx_done(sc))
@ -1931,20 +1944,17 @@ mlx_done(struct mlx_softc *sc)
debug("called");
s = splbio();
mc = NULL;
slot = 0;
/* poll for a completed command's identifier and status */
s = splbio();
if (sc->mlx_findcomplete(sc, &slot, &status)) {
mc = sc->mlx_busycmd[slot]; /* find command */
if (mc != NULL) { /* paranoia */
mc = sc->mlx_busycmd[slot]; /* find command */
if (mc != NULL) { /* paranoia */
if (mc->mc_status == MLX_STATUS_BUSY) {
mc->mc_status = status; /* save status */
/* move completed command to 'done' queue */
TAILQ_INSERT_TAIL(&sc->mlx_donecmd, mc, mc_link);
/* free slot for reuse */
sc->mlx_busycmd[slot] = NULL;
sc->mlx_busycmds--;
@ -1981,35 +1991,40 @@ mlx_complete(struct mlx_softc *sc)
count = 0;
/* scan the list of done commands */
mc = TAILQ_FIRST(&sc->mlx_donecmd);
mc = TAILQ_FIRST(&sc->mlx_work);
while (mc != NULL) {
nc = TAILQ_NEXT(mc, mc_link);
/* XXX this is slightly bogus */
if (count++ > (sc->mlx_maxiop * 2))
panic("mlx_donecmd list corrupt!");
panic("mlx_work list corrupt!");
/*
* Does the command have a completion handler?
*/
if (mc->mc_complete != NULL) {
/* remove from list and give to handler */
TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link);
mc->mc_complete(mc);
/*
* Is there a sleeper waiting on this command?
*/
} else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */
/* remove from list and wake up sleeper */
TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link);
wakeup_one(mc->mc_private);
/* Skip commands that are still busy */
if (mc->mc_status != MLX_STATUS_BUSY) {
/*
* Leave the command for a caller that's polling for it.
*/
} else {
* Does the command have a completion handler?
*/
if (mc->mc_complete != NULL) {
/* remove from list and give to handler */
TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
mc->mc_complete(mc);
/*
* Is there a sleeper waiting on this command?
*/
} else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */
/* remove from list and wake up sleeper */
TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
wakeup_one(mc->mc_private);
/*
* Leave the command for a caller that's polling for it.
*/
} else {
}
}
mc = nc;
}
@ -2356,6 +2371,9 @@ mlx_name_controller(u_int32_t hwid)
case 0x11:
submodel = "PJ";
break;
case 0x16:
submodel = "PTL";
break;
default:
sprintf(smbuf, " model 0x%x", hwid & 0xff);
submodel = smbuf;

View File

@ -48,6 +48,7 @@
#include <dev/mlx/mlxio.h>
#include <dev/mlx/mlxvar.h>
#include <dev/mlx/mlxreg.h>
#if 0
#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
@ -174,7 +175,6 @@ static void
mlxd_strategy(struct buf *bp)
{
struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1;
int s;
debug("called");
@ -194,10 +194,8 @@ mlxd_strategy(struct buf *bp)
if (bp->b_bcount == 0)
goto done;
s = splbio();
devstat_start_transaction(&sc->mlxd_stats);
mlx_submit_buf(sc->mlxd_controller, bp);
splx(s);
return;
bad:

View File

@ -48,6 +48,7 @@
#include <dev/mlx/mlxio.h>
#include <dev/mlx/mlxvar.h>
#include <dev/mlx/mlxreg.h>
#if 0
#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)

View File

@ -26,6 +26,11 @@
* $FreeBSD$
*/
#define MLX_CFG_BASE0 0x10 /* first region */
#define MLX_CFG_BASE1 0x14 /* second region (type 3 only) */
#define MLX_BLKSIZE 512 /* fixed feature */
/*
* Selected command codes.
*/
@ -245,3 +250,124 @@ struct mlx_rebuild_stat /* MLX_CMD_REBUILDSTAT */
u_int32_t rb_remaining;
} __attribute__ ((packed));
/*
* Inlines to build various command structures
*/
static __inline void
mlx_make_type1(struct mlx_command *mc,
u_int8_t code,
u_int16_t f1,
u_int32_t f2,
u_int8_t f3,
u_int32_t f4,
u_int8_t f5)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1 & 0xff;
mc->mc_mailbox[0x3] = (((f2 >> 24) & 0x3) << 6) | ((f1 >> 8) & 0x3f);
mc->mc_mailbox[0x4] = f2 & 0xff;
mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
mc->mc_mailbox[0x7] = f3;
mc->mc_mailbox[0x8] = f4 & 0xff;
mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f5;
}
static __inline void
mlx_make_type2(struct mlx_command *mc,
u_int8_t code,
u_int8_t f1,
u_int8_t f2,
u_int8_t f3,
u_int8_t f4,
u_int8_t f5,
u_int8_t f6,
u_int32_t f7,
u_int8_t f8)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1;
mc->mc_mailbox[0x3] = f2;
mc->mc_mailbox[0x4] = f3;
mc->mc_mailbox[0x5] = f4;
mc->mc_mailbox[0x6] = f5;
mc->mc_mailbox[0x7] = f6;
mc->mc_mailbox[0x8] = f7 & 0xff;
mc->mc_mailbox[0x9] = (f7 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f7 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f7 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f8;
}
static __inline void
mlx_make_type3(struct mlx_command *mc,
u_int8_t code,
u_int8_t f1,
u_int8_t f2,
u_int16_t f3,
u_int8_t f4,
u_int8_t f5,
u_int32_t f6,
u_int8_t f7)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1;
mc->mc_mailbox[0x3] = f2;
mc->mc_mailbox[0x4] = f3 & 0xff;
mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
mc->mc_mailbox[0x6] = f4;
mc->mc_mailbox[0x7] = f5;
mc->mc_mailbox[0x8] = f6 & 0xff;
mc->mc_mailbox[0x9] = (f6 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f6 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f6 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f7;
}
static __inline void
mlx_make_type4(struct mlx_command *mc,
u_int8_t code,
u_int16_t f1,
u_int32_t f2,
u_int32_t f3,
u_int8_t f4)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1 & 0xff;
mc->mc_mailbox[0x3] = (f1 >> 8) & 0xff;
mc->mc_mailbox[0x4] = f2 & 0xff;
mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
mc->mc_mailbox[0x7] = (f2 >> 24) & 0xff;
mc->mc_mailbox[0x8] = f3 & 0xff;
mc->mc_mailbox[0x9] = (f3 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f3 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f3 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f4;
}
static __inline void
mlx_make_type5(struct mlx_command *mc,
u_int8_t code,
u_int8_t f1,
u_int8_t f2,
u_int32_t f3,
u_int32_t f4,
u_int8_t f5)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1;
mc->mc_mailbox[0x3] = f2;
mc->mc_mailbox[0x4] = f3 & 0xff;
mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
mc->mc_mailbox[0x6] = (f3 >> 16) & 0xff;
mc->mc_mailbox[0x7] = (f3 >> 24) & 0xff;
mc->mc_mailbox[0x8] = f4 & 0xff;
mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f5;
}

View File

@ -34,13 +34,8 @@
#define MLX_NSEG 32 /* max scatter/gather segments we use */
#define MLX_NSLOTS 256 /* max number of command slots */
#define MLX_CFG_BASE0 0x10 /* first region */
#define MLX_CFG_BASE1 0x14 /* second region (type 3 only) */
#define MLX_MAXDRIVES 32
#define MLX_BLKSIZE 512 /* fixed feature */
/*
* Structure describing a System Drive as attached to the controller.
*/
@ -121,7 +116,7 @@ struct mlx_softc
/* controller queues and arrays */
TAILQ_HEAD(, mlx_command) mlx_freecmds; /* command structures available for reuse */
TAILQ_HEAD(, mlx_command) mlx_donecmd; /* commands waiting for completion processing */
TAILQ_HEAD(, mlx_command) mlx_work; /* active commands */
struct mlx_command *mlx_busycmd[MLX_NSLOTS]; /* busy commands */
int mlx_busycmds; /* count of busy commands */
struct mlx_sysdrive mlx_sysdrive[MLX_MAXDRIVES]; /* system drives */
@ -202,125 +197,4 @@ extern int mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_
caddr_t addr, int32_t flag, struct proc *p);
extern void mlxd_intr(void *data);
/*
* Inlines to build various command structures
*/
static __inline void
mlx_make_type1(struct mlx_command *mc,
u_int8_t code,
u_int16_t f1,
u_int32_t f2,
u_int8_t f3,
u_int32_t f4,
u_int8_t f5)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1 & 0xff;
mc->mc_mailbox[0x3] = (((f2 >> 24) & 0x3) << 6) | ((f1 >> 8) & 0x3f);
mc->mc_mailbox[0x4] = f2 & 0xff;
mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
mc->mc_mailbox[0x7] = f3;
mc->mc_mailbox[0x8] = f4 & 0xff;
mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f5;
}
static __inline void
mlx_make_type2(struct mlx_command *mc,
u_int8_t code,
u_int8_t f1,
u_int8_t f2,
u_int8_t f3,
u_int8_t f4,
u_int8_t f5,
u_int8_t f6,
u_int32_t f7,
u_int8_t f8)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1;
mc->mc_mailbox[0x3] = f2;
mc->mc_mailbox[0x4] = f3;
mc->mc_mailbox[0x5] = f4;
mc->mc_mailbox[0x6] = f5;
mc->mc_mailbox[0x7] = f6;
mc->mc_mailbox[0x8] = f7 & 0xff;
mc->mc_mailbox[0x9] = (f7 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f7 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f7 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f8;
}
static __inline void
mlx_make_type3(struct mlx_command *mc,
u_int8_t code,
u_int8_t f1,
u_int8_t f2,
u_int16_t f3,
u_int8_t f4,
u_int8_t f5,
u_int32_t f6,
u_int8_t f7)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1;
mc->mc_mailbox[0x3] = f2;
mc->mc_mailbox[0x4] = f3 & 0xff;
mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
mc->mc_mailbox[0x6] = f4;
mc->mc_mailbox[0x7] = f5;
mc->mc_mailbox[0x8] = f6 & 0xff;
mc->mc_mailbox[0x9] = (f6 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f6 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f6 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f7;
}
static __inline void
mlx_make_type4(struct mlx_command *mc,
u_int8_t code,
u_int16_t f1,
u_int32_t f2,
u_int32_t f3,
u_int8_t f4)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1 & 0xff;
mc->mc_mailbox[0x3] = (f1 >> 8) & 0xff;
mc->mc_mailbox[0x4] = f2 & 0xff;
mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
mc->mc_mailbox[0x7] = (f2 >> 24) & 0xff;
mc->mc_mailbox[0x8] = f3 & 0xff;
mc->mc_mailbox[0x9] = (f3 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f3 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f3 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f4;
}
static __inline void
mlx_make_type5(struct mlx_command *mc,
u_int8_t code,
u_int8_t f1,
u_int8_t f2,
u_int32_t f3,
u_int32_t f4,
u_int8_t f5)
{
mc->mc_mailbox[0x0] = code;
mc->mc_mailbox[0x2] = f1;
mc->mc_mailbox[0x3] = f2;
mc->mc_mailbox[0x4] = f3 & 0xff;
mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
mc->mc_mailbox[0x6] = (f3 >> 16) & 0xff;
mc->mc_mailbox[0x7] = (f3 >> 24) & 0xff;
mc->mc_mailbox[0x8] = f4 & 0xff;
mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
mc->mc_mailbox[0xc] = f5;
}