twa(4): Sync with FreeBSD (twa(4) version 3.80.06.003).
authorSascha Wildner <saw@online.de>
Tue, 14 Sep 2010 19:48:10 +0000 (21:48 +0200)
committerSascha Wildner <saw@online.de>
Tue, 14 Sep 2010 19:48:28 +0000 (21:48 +0200)
Thanks to Xin Li for notifying me of this update.

Tested-by: Damian Lubosch <dl@xiqit.de>
12 files changed:
sys/dev/raid/twa/tw_cl.h
sys/dev/raid/twa/tw_cl_externs.h
sys/dev/raid/twa/tw_cl_fwif.h
sys/dev/raid/twa/tw_cl_init.c
sys/dev/raid/twa/tw_cl_intr.c
sys/dev/raid/twa/tw_cl_io.c
sys/dev/raid/twa/tw_cl_misc.c
sys/dev/raid/twa/tw_cl_share.h
sys/dev/raid/twa/tw_osl.h
sys/dev/raid/twa/tw_osl_cam.c
sys/dev/raid/twa/tw_osl_freebsd.c
sys/dev/raid/twa/tw_osl_share.h

index 8963c9e..9827b05 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl.h,v 1.5 2010/07/09 17:38:15 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl.h,v 1.6 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -88,7 +88,8 @@ struct tw_cli_q_stats {
 #define TW_CLI_BUSY_Q          1       /* q of reqs submitted to fw */
 #define TW_CLI_PENDING_Q       2       /* q of reqs deferred due to 'q full' */
 #define TW_CLI_COMPLETE_Q      3       /* q of reqs completed by fw */
-#define TW_CLI_Q_COUNT         4       /* total number of queues */
+#define TW_CLI_RESET_Q         4       /* q of reqs reset by timeout */
+#define TW_CLI_Q_COUNT         5       /* total number of queues */
 
 
 /* CL's internal request context. */
@@ -133,6 +134,7 @@ struct tw_cli_ctlr_context {
        TW_UINT8                interrupts_enabled;       /* Interrupts on controller enabled. */
        TW_UINT8                internal_req_busy;        /* Data buffer for internal requests in use. */
        TW_UINT8                get_more_aens;            /* More AEN's need to be retrieved. */
+       TW_UINT8                reset_needed;             /* Controller needs a soft reset. */
        TW_UINT8                reset_in_progress;        /* Controller is being reset. */
        TW_UINT8                reset_phase1_in_progress; /* In 'phase 1' of reset. */
        TW_UINT32               flags;          /* controller settings */
index 441a841..171e92a 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_externs.h,v 1.3 2007/05/09 04:16:32 scottl Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_externs.h,v 1.4 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -86,6 +86,8 @@ extern TW_INT32       tw_cli_submit_and_poll_request(struct tw_cli_req_context *req,
 
 /* Soft reset the controller. */
 extern TW_INT32        tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr);
+extern int twa_setup_intr(struct twa_softc *sc);
+extern int twa_teardown_intr(struct twa_softc *sc);
 
 /* Send down a SCSI command to the firmware (usually, an internal Req Sense. */
 extern TW_INT32        tw_cli_send_scsi_cmd(struct tw_cli_req_context *req,
index 3c8e8a4..f4564e3 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_fwif.h,v 1.4 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_fwif.h,v 1.5 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -89,7 +89,7 @@
 #define TWA_STATUS_MINOR_VERSION_MASK          0x0F000000
 #define TWA_STATUS_MAJOR_VERSION_MASK          0xF0000000
 
-#define TWA_STATUS_UNEXPECTED_BITS             0x00F00000
+#define TWA_STATUS_UNEXPECTED_BITS             0x00D00000
 
 
 /* PCI related defines. */
index 3a8c2a1..067efe9 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_init.c,v 1.6 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_init.c,v 1.7 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -315,6 +315,7 @@ tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
        tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q);
        tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q);
        tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q);
+       tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q);
 
        /* Initialize all locks used by CL. */
        ctlr->gen_lock = &(ctlr->gen_lock_handle);
@@ -675,15 +676,14 @@ tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
        /* Submit the command, and wait for it to complete. */
        error = tw_cli_submit_and_poll_request(req,
                TW_CLI_REQUEST_TIMEOUT_PERIOD);
-       if (error == TW_OSL_ETIMEDOUT)
-               /* Clean-up done by tw_cli_submit_and_poll_request. */
-               return(error);
        if (error)
                goto out;
        if ((error = init_connect->status)) {
+#if       0
                tw_cli_create_ctlr_event(ctlr,
                        TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                        &(req->cmd_pkt->cmd_hdr));
+#endif // 0
                goto out;
        }
        if (set_features & TWA_EXTENDED_INIT_CONNECT) {
index 8f0cee9..462579a 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_intr.c,v 1.5 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_intr.c,v 1.6 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -248,8 +248,7 @@ tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
 #ifdef TW_OSL_DEBUG
                        tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
 #endif /* TW_OSL_DEBUG */
-                       tw_cl_reset_ctlr(ctlr->ctlr_handle);
-                       return(TW_OSL_EIO);
+                       continue;
                }
 
                /*
@@ -402,9 +401,7 @@ tw_cli_complete_io(struct tw_cli_req_context *req)
 #ifdef TW_OSL_DEBUG
                tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
 #endif /* TW_OSL_DEBUG */
-               tw_cl_reset_ctlr(ctlr->ctlr_handle);
-               req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
-               goto out;
+               return;
        }
 
        if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
@@ -483,6 +480,7 @@ tw_cli_scsi_complete(struct tw_cli_req_context *req)
                        cdb[8], cdb[9], cdb[10], cdb[11],
                        cdb[12], cdb[13], cdb[14], cdb[15]);
 
