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 */
90static
91SCI_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 */
127static
128SCI_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 */
185static
186void 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 */
228static
229SCI_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 */
275static
276SCI_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 */
314SCI_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 */
342SCI_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 */
370static
371SCI_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 */
399SCI_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 */
427SCI_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 */
455SCI_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 */
486SCI_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 */
518SCI_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 */
551SCI_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 */
586SCI_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 */
618SCI_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 */
650SCI_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 */
679void 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 */
705void 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 */
729void 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 */
752void 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 */
776static
777SCI_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 */
821static
822void 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 */
874static
875void 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 */
927static
928SCI_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
959SCIF_SAS_REMOTE_DEVICE_STATE_HANDLER_T
960scif_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