Deleted Added
sdiff udiff text old ( 208969 ) new ( 212008 )
full compact
1/*
2 * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3 * Copyright (c) 2004-05 Vinod Kashyap
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/twa/tw_cl_io.c 208969 2010-06-09 21:40:38Z delphij $
28 */
29
30/*
31 * AMCC'S 3ware driver for 9000 series storage controllers.
32 *
33 * Author: Vinod Kashyap
34 * Modifications by: Adam Radford
35 * Modifications by: Manjunath Ranganathaiah

--- 33 unchanged lines hidden (view full) ---

69TW_INT32
70tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
71 struct tw_cl_req_packet *req_pkt, struct tw_cl_req_handle *req_handle)
72{
73 struct tw_cli_ctlr_context *ctlr;
74 struct tw_cli_req_context *req;
75 struct tw_cl_command_9k *cmd;
76 struct tw_cl_scsi_req_packet *scsi_req;
77 TW_INT32 error;
78
79 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
80
81 ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
82
83 if (ctlr->reset_in_progress) {
84 tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
85 "I/O during reset: returning busy.");
86 return(TW_OSL_EBUSY);
87 }
88
89 /*
90 * If working with a firmware version that does not support multiple
91 * luns, and this request is directed at a non-zero lun, error it
92 * back right away.
93 */
94 if ((req_pkt->gen_req_pkt.scsi_req.lun) &&
95 (ctlr->working_srl < TWA_MULTI_LUN_FW_SRL)) {
96 req_pkt->status |= (TW_CL_ERR_REQ_INVALID_LUN |

--- 43 unchanged lines hidden (view full) ---

140 } else {
141 cmd->lun_h4__sgl_entries =
142 TW_CL_SWAP16(BUILD_LUN_H4__SGL_ENTRIES(scsi_req->lun,
143 scsi_req->sgl_entries));
144 tw_cli_fill_sg_list(ctlr, scsi_req->sg_list,
145 cmd->sg_list, scsi_req->sgl_entries);
146 }
147
148 if ((error = tw_cli_submit_cmd(req))) {
149 tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
150 "Could not start request. request = %p, error = %d",
151 req, error);
152 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
153 }
154 return(error);
155}
156

--- 9 unchanged lines hidden (view full) ---

