1. Better handle a return value of EINPROGRESS from bus_dmamap_load.
2. Check for bad return value from twe_map_request in places where there was no checking. Reviewed by: ps
This commit is contained in:
parent
efe93d08ec
commit
20e39e00cb
@ -431,16 +431,19 @@ twe_startio(struct twe_softc *sc)
|
|||||||
if (tr == NULL)
|
if (tr == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* map the command so the controller can work with it */
|
/* try to map and submit the command to controller */
|
||||||
error = twe_map_request(tr);
|
error = twe_map_request(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 */
|
if (error != 0) {
|
||||||
twe_panic(sc, "twe_map_request returned nonsense");
|
tr->tr_status = TWE_CMD_ERROR;
|
||||||
|
if (tr->tr_private != NULL) {
|
||||||
|
bp = (twe_bio *)(tr->tr_private);
|
||||||
|
TWE_BIO_SET_ERROR(bp, error);
|
||||||
|
tr->tr_private = NULL;
|
||||||
|
twed_intr(bp);
|
||||||
|
twe_release_request(tr);
|
||||||
|
} else if (tr->tr_flags & TWE_CMD_SLEEPER)
|
||||||
|
wakeup_one(tr); /* wakeup the sleeping owner */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -529,7 +532,9 @@ twe_ioctl(struct twe_softc *sc, int ioctlcmd, void *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* run the command */
|
/* run the command */
|
||||||
twe_wait_request(tr);
|
error = twe_wait_request(tr);
|
||||||
|
if (error)
|
||||||
|
goto cmd_done;
|
||||||
|
|
||||||
/* copy the command out again */
|
/* copy the command out again */
|
||||||
bcopy(cmd, &tu->tu_command, sizeof(TWE_Command));
|
bcopy(cmd, &tu->tu_command, sizeof(TWE_Command));
|
||||||
@ -880,8 +885,6 @@ twe_init_connection(struct twe_softc *sc, int mode)
|
|||||||
|
|
||||||
/* submit the command */
|
/* submit the command */
|
||||||
error = twe_immediate_request(tr);
|
error = twe_immediate_request(tr);
|
||||||
/* XXX check command result? */
|
|
||||||
twe_unmap_request(tr);
|
|
||||||
twe_release_request(tr);
|
twe_release_request(tr);
|
||||||
|
|
||||||
if (mode == TWE_INIT_MESSAGE_CREDITS)
|
if (mode == TWE_INIT_MESSAGE_CREDITS)
|
||||||
@ -910,7 +913,7 @@ twe_wait_request(struct twe_request *tr)
|
|||||||
tsleep(tr, PRIBIO, "twewait", 0);
|
tsleep(tr, PRIBIO, "twewait", 0);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
return(0);
|
return(tr->tr_status != TWE_CMD_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
@ -921,13 +924,14 @@ twe_wait_request(struct twe_request *tr)
|
|||||||
static int
|
static int
|
||||||
twe_immediate_request(struct twe_request *tr)
|
twe_immediate_request(struct twe_request *tr)
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
debug_called(4);
|
debug_called(4);
|
||||||
|
|
||||||
tr->tr_flags |= TWE_CMD_IMMEDIATE;
|
tr->tr_flags |= TWE_CMD_IMMEDIATE;
|
||||||
tr->tr_status = TWE_CMD_BUSY;
|
tr->tr_status = TWE_CMD_BUSY;
|
||||||
twe_map_request(tr);
|
if ((error = twe_map_request(tr)) != 0)
|
||||||
|
return(error);
|
||||||
while (tr->tr_status == TWE_CMD_BUSY){
|
while (tr->tr_status == TWE_CMD_BUSY){
|
||||||
twe_done(tr->tr_sc);
|
twe_done(tr->tr_sc);
|
||||||
}
|
}
|
||||||
@ -1174,8 +1178,6 @@ twe_complete(struct twe_softc *sc)
|
|||||||
debug(2, "command left for owner");
|
debug(2, "command left for owner");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc->twe_state &= ~TWE_STATE_FRZN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
@ -1842,7 +1844,7 @@ twe_panic(struct twe_softc *sc, char *reason)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TWE_DEBUG
|
#if 0
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* Print a request/command in human-readable format.
|
* Print a request/command in human-readable format.
|
||||||
*/
|
*/
|
||||||
|
@ -939,6 +939,8 @@ twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int err
|
|||||||
|
|
||||||
tr->tr_flags |= TWE_CMD_MAPPED;
|
tr->tr_flags |= TWE_CMD_MAPPED;
|
||||||
|
|
||||||
|
if (tr->tr_flags & TWE_CMD_IN_PROGRESS)
|
||||||
|
sc->twe_state &= ~TWE_STATE_FRZN;
|
||||||
/* save base of first segment in command (applicable if there only one segment) */
|
/* save base of first segment in command (applicable if there only one segment) */
|
||||||
tr->tr_dataphys = segs[0].ds_addr;
|
tr->tr_dataphys = segs[0].ds_addr;
|
||||||
|
|
||||||
@ -1051,26 +1053,35 @@ twe_map_request(struct twe_request *tr)
|
|||||||
if (((vm_offset_t)tr->tr_data % TWE_ALIGNMENT) != 0) {
|
if (((vm_offset_t)tr->tr_data % TWE_ALIGNMENT) != 0) {
|
||||||
tr->tr_realdata = tr->tr_data; /* save pointer to 'real' data */
|
tr->tr_realdata = tr->tr_data; /* save pointer to 'real' data */
|
||||||
tr->tr_flags |= TWE_CMD_ALIGNBUF;
|
tr->tr_flags |= TWE_CMD_ALIGNBUF;
|
||||||
tr->tr_data = malloc(tr->tr_length, TWE_MALLOC_CLASS, M_NOWAIT); /* XXX check result here */
|
tr->tr_data = malloc(tr->tr_length, TWE_MALLOC_CLASS, M_NOWAIT);
|
||||||
|
if (tr->tr_data == NULL) {
|
||||||
|
twe_printf(sc, "%s: malloc failed\n", __func__);
|
||||||
|
tr->tr_data = tr->tr_realdata; /* restore original data pointer */
|
||||||
|
return(ENOMEM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map the data buffer into bus space and build the s/g list.
|
* Map the data buffer into bus space and build the s/g list.
|
||||||
*/
|
*/
|
||||||
if (tr->tr_flags & TWE_CMD_IMMEDIATE) {
|
if (tr->tr_flags & TWE_CMD_IMMEDIATE) {
|
||||||
bcopy(tr->tr_data, sc->twe_immediate, tr->tr_length);
|
bcopy(tr->tr_data, sc->twe_immediate, tr->tr_length);
|
||||||
bus_dmamap_load(sc->twe_immediate_dmat, sc->twe_immediate_map, sc->twe_immediate,
|
error = bus_dmamap_load(sc->twe_immediate_dmat, sc->twe_immediate_map, sc->twe_immediate,
|
||||||
tr->tr_length, twe_setup_data_dmamap, tr, 0);
|
tr->tr_length, twe_setup_data_dmamap, tr, 0);
|
||||||
} else {
|
} else {
|
||||||
error = bus_dmamap_load(sc->twe_buffer_dmat, tr->tr_dmamap, tr->tr_data, tr->tr_length,
|
error = bus_dmamap_load(sc->twe_buffer_dmat, tr->tr_dmamap, tr->tr_data, tr->tr_length,
|
||||||
twe_setup_data_dmamap, tr, 0);
|
twe_setup_data_dmamap, tr, 0);
|
||||||
}
|
}
|
||||||
if (error == EINPROGRESS) {
|
if (error == EINPROGRESS) {
|
||||||
|
tr->tr_flags |= TWE_CMD_IN_PROGRESS;
|
||||||
sc->twe_state |= TWE_STATE_FRZN;
|
sc->twe_state |= TWE_STATE_FRZN;
|
||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
error = twe_start(tr);
|
if ((error = twe_start(tr)) == EBUSY) {
|
||||||
|
twe_requeue_ready(tr);
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
@ -1127,6 +1138,7 @@ twe_unmap_request(struct twe_request *tr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TWE_DEBUG
|
#ifdef TWE_DEBUG
|
||||||
|
void twe_report(void);
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* Print current controller status, call from DDB.
|
* Print current controller status, call from DDB.
|
||||||
*/
|
*/
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
* The scheme for the driver version is:
|
* The scheme for the driver version is:
|
||||||
* <major change>.<external release>.<3ware internal release>.<development release>
|
* <major change>.<external release>.<3ware internal release>.<development release>
|
||||||
*/
|
*/
|
||||||
#define TWE_DRIVER_VERSION_STRING "1.50.00.000"
|
#define TWE_DRIVER_VERSION_STRING "1.50.01.000"
|
||||||
|
|
||||||
#ifdef TWE_DEBUG
|
#ifdef TWE_DEBUG
|
||||||
#define debug(level, fmt, args...) \
|
#define debug(level, fmt, args...) \
|
||||||
@ -89,6 +89,7 @@ struct twe_request
|
|||||||
#define TWE_CMD_SETUP 0 /* being assembled */
|
#define TWE_CMD_SETUP 0 /* being assembled */
|
||||||
#define TWE_CMD_BUSY 1 /* submitted to controller */
|
#define TWE_CMD_BUSY 1 /* submitted to controller */
|
||||||
#define TWE_CMD_COMPLETE 2 /* completed by controller (maybe with error) */
|
#define TWE_CMD_COMPLETE 2 /* completed by controller (maybe with error) */
|
||||||
|
#define TWE_CMD_ERROR 3 /* encountered error, even before submission to controller */
|
||||||
int tr_flags;
|
int tr_flags;
|
||||||
#define TWE_CMD_DATAIN (1<<0)
|
#define TWE_CMD_DATAIN (1<<0)
|
||||||
#define TWE_CMD_DATAOUT (1<<1)
|
#define TWE_CMD_DATAOUT (1<<1)
|
||||||
@ -96,6 +97,7 @@ struct twe_request
|
|||||||
#define TWE_CMD_SLEEPER (1<<3) /* owner is sleeping on this command */
|
#define TWE_CMD_SLEEPER (1<<3) /* owner is sleeping on this command */
|
||||||
#define TWE_CMD_IMMEDIATE (1<<4) /* immediate request */
|
#define TWE_CMD_IMMEDIATE (1<<4) /* immediate request */
|
||||||
#define TWE_CMD_MAPPED (1<<5)
|
#define TWE_CMD_MAPPED (1<<5)
|
||||||
|
#define TWE_CMD_IN_PROGRESS (1<<6) /* bus_dmamap_load returned EINPROGRESS */
|
||||||
void (* tr_complete)(struct twe_request *tr); /* completion handler */
|
void (* tr_complete)(struct twe_request *tr); /* completion handler */
|
||||||
void *tr_private; /* submitter-private data or wait channel */
|
void *tr_private; /* submitter-private data or wait channel */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user