+#if       0
                /*
                 * Print the error. Firmware doesn't yet support
                 * the 'Mode Sense' cmd.  Don't print if the cmd
@@ -493,6 +491,7 @@ tw_cli_scsi_complete(struct tw_cli_req_context *req)
                        tw_cli_create_ctlr_event(req->ctlr,
                                TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                                cmd_hdr);
+#endif // 0
        }
 
        if (scsi_req->sense_data) {
@@ -530,9 +529,11 @@ tw_cli_param_callback(struct tw_cli_req_context *req)
         */
        if (! req->error_code)
                if (cmd->param.status) {
+#if       0
                        tw_cli_create_ctlr_event(ctlr,
                                TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                                &(req->cmd_pkt->cmd_hdr));
+#endif // 0
                        tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
                                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
                                0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
@@ -590,9 +591,11 @@ tw_cli_aen_callback(struct tw_cli_req_context *req)
                if ((error = cmd->status)) {
                        cmd_hdr = (struct tw_cl_command_header *)
                                (&(req->cmd_pkt->cmd_hdr));
+#if       0
                        tw_cli_create_ctlr_event(ctlr,
                                TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                                cmd_hdr);
+#endif // 0
                        tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
                                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
                                0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
index bd2244a..e3da8e9 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_io.c,v 1.6 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_io.c,v 1.7 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -74,18 +74,12 @@ tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
        struct tw_cli_req_context               *req;
        struct tw_cl_command_9k                 *cmd;
        struct tw_cl_scsi_req_packet            *scsi_req;
-       TW_INT32                                error;
+       TW_INT32                                error = TW_CL_ERR_REQ_SUCCESS;
 
        tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
 
        ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
 
-       if (ctlr->reset_in_progress) {
-               tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
-                       "I/O during reset: returning busy.");
-               return(TW_OSL_EBUSY);
-       }
-
        /*
         * If working with a firmware version that does not support multiple
         * luns, and this request is directed at a non-zero lun, error it
@@ -145,7 +139,12 @@ tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
                        cmd->sg_list, scsi_req->sgl_entries);
        }
 
-       if ((error = tw_cli_submit_cmd(req))) {
+       if (((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) != TW_CL_NULL) ||
+               (ctlr->reset_in_progress)) {
+               tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
+               TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
+                       TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
+       } else if ((error = tw_cli_submit_cmd(req))) {
                tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
                        "Could not start request. request = %p, error = %d",
                        req, error);
@@ -171,7 +170,7 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
        struct tw_cli_ctlr_context      *ctlr = req->ctlr;
        struct tw_cl_ctlr_handle        *ctlr_handle = ctlr->ctlr_handle;
        TW_UINT32                       status_reg;
-       TW_INT32                        error;
+       TW_INT32                        error = 0;
 
        tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
 
@@ -185,11 +184,7 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
                                 TWA_COMMAND_QUEUE_OFFSET_LOW,
                                 (TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4);
 
-       /* Check to see if we can post a command. */
        status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
-       if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
-               goto out;
-
        if (status_reg & TWA_STATUS_COMMAND_QUEUE_FULL) {
                struct tw_cl_req_packet *req_pkt =
                        (struct tw_cl_req_packet *)(req->orig_req);
@@ -207,14 +202,12 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
                                        "pending internal/ioctl request");
                                req->state = TW_CLI_REQ_STATE_PENDING;
                                tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
-                               error = 0;
                                /* Unmask command interrupt. */
                                TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
                                        TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
                        } else
                                error = TW_OSL_EBUSY;
                } else {
-                       tw_osl_ctlr_busy(ctlr_handle, req->req_handle);
                        error = TW_OSL_EBUSY;
                }
        } else {
@@ -246,7 +239,7 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
                                                 (TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4);
                }
        }
-out:
+
        tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
 
        return(error);
@@ -277,18 +270,12 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
        TW_UINT8                                opcode;
        TW_UINT8                                sgl_offset;
        TW_VOID                                 *sgl = TW_CL_NULL;
-       TW_INT32                                error;
+       TW_INT32                                error = TW_CL_ERR_REQ_SUCCESS;
 
        tw_cli_dbg_printf(5, ctlr_handle, tw_osl_cur_func(), "entered");
 
        ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
 