166 * non-zero-- failure
167 */
168TW_INT32
169tw_cli_submit_cmd(struct tw_cli_req_context *req)
170{
171 struct tw_cli_ctlr_context *ctlr = req->ctlr;
172 struct tw_cl_ctlr_handle *ctlr_handle = ctlr->ctlr_handle;
173 TW_UINT32 status_reg;
174 TW_INT32 error;
175
176 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
177
178 /* Serialize access to the controller cmd queue. */
179 tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
180
181 /* For 9650SE first write low 4 bytes */
182 if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) ||
183 (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA))
184 tw_osl_write_reg(ctlr_handle,
185 TWA_COMMAND_QUEUE_OFFSET_LOW,
186 (TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4);
187
188 /* Check to see if we can post a command. */
189 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
190 if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
191 goto out;
192
193 if (status_reg & TWA_STATUS_COMMAND_QUEUE_FULL) {
194 struct tw_cl_req_packet *req_pkt =
195 (struct tw_cl_req_packet *)(req->orig_req);
196
197 tw_cli_dbg_printf(7, ctlr_handle, tw_osl_cur_func(),
198 "Cmd queue full");
199
200 if ((req->flags & TW_CLI_REQ_FLAGS_INTERNAL)
201 || ((req_pkt) &&
202 (req_pkt->flags & TW_CL_REQ_RETRY_ON_BUSY))
203 ) {
204 if (req->state != TW_CLI_REQ_STATE_PENDING) {
205 tw_cli_dbg_printf(2, ctlr_handle,
206 tw_osl_cur_func(),
207 "pending internal/ioctl request");
208 req->state = TW_CLI_REQ_STATE_PENDING;
209 tw_cli_req_q_insert_tail(req, TW_CLI_PENDING_Q);
210 error = 0;
211 /* Unmask command interrupt. */
212 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
213 TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
214 } else
215 error = TW_OSL_EBUSY;
216 } else {
217 tw_osl_ctlr_busy(ctlr_handle, req->req_handle);
218 error = TW_OSL_EBUSY;
219 }
220 } else {
221 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
222 "Submitting command");
223
224 /* Insert command into busy queue */
225 req->state = TW_CLI_REQ_STATE_BUSY;

--- 15 unchanged lines hidden (view full) ---

241 TWA_COMMAND_QUEUE_OFFSET_HIGH,
242 (TW_UINT32)(((TW_UINT64)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)))>>32), 4);
243 } else
244 tw_osl_write_reg(ctlr_handle,
245 TWA_COMMAND_QUEUE_OFFSET,
246 (TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4);
247 }
248 }
249out:
250 tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
251
252 return(error);
253}
254
255
256
257/*

--- 14 unchanged lines hidden (view full) ---

272 struct tw_cli_ctlr_context *ctlr;
273 struct tw_cli_req_context *req;
274 union tw_cl_command_7k *cmd_7k;
275 struct tw_cl_command_9k *cmd_9k;
276 struct tw_cl_passthru_req_packet *pt_req;
277 TW_UINT8 opcode;
278 TW_UINT8 sgl_offset;
279 TW_VOID *sgl = TW_CL_NULL;
280 TW_INT32 error;
281
282 tw_cli_dbg_printf(5, ctlr_handle, tw_osl_cur_func(), "entered");
283
284 ctlr = (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
285
286 if (ctlr->reset_in_progress) {
287 tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
288 "Passthru request during reset: returning busy.");
289 return(TW_OSL_EBUSY);
290 }
291
292 if ((req = tw_cli_get_request(ctlr
293 )) == TW_CL_NULL) {
294 tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
295 "Out of request context packets: returning busy");
296 return(TW_OSL_EBUSY);
297 }
298
299 req_handle->cl_req_ctxt = req;
300 req->req_handle = req_handle;
301 req->orig_req = req_pkt;
302 req->tw_cli_callback = tw_cli_complete_io;
303
304 req->flags |= (TW_CLI_REQ_FLAGS_EXTERNAL | TW_CLI_REQ_FLAGS_PASSTHRU);
305
306 pt_req = &(req_pkt->gen_req_pkt.pt_req);
307
308 tw_osl_memcpy(req->cmd_pkt, pt_req->cmd_pkt,
309 pt_req->cmd_pkt_length);
310 /* Build the cmd pkt. */
311 if ((opcode = GET_OPCODE(((TW_UINT8 *)
312 (pt_req->cmd_pkt))[sizeof(struct tw_cl_command_header)]))

--- 30 unchanged lines hidden (view full) ---

343 ((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2);
344 }
345 }
346
347 if (sgl)
348 tw_cli_fill_sg_list(ctlr, pt_req->sg_list,
349 sgl, pt_req->sgl_entries);
350
351 if ((error = tw_cli_submit_cmd(req))) {
352 tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
353 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
354 0x1100, 0x1, TW_CL_SEVERITY_ERROR_STRING,
355 "Failed to start passthru command",
356 "error = %d", error);
357 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
358 }
359 return(error);

--- 395 unchanged lines hidden (view full) ---

