summaryrefslogtreecommitdiffstats
path: root/sys/dev/twa/tw_cl_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/twa/tw_cl_io.c')
-rw-r--r--sys/dev/twa/tw_cl_io.c204
1 files changed, 106 insertions, 98 deletions
diff --git a/sys/dev/twa/tw_cl_io.c b/sys/dev/twa/tw_cl_io.c
index 51ce08c..1e1ca6c 100644
--- a/sys/dev/twa/tw_cl_io.c
+++ b/sys/dev/twa/tw_cl_io.c
@@ -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,
+ /* 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;
+ }
+
+#ifdef TW_OSL_DEBUG
+ 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);
- goto out;
- }
+ 0x1107, 0x3, TW_CL_SEVERITY_INFO_STRING,
+ "Controller reset done!", " ");
+#endif /* TW_OSL_DEBUG */
+ break;
+ } /* End of while */
- 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!",
- " ");
+ /* 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);
+ }
-out:
+ 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;
- xpt_release_simq(sc->sim, 1);
+ ctlr->reset_needed = TW_CL_FALSE;
- /*
- * Enable interrupts, and also clear attention and response interrupts.
- */
- tw_cli_enable_interrupts(ctlr);
-
/* 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,26 +1264,14 @@ 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",
"error = %d", error);
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);
}
OpenPOWER on IntegriCloud