-       if (ctlr->reset_in_progress) {
-               tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
-                       "Passthru request during reset: returning busy.");
-               return(TW_OSL_EBUSY);
-       }
-
        if ((req = tw_cli_get_request(ctlr
                )) == TW_CL_NULL) {
                tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
@@ -301,7 +288,7 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
        req->orig_req = req_pkt;
        req->tw_cli_callback = tw_cli_complete_io;
 
-       req->flags |= (TW_CLI_REQ_FLAGS_EXTERNAL | TW_CLI_REQ_FLAGS_PASSTHRU);
+       req->flags |= TW_CLI_REQ_FLAGS_PASSTHRU;
 
        pt_req = &(req_pkt->gen_req_pkt.pt_req);
 
@@ -348,7 +335,12 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
                tw_cli_fill_sg_list(ctlr, pt_req->sg_list,
                        sgl, pt_req->sgl_entries);
 
-       if ((error = tw_cli_submit_cmd(req))) {
+       if (((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) != TW_CL_NULL) ||
+               (ctlr->reset_in_progress)) {
+               tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
+               TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
+                       TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
+       } else if ((error = tw_cli_submit_cmd(req))) {
                tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                        TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
                        0x1100, 0x1, TW_CL_SEVERITY_ERROR_STRING,
@@ -760,8 +752,7 @@ tw_cli_get_param(struct tw_cli_ctlr_context *ctlr, TW_INT32 table_id,
 
        cmd->param.sgl_off__opcode =
                BUILD_SGL_OFF__OPCODE(2, TWA_FW_CMD_GET_PARAM);
-       cmd->param.request_id =
-               (TW_UINT8)(TW_CL_SWAP16(req->request_id));
+       cmd->param.request_id = (TW_UINT8)(TW_CL_SWAP16(req->request_id));
        cmd->param.host_id__unit = BUILD_HOST_ID__UNIT(0, 0);
        cmd->param.param_count = TW_CL_SWAP16(1);
 
@@ -789,15 +780,14 @@ tw_cli_get_param(struct tw_cli_ctlr_context *ctlr, TW_INT32 table_id,
                /* There's no call back; wait till the command completes. */
                error = tw_cli_submit_and_poll_request(req,
                                TW_CLI_REQUEST_TIMEOUT_PERIOD);
-               if (error == TW_OSL_ETIMEDOUT)
-                       /* Clean-up done by tw_cli_submit_and_poll_request. */
-                       return(error);
                if (error)
                        goto out;
                if ((error = cmd->param.status)) {
+#if       0
                        tw_cli_create_ctlr_event(ctlr,
                                TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                                &(req->cmd_pkt->cmd_hdr));
+#endif // 0
                        goto out;
                }
                tw_osl_memcpy(param_data, param->data, param_size);
@@ -905,18 +895,17 @@ tw_cli_set_param(struct tw_cli_ctlr_context *ctlr, TW_INT32 table_id,
 
        /* Submit the command. */
        if (callback == TW_CL_NULL) {
-               /* There's no call back;  wait till the command completes. */
+               /* There's no call back; wait till the command completes. */
                error = tw_cli_submit_and_poll_request(req,
-                       TW_CLI_REQUEST_TIMEOUT_PERIOD);
-               if (error == TW_OSL_ETIMEDOUT)
-                       /* Clean-up done by tw_cli_submit_and_poll_request. */
-                       return(error);
+                               TW_CLI_REQUEST_TIMEOUT_PERIOD);
                if (error)
                        goto out;
                if ((error = cmd->param.status)) {
+#if       0
                        tw_cli_create_ctlr_event(ctlr,
                                TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                                &(req->cmd_pkt->cmd_hdr));
+#endif // 0
                        goto out;
                }
                ctlr->internal_req_busy = TW_CL_FALSE;
@@ -1022,9 +1011,7 @@ tw_cli_submit_and_poll_request(struct tw_cli_req_context *req,
         * tw_cli_submit_pending_queue.  There could be a race in that case.
         * Need to revisit.
         */
-       if (req->state != TW_CLI_REQ_STATE_PENDING)
-               tw_cl_reset_ctlr(ctlr->ctlr_handle);
-       else {
+       if (req->state == TW_CLI_REQ_STATE_PENDING) {
                tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(),
                        "Removing request from pending queue");
                /*
@@ -1053,6 +1040,7 @@ tw_cli_submit_and_poll_request(struct tw_cli_req_context *req,
  *                     drains any incomplete requests.
  *
  * Input:              ctlr    -- ptr to per ctlr structure
+ *                     req_handle      -- ptr to request handle
  * Output:             None
  * Return value:       0       -- success
  *                     non-zero-- failure
@@ -1063,15 +1051,15 @@ tw_cl_reset_ctlr(struct tw_cl_ctlr_handle *ctlr_handle)
        struct tw_cli_ctlr_context      *ctlr =
                (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
        struct twa_softc                *sc = ctlr_handle->osl_ctlr_ctxt;
+       struct tw_cli_req_context       *req;
        TW_INT32                        reset_attempt = 1;
-       TW_INT32                        error;
+       TW_INT32                        error = 0;
 
        tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(), "entered");
 
        ctlr->reset_in_progress = TW_CL_TRUE;
-       xpt_freeze_simq(sc->sim, 1);
+       twa_teardown_intr(sc);
 
-       tw_cli_disable_interrupts(ctlr);
 
        /*
         * Error back all requests in the complete, busy, and pending queues.
@@ -1080,8 +1068,6 @@ tw_cl_reset_ctlr(struct tw_cl_ctlr_handle *ctlr_handle)
         * will continue its course and get submitted to the controller after
         * the reset is done (and io_lock is released).
         */
-       tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
-               "Draining all queues following reset");
        tw_cli_drain_complete_queue(ctlr);
        tw_cli_drain_busy_queue(ctlr);
        tw_cli_drain_pending_queue(ctlr);
@@ -1089,53 +1075,88 @@ tw_cl_reset_ctlr(struct tw_cl_ctlr_handle *ctlr_handle)
        ctlr->get_more_aens     = TW_CL_FALSE;
 
        /* Soft reset the controller. */
-try_reset:
-       if ((error = tw_cli_soft_reset(ctlr))) {
-               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
-                       TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
-                       0x1105, 0x1, TW_CL_SEVERITY_ERROR_STRING,
-                       "Controller reset failed",
-                       "error = %d; attempt %d", error, reset_attempt++);
-               if (reset_attempt <= TW_CLI_MAX_RESET_ATTEMPTS)
-                       goto try_reset;
-               else
-                       goto out;
-       }
+       while (reset_attempt <= TW_CLI_MAX_RESET_ATTEMPTS) {
+               if ((error = tw_cli_soft_reset(ctlr))) {
+                       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
+                               TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
+                               0x1105, 0x1, TW_CL_SEVERITY_ERROR_STRING,
+                               "Controller reset failed",
+                               "error = %d; attempt %d", error, reset_attempt++);
+                       reset_attempt++;
+                       continue;
+               }
 
-       /* Re-establish logical connection with the controller. */
-       if ((error = tw_cli_init_connection(ctlr,
-                       (TW_UINT16)(ctlr->max_simult_reqs),
-                       0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
-                       TW_CL_NULL, TW_CL_NULL))) {
-               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
-                       TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
-                       0x1106, 0x1, TW_CL_SEVERITY_ERROR_STRING,
-                       "Can't initialize connection after reset",
-                       "error = %d", error);
-               goto out;
-       }
+               /* Re-establish logical connection with the controller. */
+               if ((error = tw_cli_init_connection(ctlr,
+                               (TW_UINT16)(ctlr->max_simult_reqs),
+                               0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
+                               TW_CL_NULL, TW_CL_NULL))) {
+                       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
+                               TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
+                               0x1106, 0x1, TW_CL_SEVERITY_ERROR_STRING,
+                               "Can't initialize connection after reset",
+                               "error = %d", error);
+                       reset_attempt++;
+                       continue;
+               }
 
-       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
-               TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
-               0x1107, 0x3, TW_CL_SEVERITY_INFO_STRING,
-               "Controller reset done!",
-               " ");
+#ifdef    TW_OSL_DEBUG
+               tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
+                       TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
+                       0x1107, 0x3, TW_CL_SEVERITY_INFO_STRING,
+                       "Controller reset done!", " ");
+#endif /* TW_OSL_DEBUG */
+               break;
+       } /* End of while */
 
-out:
-       ctlr->reset_in_progress = TW_CL_FALSE;
-       xpt_release_simq(sc->sim, 1);
+       /* Move commands from the reset queue to the pending queue. */
+       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_RESET_Q)) != TW_CL_NULL) {
+               tw_osl_timeout(req->req_handle);
+               tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
+       }
 
-       /*
-        * Enable interrupts, and also clear attention and response interrupts.
-        */
+       twa_setup_intr(sc);
        tw_cli_enable_interrupts(ctlr);
+       if ((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) != TW_CL_NULL)
+               TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
+                       TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
+       ctlr->reset_in_progress = TW_CL_FALSE;
+       ctlr->reset_needed = TW_CL_FALSE;
 
        /* Request for a bus re-scan. */