755
756 /* Build the cmd pkt. */
757 cmd = &(req->cmd_pkt->command.cmd_pkt_7k);
758
759 req->cmd_pkt->cmd_hdr.header_desc.size_header = 128;
760
761 cmd->param.sgl_off__opcode =
762 BUILD_SGL_OFF__OPCODE(2, TWA_FW_CMD_GET_PARAM);
763 cmd->param.request_id =
764 (TW_UINT8)(TW_CL_SWAP16(req->request_id));
765 cmd->param.host_id__unit = BUILD_HOST_ID__UNIT(0, 0);
766 cmd->param.param_count = TW_CL_SWAP16(1);
767
768 if (ctlr->flags & TW_CL_64BIT_ADDRESSES) {
769 ((struct tw_cl_sg_desc64 *)(cmd->param.sgl))[0].address =
770 TW_CL_SWAP64(req->data_phys);
771 ((struct tw_cl_sg_desc64 *)(cmd->param.sgl))[0].length =
772 TW_CL_SWAP32(req->length);

--- 11 unchanged lines hidden (view full) ---

784 param->parameter_id = (TW_UINT8)(param_id);
785 param->parameter_size_bytes = TW_CL_SWAP16(param_size);
786
787 /* Submit the command. */
788 if (callback == TW_CL_NULL) {
789 /* There's no call back; wait till the command completes. */
790 error = tw_cli_submit_and_poll_request(req,
791 TW_CLI_REQUEST_TIMEOUT_PERIOD);
792 if (error == TW_OSL_ETIMEDOUT)
793 /* Clean-up done by tw_cli_submit_and_poll_request. */
794 return(error);
795 if (error)
796 goto out;
797 if ((error = cmd->param.status)) {
798 tw_cli_create_ctlr_event(ctlr,
799 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
800 &(req->cmd_pkt->cmd_hdr));
801 goto out;
802 }
803 tw_osl_memcpy(param_data, param->data, param_size);
804 ctlr->internal_req_busy = TW_CL_FALSE;
805 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
806 } else {
807 /* There's a call back. Simply submit the command. */
808 req->tw_cli_callback = callback;

--- 91 unchanged lines hidden (view full) ---

900 /* Specify which parameter we want to set. */
901 param->table_id = TW_CL_SWAP16(table_id | TWA_9K_PARAM_DESCRIPTOR);
902 param->parameter_id = (TW_UINT8)(param_id);
903 param->parameter_size_bytes = TW_CL_SWAP16(param_size);
904 tw_osl_memcpy(param->data, data, param_size);
905
906 /* Submit the command. */
907 if (callback == TW_CL_NULL) {
908 /* There's no call back; wait till the command completes. */
909 error = tw_cli_submit_and_poll_request(req,
910 TW_CLI_REQUEST_TIMEOUT_PERIOD);
911 if (error == TW_OSL_ETIMEDOUT)
912 /* Clean-up done by tw_cli_submit_and_poll_request. */
913 return(error);
914 if (error)
915 goto out;
916 if ((error = cmd->param.status)) {
917 tw_cli_create_ctlr_event(ctlr,
918 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
919 &(req->cmd_pkt->cmd_hdr));
920 goto out;
921 }
922 ctlr->internal_req_busy = TW_CL_FALSE;
923 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
924 } else {
925 /* There's a call back. Simply submit the command. */
926 req->tw_cli_callback = callback;
927 if ((error = tw_cli_submit_cmd(req)))

--- 89 unchanged lines hidden (view full) ---

1017 */
1018
1019 /*
1020 * We have to make sure that this timed out request, if it were in the
1021 * pending queue, doesn't get submitted while we are here, from
1022 * tw_cli_submit_pending_queue. There could be a race in that case.
1023 * Need to revisit.
1024 */
1025 if (req->state != TW_CLI_REQ_STATE_PENDING)
1026 tw_cl_reset_ctlr(ctlr->ctlr_handle);
1027 else {
1028 tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(),
1029 "Removing request from pending queue");
1030 /*
1031 * Request was never submitted. Clean up. Note that we did
1032 * not do a reset. So, we have to remove the request ourselves
1033 * from the pending queue (as against tw_cli_drain_pendinq_queue
1034 * taking care of it).
1035 */

--- 12 unchanged lines hidden (view full) ---

1048
1049
1050/*
1051 * Function name: tw_cl_reset_ctlr
1052 * Description: Soft resets and then initializes the controller;
1053 * drains any incomplete requests.
1054 *
1055 * Input: ctlr -- ptr to per ctlr structure
1056 * Output: None
1057 * Return value: 0 -- success
1058 * non-zero-- failure
1059 */
1060TW_INT32
1061tw_cl_reset_ctlr(struct tw_cl_ctlr_handle *ctlr_handle)
1062{
1063 struct tw_cli_ctlr_context *ctlr =
1064 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
1065 struct twa_softc *sc = ctlr_handle->osl_ctlr_ctxt;
1066 TW_INT32 reset_attempt = 1;
1067 TW_INT32 error;
1068
1069 tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(), "entered");
1070
1071 ctlr->reset_in_progress = TW_CL_TRUE;
1072 xpt_freeze_simq(sc->sim, 1);
1073
1074 tw_cli_disable_interrupts(ctlr);
1075
1076 /*
1077 * Error back all requests in the complete, busy, and pending queues.
1078 * If any request is already on its way to getting submitted, it's in
1079 * none of these queues and so, will not be completed. That request
1080 * will continue its course and get submitted to the controller after
1081 * the reset is done (and io_lock is released).
1082 */
1083 tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
1084 "Draining all queues following reset");
1085 tw_cli_drain_complete_queue(ctlr);
1086 tw_cli_drain_busy_queue(ctlr);
1087 tw_cli_drain_pending_queue(ctlr);
1088 ctlr->internal_req_busy = TW_CL_FALSE;
1089 ctlr->get_more_aens = TW_CL_FALSE;
1090
1091 /* Soft reset the controller. */
1092try_reset:
1093 if ((error = tw_cli_soft_reset(ctlr))) {
1094 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1095 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1096 0x1105, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1097 "Controller reset failed",
1098 "error = %d; attempt %d", error, reset_attempt++);
1099 if (reset_attempt <= TW_CLI_MAX_RESET_ATTEMPTS)
1100 goto try_reset;
1101 else
1102 goto out;
1103 }
1104
1105 /* Re-establish logical connection with the controller. */
1106 if ((error = tw_cli_init_connection(ctlr,
1107 (TW_UINT16)(ctlr->max_simult_reqs),
1108 0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
1109 TW_CL_NULL, TW_CL_NULL))) {
1110 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1111 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1112 0x1106, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1113 "Can't initialize connection after reset",
1114 "error = %d", error);
1115 goto out;
1116 }
1117
1118 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1119 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1120 0x1107, 0x3, TW_CL_SEVERITY_INFO_STRING,
1121 "Controller reset done!",
1122 " ");
1123
1124out:
1125 ctlr->reset_in_progress = TW_CL_FALSE;
1126 xpt_release_simq(sc->sim, 1);
1127
1128 /*
1129 * Enable interrupts, and also clear attention and response interrupts.
1130 */
1131 tw_cli_enable_interrupts(ctlr);
1132
1133 /* Request for a bus re-scan. */
1134 if (!error)
1135 tw_osl_scan_bus(ctlr_handle);
1136 return(error);
1137}
1138
1139
1140
1141/*
1142 * Function name: tw_cli_soft_reset
1143 * Description: Does the actual soft reset.
1144 *
1145 * Input: ctlr -- ptr to per ctlr structure
1146 * Output: None
1147 * Return value: 0 -- success
1148 * non-zero-- failure
1149 */
1150TW_INT32
1151tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
1152{
1153 struct tw_cl_ctlr_handle *ctlr_handle = ctlr->ctlr_handle;
1154 TW_UINT32 status_reg;
1155 int found;
1156 int loop_count;
1157 TW_UINT32 error;
1158
1159 tw_cli_dbg_printf(1, ctlr_handle, tw_osl_cur_func(), "entered");
1160
1161 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1162 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1163 0x1108, 0x3, TW_CL_SEVERITY_INFO_STRING,
1164 "Resetting controller...",
1165 " ");
1166
1167 /* Don't let any new commands get submitted to the controller. */
1168 tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
1169

