Integrate changes from LSI vendor driver 10.80.00.005 to FreeBSD.
PR: kern/172833 Submitted by: "Charles O'Donnell" <cao bus net> MFC after: 1 week
This commit is contained in:
parent
f4c22f128c
commit
3362252a56
@ -405,6 +405,8 @@ tws_detach(device_t dev)
|
||||
free(sc->reqs, M_TWS);
|
||||
free(sc->sense_bufs, M_TWS);
|
||||
free(sc->scan_ccb, M_TWS);
|
||||
if (sc->ioctl_data_mem)
|
||||
bus_dmamem_free(sc->data_tag, sc->ioctl_data_mem, sc->ioctl_data_map);
|
||||
free(sc->aen_q.q, M_TWS);
|
||||
free(sc->trace_q.q, M_TWS);
|
||||
mtx_destroy(&sc->q_lock);
|
||||
@ -609,6 +611,11 @@ tws_init(struct tws_softc *sc)
|
||||
TWS_TRACE_DEBUG(sc, "ccb malloc failed", 0, sc->is64bit);
|
||||
return(ENOMEM);
|
||||
}
|
||||
if (bus_dmamem_alloc(sc->data_tag, (void **)&sc->ioctl_data_mem,
|
||||
(BUS_DMA_NOWAIT | BUS_DMA_ZERO), &sc->ioctl_data_map)) {
|
||||
device_printf(sc->tws_dev, "Cannot allocate ioctl data mem\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
if ( !tws_ctlr_ready(sc) )
|
||||
if( !tws_ctlr_reset(sc) )
|
||||
|
@ -65,7 +65,7 @@ MALLOC_DECLARE(M_TWS);
|
||||
extern int tws_queue_depth;
|
||||
|
||||
|
||||
#define TWS_DRIVER_VERSION_STRING "10.80.00.003"
|
||||
#define TWS_DRIVER_VERSION_STRING "10.80.00.005"
|
||||
#define TWS_MAX_NUM_UNITS 65
|
||||
#define TWS_MAX_NUM_LUNS 16
|
||||
#define TWS_MAX_IRQS 2
|
||||
@ -247,7 +247,7 @@ struct tws_softc {
|
||||
struct mtx io_lock; /* IO lock */
|
||||
struct tws_ioctl_lock ioctl_lock; /* ioctl lock */
|
||||
u_int32_t seq_id; /* Sequence id */
|
||||
int chan; /* wait channel */
|
||||
void *chan; /* IOCTL req wait channel */
|
||||
struct tws_circular_q aen_q; /* aen q */
|
||||
struct tws_circular_q trace_q; /* trace q */
|
||||
struct tws_stats stats; /* I/O stats */
|
||||
@ -260,6 +260,8 @@ struct tws_softc {
|
||||
void *dma_mem; /* pointer to dmable memory */
|
||||
u_int64_t dma_mem_phys; /* phy addr */
|
||||
bus_dma_tag_t data_tag; /* data DMA tag */
|
||||
void *ioctl_data_mem; /* ioctl dmable memory */
|
||||
bus_dmamap_t ioctl_data_map; /* ioctl data map */
|
||||
struct tws_request *reqs; /* pointer to requests */
|
||||
struct tws_sense *sense_bufs; /* pointer to sense buffers */
|
||||
boolean obfl_q_overrun; /* OBFL overrun flag */
|
||||
|
@ -970,6 +970,7 @@ tws_map_request(struct tws_softc *sc, struct tws_request *req)
|
||||
if (error == EINPROGRESS) {
|
||||
TWS_TRACE(sc, "in progress", 0, error);
|
||||
tws_freeze_simq(sc, req);
|
||||
error = 0; // EINPROGRESS is not a fatal error.
|
||||
}
|
||||
} else { /* no data involved */
|
||||
error = tws_submit_command(sc, req);
|
||||
@ -989,6 +990,10 @@ tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs,
|
||||
struct tws_cmd_generic *gcmd;
|
||||
|
||||
|
||||
if ( error ) {
|
||||
TWS_TRACE(sc, "SOMETHING BAD HAPPENED! error = %d\n", error, 0);
|
||||
}
|
||||
|
||||
if ( error == EFBIG ) {
|
||||
TWS_TRACE(sc, "not enough data segs", 0, nseg);
|
||||
req->error_code = error;
|
||||
@ -1010,12 +1015,12 @@ tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs,
|
||||
gcmd = &req->cmd_pkt->cmd.pkt_g.generic;
|
||||
sgl_ptr = (u_int32_t *)(gcmd) + gcmd->size;
|
||||
gcmd->size += sgls *
|
||||
((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 :2 );
|
||||
((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 : 2 );
|
||||
tws_fill_sg_list(req->sc, (void *)segs, sgl_ptr, sgls);
|
||||
|
||||
} else {
|
||||
tws_fill_sg_list(req->sc, (void *)segs,
|
||||
(void *)req->cmd_pkt->cmd.pkt_a.sg_list, sgls);
|
||||
(void *)&(req->cmd_pkt->cmd.pkt_a.sg_list), sgls);
|
||||
req->cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= sgls ;
|
||||
}
|
||||
}
|
||||
@ -1318,10 +1323,7 @@ tws_reinit(void *arg)
|
||||
|
||||
tws_turn_on_interrupts(sc);
|
||||
|
||||
if ( sc->chan ) {
|
||||
sc->chan = 0;
|
||||
wakeup_one((void *)&sc->chan);
|
||||
}
|
||||
wakeup_one(sc->chan);
|
||||
}
|
||||
|
||||
|
||||
|
@ -174,7 +174,7 @@ enum tws_sense_severity {
|
||||
#define TWS_FW_CMD_INIT_CONNECTION 0x01
|
||||
#define TWS_FW_CMD_EXECUTE_SCSI 0x10
|
||||
|
||||
#define TWS_FW_CMD_ATA_PASSTHROUGH 0x11
|
||||
#define TWS_FW_CMD_ATA_PASSTHROUGH 0x11 // This is really a PASSTHROUGH for both ATA and SCSI commands.
|
||||
#define TWS_FW_CMD_GET_PARAM 0x12
|
||||
#define TWS_FW_CMD_SET_PARAM 0x13
|
||||
|
||||
|
@ -94,41 +94,46 @@ tws_passthru(struct tws_softc *sc, void *buf)
|
||||
int error;
|
||||
u_int16_t lun4;
|
||||
|
||||
|
||||
if ( tws_get_state(sc) != TWS_ONLINE) {
|
||||
return(EBUSY);
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Get a command
|
||||
//
|
||||
do {
|
||||
req = tws_get_request(sc, TWS_REQ_TYPE_PASSTHRU);
|
||||
if ( !req ) {
|
||||
sc->chan = 1;
|
||||
error = tsleep((void *)&sc->chan, 0,
|
||||
"tws_sleep", TWS_IOCTL_TIMEOUT*hz);
|
||||
sc->chan = (void *)sc;
|
||||
error = tsleep(sc->chan, 0, "tws_sleep", TWS_IOCTL_TIMEOUT*hz);
|
||||
if ( error == EWOULDBLOCK ) {
|
||||
return(ETIMEDOUT);
|
||||
}
|
||||
} else {
|
||||
// Make sure we are still ready for new commands...
|
||||
if ( tws_get_state(sc) != TWS_ONLINE) {
|
||||
return(EBUSY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}while(1);
|
||||
} while(1);
|
||||
|
||||
req->length = ubuf->driver_pkt.buffer_length;
|
||||
req->length = (ubuf->driver_pkt.buffer_length + 511) & ~511;
|
||||
TWS_TRACE_DEBUG(sc, "datal,rid", req->length, req->request_id);
|
||||
if ( req->length ) {
|
||||
req->data = malloc(req->length, M_TWS, M_WAITOK | M_ZERO);
|
||||
if ( !req->data ) {
|
||||
TWS_TRACE_DEBUG(sc, "malloc failed", 0, req->request_id);
|
||||
req->state = TWS_REQ_STATE_FREE;
|
||||
ubuf->driver_pkt.os_status = ENOMEM;
|
||||
if ( sc->chan ) {
|
||||
sc->chan = 0;
|
||||
wakeup_one((void *)&sc->chan);
|
||||
}
|
||||
return(ENOMEM);
|
||||
}
|
||||
bzero(req->data, req->length);
|
||||
req->data = sc->ioctl_data_mem;
|
||||
req->dma_map = sc->ioctl_data_map;
|
||||
|
||||
//==========================================================================================
|
||||
// Copy data in from user space
|
||||
//
|
||||
error = copyin(ubuf->pdata, req->data, req->length);
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Set command fields
|
||||
//
|
||||
req->flags = TWS_DIR_IN | TWS_DIR_OUT;
|
||||
req->cb = tws_passthru_complete;
|
||||
|
||||
@ -141,16 +146,22 @@ tws_passthru(struct tws_softc *sc, void *buf)
|
||||
req->cmd_pkt->cmd.pkt_a.lun_l4__req_id = lun4 | req->request_id;
|
||||
} else {
|
||||
req->cmd_pkt->cmd.pkt_g.generic.request_id = (u_int8_t) req->request_id;
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================================
|
||||
// Send command to controller
|
||||
//
|
||||
error = tws_map_request(sc, req);
|
||||
if (error) {
|
||||
ubuf->driver_pkt.os_status = error;
|
||||
goto out;
|
||||
goto out_data;
|
||||
}
|
||||
|
||||
if ( req->state == TWS_REQ_STATE_COMPLETE ) {
|
||||
ubuf->driver_pkt.os_status = req->error_code;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
mtx_lock(&sc->gen_lock);
|
||||
error = mtx_sleep(req, &sc->gen_lock, 0, "tws_passthru", TWS_IOCTL_TIMEOUT*hz);
|
||||
mtx_unlock(&sc->gen_lock);
|
||||
@ -159,6 +170,7 @@ tws_passthru(struct tws_softc *sc, void *buf)
|
||||
tws_timeout((void*) req);
|
||||
}
|
||||
|
||||
out_unmap:
|
||||
if ( req->error_code == TWS_REQ_RET_RESET ) {
|
||||
error = EBUSY;
|
||||
req->error_code = EBUSY;
|
||||
@ -167,15 +179,20 @@ tws_passthru(struct tws_softc *sc, void *buf)
|
||||
|
||||
tws_unmap_request(sc, req);
|
||||
|
||||
//==============================================================================================
|
||||
// Return command status to user space
|
||||
//
|
||||
memcpy(&ubuf->cmd_pkt.hdr, &req->cmd_pkt->hdr, sizeof(struct tws_command_apache));
|
||||
memcpy(&ubuf->cmd_pkt.cmd, &req->cmd_pkt->cmd, sizeof(struct tws_command_apache));
|
||||
if ( !error && req->length ) {
|
||||
error = copyout(req->data, ubuf->pdata, req->length);
|
||||
}
|
||||
//==================================================================================================
|
||||
|
||||
out:
|
||||
free(req->data, M_TWS);
|
||||
out_data:
|
||||
if ( req->length ) {
|
||||
//==========================================================================================
|
||||
// Copy data out to user space
|
||||
//
|
||||
if ( !error )
|
||||
error = copyout(req->data, ubuf->pdata, ubuf->driver_pkt.buffer_length);
|
||||
}
|
||||
|
||||
if ( error )
|
||||
TWS_TRACE_DEBUG(sc, "errored", error, 0);
|
||||
@ -183,12 +200,13 @@ out:
|
||||
if ( req->error_code != TWS_REQ_RET_SUBMIT_SUCCESS )
|
||||
ubuf->driver_pkt.os_status = error;
|
||||
|
||||
//==============================================================================================
|
||||
// Free command
|
||||
//
|
||||
req->state = TWS_REQ_STATE_FREE;
|
||||
|
||||
if ( sc->chan && (tws_get_state(sc) == TWS_ONLINE) ) {
|
||||
sc->chan = 0;
|
||||
wakeup_one((void *)&sc->chan);
|
||||
}
|
||||
wakeup_one(sc->chan);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user