-       if (!error)
-               tw_osl_scan_bus(ctlr_handle);
+       tw_osl_scan_bus(ctlr_handle);
+
        return(error);
 }
 
+TW_VOID
+tw_cl_set_reset_needed(struct tw_cl_ctlr_handle *ctlr_handle)
+{
+       struct tw_cli_ctlr_context      *ctlr =
+               (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
+
+       ctlr->reset_needed = TW_CL_TRUE;
+}
+
+TW_INT32
+tw_cl_is_reset_needed(struct tw_cl_ctlr_handle *ctlr_handle)
+{
+       struct tw_cli_ctlr_context      *ctlr =
+               (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
+
+       return(ctlr->reset_needed);
+}
+
+TW_INT32
+tw_cl_is_active(struct tw_cl_ctlr_handle *ctlr_handle)
+{
+       struct tw_cli_ctlr_context      *ctlr =
+               (struct tw_cli_ctlr_context *)
+               (ctlr_handle->cl_ctlr_ctxt);
+
+               return(ctlr->active);
+}
+
 
 
 /*
@@ -1151,14 +1172,13 @@ TW_INT32
 tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
 {
        struct tw_cl_ctlr_handle        *ctlr_handle = ctlr->ctlr_handle;
-       TW_UINT32                       status_reg;
        int                             found;
        int                             loop_count;
        TW_UINT32                       error;
 
        tw_cli_dbg_printf(1, ctlr_handle, tw_osl_cur_func(), "entered");
 
-       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                0x1108, 0x3, TW_CL_SEVERITY_INFO_STRING,
                "Resetting controller...",
@@ -1193,7 +1213,7 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
                } while (!found && (loop_count < 6000000)); /* Loop for no more than 60 seconds */
 
                if (!found) {
-                       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+                       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                                0x1109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                                "Missed firmware handshake after soft-reset",
@@ -1210,7 +1230,7 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
                        TWA_STATUS_MICROCONTROLLER_READY |
                        TWA_STATUS_ATTENTION_INTERRUPT,
                        TW_CLI_RESET_TIMEOUT_PERIOD))) {
-               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+               tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                        TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                        0x1109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                        "Micro-ctlr not ready/No attn intr after reset",
@@ -1244,7 +1264,7 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
        }
 
        if ((error = tw_cli_find_aen(ctlr, TWA_AEN_SOFT_RESET))) {
-               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+               tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                        TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                        0x110C, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                        "Reset not reported by controller",
@@ -1252,18 +1272,6 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
                return(error);
        }
 
-       status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
-
-       if ((error = TW_CLI_STATUS_ERRORS(status_reg)) ||
-                       (error = tw_cli_check_ctlr_state(ctlr, status_reg))) {
-               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
-                       TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
-                       0x110D, 0x1, TW_CL_SEVERITY_ERROR_STRING,
-                       "Controller errors detected after reset",
-                       "error = %d", error);
-               return(error);
-       }
-
        return(TW_OSL_ESUCCESS);
 }
 
index 7993430..9b4e7f8 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_misc.c,v 1.6 2010/06/17 19:48:03 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_misc.c,v 1.7 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -83,7 +83,8 @@ tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr)
        tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
 
        /* Walk the busy queue. */
-       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q))) {
+       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
+               TW_CL_NULL) {
                if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
                        /*
                         * It's an internal request.  Set the appropriate
@@ -97,20 +98,21 @@ tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr)
                        req->error_code = TW_CL_ERR_REQ_BUS_RESET;
                        if (req->tw_cli_callback)
                                req->tw_cli_callback(req);
-               } else {
-                       if ((req_pkt = req->orig_req)) {
-                               /* It's a SCSI request.  Complete it. */
-                               tw_cli_dbg_printf(2, ctlr->ctlr_handle,
-                                       tw_osl_cur_func(),
-                                       "Completing complete request %p "
-                                       "on reset",
-                                       req);
+               } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
+                       /* It's a passthru request.  Complete it. */
+                       if ((req_pkt = req->orig_req) != TW_CL_NULL) {
                                req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
-                               req_pkt->tw_osl_callback(req->req_handle);
+
+                               if (req_pkt->tw_osl_callback)
+                                       req_pkt->tw_osl_callback(req->req_handle);
                        }
                        tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
+               } else {
+                       /* It's an external (SCSI) request.  Add it to the reset queue. */
+                       tw_osl_untimeout(req->req_handle);
+                       tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
                }
-       }
+       } /* End of while loop */
 }
 
 
@@ -135,7 +137,8 @@ tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr)
        tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
 
        /* Walk the busy queue. */
-       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_BUSY_Q))) {
+       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_BUSY_Q)) !=
+               TW_CL_NULL) {
                if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
                        /*
                         * It's an internal request.  Set the appropriate
@@ -149,19 +152,21 @@ tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr)
                        req->error_code = TW_CL_ERR_REQ_BUS_RESET;
                        if (req->tw_cli_callback)
                                req->tw_cli_callback(req);
-               } else {
-                       if ((req_pkt = req->orig_req)) {
-                               /* It's a SCSI request.  Complete it. */
-                               tw_cli_dbg_printf(2, ctlr->ctlr_handle,
-                                       tw_osl_cur_func(),
-                                       "Completing busy request %p on reset",
-                                       req);
+               } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
+                       /* It's a passthru request.  Complete it. */
+                       if ((req_pkt = req->orig_req) != TW_CL_NULL) {
                                req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
-                               req_pkt->tw_osl_callback(req->req_handle);
+
+                               if (req_pkt->tw_osl_callback)
+                                       req_pkt->tw_osl_callback(req->req_handle);
                        }
                        tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
+               } else {
+                       /* It's an external (SCSI) request.  Add it to the reset queue. */
+                       tw_osl_untimeout(req->req_handle);
+                       tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
                }
-       }
+       } /* End of while loop */
 }
 
 
@@ -188,7 +193,8 @@ tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr)
        /*
         * Pull requests off the pending queue, and complete them.
         */
