diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/isci/Makefile | 1 | ||||
-rw-r--r-- | drivers/scsi/isci/request.c | 185 | ||||
-rw-r--r-- | drivers/scsi/isci/request.h | 38 | ||||
-rw-r--r-- | drivers/scsi/isci/ssp_request.c | 240 |
4 files changed, 178 insertions, 286 deletions
diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile index 48218ca908fe..43d2c050bd49 100644 --- a/drivers/scsi/isci/Makefile +++ b/drivers/scsi/isci/Makefile | |||
@@ -7,6 +7,5 @@ isci-objs := init.o phy.o request.o sata.o \ | |||
7 | remote_node_table.o \ | 7 | remote_node_table.o \ |
8 | unsolicited_frame_control.o \ | 8 | unsolicited_frame_control.o \ |
9 | stp_request.o \ | 9 | stp_request.o \ |
10 | ssp_request.o \ | ||
11 | smp_request.o \ | 10 | smp_request.o \ |
12 | port_config.o \ | 11 | port_config.o \ |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 48e2dac72528..5f5168110556 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
@@ -656,7 +656,7 @@ enum sci_status scic_sds_io_request_frame_handler( | |||
656 | * @sci_req: This parameter specifies the request object for which to copy | 656 | * @sci_req: This parameter specifies the request object for which to copy |
657 | * the response data. | 657 | * the response data. |
658 | */ | 658 | */ |
659 | void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) | 659 | static void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) |
660 | { | 660 | { |
661 | void *resp_buf; | 661 | void *resp_buf; |
662 | u32 len; | 662 | u32 len; |
@@ -978,7 +978,6 @@ scic_sds_io_request_tc_completion(struct scic_sds_request *request, u32 completi | |||
978 | sci_base_state_machine_get_state(&request->state_machine)); | 978 | sci_base_state_machine_get_state(&request->state_machine)); |
979 | 979 | ||
980 | return SCI_FAILURE_INVALID_STATE; | 980 | return SCI_FAILURE_INVALID_STATE; |
981 | |||
982 | } | 981 | } |
983 | 982 | ||
984 | /* | 983 | /* |
@@ -1151,9 +1150,119 @@ static enum sci_status scic_sds_request_aborting_state_frame_handler( | |||
1151 | return SCI_SUCCESS; | 1150 | return SCI_SUCCESS; |
1152 | } | 1151 | } |
1153 | 1152 | ||
1153 | /** | ||
1154 | * This method processes the completions transport layer (TL) status to | ||
1155 | * determine if the RAW task management frame was sent successfully. If the | ||
1156 | * raw frame was sent successfully, then the state for the task request | ||
1157 | * transitions to waiting for a response frame. | ||
1158 | * @sci_req: This parameter specifies the request for which the TC | ||
1159 | * completion was received. | ||
1160 | * @completion_code: This parameter indicates the completion status information | ||
1161 | * for the TC. | ||
1162 | * | ||
1163 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
1164 | * this method always returns success. | ||
1165 | */ | ||
1166 | static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( | ||
1167 | struct scic_sds_request *sci_req, | ||
1168 | u32 completion_code) | ||
1169 | { | ||
1170 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1171 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1172 | scic_sds_request_set_status(sci_req, SCU_TASK_DONE_GOOD, | ||
1173 | SCI_SUCCESS); | ||
1174 | |||
1175 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
1176 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); | ||
1177 | break; | ||
1178 | |||
1179 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): | ||
1180 | /* | ||
1181 | * Currently, the decision is to simply allow the task request to | ||
1182 | * timeout if the task IU wasn't received successfully. | ||
1183 | * There is a potential for receiving multiple task responses if we | ||
1184 | * decide to send the task IU again. */ | ||
1185 | dev_warn(scic_to_dev(sci_req->owning_controller), | ||
1186 | "%s: TaskRequest:0x%p CompletionCode:%x - " | ||
1187 | "ACK/NAK timeout\n", | ||
1188 | __func__, | ||
1189 | sci_req, | ||
1190 | completion_code); | ||
1191 | |||
1192 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
1193 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE); | ||
1194 | break; | ||
1195 | |||
1196 | default: | ||
1197 | /* | ||
1198 | * All other completion status cause the IO to be complete. If a NAK | ||
1199 | * was received, then it is up to the user to retry the request. */ | ||
1200 | scic_sds_request_set_status( | ||
1201 | sci_req, | ||
1202 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1203 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1204 | ); | ||
1205 | |||
1206 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
1207 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1208 | break; | ||
1209 | } | ||
1210 | |||
1211 | return SCI_SUCCESS; | ||
1212 | } | ||
1213 | |||
1214 | /** | ||
1215 | * This method is responsible for processing a terminate/abort request for this | ||
1216 | * TC while the request is waiting for the task management response | ||
1217 | * unsolicited frame. | ||
1218 | * @sci_req: This parameter specifies the request for which the | ||
1219 | * termination was requested. | ||
1220 | * | ||
1221 | * This method returns an indication as to whether the abort request was | ||
1222 | * successfully handled. need to update to ensure the received UF doesn't cause | ||
1223 | * damage to subsequent requests (i.e. put the extended tag in a holding | ||
1224 | * pattern for this particular device). | ||
1225 | */ | ||
1226 | static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( | ||
1227 | struct scic_sds_request *request) | ||
1228 | { | ||
1229 | sci_base_state_machine_change_state(&request->state_machine, | ||
1230 | SCI_BASE_REQUEST_STATE_ABORTING); | ||
1231 | sci_base_state_machine_change_state(&request->state_machine, | ||
1232 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1233 | return SCI_SUCCESS; | ||
1234 | } | ||
1235 | |||
1236 | /** | ||
1237 | * This method processes an unsolicited frame while the task mgmt request is | ||
1238 | * waiting for a response frame. It will copy the response data, release | ||
1239 | * the unsolicited frame, and transition the request to the | ||
1240 | * SCI_BASE_REQUEST_STATE_COMPLETED state. | ||
1241 | * @sci_req: This parameter specifies the request for which the | ||
1242 | * unsolicited frame was received. | ||
1243 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
1244 | * should contain the response. | ||
1245 | * | ||
1246 | * This method returns an indication of whether the TC response frame was | ||
1247 | * handled successfully or not. SCI_SUCCESS Currently this value is always | ||
1248 | * returned and indicates successful processing of the TC response. Should | ||
1249 | * probably update to check frame type and make sure it is a response frame. | ||
1250 | */ | ||
1251 | static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( | ||
1252 | struct scic_sds_request *request, | ||
1253 | u32 frame_index) | ||
1254 | { | ||
1255 | scic_sds_io_request_copy_response(request); | ||
1256 | |||
1257 | sci_base_state_machine_change_state(&request->state_machine, | ||
1258 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
1259 | scic_sds_controller_release_frame(request->owning_controller, | ||
1260 | frame_index); | ||
1261 | return SCI_SUCCESS; | ||
1262 | } | ||
1263 | |||
1154 | static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { | 1264 | static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { |
1155 | [SCI_BASE_REQUEST_STATE_INITIAL] = { | 1265 | [SCI_BASE_REQUEST_STATE_INITIAL] = { }, |
1156 | }, | ||
1157 | [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { | 1266 | [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { |
1158 | .start_handler = scic_sds_request_constructed_state_start_handler, | 1267 | .start_handler = scic_sds_request_constructed_state_start_handler, |
1159 | .abort_handler = scic_sds_request_constructed_state_abort_handler, | 1268 | .abort_handler = scic_sds_request_constructed_state_abort_handler, |
@@ -1163,6 +1272,14 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han | |||
1163 | .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, | 1272 | .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, |
1164 | .frame_handler = scic_sds_request_started_state_frame_handler, | 1273 | .frame_handler = scic_sds_request_started_state_frame_handler, |
1165 | }, | 1274 | }, |
1275 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
1276 | .abort_handler = scic_sds_request_started_state_abort_handler, | ||
1277 | .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, | ||
1278 | }, | ||
1279 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | ||
1280 | .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, | ||
1281 | .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, | ||
1282 | }, | ||
1166 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { | 1283 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { |
1167 | .complete_handler = scic_sds_request_completed_state_complete_handler, | 1284 | .complete_handler = scic_sds_request_completed_state_complete_handler, |
1168 | }, | 1285 | }, |
@@ -1171,8 +1288,7 @@ static const struct scic_sds_io_request_state_handler scic_sds_request_state_han | |||
1171 | .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, | 1288 | .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, |
1172 | .frame_handler = scic_sds_request_aborting_state_frame_handler, | 1289 | .frame_handler = scic_sds_request_aborting_state_frame_handler, |
1173 | }, | 1290 | }, |
1174 | [SCI_BASE_REQUEST_STATE_FINAL] = { | 1291 | [SCI_BASE_REQUEST_STATE_FINAL] = { }, |
1175 | }, | ||
1176 | }; | 1292 | }; |
1177 | 1293 | ||
1178 | 1294 | ||
@@ -1919,6 +2035,9 @@ static void scic_sds_request_constructed_state_enter(void *object) | |||
1919 | static void scic_sds_request_started_state_enter(void *object) | 2035 | static void scic_sds_request_started_state_enter(void *object) |
1920 | { | 2036 | { |
1921 | struct scic_sds_request *sci_req = object; | 2037 | struct scic_sds_request *sci_req = object; |
2038 | struct sci_base_state_machine *sm = &sci_req->state_machine; | ||
2039 | struct isci_request *ireq = sci_req_to_ireq(sci_req); | ||
2040 | struct domain_device *dev = sci_dev_to_domain(sci_req->target_device); | ||
1922 | 2041 | ||
1923 | SET_STATE_HANDLER( | 2042 | SET_STATE_HANDLER( |
1924 | sci_req, | 2043 | sci_req, |
@@ -1926,9 +2045,13 @@ static void scic_sds_request_started_state_enter(void *object) | |||
1926 | SCI_BASE_REQUEST_STATE_STARTED | 2045 | SCI_BASE_REQUEST_STATE_STARTED |
1927 | ); | 2046 | ); |
1928 | 2047 | ||
1929 | /* | 2048 | if (ireq->ttype == tmf_task && dev->dev_type == SAS_END_DEV) |
1930 | * Most of the request state machines have a started substate machine so | 2049 | sci_base_state_machine_change_state(sm, |
1931 | * start its execution on the entry to the started state. */ | 2050 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION); |
2051 | |||
2052 | /* Most of the request state machines have a started substate machine so | ||
2053 | * start its execution on the entry to the started state. | ||
2054 | */ | ||
1932 | if (sci_req->has_started_substate_machine == true) | 2055 | if (sci_req->has_started_substate_machine == true) |
1933 | sci_base_state_machine_start(&sci_req->started_substate_machine); | 2056 | sci_base_state_machine_start(&sci_req->started_substate_machine); |
1934 | } | 2057 | } |
@@ -2026,6 +2149,30 @@ static void scic_sds_request_final_state_enter(void *object) | |||
2026 | ); | 2149 | ); |
2027 | } | 2150 | } |
2028 | 2151 | ||
2152 | static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( | ||
2153 | void *object) | ||
2154 | { | ||
2155 | struct scic_sds_request *sci_req = object; | ||
2156 | |||
2157 | SET_STATE_HANDLER( | ||
2158 | sci_req, | ||
2159 | scic_sds_request_state_handler_table, | ||
2160 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
2161 | ); | ||
2162 | } | ||
2163 | |||
2164 | static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( | ||
2165 | void *object) | ||
2166 | { | ||
2167 | struct scic_sds_request *sci_req = object; | ||
2168 | |||
2169 | SET_STATE_HANDLER( | ||
2170 | sci_req, | ||
2171 | scic_sds_request_state_handler_table, | ||
2172 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
2173 | ); | ||
2174 | } | ||
2175 | |||
2029 | static const struct sci_base_state scic_sds_request_state_table[] = { | 2176 | static const struct sci_base_state scic_sds_request_state_table[] = { |
2030 | [SCI_BASE_REQUEST_STATE_INITIAL] = { | 2177 | [SCI_BASE_REQUEST_STATE_INITIAL] = { |
2031 | .enter_state = scic_sds_request_initial_state_enter, | 2178 | .enter_state = scic_sds_request_initial_state_enter, |
@@ -2037,6 +2184,12 @@ static const struct sci_base_state scic_sds_request_state_table[] = { | |||
2037 | .enter_state = scic_sds_request_started_state_enter, | 2184 | .enter_state = scic_sds_request_started_state_enter, |
2038 | .exit_state = scic_sds_request_started_state_exit | 2185 | .exit_state = scic_sds_request_started_state_exit |
2039 | }, | 2186 | }, |
2187 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
2188 | .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, | ||
2189 | }, | ||
2190 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | ||
2191 | .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, | ||
2192 | }, | ||
2040 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { | 2193 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { |
2041 | .enter_state = scic_sds_request_completed_state_enter, | 2194 | .enter_state = scic_sds_request_completed_state_enter, |
2042 | }, | 2195 | }, |
@@ -2126,19 +2279,9 @@ enum sci_status scic_task_request_construct(struct scic_sds_controller *scic, | |||
2126 | /* Build the common part of the request */ | 2279 | /* Build the common part of the request */ |
2127 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); | 2280 | scic_sds_general_request_construct(scic, sci_dev, io_tag, sci_req); |
2128 | 2281 | ||
2129 | if (dev->dev_type == SAS_END_DEV) { | 2282 | if (dev->dev_type == SAS_END_DEV) |
2130 | scic_sds_ssp_task_request_assign_buffers(sci_req); | 2283 | scic_sds_ssp_task_request_assign_buffers(sci_req); |
2131 | 2284 | else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) | |
2132 | sci_req->has_started_substate_machine = true; | ||
2133 | |||
2134 | /* Construct the started sub-state machine. */ | ||
2135 | sci_base_state_machine_construct( | ||
2136 | &sci_req->started_substate_machine, | ||
2137 | sci_req, | ||
2138 | scic_sds_io_request_started_task_mgmt_substate_table, | ||
2139 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
2140 | ); | ||
2141 | } else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) | ||
2142 | scic_sds_stp_request_assign_buffers(sci_req); | 2285 | scic_sds_stp_request_assign_buffers(sci_req); |
2143 | else | 2286 | else |
2144 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | 2287 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; |
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h index 932ea767c8c2..b5c5b063a369 100644 --- a/drivers/scsi/isci/request.h +++ b/drivers/scsi/isci/request.h | |||
@@ -296,6 +296,20 @@ enum sci_base_request_states { | |||
296 | SCI_BASE_REQUEST_STATE_STARTED, | 296 | SCI_BASE_REQUEST_STATE_STARTED, |
297 | 297 | ||
298 | /** | 298 | /** |
299 | * The AWAIT_TC_COMPLETION sub-state indicates that the started raw | ||
300 | * task management request is waiting for the transmission of the | ||
301 | * initial frame (i.e. command, task, etc.). | ||
302 | */ | ||
303 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, | ||
304 | |||
305 | /** | ||
306 | * This sub-state indicates that the started task management request | ||
307 | * is waiting for the reception of an unsolicited frame | ||
308 | * (i.e. response IU). | ||
309 | */ | ||
310 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, | ||
311 | |||
312 | /** | ||
299 | * This state indicates that the request has completed. | 313 | * This state indicates that the request has completed. |
300 | * This state is entered from the STARTED state. This state is entered from | 314 | * This state is entered from the STARTED state. This state is entered from |
301 | * the ABORTING state. | 315 | * the ABORTING state. |
@@ -451,7 +465,6 @@ void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req); | |||
451 | void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); | 465 | void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); |
452 | enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); | 466 | enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); |
453 | enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); | 467 | enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); |
454 | void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req); | ||
455 | enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, | 468 | enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, |
456 | u32 event_code); | 469 | u32 event_code); |
457 | enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, | 470 | enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, |
@@ -459,29 +472,6 @@ enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_r | |||
459 | enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); | 472 | enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); |
460 | enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); | 473 | enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); |
461 | 474 | ||
462 | /** | ||
463 | * enum _scic_sds_io_request_started_task_mgmt_substates - This enumeration | ||
464 | * depicts all of the substates for a task management request to be | ||
465 | * performed in the STARTED super-state. | ||
466 | * | ||
467 | * | ||
468 | */ | ||
469 | enum scic_sds_raw_request_started_task_mgmt_substates { | ||
470 | /** | ||
471 | * The AWAIT_TC_COMPLETION sub-state indicates that the started raw | ||
472 | * task management request is waiting for the transmission of the | ||
473 | * initial frame (i.e. command, task, etc.). | ||
474 | */ | ||
475 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, | ||
476 | |||
477 | /** | ||
478 | * This sub-state indicates that the started task management request | ||
479 | * is waiting for the reception of an unsolicited frame | ||
480 | * (i.e. response IU). | ||
481 | */ | ||
482 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, | ||
483 | }; | ||
484 | |||
485 | 475 | ||
486 | /** | 476 | /** |
487 | * enum _scic_sds_smp_request_started_substates - This enumeration depicts all | 477 | * enum _scic_sds_smp_request_started_substates - This enumeration depicts all |
diff --git a/drivers/scsi/isci/ssp_request.c b/drivers/scsi/isci/ssp_request.c deleted file mode 100644 index 4b6317aeef7d..000000000000 --- a/drivers/scsi/isci/ssp_request.c +++ /dev/null | |||
@@ -1,240 +0,0 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "host.h" | ||
57 | #include "request.h" | ||
58 | #include "state_machine.h" | ||
59 | #include "scu_task_context.h" | ||
60 | #include "scu_completion_codes.h" | ||
61 | |||
62 | /** | ||
63 | * This method processes the completions transport layer (TL) status to | ||
64 | * determine if the RAW task management frame was sent successfully. If the | ||
65 | * raw frame was sent successfully, then the state for the task request | ||
66 | * transitions to waiting for a response frame. | ||
67 | * @sci_req: This parameter specifies the request for which the TC | ||
68 | * completion was received. | ||
69 | * @completion_code: This parameter indicates the completion status information | ||
70 | * for the TC. | ||
71 | * | ||
72 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
73 | * this method always returns success. | ||
74 | */ | ||
75 | static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( | ||
76 | struct scic_sds_request *sci_req, | ||
77 | u32 completion_code) | ||
78 | { | ||
79 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
80 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
81 | scic_sds_request_set_status( | ||
82 | sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
83 | ); | ||
84 | |||
85 | sci_base_state_machine_change_state( | ||
86 | &sci_req->started_substate_machine, | ||
87 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
88 | ); | ||
89 | break; | ||
90 | |||
91 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): | ||
92 | /* | ||
93 | * Currently, the decision is to simply allow the task request to | ||
94 | * timeout if the task IU wasn't received successfully. | ||
95 | * There is a potential for receiving multiple task responses if we | ||
96 | * decide to send the task IU again. */ | ||
97 | dev_warn(scic_to_dev(sci_req->owning_controller), | ||
98 | "%s: TaskRequest:0x%p CompletionCode:%x - " | ||
99 | "ACK/NAK timeout\n", | ||
100 | __func__, | ||
101 | sci_req, | ||
102 | completion_code); | ||
103 | |||
104 | sci_base_state_machine_change_state( | ||
105 | &sci_req->started_substate_machine, | ||
106 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
107 | ); | ||
108 | break; | ||
109 | |||
110 | default: | ||
111 | /* | ||
112 | * All other completion status cause the IO to be complete. If a NAK | ||
113 | * was received, then it is up to the user to retry the request. */ | ||
114 | scic_sds_request_set_status( | ||
115 | sci_req, | ||
116 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
117 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
118 | ); | ||
119 | |||
120 | sci_base_state_machine_change_state(&sci_req->state_machine, | ||
121 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | return SCI_SUCCESS; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * This method is responsible for processing a terminate/abort request for this | ||
130 | * TC while the request is waiting for the task management response | ||
131 | * unsolicited frame. | ||
132 | * @sci_req: This parameter specifies the request for which the | ||
133 | * termination was requested. | ||
134 | * | ||
135 | * This method returns an indication as to whether the abort request was | ||
136 | * successfully handled. need to update to ensure the received UF doesn't cause | ||
137 | * damage to subsequent requests (i.e. put the extended tag in a holding | ||
138 | * pattern for this particular device). | ||
139 | */ | ||
140 | static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( | ||
141 | struct scic_sds_request *request) | ||
142 | { | ||
143 | sci_base_state_machine_change_state(&request->state_machine, | ||
144 | SCI_BASE_REQUEST_STATE_ABORTING); | ||
145 | sci_base_state_machine_change_state(&request->state_machine, | ||
146 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
147 | return SCI_SUCCESS; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * This method processes an unsolicited frame while the task mgmt request is | ||
152 | * waiting for a response frame. It will copy the response data, release | ||
153 | * the unsolicited frame, and transition the request to the | ||
154 | * SCI_BASE_REQUEST_STATE_COMPLETED state. | ||
155 | * @sci_req: This parameter specifies the request for which the | ||
156 | * unsolicited frame was received. | ||
157 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
158 | * should contain the response. | ||
159 | * | ||
160 | * This method returns an indication of whether the TC response frame was | ||
161 | * handled successfully or not. SCI_SUCCESS Currently this value is always | ||
162 | * returned and indicates successful processing of the TC response. Should | ||
163 | * probably update to check frame type and make sure it is a response frame. | ||
164 | */ | ||
165 | static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( | ||
166 | struct scic_sds_request *request, | ||
167 | u32 frame_index) | ||
168 | { | ||
169 | scic_sds_io_request_copy_response(request); | ||
170 | |||
171 | sci_base_state_machine_change_state(&request->state_machine, | ||
172 | SCI_BASE_REQUEST_STATE_COMPLETED); | ||
173 | scic_sds_controller_release_frame(request->owning_controller, | ||
174 | frame_index); | ||
175 | return SCI_SUCCESS; | ||
176 | } | ||
177 | |||
178 | static const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { | ||
179 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
180 | .abort_handler = scic_sds_request_started_state_abort_handler, | ||
181 | .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, | ||
182 | }, | ||
183 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | ||
184 | .abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, | ||
185 | .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, | ||
186 | } | ||
187 | }; | ||
188 | |||
189 | /** | ||
190 | * This method performs the actions required when entering the | ||
191 | * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
192 | * sub-state. This includes setting the IO request state handlers for this | ||
193 | * sub-state. | ||
194 | * @object: This parameter specifies the request object for which the sub-state | ||
195 | * change is occurring. | ||
196 | * | ||
197 | * none. | ||
198 | */ | ||
199 | static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( | ||
200 | void *object) | ||
201 | { | ||
202 | struct scic_sds_request *sci_req = object; | ||
203 | |||
204 | SET_STATE_HANDLER( | ||
205 | sci_req, | ||
206 | scic_sds_ssp_task_request_started_substate_handler_table, | ||
207 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
208 | ); | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * This method performs the actions required when entering the | ||
213 | * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This | ||
214 | * includes setting the IO request state handlers for this sub-state. | ||
215 | * @object: This parameter specifies the request object for which the sub-state | ||
216 | * change is occurring. | ||
217 | * | ||
218 | * none. | ||
219 | */ | ||
220 | static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( | ||
221 | void *object) | ||
222 | { | ||
223 | struct scic_sds_request *sci_req = object; | ||
224 | |||
225 | SET_STATE_HANDLER( | ||
226 | sci_req, | ||
227 | scic_sds_ssp_task_request_started_substate_handler_table, | ||
228 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
229 | ); | ||
230 | } | ||
231 | |||
232 | const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = { | ||
233 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
234 | .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, | ||
235 | }, | ||
236 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | ||
237 | .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, | ||
238 | }, | ||
239 | }; | ||
240 | |||