Vendor update to version 3.80.06.003 to fix a panic with ZFS when under
heavy I/O load. Many thanks to LSI for continuing to support FreeBSD. PR: kern/149968 Submitted by: LSI (Tom Couch) Reported by: Kai Kockro <kkockro web de> Tested by: Kai Kockro, jpaetzel MFC after: 7 days
This commit is contained in:
parent
400dda6646
commit
a806ad4021
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
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_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,
|
||||
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;
|
||||
0x1107, 0x3, TW_CL_SEVERITY_INFO_STRING,
|
||||
"Controller reset done!", " ");
|
||||
#endif /* TW_OSL_DEBUG */
|
||||
break;
|
||||
} /* End of while */
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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!",
|
||||
" ");
|
||||
|
||||
out:
|
||||
ctlr->reset_in_progress = TW_CL_FALSE;
|
||||
xpt_release_simq(sc->sim, 1);
|
||||
|
||||
/*
|
||||
* 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,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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 mtx sim_lock_handle;/* sim lock shared with cam */
|
||||
struct mtx *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 */
|
||||
|
@ -55,7 +55,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_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
|
||||
union ccb *ccb);
|
||||
@ -81,7 +80,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,
|
||||
@ -275,6 +274,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);
|
||||
}
|
||||
@ -290,6 +290,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);
|
||||
}
|
||||
@ -306,13 +307,20 @@ tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
|
||||
return(1);
|
||||
}
|
||||
|
||||
ccb_h->timeout_ch = timeout(twa_timeout, req,
|
||||
(ccb_h->timeout * hz) / 1000);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -345,10 +353,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;
|
||||
@ -364,25 +382,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",
|
||||
" ");
|
||||
|
||||
mtx_unlock(sc->sim_lock);
|
||||
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;
|
||||
|
||||
mtx_lock(sc->sim_lock);
|
||||
tw_cl_set_reset_needed(&(sc->ctlr_handle));
|
||||
ccb_h->status = CAM_REQ_CMP;
|
||||
xpt_done(ccb);
|
||||
break;
|
||||
|
||||
@ -450,6 +457,7 @@ 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;
|
||||
path_inq->maxio = TW_CL_MAX_IO_SIZE;
|
||||
ccb_h->status = CAM_REQ_CMP;
|
||||
xpt_done(ccb);
|
||||
break;
|
||||
@ -486,31 +494,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.
|
||||
@ -574,20 +557,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)
|
||||
{
|
||||
tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt, 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)
|
||||
{
|
||||
struct tw_osli_req_context *req = req_handle->osl_req_ctxt;
|
||||
|
||||
req->deadline = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -655,7 +657,7 @@ tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
|
||||
|
||||
tw_osli_unmap_request(req);
|
||||
|
||||
untimeout(twa_timeout, req, 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) {
|
||||
@ -682,7 +684,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.
|
||||
|
@ -175,6 +175,9 @@ static TW_INT32 twa_detach(device_t dev);
|
||||
static TW_INT32 twa_shutdown(device_t dev);
|
||||
static TW_VOID twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op);
|
||||
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);
|
||||
@ -238,6 +241,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,
|
||||
INTR_TYPE_CAM | INTR_MPSAFE,
|
||||
NULL, twa_pci_intr,
|
||||
sc, &sc->intr_handle);
|
||||
}
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@ -354,10 +383,7 @@ twa_attach(device_t dev)
|
||||
tw_osli_free_resources(sc);
|
||||
return(ENXIO);
|
||||
}
|
||||
if ((error = bus_setup_intr(sc->bus_dev, sc->irq_res,
|
||||
INTR_TYPE_CAM | INTR_MPSAFE,
|
||||
NULL, twa_pci_intr,
|
||||
sc, &sc->intr_handle))) {
|
||||
if ((error = twa_setup_intr(sc))) {
|
||||
tw_osli_printf(sc, "error = %d",
|
||||
TW_CL_SEVERITY_ERROR_STRING,
|
||||
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
|
||||
@ -412,10 +438,77 @@ twa_attach(device_t dev)
|
||||
return(error);
|
||||
}
|
||||
|
||||
sc->watchdog_index = 0;
|
||||
callout_init(&(sc->watchdog_callout[0]), CALLOUT_MPSAFE);
|
||||
callout_init(&(sc->watchdog_callout[1]), CALLOUT_MPSAFE);
|
||||
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;
|
||||
int my_watchdog_was_pending = 1234;
|
||||
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 = %p, c = %p\n", i, (void*)my_req->deadline, (void*)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 */
|
||||
my_watchdog_was_pending =
|
||||
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) {
|
||||
my_watchdog_was_pending =
|
||||
callout_reset(&(sc->watchdog_callout[i]), 5*hz, twa_watchdog, &sc->ctlr_handle);
|
||||
}
|
||||
#ifdef TW_OSL_DEBUG
|
||||
if (i_need_a_reset || my_watchdog_was_pending)
|
||||
device_printf((sc)->bus_dev, "i_need_a_reset = %d, "
|
||||
"driver_is_active = %d, my_watchdog_was_pending = %d\n",
|
||||
i_need_a_reset, driver_is_active, my_watchdog_was_pending);
|
||||
#endif /* TW_OSL_DEBUG */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function name: tw_osli_alloc_mem
|
||||
@ -715,9 +808,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);
|
||||
|
||||
@ -809,6 +900,9 @@ twa_shutdown(device_t dev)
|
||||
|
||||
tw_osli_dbg_dprintf(3, sc, "entered");
|
||||
|
||||
/* Disconnect interrupts. */
|
||||
error = twa_teardown_intr(sc);
|
||||
|
||||
/* Disconnect from the controller. */
|
||||
if ((error = tw_cl_shutdown_ctlr(&(sc->ctlr_handle), 0))) {
|
||||
tw_osli_printf(sc, "error = %d",
|
||||
@ -997,33 +1091,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))
|
||||
@ -1037,19 +1133,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. */
|
||||
@ -1073,6 +1159,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");
|
||||
@ -1120,6 +1208,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,
|
||||
@ -1166,6 +1257,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 */
|
||||
@ -1207,6 +1299,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. */
|
||||
@ -1400,6 +1497,14 @@ tw_osli_map_request(struct tw_osli_req_context *req)
|
||||
mtx_unlock_spin(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) {
|
||||
|
@ -75,7 +75,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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user