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