1/*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license.  When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 *   * Redistributions of source code must retain the above copyright
36 *     notice, this list of conditions and the following disclaimer.
37 *   * Redistributions in binary form must reproduce the above copyright
38 *     notice, this list of conditions and the following disclaimer in
39 *     the documentation and/or other materials provided with the
40 *     distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55#include <sys/cdefs.h>
56__FBSDID("$FreeBSD$");
57
58/**
59 * @file
60 *
61 * @brief This file contains all of the method implementations pertaining
62 *        to the framework remote device READY sub-state handler methods.
63 */
64
65#include <dev/isci/scil/scic_remote_device.h>
66#include <dev/isci/scil/scic_io_request.h>
67
68#include <dev/isci/scil/scif_sas_logger.h>
69#include <dev/isci/scil/scif_sas_remote_device.h>
70#include <dev/isci/scil/scif_sas_domain.h>
71#include <dev/isci/scil/scif_sas_task_request.h>
72#include <dev/isci/scil/scif_sas_io_request.h>
73#include <dev/isci/scil/scif_sas_internal_io_request.h>
74#include <dev/isci/scil/scif_sas_controller.h>
75#include <dev/isci/scil/sci_abstract_list.h>
76#include <dev/isci/scil/intel_sat.h>
77#include <dev/isci/scil/sci_controller.h>
78
79//******************************************************************************
80//* P R I V A T E   M E T H O D S
81//******************************************************************************
82
83/**
84 * @brief This method implements the behavior common to starting a task mgmt
85 *        request.  It will change the ready substate to task management.
86 *
87 * @param[in]  fw_device This parameter specifies the remote device for
88 *             which to complete a request.
89 * @param[in]  fw_task This parameter specifies the task management
90 *             request being started.
91 *
92 * @return This method returns a value indicating the status of the
93 *         start operation.
94 */
95static
96SCI_STATUS scif_sas_remote_device_start_task_request(
97   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
98   SCIF_SAS_TASK_REQUEST_T  * fw_task
99)
100{
101   // Transition into the TASK MGMT substate if not already in it.
102   if (fw_device->ready_substate_machine.current_state_id
103       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
104   {
105      sci_base_state_machine_change_state(
106         &fw_device->ready_substate_machine,
107         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
108      );
109   }
110
111   fw_device->request_count++;
112   fw_device->task_request_count++;
113
114   return SCI_SUCCESS;
115}
116
117//******************************************************************************
118//* R E A D Y   O P E R A T I O N A L   H A N D L E R S
119//******************************************************************************
120
121/**
122 * @brief This method provides OPERATIONAL sub-state specific handling for
123 *        when the core remote device object issues a device not ready
124 *        notification.
125 *
126 * @param[in]  remote_device This parameter specifies the remote device
127 *             object for which the notification occurred.
128 *
129 * @return none.
130 */
131static
132void scif_sas_remote_device_ready_operational_not_ready_handler(
133   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
134   U32                        reason_code
135)
136{
137   if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED)
138   {
139      sci_base_state_machine_change_state(
140         &fw_device->ready_substate_machine,
141         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
142      );
143   }
144   else
145   {
146      // Even though we are in the OPERATIONAL state, the core remote device is not
147      // ready.  As a result, we process user requests/events as if we were
148      // stopping the framework remote device.
149      sci_base_state_machine_change_state(
150         &fw_device->ready_substate_machine,
151         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
152      );
153   }
154}
155
156/**
157 * @brief This method provides TASK MGMT sub-state specific handling for when
158 *        the core remote device object issues a device not ready notification.
159 *
160 * @param[in]  remote_device This parameter specifies the remote device
161 *             object for which the notification occurred.
162 *
163 * @return none.
164 */
165static
166void scif_sas_remote_device_ready_task_management_not_ready_handler(
167   SCIF_SAS_REMOTE_DEVICE_T * fw_device,
168   U32                        reason_code
169)
170{
171   //do nothing. Don't need to go to suspended substate.
172}
173
174/**
175 * @brief This method provides OPERATIONAL sub-state specific handling for
176 *        when the remote device is being stopped by the framework.
177 *
178 * @param[in]  remote_device This parameter specifies the remote device
179 *             object for which the stop operation is being requested.
180 *
181 * @return This method returns an indication as to whether the failure
182 *         operation completed successfully.
183 */
184static
185SCI_STATUS scif_sas_remote_device_ready_operational_stop_handler(
186   SCI_BASE_REMOTE_DEVICE_T * remote_device
187)
188{
189   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
190                                          remote_device;
191
192   sci_base_state_machine_change_state(
193      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
194   );
195
196   return fw_device->operation_status;
197}
198
199/**
200 * @brief This method provides OPERATIONAL sub-state specific handling for
201 *        when the user attempts to destruct the remote device.  In
202 *        the READY state the framework must first stop the device
203 *        before destructing it.
204 *
205 * @param[in]  remote_device This parameter specifies the remote device
206 *             object for which the framework is attempting to start.
207 *
208 * @return This method returns an indication as to whether the destruct
209 *         operation completed successfully.
210 */
211static
212SCI_STATUS scif_sas_remote_device_ready_operational_destruct_handler(
213   SCI_BASE_REMOTE_DEVICE_T * remote_device
214)
215{
216   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
217                                          remote_device;
218
219   fw_device->destruct_when_stopped = TRUE;
220
221   return (fw_device->state_handlers->parent.stop_handler(&fw_device->parent));
222}
223
224/**
225 * @brief This method provides OPERATIONAL sub-state specific handling for
226 *        when the remote device undergoes a failure condition.
227 *
228 * @param[in]  remote_device This parameter specifies the remote device
229 *             object for which the failure condition occurred.
230 *
231 * @return This method returns an indication as to whether the failure
232 *         operation completed successfully.
233 */
234static
235SCI_STATUS scif_sas_remote_device_ready_operational_fail_handler(
236   SCI_BASE_REMOTE_DEVICE_T * remote_device
237)
238{
239   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
240                                          remote_device;
241
242   SCIF_LOG_WARNING((
243      sci_base_object_get_logger(fw_device),
244      SCIF_LOG_OBJECT_REMOTE_DEVICE,
245      "RemoteDevice:0x%x ready device failed\n",
246      fw_device
247   ));
248
249   sci_base_state_machine_change_state(
250      &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FAILED
251   );
252
253   /// @todo Fix the return code handling.
254   return SCI_FAILURE;
255}
256
257/**
258 * @brief This method provides OPERATIONAL sub-state specific handling for
259 *        when a user attempts to start an IO request on a remote
260 *        device.
261 *
262 * @param[in]  remote_device This parameter specifies the remote device
263 *             object on which the user is attempting to perform a start
264 *             IO operation.
265 * @param[in]  io_request This parameter specifies the IO request to be
266 *             started.
267 *
268 * @return This method returns an indication as to whether the IO request
269 *         started successfully.
270 */
271static
272SCI_STATUS scif_sas_remote_device_ready_operational_start_io_handler(
273   SCI_BASE_REMOTE_DEVICE_T * remote_device,
274   SCI_BASE_REQUEST_T       * io_request
275)
276{
277   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
278                                          remote_device;
279   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;
280   SCI_STATUS                 status;
281
282   status = fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
283
284   if (status == SCI_SUCCESS)
285   {
286      fw_device->request_count++;
287   }
288
289   return status;
290}
291
292/**
293 * @brief This method provides OPERATIONAL sub-state specific handling for
294 *        when a user attempts to start an IO request on a remote
295 *        device.
296 *
297 * @param[in]  remote_device This parameter specifies the remote device
298 *             object on which the user is attempting to perform a complete
299 *             IO operation.
300 * @param[in]  io_request This parameter specifies the IO request to
301 *             be completed.
302 *
303 * @return This method returns an indication as to whether the IO request
304 *         completed successfully.
305 */
306SCI_STATUS scif_sas_remote_device_ready_operational_complete_io_handler(
307   SCI_BASE_REMOTE_DEVICE_T * remote_device,
308   SCI_BASE_REQUEST_T       * io_request
309)
310{
311   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
312                                          remote_device;
313   fw_device->request_count--;
314   return SCI_SUCCESS;
315}
316
317
318/**
319 * @brief This method provides OPERATIONAL sub-state specific handling for
320 *        when a user attempts to start an IO request on a remote
321 *        device.
322 *
323 * @param[in]  remote_device This parameter specifies the remote device
324 *             object on which the user is attempting to perform a complete
325 *             IO operation.
326 * @param[in]  io_request This parameter specifies the IO request to
327 *             be completed.
328 *
329 * @return This method returns an indication as to whether the IO request
330 *         completed successfully.
331 */
332static
333SCI_STATUS scif_sas_remote_device_ready_operational_complete_high_priority_io_handler(
334   SCI_BASE_REMOTE_DEVICE_T * remote_device,
335   SCI_BASE_REQUEST_T       * io_request,
336   void                     * response_data,
337   SCI_IO_STATUS              completion_status
338)
339{
340   SCIF_LOG_WARNING((
341      sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
342      SCIF_LOG_OBJECT_REMOTE_DEVICE,
343      "RemoteDevice:0x%x State:0x%x invalid state to complete high priority IO\n",
344      remote_device,
345      sci_base_state_machine_get_state(
346         &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
347   ));
348
349   return SCI_FAILURE_INVALID_STATE;
350}
351
352
353/**
354 * @brief This method provides OPERATIONAL sub-state specific handling for when
355 *        the framework attempts to continue an IO request on a remote
356 *        device.
357 *
358 * @param[in]  remote_device This parameter specifies the remote device
359 *             object on which the user is attempting to perform a continue
360 *             IO operation.
361 * @param[in]  io_request This parameter specifies the IO request to
362 *             be continued.
363 *
364 * @return This method returns an indication as to whether the IO request
365 *         completed successfully.
366 */
367static
368SCI_STATUS scif_sas_remote_device_ready_operational_continue_io_handler(
369   SCI_BASE_REMOTE_DEVICE_T * remote_device,
370   SCI_BASE_REQUEST_T       * io_request
371)
372{
373   /// @todo Fix the return code handling.
374   return SCI_FAILURE;
375}
376
377/**
378 * @brief This method provides OPERATIONAL sub-state specific handling for
379 *        when a user attempts to start a task management request on
380 *        a remote device.  This includes terminating all of the affected
381 *        ongoing IO requests (i.e. aborting them in the silicon) and then
382 *        issuing the task management request to the silicon.
383 *
384 * @param[in]  remote_device This parameter specifies the remote device
385 *             object on which the user is attempting to perform a start
386 *             task operation.
387 * @param[in]  task_request This parameter specifies the task management
388 *             request to be started.
389 *
390 * @return This method returns an indication as to whether the task
391 *         management request started successfully.
392 */
393static
394SCI_STATUS scif_sas_remote_device_ready_operational_start_task_handler(
395   SCI_BASE_REMOTE_DEVICE_T * remote_device,
396   SCI_BASE_REQUEST_T       * task_request
397)
398{
399   SCI_STATUS                 status     = SCI_FAILURE;
400   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
401                                           remote_device;
402   SCIF_SAS_TASK_REQUEST_T  * fw_task    = (SCIF_SAS_TASK_REQUEST_T*)
403                                           task_request;
404   U8 task_function =
405         scif_sas_task_request_get_function(fw_task);
406
407   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
408
409   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
410   if (   dev_protocols.u.bits.attached_ssp_target
411       || dev_protocols.u.bits.attached_stp_target)
412   {
413      // //NOTE: For STP/SATA targets we currently terminate all requests for
414      //       any type of task management.
415      if (  (task_function == SCI_SAS_ABORT_TASK_SET)
416         || (task_function == SCI_SAS_CLEAR_TASK_SET)
417         || (task_function == SCI_SAS_LOGICAL_UNIT_RESET)
418         || (task_function == SCI_SAS_I_T_NEXUS_RESET)
419         || (task_function == SCI_SAS_HARD_RESET) )
420      {
421         // Terminate all of the requests in the silicon for this device.
422         scif_sas_domain_terminate_requests(
423            fw_device->domain, fw_device, NULL, fw_task
424         );
425
426         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
427      }
428      else if (  (task_function == SCI_SAS_CLEAR_ACA)
429              || (task_function == SCI_SAS_QUERY_TASK)
430              || (task_function == SCI_SAS_QUERY_TASK_SET)
431              || (task_function == SCI_SAS_QUERY_ASYNCHRONOUS_EVENT) )
432      {
433       ASSERT(!dev_protocols.u.bits.attached_stp_target);
434         status = scif_sas_remote_device_start_task_request(fw_device, fw_task);
435      }
436      else if (task_function == SCI_SAS_ABORT_TASK)
437      {
438         SCIF_SAS_REQUEST_T * fw_request
439            = scif_sas_domain_get_request_by_io_tag(
440                 fw_device->domain, fw_task->io_tag_to_manage
441              );
442
443         // Determine if the request being aborted was found.
444         if (fw_request != NULL)
445         {
446            scif_sas_domain_terminate_requests(
447               fw_device->domain, fw_device, fw_request, fw_task
448            );
449
450            status = scif_sas_remote_device_start_task_request(
451                        fw_device, fw_task
452                     );
453         }
454         else
455            status = SCI_FAILURE_INVALID_IO_TAG;
456      }
457   }
458   else
459      status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
460
461   if (status != SCI_SUCCESS)
462   {
463      SCIF_LOG_ERROR((
464         sci_base_object_get_logger(fw_device),
465         SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
466         "Controller:0x%x TaskRequest:0x%x Status:0x%x start task failure\n",
467         fw_device, fw_task, status
468      ));
469   }
470
471   return status;
472}
473
474/**
475 * @brief This method provides OPERATIONAL sub-state specific handling for
476 *        when a user attempts to complete a task management request on
477 *        a remote device.
478 *
479 * @param[in]  remote_device This parameter specifies the remote device object
480 *             on which the user is attempting to perform a complete task
481 *             operation.
482 * @param[in]  task_request This parameter specifies the task management
483 *             request to be completed.
484 *
485 * @return This method returns an indication as to whether the task
486 *         management request succeeded.
487 */
488SCI_STATUS scif_sas_remote_device_ready_operational_complete_task_handler(
489   SCI_BASE_REMOTE_DEVICE_T * remote_device,
490   SCI_BASE_REQUEST_T       * task_request
491)
492{
493   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
494                                          remote_device;
495   fw_device->request_count--;
496   fw_device->task_request_count--;
497
498   return SCI_SUCCESS;
499}
500
501/**
502 * @brief This method provides OPERATIONAL sub-state specific handling for
503 *        when a user attempts to start a high priority IO request on a remote
504 *        device.
505 *
506 * @param[in]  remote_device This parameter specifies the remote device
507 *             object on which the user is attempting to perform a start
508 *             IO operation.
509 * @param[in]  io_request This parameter specifies the IO request to be
510 *             started.
511 *
512 * @return This method returns an indication as to whether the IO request
513 *         started successfully.
514 */
515static
516SCI_STATUS scif_sas_remote_device_ready_operational_start_high_priority_io_handler(
517   SCI_BASE_REMOTE_DEVICE_T * remote_device,
518   SCI_BASE_REQUEST_T       * io_request
519)
520{
521   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
522                                          remote_device;
523   SCIF_SAS_IO_REQUEST_T    * fw_io     = (SCIF_SAS_IO_REQUEST_T*) io_request;
524
525   SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
526
527   scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
528
529   if (dev_protocols.u.bits.attached_smp_target)
530   {
531      //transit to task management state for smp request phase.
532      if (fw_device->ready_substate_machine.current_state_id
533       != SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT)
534      {
535         sci_base_state_machine_change_state(
536            &fw_device->ready_substate_machine,
537            SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
538         );
539      }
540   }
541
542   fw_device->request_count++;
543
544   return fw_io->parent.state_handlers->start_handler(&fw_io->parent.parent);
545}
546
547
548/**
549 * @brief This method provides TASK MANAGEMENT sub-state specific handling for
550 *        when a user attempts to complete a task management request on
551 *        a remote device.
552 *
553 * @param[in]  remote_device This parameter specifies the remote device object
554 *             on which the user is attempting to perform a complete task
555 *             operation.
556 * @param[in]  task_request This parameter specifies the task management
557 *             request to be completed.
558 *
559 * @return This method returns an indication as to whether the task
560 *         management request succeeded.
561 */
562SCI_STATUS scif_sas_remote_device_ready_task_management_complete_task_handler(
563   SCI_BASE_REMOTE_DEVICE_T * remote_device,
564   SCI_BASE_REQUEST_T       * task_request
565)
566{
567   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
568                                          remote_device;
569
570   SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T *)
571                                       task_request;
572
573   fw_device->request_count--;
574   fw_device->task_request_count--;
575
576   // All existing task management requests and all of the IO requests
577   // affectected by the task management request must complete before
578   // the remote device can transition back into the READY / OPERATIONAL
579   // state.
580   if (  (fw_device->task_request_count == 0)
581      && (fw_task->affected_request_count == 0) )
582   {
583      sci_base_state_machine_change_state(
584         &fw_device->ready_substate_machine,
585         SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
586      );
587   }
588
589   return SCI_SUCCESS;
590}
591
592/**
593 * @brief This method provides SUSPENDED sub-state specific handling for
594 *        when the core remote device object issues a device ready
595 *        notification.  This effectively causes the framework remote
596 *        device to transition back into the OPERATIONAL state.
597 *
598 * @param[in]  remote_device This parameter specifies the remote device
599 *             object for which the notification occurred.
600 *
601 * @return none.
602 */
603static
604void scif_sas_remote_device_ready_suspended_ready_handler(
605   SCIF_SAS_REMOTE_DEVICE_T * fw_device
606)
607{
608   sci_base_state_machine_change_state(
609      &fw_device->ready_substate_machine,
610      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
611   );
612}
613
614
615/**
616 * @brief This handler is currently solely used by smp remote device for
617 *        discovering.
618 *
619 * @param[in]  remote_device This parameter specifies the remote device
620 *             object on which the user is attempting to perform a complete high
621 *             priority IO operation.
622 * @param[in]  io_request This parameter specifies the high priority IO request
623 *             to be completed.
624 *
625 * @return SCI_STATUS indicate whether the io complete successfully.
626 */
627SCI_STATUS
628scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(
629   SCI_BASE_REMOTE_DEVICE_T * remote_device,
630   SCI_BASE_REQUEST_T       * io_request,
631   void                     * response_data,
632   SCI_IO_STATUS              completion_status
633)
634{
635   SCIF_SAS_REMOTE_DEVICE_T * fw_device  = (SCIF_SAS_REMOTE_DEVICE_T*)
636                                           remote_device;
637   SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T*) io_request;
638   SCI_STATUS                 status     = SCI_SUCCESS;
639   SCIC_TRANSPORT_PROTOCOL    protocol;
640
641   SCIF_LOG_TRACE((
642      sci_base_object_get_logger(remote_device),
643      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
644      "scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
645      remote_device, io_request, response_data, completion_status
646   ));
647
648   fw_device->request_count--;
649
650   // we are back to ready operational sub state here.
651   sci_base_state_machine_change_state(
652      &fw_device->ready_substate_machine,
653      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
654   );
655
656   protocol = scic_io_request_get_protocol(fw_request->core_object);
657
658   // If this request was an SMP initiator request we created, then
659   // decode the response.
660   if (protocol == SCIC_SMP_PROTOCOL)
661   {
662      if (completion_status != SCI_IO_FAILURE_TERMINATED)
663      {
664         status = scif_sas_smp_remote_device_decode_smp_response(
665                     fw_device, fw_request, response_data, completion_status
666                  );
667      }
668      else
669         scif_sas_smp_remote_device_terminated_request_handler(fw_device, fw_request);
670   }
671   else
672   {
673      // Currently, there are only internal SMP requests.  So, default work
674      // is simply to clean up the internal request.
675      if (fw_request->is_internal == TRUE)
676      {
677         scif_sas_internal_io_request_complete(
678            fw_device->domain->controller,
679            (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_request,
680            SCI_SUCCESS
681         );
682      }
683   }
684
685   return status;
686}
687
688
689SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
690scif_sas_remote_device_ready_substate_handler_table[] =
691{
692   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
693   {
694      {
695         scif_sas_remote_device_default_start_handler,
696         scif_sas_remote_device_ready_operational_stop_handler,
697         scif_sas_remote_device_ready_operational_fail_handler,
698         scif_sas_remote_device_ready_operational_destruct_handler,
699         scif_sas_remote_device_default_reset_handler,
700         scif_sas_remote_device_default_reset_complete_handler,
701         scif_sas_remote_device_ready_operational_start_io_handler,
702         scif_sas_remote_device_ready_operational_complete_io_handler,
703         scif_sas_remote_device_ready_operational_continue_io_handler,
704         scif_sas_remote_device_ready_operational_start_task_handler,
705         scif_sas_remote_device_ready_operational_complete_task_handler
706      },
707      scif_sas_remote_device_default_start_complete_handler,
708      scif_sas_remote_device_default_stop_complete_handler,
709      scif_sas_remote_device_default_ready_handler,
710      scif_sas_remote_device_ready_operational_not_ready_handler,
711      scif_sas_remote_device_ready_operational_start_high_priority_io_handler,  //
712      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
713   },
714   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
715   {
716      {
717         scif_sas_remote_device_default_start_handler,
718         scif_sas_remote_device_ready_operational_stop_handler,
719         scif_sas_remote_device_ready_operational_fail_handler,
720         scif_sas_remote_device_ready_operational_destruct_handler,
721         scif_sas_remote_device_default_reset_handler,
722         scif_sas_remote_device_default_reset_complete_handler,
723         scif_sas_remote_device_default_start_io_handler,
724         scif_sas_remote_device_ready_operational_complete_io_handler,
725         scif_sas_remote_device_default_continue_io_handler,
726         scif_sas_remote_device_ready_operational_start_task_handler,
727         scif_sas_remote_device_ready_operational_complete_task_handler
728      },
729      scif_sas_remote_device_default_start_complete_handler,
730      scif_sas_remote_device_default_stop_complete_handler,
731      scif_sas_remote_device_ready_suspended_ready_handler,
732      scif_sas_remote_device_default_not_ready_handler,
733      scif_sas_remote_device_default_start_io_handler,
734      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
735   },
736   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
737   {
738      {
739         scif_sas_remote_device_default_start_handler,
740         scif_sas_remote_device_ready_operational_stop_handler,
741         scif_sas_remote_device_ready_operational_fail_handler,
742         scif_sas_remote_device_ready_operational_destruct_handler,
743         scif_sas_remote_device_default_reset_handler,
744         scif_sas_remote_device_default_reset_complete_handler,
745         scif_sas_remote_device_default_start_io_handler,
746         scif_sas_remote_device_ready_operational_complete_io_handler,
747         scif_sas_remote_device_ready_operational_continue_io_handler,
748         scif_sas_remote_device_ready_operational_start_task_handler,
749         scif_sas_remote_device_ready_task_management_complete_task_handler
750      },
751      scif_sas_remote_device_default_start_complete_handler,
752      scif_sas_remote_device_default_stop_complete_handler,
753      scif_sas_remote_device_default_ready_handler,
754      scif_sas_remote_device_ready_task_management_not_ready_handler,
755      scif_sas_remote_device_ready_operational_start_high_priority_io_handler,
756      scif_sas_remote_device_ready_task_management_complete_high_priority_io_handler
757   },
758   // SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
759   {
760      {
761         scif_sas_remote_device_default_start_handler,
762         scif_sas_remote_device_ready_operational_stop_handler,
763         scif_sas_remote_device_ready_operational_fail_handler,
764         scif_sas_remote_device_ready_operational_destruct_handler,
765         scif_sas_remote_device_default_reset_handler,
766         scif_sas_remote_device_default_reset_complete_handler,
767         scif_sas_remote_device_default_start_io_handler,
768         scif_sas_remote_device_ready_operational_complete_io_handler,
769         scif_sas_remote_device_default_continue_io_handler,
770         scif_sas_remote_device_ready_operational_start_task_handler,
771         scif_sas_remote_device_ready_operational_complete_task_handler
772      },
773      scif_sas_remote_device_default_start_complete_handler,
774      scif_sas_remote_device_default_stop_complete_handler,
775      scif_sas_remote_device_ready_suspended_ready_handler,
776      scif_sas_remote_device_default_not_ready_handler,
777      scif_sas_remote_device_default_start_io_handler,
778      scif_sas_remote_device_ready_operational_complete_high_priority_io_handler
779   },
780};
781
782