--- 18 unchanged lines hidden (view full) ---

1188 do {
1189 found = (tw_cli_find_response(ctlr, TWA_RESET_PHASE1_NOTIFICATION_RESPONSE) == TW_OSL_ESUCCESS);
1190 tw_osl_delay(10);
1191 loop_count++;
1192 error = 0x7888;
1193 } while (!found && (loop_count < 6000000)); /* Loop for no more than 60 seconds */
1194
1195 if (!found) {
1196 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1197 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1198 0x1109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1199 "Missed firmware handshake after soft-reset",
1200 "error = %d", error);
1201 tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
1202 return(error);
1203 }
1204
1205 tw_osl_delay(TWA_RESET_PHASE1_WAIT_TIME_MS * 1000);
1206 ctlr->reset_phase1_in_progress = TW_CL_FALSE;
1207 }
1208
1209 if ((error = tw_cli_poll_status(ctlr,
1210 TWA_STATUS_MICROCONTROLLER_READY |
1211 TWA_STATUS_ATTENTION_INTERRUPT,
1212 TW_CLI_RESET_TIMEOUT_PERIOD))) {
1213 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1214 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1215 0x1109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1216 "Micro-ctlr not ready/No attn intr after reset",
1217 "error = %d", error);
1218 tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
1219 return(error);
1220 }
1221

--- 17 unchanged lines hidden (view full) ---

1239 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
1240 0x110B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1241 "Can't drain AEN queue after reset",
1242 "error = %d", error);
1243 return(error);
1244 }
1245
1246 if ((error = tw_cli_find_aen(ctlr, TWA_AEN_SOFT_RESET))) {
1247 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1248 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1249 0x110C, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1250 "Reset not reported by controller",
1251 "error = %d", error);
1252 return(error);
1253 }
1254
1255 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
1256
1257 if ((error = TW_CLI_STATUS_ERRORS(status_reg)) ||
1258 (error = tw_cli_check_ctlr_state(ctlr, status_reg))) {
1259 tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
1260 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
1261 0x110D, 0x1, TW_CL_SEVERITY_ERROR_STRING,
1262 "Controller errors detected after reset",
1263 "error = %d", error);
1264 return(error);
1265 }
1266
1267 return(TW_OSL_ESUCCESS);
1268}
1269
1270
1271
1272/*
1273 * Function name: tw_cli_send_scsi_cmd
1274 * Description: Sends down a scsi cmd to fw.

--- 157 unchanged lines hidden ---