-       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q))) {
+       while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
+               TW_CL_NULL) {
                if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
                        /*
                         * It's an internal request.  Set the appropriate
@@ -202,19 +208,21 @@ tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr)
                        req->error_code = TW_CL_ERR_REQ_BUS_RESET;
                        if (req->tw_cli_callback)
                                req->tw_cli_callback(req);
-               } else {
-                       if ((req_pkt = req->orig_req)) {
-                               /* It's an external request.  Complete it. */
-                               tw_cli_dbg_printf(2, ctlr->ctlr_handle,
-                                       tw_osl_cur_func(),
-                                       "Completing pending request %p "
-                                       "on reset", req);
+               } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
+                       /* It's a passthru request.  Complete it. */
+                       if ((req_pkt = req->orig_req) != TW_CL_NULL) {
                                req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
-                               req_pkt->tw_osl_callback(req->req_handle);
+
+                               if (req_pkt->tw_osl_callback)
+                                       req_pkt->tw_osl_callback(req->req_handle);
                        }
                        tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
+               } else {
+                       /* It's an external (SCSI) request.  Add it to the reset queue. */
+                       tw_osl_untimeout(req->req_handle);
+                       tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
                }
-       }
+       } /* End of while loop */
 }
 
 
@@ -239,9 +247,6 @@ tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr)
        for (;;) {
                status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
 
-               if (tw_cli_check_ctlr_state(ctlr, status_reg))
-                       return(TW_OSL_EGENFAILURE);
-
                if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
                        return(TW_OSL_ESUCCESS); /* no more response queue entries */
 
@@ -273,9 +278,6 @@ tw_cli_find_response(struct tw_cli_ctlr_context *ctlr, TW_INT32 req_id)
        for (;;) {
                status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
 
-               if (tw_cli_check_ctlr_state(ctlr, status_reg))
-                       return(TW_OSL_EGENFAILURE);
-
                if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
                        return(TW_OSL_ENOTTY); /* no more response queue entries */
 
@@ -356,9 +358,11 @@ tw_cli_drain_aen_queue(struct tw_cli_ctlr_context *ctlr)
 
                if ((error = req->cmd_pkt->command.cmd_pkt_9k.status)) {
                        cmd_hdr = &req->cmd_pkt->cmd_hdr;
+#if       0
                        tw_cli_create_ctlr_event(ctlr,
                                TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
                                cmd_hdr);
+#endif // 0
                        break;
                }
 
@@ -714,7 +718,7 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
 
                tw_osl_memzero(desc, 200);
                if (!(ctlr->reset_phase1_in_progress)) {
-                       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+                       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                                0x1301, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                                "Missing expected status bit(s)",
@@ -738,7 +742,7 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
                     (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
                    (!(ctlr->reset_in_progress)) ||
                    ((status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) == 0))
-               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+               tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                        TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                        0x1302, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                        "Unexpected status bit(s)",
@@ -748,7 +752,7 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
                                TWA_STATUS_UNEXPECTED_BITS, desc));
 
                if (status_reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) {
-                       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+                       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                                0x1303, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                                "PCI parity error: clearing... "
@@ -768,7 +772,7 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
                }
 
                if (status_reg & TWA_STATUS_PCI_ABORT_INTERRUPT) {
-                       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+                       tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                                TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                                0x1304, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                                "PCI abort: clearing... ",
@@ -791,7 +795,7 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
                        if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
                             (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
                            (!(ctlr->reset_in_progress)))
-                               tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
+                               tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
                                                   TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
                                                   0x1305, 0x1, TW_CL_SEVERITY_ERROR_STRING,
                                                   "Controller queue error: clearing... ",
@@ -801,17 +805,6 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
                        TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
                                TWA_CONTROL_CLEAR_QUEUE_ERROR);
                }
-
-               if (status_reg & TWA_STATUS_MICROCONTROLLER_ERROR) {
-                       tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
-                               TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
-                               0x1307, 0x1, TW_CL_SEVERITY_ERROR_STRING,
-                               "Micro-controller error! ",
-                               "status reg = 0x%x %s",
-                               status_reg,
-                               tw_cli_describe_bits(status_reg, desc));
-                       error = TW_OSL_EGENFAILURE;
-               }
        }
        return(error);
 }
@@ -850,8 +843,6 @@ tw_cli_describe_bits(TW_UINT32 reg, TW_INT8 *str)
                tw_osl_strcpy(&str[tw_osl_strlen(str)], "HOST_INTR,");
        if (reg & TWA_STATUS_PCI_ABORT_INTERRUPT)
                tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_ABRT,");
-       if (reg & TWA_STATUS_MICROCONTROLLER_ERROR)
-               tw_osl_strcpy(&str[tw_osl_strlen(str)], "MC_ERR,");
        if (reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT)
                tw_osl_strcpy(&str[tw_osl_strlen(str)], "Q_ERR,");
        if (reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT)
index ec8326d..80dd453 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_cl_share.h,v 1.7 2010/07/09 17:38:15 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_cl_share.h,v 1.8 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -349,10 +349,14 @@ extern TW_VOID    tw_osl_breakpoint(TW_VOID);
 #endif
 
 
-#ifndef tw_osl_ctlr_busy
-/* Called when CL is too busy to accept new requests. */
-extern TW_VOID tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
-       struct tw_cl_req_handle *req_handle);
+#ifndef tw_osl_timeout
+/* Start OS timeout() routine after controller reset sequence */
+extern TW_VOID tw_osl_timeout(struct tw_cl_req_handle *req_handle);
+#endif
+
+#ifndef tw_osl_untimeout
+/* Stop OS timeout() routine during controller reset sequence */
+extern TW_VOID tw_osl_untimeout(struct tw_cl_req_handle *req_handle);
 #endif
 
 
@@ -552,6 +556,10 @@ extern TW_INT32    tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle,
        );
 
 
+extern TW_VOID  tw_cl_set_reset_needed(struct tw_cl_ctlr_handle *ctlr_handle);
+extern TW_INT32 tw_cl_is_reset_needed(struct tw_cl_ctlr_handle *ctlr_handle);
+extern TW_INT32 tw_cl_is_active(struct tw_cl_ctlr_handle *ctlr_handle);
+
 /* CL's interrupt handler. */
 extern TW_INT32        tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle);
 
index 144953a..5989065 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_osl.h,v 1.8 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_osl.h,v 1.9 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -77,6 +77,7 @@
                                                EINPROGRESS */
 #define TW_OSLI_REQ_FLAGS_PASSTHRU     (1<<5)  /* pass through request */
 #define TW_OSLI_REQ_FLAGS_SLEEPING     (1<<6)  /* owner sleeping on this cmd */
+#define TW_OSLI_REQ_FLAGS_FAILED       (1<<7)  /* bus_dmamap_load() failed */
 
 
 #ifdef TW_OSL_DEBUG
