From 77605a643472cc9eefca7aacb072f11f9e177a22 Mon Sep 17 00:00:00 2001 From: delphij Date: Sat, 20 Oct 2012 07:39:47 +0000 Subject: [PATCH] MFC r241753: Integrate changes from LSI vendor driver 10.80.00.005 to FreeBSD. PR: kern/172833 Submitted by: "Charles O'Donnell" Approved by: re (kib) git-svn-id: svn://svn.freebsd.org/base/releng/9.1@241764 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/tws/tws.c | 7 ++++ sys/dev/tws/tws.h | 6 ++-- sys/dev/tws/tws_cam.c | 14 ++++---- sys/dev/tws/tws_hdm.h | 2 +- sys/dev/tws/tws_user.c | 78 ++++++++++++++++++++++++++---------------- 5 files changed, 68 insertions(+), 39 deletions(-) diff --git a/sys/dev/tws/tws.c b/sys/dev/tws/tws.c index b1615db0..29f1173b 100644 --- a/sys/dev/tws/tws.c +++ b/sys/dev/tws/tws.c @@ -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) ) diff --git a/sys/dev/tws/tws.h b/sys/dev/tws/tws.h index 6d0f6ad0..5242d9dc 100644 --- a/sys/dev/tws/tws.h +++ b/sys/dev/tws/tws.h @@ -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 */ diff --git a/sys/dev/tws/tws_cam.c b/sys/dev/tws/tws_cam.c index df78b99f..dbcf3931 100644 --- a/sys/dev/tws/tws_cam.c +++ b/sys/dev/tws/tws_cam.c @@ -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); } diff --git a/sys/dev/tws/tws_hdm.h b/sys/dev/tws/tws_hdm.h index 5633fdf7..58feeeec 100644 --- a/sys/dev/tws/tws_hdm.h +++ b/sys/dev/tws/tws_hdm.h @@ -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 diff --git a/sys/dev/tws/tws_user.c b/sys/dev/tws/tws_user.c index 98b8a9be..cbd03c94 100644 --- a/sys/dev/tws/tws_user.c +++ b/sys/dev/tws/tws_user.c @@ -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); } -- 2.42.0