1230557Sjimharris/*-
2230557Sjimharris * This file is provided under a dual BSD/GPLv2 license.  When using or
3230557Sjimharris * redistributing this file, you may do so under either license.
4230557Sjimharris *
5230557Sjimharris * GPL LICENSE SUMMARY
6230557Sjimharris *
7230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8230557Sjimharris *
9230557Sjimharris * This program is free software; you can redistribute it and/or modify
10230557Sjimharris * it under the terms of version 2 of the GNU General Public License as
11230557Sjimharris * published by the Free Software Foundation.
12230557Sjimharris *
13230557Sjimharris * This program is distributed in the hope that it will be useful, but
14230557Sjimharris * WITHOUT ANY WARRANTY; without even the implied warranty of
15230557Sjimharris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16230557Sjimharris * General Public License for more details.
17230557Sjimharris *
18230557Sjimharris * You should have received a copy of the GNU General Public License
19230557Sjimharris * along with this program; if not, write to the Free Software
20230557Sjimharris * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21230557Sjimharris * The full GNU General Public License is included in this distribution
22230557Sjimharris * in the file called LICENSE.GPL.
23230557Sjimharris *
24230557Sjimharris * BSD LICENSE
25230557Sjimharris *
26230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27230557Sjimharris * All rights reserved.
28230557Sjimharris *
29230557Sjimharris * Redistribution and use in source and binary forms, with or without
30230557Sjimharris * modification, are permitted provided that the following conditions
31230557Sjimharris * are met:
32230557Sjimharris *
33230557Sjimharris *   * Redistributions of source code must retain the above copyright
34230557Sjimharris *     notice, this list of conditions and the following disclaimer.
35230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
36230557Sjimharris *     notice, this list of conditions and the following disclaimer in
37230557Sjimharris *     the documentation and/or other materials provided with the
38230557Sjimharris *     distribution.
39230557Sjimharris *
40230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51230557Sjimharris */
52230557Sjimharris
53230557Sjimharris#include <sys/cdefs.h>
54230557Sjimharris__FBSDID("$FreeBSD$");
55230557Sjimharris
56230557Sjimharris/**
57230557Sjimharris * @file
58230557Sjimharris *
59230557Sjimharris * @brief This file contains the task management substate handlers for the
60230557Sjimharris *        SCIC_SDS_IO_REQUEST object.
61230557Sjimharris *        This file contains the enter/exit methods associated with each of
62230557Sjimharris *        the task management raw request states.  For more information on the
63230557Sjimharris *        task management request state machine please refer to
64230557Sjimharris *        scic_sds_io_request.h
65230557Sjimharris */
66230557Sjimharris
67230557Sjimharris#include <dev/isci/scil/intel_sas.h>
68230557Sjimharris#include <dev/isci/scil/scic_sds_request.h>
69230557Sjimharris#include <dev/isci/scil/scic_controller.h>
70230557Sjimharris#include <dev/isci/scil/scic_sds_logger.h>
71230557Sjimharris#include <dev/isci/scil/scic_sds_controller.h>
72230557Sjimharris#include <dev/isci/scil/scu_completion_codes.h>
73230557Sjimharris#include <dev/isci/scil/scu_task_context.h>
74230557Sjimharris#include <dev/isci/scil/sci_base_state_machine.h>
75230557Sjimharris
76230557Sjimharris/**
77230557Sjimharris * @brief This method processes the completions transport layer (TL) status
78230557Sjimharris *        to determine if the RAW task management frame was sent successfully.
79230557Sjimharris *        If the raw frame was sent successfully, then the state for the
80230557Sjimharris *        task request transitions to waiting for a response frame.
81230557Sjimharris *
82230557Sjimharris * @param[in] this_request This parameter specifies the request for which
83230557Sjimharris *            the TC completion was received.
84230557Sjimharris * @param[in] completion_code This parameter indicates the completion status
85230557Sjimharris *            information for the TC.
86230557Sjimharris *
87230557Sjimharris * @return Indicate if the tc completion handler was successful.
88230557Sjimharris * @retval SCI_SUCCESS currently this method always returns success.
89230557Sjimharris */
90230557Sjimharrisstatic
91230557SjimharrisSCI_STATUS scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(
92230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
93230557Sjimharris   U32                  completion_code
94230557Sjimharris)
95230557Sjimharris{
96230557Sjimharris   SCIC_LOG_TRACE((
97230557Sjimharris      sci_base_object_get_logger(this_request),
98230557Sjimharris      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
99230557Sjimharris      "scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(0x%x, 0x%x) enter\n",
100230557Sjimharris      this_request, completion_code
101230557Sjimharris   ));
102230557Sjimharris
103230557Sjimharris   switch (SCU_GET_COMPLETION_TL_STATUS(completion_code))
104230557Sjimharris   {
105230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
106230557Sjimharris      scic_sds_request_set_status(
107230557Sjimharris         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
108230557Sjimharris      );
109230557Sjimharris
110230557Sjimharris      sci_base_state_machine_change_state(
111230557Sjimharris         &this_request->started_substate_machine,
112230557Sjimharris         SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
113230557Sjimharris      );
114230557Sjimharris   break;
115230557Sjimharris
116230557Sjimharris   case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
117230557Sjimharris      // Currently, the decision is to simply allow the task request to
118230557Sjimharris      // timeout if the task IU wasn't received successfully.
119230557Sjimharris      // There is a potential for receiving multiple task responses if we
120230557Sjimharris      // decide to send the task IU again.
121230557Sjimharris      SCIC_LOG_WARNING((
122230557Sjimharris         sci_base_object_get_logger(this_request),
123230557Sjimharris         SCIC_LOG_OBJECT_TASK_MANAGEMENT,
124230557Sjimharris         "TaskRequest:0x%x CompletionCode:%x - ACK/NAK timeout\n",
125230557Sjimharris         this_request, completion_code
126230557Sjimharris      ));
127230557Sjimharris
128230557Sjimharris      sci_base_state_machine_change_state(
129230557Sjimharris         &this_request->started_substate_machine,
130230557Sjimharris         SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
131230557Sjimharris      );
132230557Sjimharris   break;
133230557Sjimharris
134230557Sjimharris   default:
135230557Sjimharris      // All other completion status cause the IO to be complete.  If a NAK
136230557Sjimharris      // was received, then it is up to the user to retry the request.
137230557Sjimharris      scic_sds_request_set_status(
138230557Sjimharris         this_request,
139230557Sjimharris         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
140230557Sjimharris         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
141230557Sjimharris      );
142230557Sjimharris
143230557Sjimharris      sci_base_state_machine_change_state(
144230557Sjimharris         &this_request->parent.state_machine,
145230557Sjimharris         SCI_BASE_REQUEST_STATE_COMPLETED
146230557Sjimharris      );
147230557Sjimharris   break;
148230557Sjimharris   }
149230557Sjimharris
150230557Sjimharris   return SCI_SUCCESS;
151230557Sjimharris}
152230557Sjimharris
153230557Sjimharris/**
154230557Sjimharris * @brief This method is responsible for processing a terminate/abort
155230557Sjimharris *        request for this TC while the request is waiting for the task
156230557Sjimharris *        management response unsolicited frame.
157230557Sjimharris *
158230557Sjimharris * @param[in] this_request This parameter specifies the request for which
159230557Sjimharris *            the termination was requested.
160230557Sjimharris *
161230557Sjimharris * @return This method returns an indication as to whether the abort
162230557Sjimharris *         request was successfully handled.
163230557Sjimharris *
164230557Sjimharris * @todo need to update to ensure the received UF doesn't cause damage
165230557Sjimharris *       to subsequent requests (i.e. put the extended tag in a holding
166230557Sjimharris *       pattern for this particular device).
167230557Sjimharris */
168230557Sjimharrisstatic
169230557SjimharrisSCI_STATUS scic_sds_ssp_task_request_await_tc_response_abort_handler(
170230557Sjimharris   SCI_BASE_REQUEST_T * request
171230557Sjimharris)
172230557Sjimharris{
173230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)request;
174230557Sjimharris
175230557Sjimharris   SCIC_LOG_TRACE((
176230557Sjimharris      sci_base_object_get_logger(this_request),
177230557Sjimharris      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
178230557Sjimharris      "scic_sds_ssp_task_request_await_tc_response_abort_handler(0x%x) enter\n",
179230557Sjimharris      this_request
180230557Sjimharris   ));
181230557Sjimharris
182230557Sjimharris   sci_base_state_machine_change_state(
183230557Sjimharris      &this_request->parent.state_machine,
184230557Sjimharris      SCI_BASE_REQUEST_STATE_ABORTING
185230557Sjimharris   );
186230557Sjimharris
187230557Sjimharris   sci_base_state_machine_change_state(
188230557Sjimharris      &this_request->parent.state_machine,
189230557Sjimharris      SCI_BASE_REQUEST_STATE_COMPLETED
190230557Sjimharris   );
191230557Sjimharris
192230557Sjimharris   return SCI_SUCCESS;
193230557Sjimharris}
194230557Sjimharris
195230557Sjimharris/**
196230557Sjimharris * @brief This method processes an unsolicited frame while the task mgmt
197230557Sjimharris *        request is waiting for a response frame.  It will copy the
198230557Sjimharris *        response data, release the unsolicited frame, and transition
199230557Sjimharris *        the request to the SCI_BASE_REQUEST_STATE_COMPLETED state.
200230557Sjimharris *
201230557Sjimharris * @param[in] this_request This parameter specifies the request for which
202230557Sjimharris *            the unsolicited frame was received.
203230557Sjimharris * @param[in] frame_index This parameter indicates the unsolicited frame
204230557Sjimharris *            index that should contain the response.
205230557Sjimharris *
206230557Sjimharris * @return This method returns an indication of whether the TC response
207230557Sjimharris *         frame was handled successfully or not.
208230557Sjimharris * @retval SCI_SUCCESS Currently this value is always returned and indicates
209230557Sjimharris *         successful processing of the TC response.
210230557Sjimharris *
211230557Sjimharris * @todo Should probably update to check frame type and make sure it is
212230557Sjimharris *       a response frame.
213230557Sjimharris */
214230557Sjimharrisstatic
215230557SjimharrisSCI_STATUS scic_sds_ssp_task_request_await_tc_response_frame_handler(
216230557Sjimharris   SCIC_SDS_REQUEST_T * this_request,
217230557Sjimharris   U32                  frame_index
218230557Sjimharris)
219230557Sjimharris{
220230557Sjimharris   // Save off the controller, so that we do not touch the request after it
221230557Sjimharris   //  is completed.
222230557Sjimharris   SCIC_SDS_CONTROLLER_T * owning_controller = this_request->owning_controller;
223230557Sjimharris
224230557Sjimharris   SCIC_LOG_TRACE((
225230557Sjimharris      sci_base_object_get_logger(this_request),
226230557Sjimharris      SCIC_LOG_OBJECT_TASK_MANAGEMENT,
227230557Sjimharris      "scic_sds_ssp_task_request_await_tc_response_frame_handler(0x%x, 0x%x) enter\n",
228230557Sjimharris      this_request, frame_index
229230557Sjimharris   ));
230230557Sjimharris
231230557Sjimharris   scic_sds_io_request_copy_response(this_request);
232230557Sjimharris
233230557Sjimharris   sci_base_state_machine_change_state(
234230557Sjimharris      &this_request->parent.state_machine,
235230557Sjimharris      SCI_BASE_REQUEST_STATE_COMPLETED
236230557Sjimharris   );
237230557Sjimharris
238230557Sjimharris   scic_sds_controller_release_frame(
239230557Sjimharris      owning_controller, frame_index
240230557Sjimharris   );
241230557Sjimharris
242230557Sjimharris   return SCI_SUCCESS;
243230557Sjimharris}
244230557Sjimharris
245230557SjimharrisSCIC_SDS_IO_REQUEST_STATE_HANDLER_T
246230557Sjimharrisscic_sds_ssp_task_request_started_substate_handler_table
247230557Sjimharris[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES] =
248230557Sjimharris{
249230557Sjimharris   // SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
250230557Sjimharris   {
251230557Sjimharris      {
252230557Sjimharris         scic_sds_request_default_start_handler,
253230557Sjimharris         scic_sds_request_started_state_abort_handler,
254230557Sjimharris         scic_sds_request_default_complete_handler,
255230557Sjimharris         scic_sds_request_default_destruct_handler
256230557Sjimharris      },
257230557Sjimharris      scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler,
258230557Sjimharris      scic_sds_request_default_event_handler,
259230557Sjimharris      scic_sds_request_default_frame_handler
260230557Sjimharris   },
261230557Sjimharris   // SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
262230557Sjimharris   {
263230557Sjimharris      {
264230557Sjimharris         scic_sds_request_default_start_handler,
265230557Sjimharris         scic_sds_ssp_task_request_await_tc_response_abort_handler,
266230557Sjimharris         scic_sds_request_default_complete_handler,
267230557Sjimharris         scic_sds_request_default_destruct_handler
268230557Sjimharris      },
269230557Sjimharris      scic_sds_request_default_tc_completion_handler,
270230557Sjimharris      scic_sds_request_default_event_handler,
271230557Sjimharris      scic_sds_ssp_task_request_await_tc_response_frame_handler
272230557Sjimharris   }
273230557Sjimharris};
274230557Sjimharris
275230557Sjimharris/**
276230557Sjimharris * @brief This method performs the actions required when entering the
277230557Sjimharris *        SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
278230557Sjimharris *        sub-state.  This includes setting the IO request state handlers
279230557Sjimharris *        for this sub-state.
280230557Sjimharris *
281230557Sjimharris * @param[in]  object This parameter specifies the request object for which
282298955Spfg *             the sub-state change is occurring.
283230557Sjimharris *
284230557Sjimharris * @return none.
285230557Sjimharris */
286230557Sjimharrisstatic
287230557Sjimharrisvoid scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter(
288230557Sjimharris   SCI_BASE_OBJECT_T *object
289230557Sjimharris)
290230557Sjimharris{
291230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
292230557Sjimharris
293230557Sjimharris   SET_STATE_HANDLER(
294230557Sjimharris      this_request,
295230557Sjimharris      scic_sds_ssp_task_request_started_substate_handler_table,
296230557Sjimharris      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
297230557Sjimharris   );
298230557Sjimharris}
299230557Sjimharris
300230557Sjimharris/**
301230557Sjimharris * @brief This method performs the actions required when entering the
302230557Sjimharris *        SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state.
303230557Sjimharris *        This includes setting the IO request state handlers for this
304230557Sjimharris *        sub-state.
305230557Sjimharris *
306230557Sjimharris * @param[in]  object This parameter specifies the request object for which
307298955Spfg *             the sub-state change is occurring.
308230557Sjimharris *
309230557Sjimharris * @return none.
310230557Sjimharris */
311230557Sjimharrisstatic
312230557Sjimharrisvoid scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter(
313230557Sjimharris   SCI_BASE_OBJECT_T *object
314230557Sjimharris)
315230557Sjimharris{
316230557Sjimharris   SCIC_SDS_REQUEST_T *this_request = (SCIC_SDS_REQUEST_T *)object;
317230557Sjimharris
318230557Sjimharris   SET_STATE_HANDLER(
319230557Sjimharris      this_request,
320230557Sjimharris      scic_sds_ssp_task_request_started_substate_handler_table,
321230557Sjimharris      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
322230557Sjimharris   );
323230557Sjimharris}
324230557Sjimharris
325230557SjimharrisSCI_BASE_STATE_T scic_sds_io_request_started_task_mgmt_substate_table
326230557Sjimharris[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_MAX_SUBSTATES] =
327230557Sjimharris{
328230557Sjimharris   {
329230557Sjimharris      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
330230557Sjimharris      scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter,
331230557Sjimharris      NULL
332230557Sjimharris   },
333230557Sjimharris   {
334230557Sjimharris      SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
335230557Sjimharris      scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter,
336230557Sjimharris      NULL
337230557Sjimharris   }
338230557Sjimharris};
339230557Sjimharris
340230557Sjimharris
341