@@ -100,6 +101,7 @@ struct tw_osli_req_context {
        struct twa_softc        *ctlr;  /* ptr to OSL's controller context */
        TW_VOID                 *data;  /* ptr to data being passed to CL */
        TW_UINT32               length; /* length of buf being passed to CL */
+       TW_UINT64               deadline;/* request timeout (in absolute time) */
 
        /*
         * ptr to, and length of data passed to us from above, in case a buffer
@@ -151,6 +153,9 @@ struct twa_softc {
        struct lock             sim_lock_handle;/* sim lock shared with cam */
        struct lock             *sim_lock;/* ptr to sim lock */
 
+       struct callout          watchdog_callout[2]; /* For command timout */
+       TW_UINT32               watchdog_index;
+
 #ifdef TW_OSL_DEBUG
        struct tw_osli_q_stats  q_stats[TW_OSLI_Q_COUNT];/* queue statistics */
 #endif /* TW_OSL_DEBUG */
index a5bffa6..6b31fc1 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_osl_cam.c,v 1.14 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_osl_cam.c,v 1.15 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -56,7 +56,6 @@
 
 static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb);
 static TW_VOID twa_poll(struct cam_sim *sim);
-static TW_VOID twa_timeout(TW_VOID *arg);
 static TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
 
 static TW_INT32        tw_osli_execute_scsi(struct tw_osli_req_context *req,
@@ -83,7 +82,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
        /*
         * Create the device queue for our SIM.
         */
-       if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_REQUESTS)) == NULL) {
+       if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
                tw_osli_printf(sc, "error = %d",
                        TW_CL_SEVERITY_ERROR_STRING,
                        TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
@@ -276,6 +275,7 @@ tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
                                        "I/O size too big",
                                        csio->dxfer_len);
                                ccb_h->status = CAM_REQ_TOO_BIG;
+                               ccb_h->status &= ~CAM_SIM_QUEUED;
                                xpt_done(ccb);
                                return(1);
                        }
@@ -291,6 +291,7 @@ tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
                                0x2107,
                                "XPT_SCSI_IO: Got SGList");
                        ccb_h->status = CAM_REQ_INVALID;
+                       ccb_h->status &= ~CAM_SIM_QUEUED;
                        xpt_done(ccb);
                        return(1);
                }
@@ -307,13 +308,20 @@ tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
                return(1);
        }
 
-       callout_reset(&ccb->ccb_h.timeout_ch,
-               (ccb_h->timeout * hz) / 1000, twa_timeout, req);
+       req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
+
+
        /*
         * twa_map_load_data_callback will fill in the SGL,
         * and submit the I/O.
         */
        error = tw_osli_map_request(req);
+       if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
+               req->deadline = 0;
+               ccb_h->status = CAM_REQ_CMP_ERR;
+               ccb_h->status &= ~CAM_SIM_QUEUED;
+               xpt_done(ccb);
+       }
        return(error);
 }
 
@@ -346,10 +354,20 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
                         * Freeze the simq to maintain ccb ordering.  The next
                         * ccb that gets completed will unfreeze the simq.
                         */
+                       ccb_h->status &= ~CAM_SIM_QUEUED;
+                       ccb_h->status |= CAM_REQUEUE_REQ;
+                       xpt_done(ccb);
+                       break;
+               }
+
+               if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
+                       ccb_h->status &= ~CAM_SIM_QUEUED;
                        ccb_h->status |= CAM_REQUEUE_REQ;
                        xpt_done(ccb);
+                       tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
                        break;
                }
+
                req->req_handle.osl_req_ctxt = req;
                req->req_handle.is_io = TW_CL_TRUE;
                req->orig_req = ccb;
@@ -365,25 +383,14 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
                break;
 
        case XPT_RESET_BUS:
-               tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
+               tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
                        TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
                        0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
                        "Received Reset Bus request from CAM",
                        " ");
 
-               lockmgr(sc->sim_lock, LK_RELEASE);
-               if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
-                       tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
-                               TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
-                               0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
-                               "Failed to reset bus",
-                               " ");
-                       ccb_h->status = CAM_REQ_CMP_ERR;
-               }
-               else
-                       ccb_h->status = CAM_REQ_CMP;
-
-               lockmgr(sc->sim_lock, LK_EXCLUSIVE);
+               tw_cl_set_reset_needed(&(sc->ctlr_handle));
+               ccb_h->status = CAM_REQ_CMP;
                xpt_done(ccb);
                break;
 
@@ -451,6 +458,9 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
                 path_inq->transport_version = 2;
                 path_inq->protocol = PROTO_SCSI;
                 path_inq->protocol_version = SCSI_REV_2;
+#if 0 /* XXX swildner */
+                path_inq->maxio = TW_CL_MAX_IO_SIZE;
+#endif
                ccb_h->status = CAM_REQ_CMP;
                xpt_done(ccb);
                break;
@@ -488,31 +498,6 @@ twa_poll(struct cam_sim *sim)
 
 
 /*
- * Function name:      twa_timeout
- * Description:                Driver entry point for being alerted on a request
- *                     timing out.
- *
- * Input:              arg     -- ptr to timed out request
- * Output:             None
- * Return value:       None
- */
-static TW_VOID
-twa_timeout(TW_VOID *arg)
-{
-       struct tw_osli_req_context      *req =
-               (struct tw_osli_req_context *)arg;
-
-       tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
-               TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
-               0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
-               "Request timed out!",
-               "request = %p", req);
-       tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
-}
-
-
-
-/*
  * Function name:      tw_osli_request_bus_scan
  * Description:                Requests CAM for a scan of the bus.
  *
@@ -606,20 +591,39 @@ tw_osli_disallow_new_requests(struct twa_softc *sc,
 
 
 /*
- * Function name:      tw_osl_ctlr_busy
- * Description:                CL calls this function on cmd queue full or otherwise,
- *                     when it is too busy to accept new requests.
+ * Function name:      tw_osl_timeout
+ * Description:                Call to timeout().
  *
- * Input:              ctlr_handle     -- ptr to controller handle
- *                     req_handle      -- ptr to request handle sent by OSL.
+ * Input:              req_handle -- ptr to request handle sent by OSL.
  * Output:             None
  * Return value:       None
  */
 TW_VOID
-tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
-       struct tw_cl_req_handle *req_handle)
+tw_osl_timeout(struct tw_cl_req_handle *req_handle)
+{
+       struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
+       union ccb                       *ccb = (union ccb *)(req->orig_req);
+       struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
+
+       req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
+}
+
+
+
+/*
+ * Function name:      tw_osl_untimeout
+ * Description:                Inverse of call to timeout().
+ *
+ * Input:              req_handle -- ptr to request handle sent by OSL.
+ * Output:             None
+ * Return value:       None
+ */
+TW_VOID
+tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
 {
-       tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt, req_handle);
+       struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
+
+       req->deadline = 0;
 }
 
 
@@ -687,7 +691,7 @@ tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
 
        tw_osli_unmap_request(req);
 
-       callout_stop(&ccb->ccb_h.timeout_ch);
+       req->deadline = 0;
        if (req->error_code) {
                /* This request never got submitted to the firmware. */
                if (req->error_code == EBUSY) {
@@ -714,7 +718,7 @@ tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
                        else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
                                ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
                        else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
-                               ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
+                               ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
                        /*
                         * If none of the above errors occurred, simply
                         * mark completion error.
index 045531f..1579f03 100644 (file)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_osl_freebsd.c,v 1.15 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_osl_freebsd.c,v 1.18 2010/09/04 16:27:14 bz Exp $
  */
 
 /*
@@ -181,6 +181,9 @@ static TW_INT32     twa_shutdown(device_t dev);
 static TW_VOID twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op);
 #endif
 static TW_VOID twa_pci_intr(TW_VOID *arg);
+static TW_VOID twa_watchdog(TW_VOID *arg);
+int twa_setup_intr(struct twa_softc *sc);
+int twa_teardown_intr(struct twa_softc *sc);
 
 static TW_INT32        tw_osli_alloc_mem(struct twa_softc *sc);
 static TW_VOID tw_osli_free_resources(struct twa_softc *sc);
@@ -244,6 +247,32 @@ twa_probe(device_t dev)
        return(ENXIO);
 }
 
+int twa_setup_intr(struct twa_softc *sc)
+{
+       int error = 0;
+
+       if (!(sc->intr_handle) && (sc->irq_res)) {
+               error = bus_setup_intr(sc->bus_dev, sc->irq_res,
+                                       0,
+                                       twa_pci_intr,
+                                       sc, &sc->intr_handle, NULL);
+       }
+       return( error );
+}
+
+
+int twa_teardown_intr(struct twa_softc *sc)
+{
+       int error = 0;
+
+       if ((sc->intr_handle) && (sc->irq_res)) {
+               error = bus_teardown_intr(sc->bus_dev,
+                                               sc->irq_res, sc->intr_handle);
+               sc->intr_handle = NULL;
+       }
+       return( error );
+}
+
 
 
 /*
@@ -360,10 +389,7 @@ twa_attach(device_t dev)
                tw_osli_free_resources(sc);
                return(ENXIO);
        }
-       if ((error = bus_setup_intr(sc->bus_dev, sc->irq_res,
-                       0,
-                       twa_pci_intr,
-                       sc, &sc->intr_handle, NULL))) {
+       if ((error = twa_setup_intr(sc))) {
                tw_osli_printf(sc, "error = %d",
                        TW_CL_SEVERITY_ERROR_STRING,
                        TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
@@ -418,10 +444,74 @@ twa_attach(device_t dev)
                return(error);
        }
 
+       sc->watchdog_index = 0;
+       callout_init(&(sc->watchdog_callout[0]));
+       callout_init(&(sc->watchdog_callout[1]));
+       callout_reset(&(sc->watchdog_callout[0]), 5*hz, twa_watchdog, &sc->ctlr_handle);
+
        return(0);
 }
 
 
+static TW_VOID
+twa_watchdog(TW_VOID *arg)
+{
+       struct tw_cl_ctlr_handle *ctlr_handle =
+               (struct tw_cl_ctlr_handle *)arg;
+       struct twa_softc                *sc = ctlr_handle->osl_ctlr_ctxt;
+       int                             i;
+       int                             i_need_a_reset = 0;
+       int                             driver_is_active = 0;
+       TW_UINT64                       current_time;
+       struct tw_osli_req_context      *my_req;
+
+
+//==============================================================================
+       current_time = (TW_UINT64) (tw_osl_get_local_time());
+
+       for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
+               my_req = &(sc->req_ctx_buf[i]);
+
+               if ((my_req->state == TW_OSLI_REQ_STATE_BUSY) &&
+                       (my_req->deadline) &&
+                       (my_req->deadline < current_time)) {
+                       tw_cl_set_reset_needed(ctlr_handle);
+#ifdef    TW_OSL_DEBUG
+                       device_printf((sc)->bus_dev, "Request %d timed out! d = %llu, c = %llu\n", i, my_req->deadline, current_time);
+#else  /* TW_OSL_DEBUG */
+                       device_printf((sc)->bus_dev, "Request %d timed out!\n", i);
+#endif /* TW_OSL_DEBUG */
+                       break;
+               }
+       }
+//==============================================================================
+
+       i_need_a_reset = tw_cl_is_reset_needed(ctlr_handle);
+
+       i = (int) ((sc->watchdog_index++) & 1);
+
+       driver_is_active = tw_cl_is_active(ctlr_handle);
+
+       if (i_need_a_reset) {
+#ifdef    TW_OSL_DEBUG
+               device_printf((sc)->bus_dev, "Watchdog rescheduled in 70 seconds\n");
+#endif /* TW_OSL_DEBUG */
+               callout_reset(&(sc->watchdog_callout[i]), 70*hz, twa_watchdog, &sc->ctlr_handle);
+               tw_cl_reset_ctlr(ctlr_handle);
+#ifdef    TW_OSL_DEBUG
+               device_printf((sc)->bus_dev, "Watchdog reset completed!\n");
+#endif /* TW_OSL_DEBUG */
+       } else if (driver_is_active) {
+               callout_reset(&(sc->watchdog_callout[i]),  5*hz, twa_watchdog, &sc->ctlr_handle);
+       }
+#ifdef    TW_OSL_DEBUG
+       if (i_need_a_reset)
+               device_printf((sc)->bus_dev, "i_need_a_reset = %d, "
+               "driver_is_active = %d\n",
+               i_need_a_reset, driver_is_active);
+#endif /* TW_OSL_DEBUG */
+}
+
 
 /*
  * Function name:      tw_osli_alloc_mem
@@ -721,9 +811,7 @@ tw_osli_free_resources(struct twa_softc *sc)
 
 
        /* Disconnect the interrupt handler. */
