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 state handler methods.
63  */
64 
65 #include <dev/isci/scil/scic_remote_device.h>
66 
67 #include <dev/isci/scil/scif_sas_logger.h>
68 #include <dev/isci/scil/scif_sas_remote_device.h>
69 #include <dev/isci/scil/scif_sas_domain.h>
70 #include <dev/isci/scil/scif_sas_task_request.h>
71 #include <dev/isci/scil/scif_sas_internal_io_request.h>
72 
73 //******************************************************************************
74 //* S T O P P E D   H A N D L E R S
75 //******************************************************************************
76 
77 /**
78  * @brief This method provides STOPPED state specific handling for
79  *        when the framework attempts to start the remote device.  This
80  *        method attempts to transition the state machine into the
81  *        STARTING state.  If this is unsuccessful, then there is a direct
82  *        transition into the FAILED state.
83  *
84  * @param[in]  remote_device This parameter specifies the remote device
85  *             object for which the framework is attempting to start.
86  *
87  * @return This method returns an indication as to whether the start
88  *         operating began successfully.
89  */
90 static
91 SCI_STATUS scif_sas_remote_device_stopped_start_handler(
92    SCI_BASE_REMOTE_DEVICE_T * remote_device
93 )
94 {
95    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
96                                           remote_device;
97 
98    sci_base_state_machine_change_state(
99       &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STARTING
100    );
101 
102    // Check to see if the state transition occurred without issue.
103    if (sci_base_state_machine_get_state(&fw_device->parent.state_machine)
104        == SCI_BASE_REMOTE_DEVICE_STATE_FAILED)
105    {
106       SCIF_LOG_WARNING((
107          sci_base_object_get_logger(fw_device),
108          SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
109          "Domain:0x%x Device:0x%x Status:0x%x failed to start\n",
110          fw_device->domain, fw_device, fw_device->operation_status
111       ));
112    }
113 
114    return fw_device->operation_status;
115 }
116 
117 /**
118  * @brief This method provides STOPPED state specific handling for
119  *        when the user attempts to destruct the remote device.
120  *
121  * @param[in]  remote_device This parameter specifies the remote device
122  *             object for which the framework is attempting to start.
123  *
124  * @return This method returns an indication as to whether the destruct
125  *         operation completed successfully.
126  */
127 static
128 SCI_STATUS scif_sas_remote_device_stopped_destruct_handler(
129    SCI_BASE_REMOTE_DEVICE_T * remote_device
130 )
131 {
132    SCI_STATUS                 status;
133    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
134                                           remote_device;
135 
136    SMP_DISCOVER_RESPONSE_PROTOCOLS_T  dev_protocols;
137    scic_remote_device_get_protocols(fw_device->core_object, &dev_protocols);
138 
139    //For smp device, need to clear its smp phy list first.
140    if(dev_protocols.u.bits.attached_smp_target)
141       scif_sas_smp_remote_device_removed(fw_device);
142 
143    status = scic_remote_device_destruct(fw_device->core_object);
144    if (status == SCI_SUCCESS)
145    {
146       sci_base_state_machine_change_state(
147          &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_FINAL
148       );
149 
150       scif_sas_remote_device_deinitialize_state_logging(fw_device);
151    }
152    else
153    {
154       SCIF_LOG_ERROR((
155          sci_base_object_get_logger(fw_device),
156          SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
157          "Device:0x%x Status:0x%x failed to destruct core device\n",
158          fw_device
159       ));
160    }
161 
162    return status;
163 }
164 
165 //******************************************************************************
166 //* S T O P P I N G   H A N D L E R S
167 //******************************************************************************
168 
169 /**
170  * @brief This method provides STOPPING state specific handling for
171  *        when the core remote device object issues a stop completion
172  *        notification.
173  *
174  * @note There is no need to ensure all IO/Task requests are complete
175  *       before transitioning to the STOPPED state.  The SCI Core will
176  *       ensure this is accomplished.
177  *
178  * @param[in]  remote_device This parameter specifies the remote device
179  *             object for which the completion occurred.
180  * @param[in]  completion_status This parameter specifies the status
181  *             of the completion operation.
182  *
183  * @return none.
184  */
185 static
186 void scif_sas_remote_device_stopping_stop_complete_handler(
187    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
188    SCI_STATUS                 completion_status
189 )
190 {
191    // Transition directly to the STOPPED state since the core ensures
192    // all IO/Tasks are complete.
193    sci_base_state_machine_change_state(
194       &fw_device->parent.state_machine,
195       SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
196    );
197 
198    if (completion_status != SCI_SUCCESS)
199    {
200       SCIF_LOG_ERROR((
201          sci_base_object_get_logger(fw_device),
202          SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
203          "Device:0x%x Status:0x%x failed to stop core device\n",
204          fw_device, completion_status
205       ));
206 
207       // Something is seriously wrong.  Stopping the core remote device
208       // shouldn't fail in anyway.
209       scif_cb_controller_error(fw_device->domain->controller,
210               SCI_CONTROLLER_REMOTE_DEVICE_ERROR);
211    }
212 }
213 
214 /**
215  * @brief This method provides STOPPING state handling for high priority
216  *        IO requests, when the framework attempts to complete a high
217  *        priority request.
218  *
219  * @param[in]  remote_device This parameter specifies the remote device
220  *             object for which to complete the high priority IO.
221  * @param[in]  io_request This parameter specifies the IO request to be
222  *             completed.
223  * @param[in]  response_data This parameter is ignored, since the device
224  *             is in the stopping state.
225  *
226  * @return This method always returns success.
227  */
228 static
229 SCI_STATUS scif_sas_remote_device_stopping_complete_high_priority_io_handler(
230    SCI_BASE_REMOTE_DEVICE_T * remote_device,
231    SCI_BASE_REQUEST_T       * io_request,
232    void                     * response_data,
233    SCI_IO_STATUS              completion_status
234 )
235 {
236    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
237                                           remote_device;
238    SCIF_SAS_REQUEST_T       * fw_request = (SCIF_SAS_REQUEST_T *) io_request;
239 
240    SCIF_LOG_TRACE((
241       sci_base_object_get_logger(remote_device),
242       SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_IO_REQUEST,
243       "scif_sas_remote_device_stopping_complete_high_priority_io_handler(0x%x,0x%x,0x%x) enter\n",
244       remote_device, io_request, response_data
245    ));
246 
247    fw_device->request_count--;
248 
249    if (fw_request->is_internal == TRUE)
250    {
251       scif_sas_internal_io_request_complete(
252          fw_device->domain->controller,
253          (SCIF_SAS_INTERNAL_IO_REQUEST_T *) io_request,
254          SCI_SUCCESS
255       );
256    }
257 
258    return SCI_SUCCESS;
259 }
260 
261 //******************************************************************************
262 //* F A I L E D   H A N D L E R S
263 //******************************************************************************
264 
265 /**
266  * @brief This method provides FAILED state specific handling for
267  *        when the remote device is being stopped by the framework.
268  *
269  * @param[in]  remote_device This parameter specifies the remote device
270  *             object for which the stop operation is being requested.
271  *
272  * @return This method returns an indication as to whether the failure
273  *         operation completed successfully.
274  */
275 static
276 SCI_STATUS scif_sas_remote_device_failed_stop_handler(
277    SCI_BASE_REMOTE_DEVICE_T * remote_device
278 )
279 {
280    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
281                                           remote_device;
282 
283    SCIF_LOG_WARNING((
284       sci_base_object_get_logger(fw_device),
285       SCIF_LOG_OBJECT_REMOTE_DEVICE,
286       "RemoteDevice:0x%x stopping failed device\n",
287       fw_device
288    ));
289 
290    sci_base_state_machine_change_state(
291       &fw_device->parent.state_machine, SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
292    );
293 
294    /// @todo Fix the return code handling.
295    return SCI_FAILURE;
296 }
297 
298 //******************************************************************************
299 //* D E F A U L T   H A N D L E R S
300 //******************************************************************************
301 
302 /**
303  * @brief This method provides default handling (i.e. returns an error);
304  *        when a user attempts to start a remote device and a start operation
305  *        is not allowed.
306  *
307  * @param[in]  remote_device This parameter specifies the remote device object
308  *             on which the user is attempting to perform a start operation.
309  *
310  * @return This method returns an indication that start operations are not
311  *         allowed.
312  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
313  */
314 SCI_STATUS scif_sas_remote_device_default_start_handler(
315    SCI_BASE_REMOTE_DEVICE_T * remote_device
316 )
317 {
318    SCIF_LOG_WARNING((
319       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
320       SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
321       "RemoteDevice:0x%x State:0x%x invalid state to start\n",
322       remote_device,
323       sci_base_state_machine_get_state(
324          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
325    ));
326 
327    return SCI_FAILURE_INVALID_STATE;
328 }
329 
330 /**
331  * @brief This method provides default handling (i.e. returns an error);
332  *        when a user attempts to stop a remote device and a stop operation
333  *        is not allowed.
334  *
335  * @param[in]  remote_device This parameter specifies the remote device object
336  *             on which the user is attempting to perform a stop operation.
337  *
338  * @return This method returns an indication that stop operations are not
339  *         allowed.
340  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
341  */
342 SCI_STATUS scif_sas_remote_device_default_stop_handler(
343    SCI_BASE_REMOTE_DEVICE_T * remote_device
344 )
345 {
346    SCIF_LOG_WARNING((
347       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
348       SCIF_LOG_OBJECT_REMOTE_DEVICE,
349       "RemoteDevice:0x%x State:0x%x invalid state to stop\n",
350       remote_device,
351       sci_base_state_machine_get_state(
352          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
353    ));
354 
355    return SCI_FAILURE_INVALID_STATE;
356 }
357 
358 /**
359  * @brief This method provides default handling (i.e. returns an error);
360  *        when there is an attempt to fail a remote device from an invalid
361  *        state.
362  *
363  * @param[in]  remote_device This parameter specifies the remote device
364  *             object on which there is an attempt to fail the device.
365  *
366  * @return This method returns an indication that the fail transition is not
367  *         allowed.
368  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
369  */
370 static
371 SCI_STATUS scif_sas_remote_device_default_fail_handler(
372    SCI_BASE_REMOTE_DEVICE_T * remote_device
373 )
374 {
375    SCIF_LOG_WARNING((
376       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
377       SCIF_LOG_OBJECT_REMOTE_DEVICE,
378       "RemoteDevice:0x%x State:0x%x invalid state to fail device\n",
379       remote_device,
380       sci_base_state_machine_get_state(
381          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
382    ));
383 
384    return SCI_FAILURE_INVALID_STATE;
385 }
386 
387 /**
388  * @brief This method provides default handling (i.e. returns an error);
389  *        when there is an attempt to destruct a remote device from an
390  *        invalid state.
391  *
392  * @param[in]  remote_device This parameter specifies the remote device
393  *             object on which there is an attempt to fail the device.
394  *
395  * @return This method returns an indication that the fail transition is not
396  *         allowed.
397  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
398  */
399 SCI_STATUS scif_sas_remote_device_default_destruct_handler(
400    SCI_BASE_REMOTE_DEVICE_T * remote_device
401 )
402 {
403    SCIF_LOG_WARNING((
404       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
405       SCIF_LOG_OBJECT_REMOTE_DEVICE,
406       "RemoteDevice:0x%x State:0x%x invalid state to destruct.\n",
407       remote_device,
408       sci_base_state_machine_get_state(
409          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
410    ));
411 
412    return SCI_FAILURE_INVALID_STATE;
413 }
414 
415 /**
416  * @brief This method provides default handling (i.e. returns an error);
417  *        when there is an attempt to reset a remote device from an invalid
418  *        state.
419  *
420  * @param[in]  remote_device This parameter specifies the remote device
421  *             object on which there is an attempt to fail the device.
422  *
423  * @return This method returns an indication that the fail transition is not
424  *         allowed.
425  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
426  */
427 SCI_STATUS scif_sas_remote_device_default_reset_handler(
428    SCI_BASE_REMOTE_DEVICE_T * remote_device
429 )
430 {
431    SCIF_LOG_WARNING((
432       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
433       SCIF_LOG_OBJECT_REMOTE_DEVICE,
434       "RemoteDevice:0x%x State:0x%x invalid state to reset.\n",
435       remote_device,
436       sci_base_state_machine_get_state(
437          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
438    ));
439 
440    return SCI_FAILURE_INVALID_STATE;
441 }
442 
443 /**
444  * @brief This method provides default handling (i.e. returns an error);
445  *        when there is an attempt to complete a reset to the remote device
446  *        from an invalid state.
447  *
448  * @param[in]  remote_device This parameter specifies the remote device
449  *             object on which there is an attempt to fail the device.
450  *
451  * @return This method returns an indication that the fail transition is not
452  *         allowed.
453  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
454  */
455 SCI_STATUS scif_sas_remote_device_default_reset_complete_handler(
456    SCI_BASE_REMOTE_DEVICE_T * remote_device
457 )
458 {
459    SCIF_LOG_WARNING((
460       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
461       SCIF_LOG_OBJECT_REMOTE_DEVICE,
462       "RemoteDevice:0x%x State:0x%x invalid state to complete reset.\n",
463       remote_device,
464       sci_base_state_machine_get_state(
465          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
466    ));
467 
468    return SCI_FAILURE_INVALID_STATE;
469 }
470 
471 /**
472  * @brief This method provides default handling (i.e. returns an error);
473  *        when a user attempts to start an IO on a remote device and a start
474  *        IO operation is not allowed.
475  *
476  * @param[in]  remote_device This parameter specifies the remote device
477  *             object on which the user is attempting to perform a start IO
478  *             operation.
479  * @param[in]  io_request This parameter specifies the IO request to be
480  *             started.
481  *
482  * @return This method returns an indication that start IO operations
483  *         are not allowed.
484  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
485  */
486 SCI_STATUS scif_sas_remote_device_default_start_io_handler(
487    SCI_BASE_REMOTE_DEVICE_T * remote_device,
488    SCI_BASE_REQUEST_T       * io_request
489 )
490 {
491    SCIF_LOG_WARNING((
492       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
493       SCIF_LOG_OBJECT_REMOTE_DEVICE,
494       "RemoteDevice:0x%x State:0x%x invalid state to start IO.\n",
495       remote_device,
496       sci_base_state_machine_get_state(
497          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
498    ));
499 
500    return SCI_FAILURE_INVALID_STATE;
501 }
502 
503 /**
504  * @brief This method provides default handling (i.e. returns an error);
505  *        when a user attempts to complete an IO on a remote device and a
506  *        complete IO operation is not allowed.
507  *
508  * @param[in]  remote_device This parameter specifies the remote device
509  *             object on which the user is attempting to perform a complete
510  *             IO operation.
511  * @param[in]  io_request This parameter specifies the IO request to be
512  *             completed.
513  *
514  * @return This method returns an indication that complete IO operations
515  *         are not allowed.
516  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
517  */
518 SCI_STATUS scif_sas_remote_device_default_complete_io_handler(
519    SCI_BASE_REMOTE_DEVICE_T * remote_device,
520    SCI_BASE_REQUEST_T       * io_request
521 )
522 {
523    SCIF_LOG_WARNING((
524       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
525       SCIF_LOG_OBJECT_REMOTE_DEVICE,
526       "RemoteDevice:0x%x State:0x%x invalid state to complete IO\n",
527       remote_device,
528       sci_base_state_machine_get_state(
529          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
530    ));
531 
532    return SCI_FAILURE_INVALID_STATE;
533 }
534 
535 
536 /**
537  * @brief This method provides default handling (i.e. returns an error);
538  *        when a user attempts to complete an IO on a remote device and a
539  *        complete IO operation is not allowed.
540  *
541  * @param[in]  remote_device This parameter specifies the remote device
542  *             object on which the user is attempting to perform a start IO
543  *             operation.
544  * @param[in]  io_request This parameter specifies the IO request to be
545  *             started.
546  *
547  * @return This method returns an indication that complete IO operations
548  *         are not allowed.
549  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
550  */
551 SCI_STATUS scif_sas_remote_device_default_complete_high_priority_io_handler(
552    SCI_BASE_REMOTE_DEVICE_T * remote_device,
553    SCI_BASE_REQUEST_T       * io_request,
554    void                     * response_data,
555    SCI_IO_STATUS              completion_status
556 )
557 {
558    SCIF_LOG_WARNING((
559       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
560       SCIF_LOG_OBJECT_REMOTE_DEVICE,
561       "RemoteDevice:0x%x State:0x%x invalid state to complete high priority IO\n",
562       remote_device,
563       sci_base_state_machine_get_state(
564          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
565    ));
566 
567    return SCI_FAILURE_INVALID_STATE;
568 }
569 
570 
571 /**
572  * @brief This method provides default handling (i.e. returns an error);
573  *        when a user attempts to continue an IO on a remote device and a
574  *        continue IO operation is not allowed.
575  *
576  * @param[in]  remote_device This parameter specifies the remote device
577  *             object on which the user is attempting to perform a start IO
578  *             operation.
579  * @param[in]  io_request This parameter specifies the IO request to be
580  *             started.
581  *
582  * @return This method returns an indication that continue IO operations
583  *         are not allowed.
584  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
585  */
586 SCI_STATUS scif_sas_remote_device_default_continue_io_handler(
587    SCI_BASE_REMOTE_DEVICE_T * remote_device,
588    SCI_BASE_REQUEST_T       * io_request
589 )
590 {
591    SCIF_LOG_WARNING((
592       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
593       SCIF_LOG_OBJECT_REMOTE_DEVICE,
594       "RemoteDevice:0x%x State:0x%x invalid state to continue IO\n",
595       remote_device,
596       sci_base_state_machine_get_state(
597          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
598    ));
599 
600    return SCI_FAILURE_INVALID_STATE;
601 }
602 
603 /**
604  * @brief This method provides default handling (i.e. returns an error);
605  *        when a user attempts to start a task on a remote device and a
606  *        start task operation is not allowed.
607  *
608  * @param[in]  remote_device This parameter specifies the remote device
609  *             object on which the user is attempting to perform a start
610  *             task operation.
611  * @param[in]  task_request This parameter specifies the task management
612  *             request to be started.
613  *
614  * @return This method returns an indication that start task operations
615  *         are not allowed.
616  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
617  */
618 SCI_STATUS scif_sas_remote_device_default_start_task_handler(
619    SCI_BASE_REMOTE_DEVICE_T * remote_device,
620    SCI_BASE_REQUEST_T       * task_request
621 )
622 {
623    SCIF_LOG_WARNING((
624       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
625       SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
626       "RemoteDevice:0x%x State:0x%x invalid state to start task\n",
627       remote_device,
628       sci_base_state_machine_get_state(
629          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
630    ));
631 
632    return SCI_FAILURE_INVALID_STATE;
633 }
634 
635 /**
636  * @brief This method provides default handling (i.e. returns an error);
637  *        when a user attempts to complete a task on a remote device and a
638  *        complete task operation is not allowed.
639  *
640  * @param[in]  remote_device This parameter specifies the remote device object
641  *             on which the user is attempting to perform a complete task
642  *             operation.
643  * @param[in]  task_request This parameter specifies the task management
644  *             request to be completed.
645  *
646  * @return This method returns an indication that complete task operations
647  *         are not allowed.
648  * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
649  */
650 SCI_STATUS scif_sas_remote_device_default_complete_task_handler(
651    SCI_BASE_REMOTE_DEVICE_T * remote_device,
652    SCI_BASE_REQUEST_T       * task_request
653 )
654 {
655    SCIF_LOG_WARNING((
656       sci_base_object_get_logger((SCIF_SAS_REMOTE_DEVICE_T *)remote_device),
657       SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
658       "RemoteDevice:0x%x State:0x%x invalid state to complete task\n",
659       remote_device,
660       sci_base_state_machine_get_state(
661          &((SCIF_SAS_REMOTE_DEVICE_T *)remote_device)->parent.state_machine)
662    ));
663 
664    return SCI_FAILURE_INVALID_STATE;
665 }
666 
667 /**
668  * @brief This method provides default handling (i.e. returns an error);
669  *        for when the core issues a start completion notification and
670  *        such a notification isn't supported.
671  *
672  * @param[in]  remote_device This parameter specifies the remote device object
673  *             for which the completion notification has occurred.
674  * @param[in]  completion_status This parameter specifies the status
675  *             of the completion operation.
676  *
677  * @return none.
678  */
679 void scif_sas_remote_device_default_start_complete_handler(
680    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
681    SCI_STATUS                 completion_status
682 )
683 {
684    SCIF_LOG_WARNING((
685       sci_base_object_get_logger(fw_device),
686       SCIF_LOG_OBJECT_REMOTE_DEVICE,
687       "RemoteDevice:0x%x State:0x%x invalid state to start complete\n",
688       fw_device,
689       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
690    ));
691 }
692 
693 /**
694  * @brief This method provides default handling (i.e. returns an error);
695  *        for when the core issues a stop completion notification and
696  *        such a notification isn't supported.
697  *
698  * @param[in]  remote_device This parameter specifies the remote device object
699  *             for which the completion notification has occurred.
700  * @param[in]  completion_status This parameter specifies the status
701  *             of the completion operation.
702  *
703  * @return none.
704  */
705 void scif_sas_remote_device_default_stop_complete_handler(
706    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
707    SCI_STATUS                 completion_status
708 )
709 {
710    SCIF_LOG_WARNING((
711       sci_base_object_get_logger(fw_device),
712       SCIF_LOG_OBJECT_REMOTE_DEVICE,
713       "RemoteDevice:0x%x State:0x%x invalid state to stop complete\n",
714       fw_device,
715       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
716    ));
717 }
718 
719 /**
720  * @brief This method provides default handling (i.e. returns an error);
721  *        for when the core issues a ready notification and such a
722  *        notification isn't supported.
723  *
724  * @param[in]  remote_device This parameter specifies the remote device object
725  *             for which the notification has occurred.
726  *
727  * @return none.
728  */
729 void scif_sas_remote_device_default_ready_handler(
730    SCIF_SAS_REMOTE_DEVICE_T * fw_device
731 )
732 {
733    SCIF_LOG_WARNING((
734       sci_base_object_get_logger(fw_device),
735       SCIF_LOG_OBJECT_REMOTE_DEVICE,
736       "RemoteDevice:0x%x State:0x%x invalid state to handle ready\n",
737       fw_device,
738       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
739    ));
740 }
741 
742 /**
743  * @brief This method provides default handling (i.e. returns an error);
744  *        for when the core issues a not ready notification and such a
745  *        notification isn't supported.
746  *
747  * @param[in]  remote_device This parameter specifies the remote device object
748  *             for which the notification has occurred.
749  *
750  * @return none.
751  */
752 void scif_sas_remote_device_default_not_ready_handler(
753    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
754    U32                        reason_code
755 )
756 {
757    SCIF_LOG_WARNING((
758       sci_base_object_get_logger(fw_device),
759       SCIF_LOG_OBJECT_REMOTE_DEVICE,
760       "RemoteDevice:0x%x State:0x%x invalid state to handle not ready\n",
761       fw_device,
762       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
763    ));
764 }
765 
766 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
767 /**
768  * @brief This method provides handling of device start complete duing
769  *        UPDATING_PORT_WIDTH state.
770  *
771  * @param[in]  remote_device This parameter specifies the remote device object
772  *             which is start complete.
773  *
774  * @return none.
775  */
776 static
777 SCI_STATUS scif_sas_remote_device_updating_port_width_state_complete_io_handler(
778    SCI_BASE_REMOTE_DEVICE_T * remote_device,
779    SCI_BASE_REQUEST_T       * io_request
780 )
781 {
782    SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
783                                           remote_device;
784    fw_device->request_count--;
785 
786    //If the request count is zero, go ahead to update the RNC.
787    if (fw_device->request_count == 0 )
788    {
789       if (fw_device->destination_state == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING)
790       {
791          //if the destination state of this device change to STOPPING, no matter
792          //whether we need to update the port width, just make the device
793          //go to the STOPPING state, the device will be removed anyway.
794          sci_base_state_machine_change_state(
795             &fw_device->parent.state_machine,
796             SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
797          );
798       }
799       else
800       {
801          //stop the device, upon the stop complete callback, start the device again
802          //with the updated port width.
803          scic_remote_device_stop(
804             fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
805       }
806    }
807 
808    return SCI_SUCCESS;
809 }
810 
811 
812 /**
813  * @brief This method provides handling of device start complete duing
814  *        UPDATING_PORT_WIDTH state.
815  *
816  * @param[in]  remote_device This parameter specifies the remote device object
817  *             which is start complete.
818  *
819  * @return none.
820  */
821 static
822 void scif_sas_remote_device_updating_port_width_state_start_complete_handler(
823    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
824    SCI_STATUS                 completion_status
825 )
826 {
827    SCIF_LOG_INFO((
828       sci_base_object_get_logger(fw_device),
829       SCIF_LOG_OBJECT_REMOTE_DEVICE,
830       "RemoteDevice:0x%x updating port width state start complete handler\n",
831       fw_device,
832       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
833    ));
834 
835    if ( fw_device->destination_state
836            == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING )
837    {
838       //if the destination state of this device change to STOPPING, no matter
839       //whether we need to update the port width again, just make the device
840       //go to the STOPPING state.
841       sci_base_state_machine_change_state(
842          &fw_device->parent.state_machine,
843          SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
844       );
845    }
846    else if ( scic_remote_device_get_port_width(fw_device->core_object)
847                 != fw_device->device_port_width
848             && fw_device->device_port_width != 0)
849    {
850       scic_remote_device_stop(
851          fw_device->core_object,
852          SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT
853       );
854    }
855    else
856    {
857       //Port width updating succeeds. Transfer to destination state.
858       sci_base_state_machine_change_state(
859          &fw_device->parent.state_machine,
860          SCI_BASE_REMOTE_DEVICE_STATE_READY
861       );
862    }
863 }
864 
865 /**
866  * @brief This method provides handling of device stop complete duing
867  *        UPDATING_PORT_WIDTH state.
868  *
869  * @param[in]  remote_device This parameter specifies the remote device object
870  *             which is stop complete.
871  *
872  * @return none.
873  */
874 static
875 void scif_sas_remote_device_updating_port_width_state_stop_complete_handler(
876    SCIF_SAS_REMOTE_DEVICE_T * fw_device,
877    SCI_STATUS                 completion_status
878 )
879 {
880    SCIF_LOG_INFO((
881       sci_base_object_get_logger(fw_device),
882       SCIF_LOG_OBJECT_REMOTE_DEVICE,
883       "RemoteDevice:0x%x updating port width state stop complete handler\n",
884       fw_device,
885       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
886    ));
887 
888    if ( fw_device->destination_state
889            == SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING )
890    {
891       //Device directly transits to STOPPED STATE from UPDATING_PORT_WIDTH state,
892       fw_device->domain->device_start_count--;
893 
894       //if the destination state of this device change to STOPPING, no matter
895       //whether we need to update the port width again, just make the device
896       //go to the STOPPED state.
897       sci_base_state_machine_change_state(
898          &fw_device->parent.state_machine,
899          SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
900       );
901    }
902    else
903    {
904       scic_remote_device_set_port_width(
905          fw_device->core_object,
906          fw_device->device_port_width
907       );
908 
909       //Device stop complete, means the RNC has been destructed. Now we need to
910       //start core device so the RNC with updated port width will be posted.
911       scic_remote_device_start(
912          fw_device->core_object, SCIF_SAS_REMOTE_DEVICE_CORE_OP_TIMEOUT);
913    }
914 }
915 
916 /**
917  * @brief This method provides handling (i.e. returns an error);
918  *        when a user attempts to stop a remote device during the updating
919  *        port width state, it will record the destination state for this
920  *        device to be STOPPING, instead of usually READY state.
921  *
922  * @param[in]  remote_device This parameter specifies the remote device object
923  *             on which the user is attempting to perform a stop operation.
924  *
925  * @return This method always return SCI_SUCCESS.
926  */
927 static
928 SCI_STATUS scif_sas_remote_device_updating_port_width_state_stop_handler(
929    SCI_BASE_REMOTE_DEVICE_T * remote_device
930 )
931 {
932    SCIF_SAS_REMOTE_DEVICE_T * fw_device =
933       (SCIF_SAS_REMOTE_DEVICE_T *)remote_device;
934 
935    SCIF_LOG_INFO((
936       sci_base_object_get_logger(fw_device),
937       SCIF_LOG_OBJECT_REMOTE_DEVICE,
938       "RemoteDevice:0x%x updating port width state stop handler\n",
939       fw_device,
940       sci_base_state_machine_get_state(&fw_device->parent.state_machine)
941    ));
942 
943    //Can't stop the device right now. Remember the pending stopping request.
944    //When exit the UPDATING_PORT_WIDTH state, we will check this variable
945    //to decide which state to go.
946    fw_device->destination_state =
947       SCIF_SAS_REMOTE_DEVICE_DESTINATION_STATE_STOPPING;
948 
949    return SCI_SUCCESS;
950 }
951 
952 #endif //#if !defined(DISABLE_WIDE_PORTED_TARGETS)
953 
954 #define scif_sas_remote_device_stopping_complete_io_handler   \
955         scif_sas_remote_device_ready_operational_complete_io_handler
956 #define scif_sas_remote_device_stopping_complete_task_handler \
957         scif_sas_remote_device_ready_operational_complete_task_handler
958 
959 SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
960 scif_sas_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] =
961 {
962    // SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
963    {
964       {
965          scif_sas_remote_device_default_start_handler,
966          scif_sas_remote_device_default_stop_handler,
967          scif_sas_remote_device_default_fail_handler,
968          scif_sas_remote_device_default_destruct_handler,
969          scif_sas_remote_device_default_reset_handler,
970          scif_sas_remote_device_default_reset_complete_handler,
971          scif_sas_remote_device_default_start_io_handler,
972          scif_sas_remote_device_default_complete_io_handler,
973          scif_sas_remote_device_default_continue_io_handler,
974          scif_sas_remote_device_default_start_task_handler,
975          scif_sas_remote_device_default_complete_task_handler
976       },
977       scif_sas_remote_device_default_start_complete_handler,
978       scif_sas_remote_device_default_stop_complete_handler,
979       scif_sas_remote_device_default_ready_handler,
980       scif_sas_remote_device_default_not_ready_handler,
981       scif_sas_remote_device_default_start_io_handler,
982       scif_sas_remote_device_default_complete_high_priority_io_handler
983    },
984    // SCI_BASE_REMOTE_DEVICE_STATE_STOPPED
985    {
986       {
987          scif_sas_remote_device_stopped_start_handler,
988          scif_sas_remote_device_default_stop_handler,
989          scif_sas_remote_device_default_fail_handler,
990          scif_sas_remote_device_stopped_destruct_handler,
991          scif_sas_remote_device_default_reset_handler,
992          scif_sas_remote_device_default_reset_complete_handler,
993          scif_sas_remote_device_default_start_io_handler,
994          scif_sas_remote_device_default_complete_io_handler,
995          scif_sas_remote_device_default_continue_io_handler,
996          scif_sas_remote_device_default_start_task_handler,
997          scif_sas_remote_device_default_complete_task_handler
998       },
999       scif_sas_remote_device_default_start_complete_handler,
1000       scif_sas_remote_device_default_stop_complete_handler,
1001       scif_sas_remote_device_default_ready_handler,
1002       scif_sas_remote_device_default_not_ready_handler,
1003       scif_sas_remote_device_default_start_io_handler,
1004       scif_sas_remote_device_default_complete_high_priority_io_handler
1005    },
1006    // SCI_BASE_REMOTE_DEVICE_STATE_STARTING
1007    {
1008       {
1009          scif_sas_remote_device_default_start_handler,
1010          scif_sas_remote_device_default_stop_handler,
1011          scif_sas_remote_device_default_fail_handler,
1012          scif_sas_remote_device_default_destruct_handler,
1013          scif_sas_remote_device_default_reset_handler,
1014          scif_sas_remote_device_default_reset_complete_handler,
1015          scif_sas_remote_device_default_start_io_handler,
1016          scif_sas_remote_device_default_complete_io_handler,
1017          scif_sas_remote_device_default_continue_io_handler,
1018          scif_sas_remote_device_default_start_task_handler,
1019          scif_sas_remote_device_default_complete_task_handler
1020       },
1021       scif_sas_remote_device_default_start_complete_handler,
1022       scif_sas_remote_device_default_stop_complete_handler,
1023       scif_sas_remote_device_default_ready_handler,
1024       scif_sas_remote_device_default_not_ready_handler,
1025       scif_sas_remote_device_default_start_io_handler,
1026       scif_sas_remote_device_default_complete_high_priority_io_handler
1027    },
1028    // SCI_BASE_REMOTE_DEVICE_STATE_READY - see substate handlers
1029    {
1030       {
1031          scif_sas_remote_device_default_start_handler,
1032          scif_sas_remote_device_default_stop_handler,
1033          scif_sas_remote_device_default_fail_handler,
1034          scif_sas_remote_device_default_destruct_handler,
1035          scif_sas_remote_device_default_reset_handler,
1036          scif_sas_remote_device_default_reset_complete_handler,
1037          scif_sas_remote_device_default_start_io_handler,
1038          scif_sas_remote_device_default_complete_io_handler,
1039          scif_sas_remote_device_default_continue_io_handler,
1040          scif_sas_remote_device_default_start_task_handler,
1041          scif_sas_remote_device_default_complete_task_handler
1042       },
1043       scif_sas_remote_device_default_start_complete_handler,
1044       scif_sas_remote_device_default_stop_complete_handler,
1045       scif_sas_remote_device_default_ready_handler,
1046       scif_sas_remote_device_default_not_ready_handler,
1047       scif_sas_remote_device_default_start_io_handler,
1048       scif_sas_remote_device_default_complete_high_priority_io_handler
1049    },
1050    // SCI_BASE_REMOTE_DEVICE_STATE_STOPPING
1051    {
1052       {
1053          scif_sas_remote_device_default_start_handler,
1054          scif_sas_remote_device_default_stop_handler,
1055          scif_sas_remote_device_default_fail_handler,
1056          scif_sas_remote_device_default_destruct_handler,
1057          scif_sas_remote_device_default_reset_handler,
1058          scif_sas_remote_device_default_reset_complete_handler,
1059          scif_sas_remote_device_default_start_io_handler,
1060          scif_sas_remote_device_stopping_complete_io_handler,
1061          scif_sas_remote_device_default_continue_io_handler,
1062          scif_sas_remote_device_default_start_task_handler,
1063          scif_sas_remote_device_stopping_complete_task_handler
1064       },
1065       scif_sas_remote_device_default_start_complete_handler,
1066       scif_sas_remote_device_stopping_stop_complete_handler,
1067       scif_sas_remote_device_default_ready_handler,
1068       scif_sas_remote_device_default_not_ready_handler,
1069       scif_sas_remote_device_default_start_io_handler,
1070       scif_sas_remote_device_stopping_complete_high_priority_io_handler
1071    },
1072    // SCI_BASE_REMOTE_DEVICE_STATE_FAILED
1073    {
1074       {
1075          scif_sas_remote_device_default_start_handler,
1076          scif_sas_remote_device_failed_stop_handler,
1077          scif_sas_remote_device_default_fail_handler,
1078          scif_sas_remote_device_default_destruct_handler,
1079          scif_sas_remote_device_default_reset_handler,
1080          scif_sas_remote_device_default_reset_complete_handler,
1081          scif_sas_remote_device_default_start_io_handler,
1082          scif_sas_remote_device_default_complete_io_handler,
1083          scif_sas_remote_device_default_continue_io_handler,
1084          scif_sas_remote_device_default_start_task_handler,
1085          scif_sas_remote_device_default_complete_task_handler
1086       },
1087       scif_sas_remote_device_default_start_complete_handler,
1088       scif_sas_remote_device_default_stop_complete_handler,
1089       scif_sas_remote_device_default_ready_handler,
1090       scif_sas_remote_device_default_not_ready_handler,
1091       scif_sas_remote_device_default_start_io_handler,
1092       scif_sas_remote_device_default_complete_high_priority_io_handler
1093    },
1094    // SCI_BASE_REMOTE_DEVICE_STATE_RESETTING - is unused by framework
1095    {
1096       {
1097          scif_sas_remote_device_default_start_handler,
1098          scif_sas_remote_device_default_stop_handler,
1099          scif_sas_remote_device_default_fail_handler,
1100          scif_sas_remote_device_default_destruct_handler,
1101          scif_sas_remote_device_default_reset_handler,
1102          scif_sas_remote_device_default_reset_complete_handler,
1103          scif_sas_remote_device_default_start_io_handler,
1104          scif_sas_remote_device_default_complete_io_handler,
1105          scif_sas_remote_device_default_continue_io_handler,
1106          scif_sas_remote_device_default_start_task_handler,
1107          scif_sas_remote_device_default_complete_task_handler
1108       },
1109       scif_sas_remote_device_default_start_complete_handler,
1110       scif_sas_remote_device_default_stop_complete_handler,
1111       scif_sas_remote_device_default_ready_handler,
1112       scif_sas_remote_device_default_not_ready_handler,
1113       scif_sas_remote_device_default_start_io_handler,
1114       scif_sas_remote_device_default_complete_high_priority_io_handler
1115    },
1116 #if !defined(DISABLE_WIDE_PORTED_TARGETS)
1117    // SCI_BASE_REMOTE_DEVICE_STATE_UPDATING_PORT_WIDTH
1118    {
1119       {
1120          scif_sas_remote_device_default_start_handler,
1121          scif_sas_remote_device_updating_port_width_state_stop_handler,
1122          scif_sas_remote_device_default_fail_handler,
1123          scif_sas_remote_device_default_destruct_handler,
1124          scif_sas_remote_device_default_reset_handler,
1125          scif_sas_remote_device_default_reset_complete_handler,
1126          scif_sas_remote_device_default_start_io_handler,
1127          scif_sas_remote_device_updating_port_width_state_complete_io_handler,
1128          scif_sas_remote_device_default_continue_io_handler,
1129          scif_sas_remote_device_default_start_task_handler,
1130          scif_sas_remote_device_default_complete_task_handler
1131       },
1132       scif_sas_remote_device_updating_port_width_state_start_complete_handler,
1133       scif_sas_remote_device_updating_port_width_state_stop_complete_handler,
1134       scif_sas_remote_device_default_ready_handler,
1135       scif_sas_remote_device_default_not_ready_handler,
1136       scif_sas_remote_device_default_start_io_handler,
1137       scif_sas_remote_device_default_complete_high_priority_io_handler
1138    },
1139 #endif
1140    // SCI_BASE_REMOTE_DEVICE_STATE_FINAL
1141    {
1142       {
1143          scif_sas_remote_device_default_start_handler,
1144          scif_sas_remote_device_default_stop_handler,
1145          scif_sas_remote_device_default_fail_handler,
1146          scif_sas_remote_device_default_destruct_handler,
1147          scif_sas_remote_device_default_reset_handler,
1148          scif_sas_remote_device_default_reset_complete_handler,
1149          scif_sas_remote_device_default_start_io_handler,
1150          scif_sas_remote_device_default_complete_io_handler,
1151          scif_sas_remote_device_default_continue_io_handler,
1152          scif_sas_remote_device_default_start_task_handler,
1153          scif_sas_remote_device_default_complete_task_handler
1154       },
1155       scif_sas_remote_device_default_start_complete_handler,
1156       scif_sas_remote_device_default_stop_complete_handler,
1157       scif_sas_remote_device_default_ready_handler,
1158       scif_sas_remote_device_default_not_ready_handler,
1159       scif_sas_remote_device_default_start_io_handler,
1160       scif_sas_remote_device_default_complete_high_priority_io_handler
1161    }
1162 };
1163 
1164