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"

Reply via email to