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  */
95 static
96 SCI_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  */
131 static
132 void 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  */
165 static
166 void 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  */
184 static
185 SCI_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  */
211 static
212 SCI_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  */
234 static
235 SCI_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  */
271 static
272 SCI_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  */
306 SCI_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  */
332 static
333 SCI_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  */
367 static
368 SCI_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  */
393 static
394 SCI_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  */
488 SCI_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  */
515 static
516 SCI_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  */
562 SCI_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  */
603 static
604 void 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  */
627 SCI_STATUS
628 scif_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 
689 SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
690 scif_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