1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-19 02:29:40 +00:00

- add support for crashdumps (courtesy of ps and Y!)

- standardise error reporting for commands
 - simplify the driver-to-controller bio transfer
 - add bio in/out accounting
 - correctly preserve the command ID in twe_ioctl (thanks to joel@3ware)
This commit is contained in:
Mike Smith 2000-12-03 02:11:35 +00:00
parent ab8b98a151
commit b09d2ca319
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=69543
3 changed files with 273 additions and 185 deletions

View File

@ -54,7 +54,6 @@ static int twe_set_param(struct twe_softc *sc, int table_id, int param_id, int p
static int twe_init_connection(struct twe_softc *sc, int mode);
static int twe_wait_request(struct twe_request *tr);
static int twe_immediate_request(struct twe_request *tr);
static void twe_startio(struct twe_softc *sc);
static void twe_completeio(struct twe_request *tr);
static void twe_reset(struct twe_softc *sc);
@ -96,6 +95,7 @@ static void twe_release_request(struct twe_request *tr);
* Debugging.
*/
static char *twe_format_aen(struct twe_softc *sc, u_int16_t aen);
static int twe_report_request(struct twe_request *tr);
static int twe_request_qlen(struct twe_request *tr);
static void twe_panic(struct twe_softc *sc, char *reason);
@ -320,20 +320,113 @@ twe_intr(struct twe_softc *sc)
twe_done(sc);
};
/*******************************************************************************
* Receive a bio structure from a child device and queue it on a particular
* controller, then poke the controller to start as much work as it can.
/********************************************************************************
* Pull as much work off the softc's work queue as possible and give it to the
* controller.
*/
int
twe_submit_bio(struct twe_softc *sc, twe_bio *bp)
void
twe_startio(struct twe_softc *sc)
{
struct twe_request *tr;
TWE_Command *cmd;
twe_bio *bp;
int error;
debug_called(4);
twe_enqueue_bio(sc, bp);
/* spin until something prevents us from doing any work */
for (;;) {
twe_startio(sc);
return(0);
/* try to get a command that's already ready to go */
tr = twe_dequeue_ready(sc);
/* build a command from an outstanding bio */
if (tr == NULL) {
/* see if there's work to be done */
if ((bp = twe_dequeue_bio(sc)) == NULL)
break;
/* get a command to handle the bio with */
if (twe_get_request(sc, &tr)) {
twe_enqueue_bio(sc, bp); /* failed, put the bio back */
break;
}
/* connect the bio to the command */
tr->tr_complete = twe_completeio;
tr->tr_private = bp;
tr->tr_data = TWE_BIO_DATA(bp);
tr->tr_length = TWE_BIO_LENGTH(bp);
cmd = &tr->tr_command;
if (TWE_BIO_IS_READ(bp)) {
tr->tr_flags |= TWE_CMD_DATAIN;
cmd->io.opcode = TWE_OP_READ;
} else {
tr->tr_flags |= TWE_CMD_DATAOUT;
cmd->io.opcode = TWE_OP_WRITE;
}
/* build a suitable I/O command (assumes 512-byte rounded transfers) */
cmd->io.size = 3;
cmd->io.unit = TWE_BIO_UNIT(bp);
cmd->io.block_count = (tr->tr_length + TWE_BLOCK_SIZE - 1) / TWE_BLOCK_SIZE;
cmd->io.lba = TWE_BIO_LBA(bp);
/* map the command so the controller can work with it */
twe_map_request(tr);
}
/* did we find something to do? */
if (tr == NULL)
break;
/* try to give command to controller */
error = twe_start(tr);
if (error != 0) {
if (error == EBUSY) {
twe_requeue_ready(tr); /* try it again later */
break; /* don't try anything more for now */
}
/* we don't support any other return from twe_start */
twe_panic(sc, "twe_start returned nonsense");
}
}
}
/********************************************************************************
* Write blocks from memory to disk, for system crash dumps.
*/
int
twe_dump_blocks(struct twe_softc *sc, int unit, u_int32_t lba, void *data, int nblks)
{
struct twe_request *tr;
TWE_Command *cmd;
int error;
if (twe_get_request(sc, &tr))
return(ENOMEM);
tr->tr_data = data;
tr->tr_status = TWE_CMD_SETUP;
tr->tr_length = nblks * TWE_BLOCK_SIZE;
tr->tr_flags = TWE_CMD_DATAOUT;
cmd = &tr->tr_command;
cmd->io.opcode = TWE_OP_WRITE;
cmd->io.size = 3;
cmd->io.unit = unit;
cmd->io.block_count = nblks;
cmd->io.lba = lba;
twe_map_request(tr);
error = twe_immediate_request(tr);
if (error == 0)
if (twe_report_request(tr))
error = EIO;
twe_release_request(tr);
return(error);
}
/********************************************************************************
@ -349,6 +442,7 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
void *data;
int *arg = (int *)addr;
struct twe_request *tr;
u_int8_t srid;
int s, error;
error = 0;
@ -361,8 +455,13 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
goto cmd_done;
}
/* copy the user-supplied command */
/*
* Save the command's request ID, copy the user-supplied command in,
* restore the request ID.
*/
srid = tr->tr_command.generic.request_id;
bcopy(&tu->tu_command, &tr->tr_command, sizeof(TWE_Command));
tr->tr_command.generic.request_id = srid;
/* if there's a data buffer, allocate and copy it in */
tr->tr_length = tu->tu_size;
@ -377,6 +476,7 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr)
}
/* run the command */
twe_map_request(tr);
twe_wait_request(tr);
/* copy the command out again */
@ -590,21 +690,8 @@ twe_get_param(struct twe_softc *sc, int table_id, int param_id, size_t param_siz
/* XXX could use twe_wait_request here if interrupts were enabled? */
error = twe_immediate_request(tr);
if (error == 0) {
switch (cmd->generic.flags) {
case TWE_FLAGS_SUCCESS:
break;
case TWE_FLAGS_INFORMATIONAL:
case TWE_FLAGS_WARNING:
twe_printf(sc, "command completed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
break;
case TWE_FLAGS_FATAL:
default:
twe_printf(sc, "command failed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
if (twe_report_request(tr))
goto err;
}
}
twe_release_request(tr);
return(param);
@ -693,22 +780,8 @@ twe_set_param(struct twe_softc *sc, int table_id, int param_id, int param_size,
/* XXX could use twe_wait_request here if interrupts were enabled? */
error = twe_immediate_request(tr);
if (error == 0) {
switch (cmd->generic.flags) {
case TWE_FLAGS_SUCCESS:
break;
case TWE_FLAGS_INFORMATIONAL:
case TWE_FLAGS_WARNING:
twe_printf(sc, "command completed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
break;
case TWE_FLAGS_FATAL:
default:
twe_printf(sc, "command failed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
if (twe_report_request(tr))
error = EIO;
break;
}
}
out:
@ -805,87 +878,12 @@ twe_immediate_request(struct twe_request *tr)
return(tr->tr_status != TWE_CMD_COMPLETE);
}
/********************************************************************************
* Pull as much work off the softc's work queue as possible and give it to the
* controller.
*/
static void
twe_startio(struct twe_softc *sc)
{
struct twe_request *tr;
TWE_Command *cmd;
twe_bio *bp;
int error;
debug_called(4);
/* spin until something prevents us from doing any work */
for (;;) {
/* try to get a command that's already ready to go */
tr = twe_dequeue_ready(sc);
/* build a command from an outstanding bio */
if (tr == NULL) {
/* see if there's work to be done */
if ((bp = twe_dequeue_bio(sc)) == NULL)
break;
/* get a command */
if (twe_get_request(sc, &tr)) {
twe_enqueue_bio(sc, bp);
break;
}
/* connect the bio to the command */
tr->tr_complete = twe_completeio;
tr->tr_private = bp;
tr->tr_data = TWE_BIO_DATA(bp);
tr->tr_length = TWE_BIO_LENGTH(bp);
cmd = &tr->tr_command;
if (TWE_BIO_IS_READ(bp)) {
tr->tr_flags |= TWE_CMD_DATAIN;
cmd->io.opcode = TWE_OP_READ;
} else {
tr->tr_flags |= TWE_CMD_DATAOUT;
cmd->io.opcode = TWE_OP_WRITE;
}
/* build a suitable I/O command (assumes 512-byte rounded transfers) */
cmd->io.size = 3;
cmd->io.unit = TWE_BIO_UNIT(bp);
cmd->io.block_count = (tr->tr_length + TWE_BLOCK_SIZE - 1) / TWE_BLOCK_SIZE;
cmd->io.lba = TWE_BIO_LBA(bp);
/* map the command so the controller can work with it */
twe_map_request(tr);
}
/* did we find something to do? */
if (tr == NULL)
break;
/* try to give command to controller */
error = twe_start(tr);
if (error != 0) {
if (error == EBUSY) {
twe_requeue_ready(tr); /* try it again later */
break; /* don't try anything more for now */
}
/* otherwise, fail the command */
tr->tr_status = TWE_CMD_FAILED;
twe_completeio(tr);
}
}
}
/********************************************************************************
* Handle completion of an I/O command.
*/
static void
twe_completeio(struct twe_request *tr)
{
TWE_Command *cmd = &tr->tr_command;
struct twe_softc *sc = tr->tr_sc;
twe_bio *bp = (twe_bio *)tr->tr_private;
@ -893,36 +891,15 @@ twe_completeio(struct twe_request *tr)
if (tr->tr_status == TWE_CMD_COMPLETE) {
switch (cmd->generic.flags) {
case TWE_FLAGS_SUCCESS:
break;
case TWE_FLAGS_INFORMATIONAL:
case TWE_FLAGS_WARNING:
twe_printf(sc, "command completed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
break;
case TWE_FLAGS_FATAL:
default:
twe_printf(sc, "command failed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
if (twe_report_request(tr))
TWE_BIO_SET_ERROR(bp, EIO);
/*
* XXX some status values suggest that the controller should be reset and all outstanding
* commands retried. This might be a good place for that.
*/
break;
}
} else if (tr->tr_status == TWE_CMD_FAILED) { /* could be more verbose here? */
TWE_BIO_SET_ERROR(bp, EIO);
twe_printf(sc, "command failed submission - controller wedged\n");
/*
* XXX reset controller and retry?
*/
} else {
twe_panic(sc, "twe_completeio on incomplete command");
}
twe_release_request(tr);
tr->tr_private = NULL;
twed_intr(bp);
twe_release_request(tr);
}
/********************************************************************************
@ -935,7 +912,7 @@ twe_reset(struct twe_softc *sc)
struct twe_request *tr;
int i, s;
twe_printf(sc, "Controller reset in progress...\n");
twe_printf(sc, "controller reset in progress...\n");
/*
* Disable interrupts from the controller, and mask any accidental entry
@ -1075,15 +1052,14 @@ twe_done(struct twe_softc *sc)
found = 1;
rq = TWE_RESPONSE_QUEUE(sc);
tr = sc->twe_lookup[rq.u.response_id]; /* find command */
if (tr != NULL) { /* paranoia */
debug(3, "completed request id %d with status %d",
tr->tr_command.generic.request_id, tr->tr_command.generic.status);
/* move to completed queue */
twe_remove_busy(tr);
twe_enqueue_complete(tr);
} else {
debug(2, "done event for nonbusy id %d\n", rq.u.response_id);
}
if (tr->tr_status != TWE_CMD_BUSY)
twe_printf(sc, "completion event for nonbusy command\n");
tr->tr_status = TWE_CMD_COMPLETE;
debug(3, "completed request id %d with status %d",
tr->tr_command.generic.request_id, tr->tr_command.generic.status);
/* move to completed queue */
twe_remove_busy(tr);
twe_enqueue_complete(tr);
} else {
break; /* no response ready */
}
@ -1119,9 +1095,6 @@ twe_complete(struct twe_softc *sc)
/* unmap the command's data buffer */
twe_unmap_request(tr);
/* mark command as complete */
tr->tr_status = TWE_CMD_COMPLETE;
/* dispatch to suit command originator */
if (tr->tr_complete != NULL) { /* completion callback */
debug(2, "call completion handler %p", tr->tr_complete);
@ -1483,6 +1456,7 @@ twe_get_request(struct twe_softc *sc, struct twe_request **tr)
/* initialise some fields to their defaults */
if (*tr != NULL) {
(*tr)->tr_data = NULL;
(*tr)->tr_private = NULL;
(*tr)->tr_status = TWE_CMD_SETUP; /* command is in setup phase */
(*tr)->tr_flags = 0;
(*tr)->tr_complete = NULL;
@ -1501,6 +1475,8 @@ twe_release_request(struct twe_request *tr)
{
debug_called(4);
if (tr->tr_private != NULL)
twe_panic(tr->tr_sc, "tr_private != NULL");
twe_enqueue_free(tr);
}
@ -1653,18 +1629,47 @@ twe_format_aen(struct twe_softc *sc, u_int16_t aen)
return(buf);
}
/********************************************************************************
* Print a diagnostic if the status of the command warrants it, and return
* either zero (command was ok) or nonzero (command failed).
*/
static int
twe_request_qlen(struct twe_request *tr)
twe_report_request(struct twe_request *tr)
{
int len = 0;
struct twe_softc *sc = tr->tr_sc;
TWE_Command *cmd = &tr->tr_command;
int result;
while (tr != NULL) {
tr = TAILQ_NEXT(tr, tr_link);
len++;
switch (cmd->generic.flags) {
case TWE_FLAGS_SUCCESS:
result = 0;
break;
case TWE_FLAGS_INFORMATIONAL:
case TWE_FLAGS_WARNING:
twe_printf(sc, "command completed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
result = 0;
break;
case TWE_FLAGS_FATAL:
default:
twe_printf(sc, "command failed - %s\n",
twe_describe_code(twe_table_status, cmd->generic.status));
result = 1;
/*
* The status code 0xff requests a controller reset
*/
if (cmd->generic.status == 0xff)
twe_reset(sc);
break;
}
return(len);
return(result);
}
/********************************************************************************
* Print some controller state to aid in debugging error/panic conditions
*/
void
twe_print_controller(struct twe_softc *sc)
{
@ -1672,10 +1677,12 @@ twe_print_controller(struct twe_softc *sc)
status_reg = TWE_STATUS(sc);
twe_printf(sc, "status %b\n", status_reg, TWE_STATUS_BITS_DESCRIPTION);
twe_printf(sc, "free %d\n", twe_request_qlen(TAILQ_FIRST(&sc->twe_free)));
twe_printf(sc, "ready %d\n", twe_request_qlen(TAILQ_FIRST(&sc->twe_ready)));
twe_printf(sc, "busy %d\n", twe_request_qlen(TAILQ_FIRST(&sc->twe_busy)));
twe_printf(sc, "complete %d\n", twe_request_qlen(TAILQ_FIRST(&sc->twe_complete)));
twe_printf(sc, " current max\n");
twe_printf(sc, "free %04d %04d\n", sc->twe_qstat[TWEQ_FREE].q_length, sc->twe_qstat[TWEQ_FREE].q_max);
twe_printf(sc, "ready %04d %04d\n", sc->twe_qstat[TWEQ_READY].q_length, sc->twe_qstat[TWEQ_READY].q_max);
twe_printf(sc, "busy %04d %04d\n", sc->twe_qstat[TWEQ_BUSY].q_length, sc->twe_qstat[TWEQ_BUSY].q_max);
twe_printf(sc, "complete %04d %04d\n", sc->twe_qstat[TWEQ_COMPLETE].q_length, sc->twe_qstat[TWEQ_COMPLETE].q_max);
twe_printf(sc, "bioq %04d %04d\n", sc->twe_qstat[TWEQ_BIO].q_length, sc->twe_qstat[TWEQ_BIO].q_max);
twe_printf(sc, "AEN queue head %d tail %d\n", sc->twe_aen_head, sc->twe_aen_tail);
}

View File

@ -31,6 +31,13 @@
* FreeBSD-specific code.
*/
#include <sys/param.h>
#include <sys/cons.h>
#include <machine/bus.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <dev/twe/twe_compat.h>
#include <dev/twe/twereg.h>
#include <dev/twe/tweio.h>
@ -41,6 +48,16 @@
static devclass_t twe_devclass;
#ifdef TWE_DEBUG
static u_int32_t twed_bio_in;
#define TWED_BIO_IN twed_bio_in++
static u_int32_t twed_bio_out;
#define TWED_BIO_OUT twed_bio_out++
#else
#define TWED_BIO_IN
#define TWED_BIO_OUT
#endif
/********************************************************************************
********************************************************************************
Control device interface
@ -250,13 +267,13 @@ twe_attach(device_t dev)
/*
* Create DMA tag for mapping objects into controller-addressable space.
*/
if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */
1, 0, /* alignment, boundary */
if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */
1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
MAXBSIZE, TWE_MAX_SGL_LENGTH, /* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
MAXBSIZE, TWE_MAX_SGL_LENGTH,/* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
&sc->twe_buffer_dmat)) {
twe_printf(sc, "can't allocate data buffer DMA tag\n");
@ -551,6 +568,7 @@ DRIVER_MODULE(twed, twe, twed_driver, twed_devclass, 0, 0);
static d_open_t twed_open;
static d_close_t twed_close;
static d_strategy_t twed_strategy;
static d_dump_t twed_dump;
#define TWED_CDEV_MAJOR 147
@ -565,7 +583,7 @@ static struct cdevsw twed_cdevsw = {
twed_strategy,
"twed",
TWED_CDEV_MAJOR,
nodump,
twed_dump,
nopsize,
D_DISK,
-1
@ -639,9 +657,14 @@ twed_strategy(twe_bio *bp)
debug_called(4);
TWED_BIO_IN;
/* bogus disk? */
if (sc == NULL) {
TWE_BIO_SET_ERROR(bp, EINVAL);
printf("twe: bio for invalid disk!\n");
TWE_BIO_DONE(bp);
TWED_BIO_OUT;
return;
}
@ -649,17 +672,81 @@ twed_strategy(twe_bio *bp)
if (TWE_BIO_LENGTH(bp) == 0) {
TWE_BIO_RESID(bp) = 0;
TWE_BIO_DONE(bp);
TWED_BIO_OUT;
return;
}
/* perform accounting */
TWE_BIO_STATS_START(bp);
/* pass the bio to the controller - it can work out who we are */
twe_submit_bio(sc->twed_controller, bp);
/* queue the bio on the controller */
twe_enqueue_bio(sc->twed_controller, bp);
/* poke the controller to start I/O */
twe_startio(sc->twed_controller);
return;
}
/********************************************************************************
* System crashdump support
*/
int
twed_dump(dev_t dev)
{
struct twed_softc *twed_sc = (struct twed_softc *)dev->si_drv1;
struct twe_softc *twe_sc = (struct twe_softc *)twed_sc->twed_controller;
u_int count, blkno, secsize;
vm_offset_t addr = 0;
long blkcnt;
int dumppages = MAXDUMPPGS;
int error;
int i;
if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
return(error);
if (!twed_sc || !twe_sc)
return(ENXIO);
blkcnt = howmany(PAGE_SIZE, secsize);
while (count > 0) {
caddr_t va = NULL;
if ((count / blkcnt) < dumppages)
dumppages = count / blkcnt;
for (i = 0; i < dumppages; ++i) {
vm_offset_t a = addr + (i * PAGE_SIZE);
if (is_physical_memory(a))
va = pmap_kenter_temporary(trunc_page(a), i);
else
va = pmap_kenter_temporary(trunc_page(0), i);
}
if ((error = twe_dump_blocks(twe_sc, twed_sc->twed_drive->td_unit, blkno, va,
(PAGE_SIZE * dumppages) / TWE_BLOCK_SIZE)) != 0)
return(error);
if (addr % (1024 * 1024) == 0) {
#ifdef HW_WDOG
if (wdog_tickler)
(*wdog_tickler)();
#endif
printf("%ld ", (long)(count * DEV_BSIZE) / (1024 * 1024));
}
blkno += blkcnt * dumppages;
count -= blkcnt * dumppages;
addr += PAGE_SIZE * dumppages;
if (cncheckc() != -1)
return(EINTR);
}
return(0);
}
/********************************************************************************
* Handle completion of an I/O request.
*/
@ -674,6 +761,7 @@ twed_intr(twe_bio *bp)
TWE_BIO_STATS_END(bp);
TWE_BIO_DONE(bp);
TWED_BIO_OUT;
}
/********************************************************************************
@ -967,6 +1055,7 @@ twe_report(void)
s = splbio();
for (i = 0; (sc = devclass_get_softc(twe_devclass, i)) != NULL; i++)
twe_print_controller(sc);
printf("twed: total bio count in %u out %u\n", twed_bio_in, twed_bio_out);
splx(s);
}
#endif

View File

@ -84,7 +84,6 @@ struct twe_request
#define TWE_CMD_SETUP 0 /* being assembled */
#define TWE_CMD_BUSY 1 /* submitted to controller */
#define TWE_CMD_COMPLETE 2 /* completed by controller (maybe with error) */
#define TWE_CMD_FAILED 3 /* failed submission to controller */
int tr_flags;
#define TWE_CMD_DATAIN (1<<0)
#define TWE_CMD_DATAOUT (1<<1)
@ -122,9 +121,7 @@ struct twe_softc
#define TWE_STATE_OPEN (1<<2) /* control device is open */
#define TWE_STATE_SUSPEND (1<<3) /* controller is suspended */
int twe_host_id;
#ifdef TWE_PERFORMANCE_MONITOR
struct twe_qstat twe_qstat[TWEQ_COUNT]; /* queue statistics */
#endif
TWE_PLATFORM_SOFTC /* platform-specific softc elements */
};
@ -136,8 +133,9 @@ extern int twe_setup(struct twe_softc *sc); /* do early driver/controller setup
extern void twe_init(struct twe_softc *sc); /* init controller */
extern void twe_deinit(struct twe_softc *sc); /* stop controller */
extern void twe_intr(struct twe_softc *sc); /* hardware interrupt signalled */
extern int twe_submit_bio(struct twe_softc *sc,
twe_bio *bp); /* pass bio to core */
extern void twe_startio(struct twe_softc *sc);
extern int twe_dump_blocks(struct twe_softc *sc, int unit, /* crashdump block write */
u_int32_t lba, void *data, int nblks);
extern int twe_ioctl(struct twe_softc *sc, int cmd,
void *addr); /* handle user request */
extern void twe_describe_controller(struct twe_softc *sc); /* print controller info */
@ -156,8 +154,7 @@ extern void twe_unmap_request(struct twe_request *tr); /* cleanup after transfer
/********************************************************************************
* Queue primitives
*/
#ifdef TWE_PERFORMANCE_MONITOR
# define TWEQ_ADD(sc, qname) \
#define TWEQ_ADD(sc, qname) \
do { \
struct twe_qstat *qs = &(sc)->twe_qstat[qname]; \
\
@ -166,17 +163,12 @@ extern void twe_unmap_request(struct twe_request *tr); /* cleanup after transfer
qs->q_max = qs->q_length; \
} while(0)
# define TWEQ_REMOVE(sc, qname) (sc)->twe_qstat[qname].q_length--
# define TWEQ_INIT(sc, qname) \
#define TWEQ_REMOVE(sc, qname) (sc)->twe_qstat[qname].q_length--
#define TWEQ_INIT(sc, qname) \
do { \
sc->twe_qstat[qname].q_length = 0; \
sc->twe_qstat[qname].q_max = 0; \
} while(0)
#else
# define TWEQ_ADD(sc, qname)
# define TWEQ_REMOVE(sc, qname)
# define TWEQ_INIT(sc, qname)
#endif
#define TWEQ_REQUEST_QUEUE(name, index) \