aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-05-10 05:28:47 -0400
committerDan Williams <dan.j.williams@intel.com>2011-07-03 07:04:47 -0400
commitf139303d17c47eff4c5b5407dee0a6d43e8fd146 (patch)
treeb58d13c01567500e7b0a451bbcd46dd78ceb4da7 /drivers
parente2f8db509fdd354bb7a68c86515e9d2d8909ccc9 (diff)
isci: merge ssp task management substates into primary state machine
Remove usage of the request substate machine for ssp task management requests identified by: ireq->ttype == tmf_task && dev->dev_type == SAS_END_DEV; The only routine that checks the base 'started' state is scic_sds_io_request_tc_completion which calls the substate machine handler if we are not in the 'started' state or we are 'started' and no substate machine is defined. This routine requires no conversion because we have transitioned out of 'started' and the substate routine will be called naturally as a result. There are also no side effects of this conversion on exiting the 'started', state because it only stops the substate machine, which is no longer relevant for this transaction type. Reported-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/isci/Makefile1
-rw-r--r--drivers/scsi/isci/request.c185
-rw-r--r--drivers/scsi/isci/request.h38
-rw-r--r--drivers/scsi/isci/ssp_request.c240
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 */
659void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req) 659static 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 */
1166static 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 */
1226static 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 */
1251static 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
1154static const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { 1264static 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)
1919static void scic_sds_request_started_state_enter(void *object) 2035static 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
2152static 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
2164static 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
2029static const struct sci_base_state scic_sds_request_state_table[] = { 2176static 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);
451void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req); 465void scic_sds_smp_request_assign_buffers(struct scic_sds_request *sci_req);
452enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req); 466enum sci_status scic_sds_request_start(struct scic_sds_request *sci_req);
453enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req); 467enum sci_status scic_sds_io_request_terminate(struct scic_sds_request *sci_req);
454void scic_sds_io_request_copy_response(struct scic_sds_request *sci_req);
455enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req, 468enum sci_status scic_sds_io_request_event_handler(struct scic_sds_request *sci_req,
456 u32 event_code); 469 u32 event_code);
457enum sci_status scic_sds_io_request_frame_handler(struct scic_sds_request *sci_req, 470enum 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
459enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req); 472enum sci_status scic_sds_task_request_terminate(struct scic_sds_request *sci_req);
460enum sci_status scic_sds_request_started_state_abort_handler(struct scic_sds_request *sci_req); 473enum 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 */
469enum 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 */
75static 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 */
140static 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 */
165static 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
178static 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 */
199static 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 */
220static 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
232const 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