-       if (sc->intr_handle)
-               if ((error = bus_teardown_intr(sc->bus_dev,
-                               sc->irq_res, sc->intr_handle)))
+       if ((error = twa_teardown_intr(sc)))
                        tw_osli_dbg_dprintf(1, sc,
                                "teardown_intr returned %d", error);
 
@@ -816,6 +904,15 @@ twa_shutdown(device_t dev)
 
        tw_osli_dbg_dprintf(3, sc, "entered");
 
+       /* Disconnect interrupts. */
+       error = twa_teardown_intr(sc);
+
+#if 0 /* XXX swildner */
+       /* Stop watchdog task. */
+       callout_drain(&(sc->watchdog_callout[0]));
+       callout_drain(&(sc->watchdog_callout[1]));
+#endif
+
        /* Disconnect from the controller. */
        if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) {
                tw_osli_printf(sc, "error = %d",
@@ -1006,33 +1103,35 @@ tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf)
                                error = 0; /* False error */
                                break;
                        }
-                       tw_osli_printf(sc, "request = %p",
-                               TW_CL_SEVERITY_ERROR_STRING,
-                               TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
-                               0x2018,
-                               "Passthru request timed out!",
-                               req);
-                       /*
-                        * Should I check here if the timeout happened
-                        * because of yet another reset, and not do a
-                        * second reset?
-                        */
-                       tw_cl_reset_ctlr(&sc->ctlr_handle);
+                       if (!(tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
+#ifdef    TW_OSL_DEBUG
+                               tw_osli_printf(sc, "request = %p",
+                                       TW_CL_SEVERITY_ERROR_STRING,
+                                       TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
+                                       0x2018,
+                                       "Passthru request timed out!",
+                                       req);
+#else  /* TW_OSL_DEBUG */
+                       device_printf((sc)->bus_dev, "Passthru request timed out!\n");
+#endif /* TW_OSL_DEBUG */
+                               tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
+                       }
+
+                       error = 0;
+                       end_time = tw_osl_get_local_time() + timeout;
+                       continue;
                        /*
                         * Don't touch req after a reset.  It (and any
-                        * associated data) will already have been
+                        * associated data) will be
                         * unmapped by the callback.
                         */
-                       user_buf->driver_pkt.os_status = error;
-                       error = ETIMEDOUT;
-                       goto fw_passthru_err;
                }
                /*
                 * Either the request got completed, or we were woken up by a
                 * signal.  Calculate the new timeout, in case it was the latter.
                 */
                timeout = (end_time - tw_osl_get_local_time());
-       }
+       } /* End of while loop */
 
        /* If there was a payload, copy it back. */
        if ((!error) && (req->length))
@@ -1046,19 +1145,9 @@ tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf)
                                error);
 
 fw_passthru_err:
-       /*
-        * Print the failure message.  For some reason, on certain OS versions,
-        * printing this error message during reset hangs the display (although
-        * the rest of the system is running fine.  So, don't print it if the
-        * failure was due to a reset.
-        */
-       if ((error) && (error != TW_CL_ERR_REQ_BUS_RESET))
-               tw_osli_printf(sc, "error = %d",
-                       TW_CL_SEVERITY_ERROR_STRING,
-                       TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
-                       0x201A,
-                       "Firmware passthru failed!",
-                       error);
+
+       if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET)
+               error = EBUSY;
 
        user_buf->driver_pkt.os_status = error;
        /* Free resources. */
@@ -1082,6 +1171,8 @@ TW_VOID
 tw_osl_complete_passthru(struct tw_cl_req_handle *req_handle)
 {
        struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
+       struct tw_cl_req_packet         *req_pkt =
+               (struct tw_cl_req_packet *)(&req->req_pkt);
        struct twa_softc                *sc = req->ctlr;
 
        tw_osli_dbg_dprintf(5, sc, "entered");
@@ -1129,6 +1220,9 @@ tw_osl_complete_passthru(struct tw_cl_req_handle *req_handle)
                        if (req->flags & TW_OSLI_REQ_FLAGS_MAPPED)
                                return;
 
+                       if (req_pkt->status == TW_CL_ERR_REQ_BUS_RESET)
+                               return;
+
                        tw_osli_printf(sc, "request = %p",
                                TW_CL_SEVERITY_ERROR_STRING,
                                TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
@@ -1175,6 +1269,7 @@ tw_osli_get_request(struct twa_softc *sc)
                req->req_handle.is_io = 0;
                req->data = NULL;
                req->length = 0;
+               req->deadline = 0;
                req->real_data = NULL;
                req->real_length = 0;
                req->state = TW_OSLI_REQ_STATE_INIT;/* req being initialized */
@@ -1216,6 +1311,11 @@ twa_map_load_data_callback(TW_VOID *arg, bus_dma_segment_t *segs,
 
        tw_osli_dbg_dprintf(10, sc, "entered");
 
+       if (error == EINVAL) {
+               req->error_code = error;
+               return;
+       }
+
        /* Mark the request as currently being processed. */
        req->state = TW_OSLI_REQ_STATE_BUSY;
        /* Move the request into the busy queue. */
@@ -1409,6 +1509,14 @@ tw_osli_map_request(struct tw_osli_req_context *req)
                                spin_unlock(sc->io_lock);
                                error = 0;
                        } else {
+                               tw_osli_printf(sc, "error = %d",
+                                       TW_CL_SEVERITY_ERROR_STRING,
+                                       TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
+                                       0x9999,
+                                       "Failed to map DMA memory "
+                                       "for I/O request",
+                                       error);
+                               req->flags |= TW_OSLI_REQ_FLAGS_FAILED;
                                /* Free alignment buffer if it was used. */
                                if (req->flags &
                                        TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED) {
index 53e14ab..096c911 100644 (file)
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/dev/twa/tw_osl_share.h,v 1.10 2010/06/09 21:40:38 delphij Exp $
+ *     $FreeBSD: src/sys/dev/twa/tw_osl_share.h,v 1.11 2010/08/30 19:15:04 delphij Exp $
  */
 
 /*
@@ -76,7 +76,7 @@
 #define TW_OSL_ENCLOSURE_SUPPORT
 #endif
 
-#define TW_OSL_DRIVER_VERSION_STRING   "3.80.06.002"
+#define TW_OSL_DRIVER_VERSION_STRING   "3.80.06.003"
 
 #define        TW_OSL_CAN_SLEEP