Author: delphij Date: Fri Oct 19 22:07:40 2012 New Revision: 241753 URL: http://svn.freebsd.org/changeset/base/241753
Log: 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 Modified: head/sys/dev/tws/tws.c head/sys/dev/tws/tws.h head/sys/dev/tws/tws_cam.c head/sys/dev/tws/tws_hdm.h head/sys/dev/tws/tws_user.c Modified: head/sys/dev/tws/tws.c ============================================================================== --- head/sys/dev/tws/tws.c Fri Oct 19 20:13:08 2012 (r241752) +++ head/sys/dev/tws/tws.c Fri Oct 19 22:07:40 2012 (r241753) @@ -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) ) Modified: head/sys/dev/tws/tws.h ============================================================================== --- head/sys/dev/tws/tws.h Fri Oct 19 20:13:08 2012 (r241752) +++ head/sys/dev/tws/tws.h Fri Oct 19 22:07:40 2012 (r241753) @@ -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 */ Modified: head/sys/dev/tws/tws_cam.c ============================================================================== --- head/sys/dev/tws/tws_cam.c Fri Oct 19 20:13:08 2012 (r241752) +++ head/sys/dev/tws/tws_cam.c Fri Oct 19 22:07:40 2012 (r241753) @@ -970,6 +970,7 @@ tws_map_request(struct tws_softc *sc, st 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 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 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); } Modified: head/sys/dev/tws/tws_hdm.h ============================================================================== --- head/sys/dev/tws/tws_hdm.h Fri Oct 19 20:13:08 2012 (r241752) +++ head/sys/dev/tws/tws_hdm.h Fri Oct 19 22:07:40 2012 (r241753) @@ -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 Modified: head/sys/dev/tws/tws_user.c ============================================================================== --- head/sys/dev/tws/tws_user.c Fri Oct 19 20:13:08 2012 (r241752) +++ head/sys/dev/tws/tws_user.c Fri Oct 19 22:07:40 2012 (r241753) @@ -94,41 +94,46 @@ tws_passthru(struct tws_softc *sc, void 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 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 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 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); } _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"