diff options
Diffstat (limited to 'sys/dev/twa/tw_cl_io.c')
-rw-r--r-- | sys/dev/twa/tw_cl_io.c | 204 |
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); } |