diff options
Diffstat (limited to 'drivers/scsi/isci/request.c')
-rw-r--r-- | drivers/scsi/isci/request.c | 185 |
1 files changed, 164 insertions, 21 deletions
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; |