scif_sas_controller_state_handlers.c revision 330897
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: stable/11/sys/dev/isci/scil/scif_sas_controller_state_handlers.c 330897 2018-03-14 03:19:51Z eadler $");
57
58/**
59 * @file
60 *
61 * @brief This file contains all of the state handler routines for each
62 *        of the controller states defined by the SCI_BASE_CONTROLLER state
63 *        machine.
64 */
65
66#include <dev/isci/scil/sci_util.h>
67#include <dev/isci/scil/scic_controller.h>
68#include <dev/isci/scil/scic_port.h>
69#include <dev/isci/scil/scic_remote_device.h>
70#include <dev/isci/scil/scic_io_request.h>
71
72#include <dev/isci/scil/scif_sas_controller.h>
73#include <dev/isci/scil/scif_sas_remote_device.h>
74#include <dev/isci/scil/scif_sas_logger.h>
75#include <dev/isci/scil/scif_sas_smp_remote_device.h>
76
77//******************************************************************************
78//* P R I V A T E   M E T H O D S
79//******************************************************************************
80
81/**
82 * @brief This method simply executes the reset operation by entering
83 *        the reset state and allowing the state to perform it's work.
84 *
85 * @param[in]  fw_controller This parameter specifies the SAS framework
86 *             controller for execute the reset.
87 *
88 * @return Indicate the status of the reset operation.  Was it successful?
89 * @retval SCI_SUCCESS This value is returned if it was successfully reset.
90 */
91static
92SCI_STATUS scif_sas_controller_execute_reset(
93   SCIF_SAS_CONTROLLER_T * fw_controller
94)
95{
96   SCI_STATUS  status;
97
98   SCIF_LOG_TRACE((
99      sci_base_object_get_logger(fw_controller),
100      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
101      "scif_sas_controller_execute_reset(0x%x) enter\n",
102      fw_controller
103   ));
104
105   //clean the timer to avoid timer leak.
106   scif_sas_controller_release_resource(fw_controller);
107
108   sci_base_state_machine_change_state(
109      &fw_controller->parent.state_machine,
110      SCI_BASE_CONTROLLER_STATE_RESETTING
111   );
112
113   // Retrieve the status for the operations performed during the entrance
114   // to the resetting state were executing successfully.
115   status = fw_controller->operation_status;
116   fw_controller->operation_status = SCI_SUCCESS;
117
118   return status;
119}
120
121/**
122 * @brief This method checks that the memory descriptor list is valid
123 *        and hasn't been corrupted in some way by the user.
124 *
125 * @param[in] fw_controller This parameter specifies the framework
126 *            controller object for which to validation the MDL.
127 *
128 * @return This method returns a value indicating if the operation succeeded.
129 * @retval SCI_SUCCESS This value indicates that MDL is valid.
130 * @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value indicates
131 *         that some portion of the memory descriptor list is invalid.
132 */
133static
134SCI_STATUS scif_sas_controller_validate_mdl(
135   SCIF_SAS_CONTROLLER_T * fw_controller
136)
137{
138   BOOL is_mde_list_valid;
139
140   // Currently there is only a single MDE in the list.
141   is_mde_list_valid = sci_base_mde_is_valid(
142                          &fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
143                          4,
144                          fw_controller->internal_request_entries *
145                             scif_sas_internal_request_get_object_size(),
146                          SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
147                       );
148
149   if (is_mde_list_valid == FALSE)
150      return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
151
152   return SCI_SUCCESS;
153}
154
155
156/**
157 * @brief This method stops all the domains associated to this
158 *           controller.
159 *
160 * @param[in] fw_controller This parameter specifies the framework
161 *            controller object for whose remote devices are to be stopped.
162 *
163 * @return This method returns a value indicating if the operation succeeded.
164 * @retval SCI_SUCCESS This value indicates that all the devices are stopped.
165 * @retval SCI_FAILURE This value indicates certain failure during the process
166 *            of stopping remote devices.
167 */
168static
169SCI_STATUS scif_sas_controller_stop_domains(
170   SCIF_SAS_CONTROLLER_T * fw_controller
171)
172{
173   U8 index;
174   SCI_STATUS status = SCI_SUCCESS;
175   SCIF_SAS_DOMAIN_T * fw_domain;
176
177   SCIF_LOG_TRACE((
178      sci_base_object_get_logger(fw_controller),
179      SCIF_LOG_OBJECT_CONTROLLER,
180      "scif_sas_controller_stop_domains(0x%x) enter\n",
181      fw_controller
182   ));
183
184   for (index = 0; index < SCI_MAX_DOMAINS && status == SCI_SUCCESS; index++)
185   {
186      fw_domain = &fw_controller->domains[index];
187
188      //Change this domain to STOPPING state. All the remote devices will be
189      //stopped subsquentially.
190      if (fw_domain->parent.state_machine.current_state_id ==
191             SCI_BASE_DOMAIN_STATE_READY
192          || fw_domain->parent.state_machine.current_state_id ==
193             SCI_BASE_DOMAIN_STATE_DISCOVERING)
194      {
195         sci_base_state_machine_change_state(
196            &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
197         );
198      }
199   }
200
201   return status;
202}
203
204
205/**
206 * @brief This method continue to stop the controller after clear affiliation
207 *        is done.
208 *
209 * @param[in] fw_controller This parameter specifies the framework
210 *            controller object to be stopped.
211 *
212 * @return This method returns a value indicating if the operation succeeded.
213 * @retval SCI_SUCCESS This value indicates the controller_stop succeeds.
214 * @retval SCI_FAILURE This value indicates certain failure during the process
215 *            of stopping controller.
216 */
217SCI_STATUS scif_sas_controller_continue_to_stop(
218   SCIF_SAS_CONTROLLER_T * fw_controller
219)
220{
221   SCI_STATUS status;
222
223   SCIF_LOG_TRACE((
224      sci_base_object_get_logger(fw_controller),
225      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
226      "scif_sas_controller_continue_to_stop (0x%x).\n",
227      fw_controller
228   ));
229
230   //stop all the domains and their remote devices.
231   status = scif_sas_controller_stop_domains(fw_controller);
232
233   if (status == SCI_SUCCESS)
234   {
235      // Attempt to stop the core controller.
236      status = scic_controller_stop(fw_controller->core_object, 0);
237
238      if (status != SCI_SUCCESS)
239      {
240         SCIF_LOG_ERROR((
241            sci_base_object_get_logger(fw_controller),
242            SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
243            "Controller:0x%x Status:0x%x unable to stop controller.\n",
244            fw_controller, status
245         ));
246
247         sci_base_state_machine_change_state(
248            &fw_controller->parent.state_machine,
249            SCI_BASE_CONTROLLER_STATE_FAILED
250         );
251      }
252   }
253   else
254   {
255      SCIF_LOG_ERROR((
256         sci_base_object_get_logger(fw_controller),
257         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
258         "Controller:0x%x Status:0x%x unable to stop domains.\n",
259         fw_controller, status
260      ));
261
262      sci_base_state_machine_change_state(
263         &fw_controller->parent.state_machine,
264         SCI_BASE_CONTROLLER_STATE_FAILED
265      );
266   }
267
268   return status;
269}
270
271
272//******************************************************************************
273//* R E S E T   H A N D L E R S
274//******************************************************************************
275
276/**
277 * @brief This method provides RESET state specific handling for
278 *        when a user attempts to initialize a controller.  This is a legal
279 *        state in which to attempt an initialize call.
280 *
281 * @param[in]  controller This parameter specifies the controller object
282 *             on which the user is attempting to perform an initialize
283 *             operation.
284 *
285 * @return This method returns an indication of whether the initialize
286 *         operation succeeded.
287 * @retval SCI_SUCCESS This value when the initialization completes
288 *         successfully.
289 */
290static
291SCI_STATUS scif_sas_controller_reset_initialize_handler(
292   SCI_BASE_CONTROLLER_T    * controller
293)
294{
295   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
296   SCI_STATUS              status;
297   U32                     index;
298
299   SCIF_LOG_TRACE((
300      sci_base_object_get_logger(fw_controller),
301      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
302      "scif_sas_controller_reset_initialize_handler(0x%x) enter\n",
303      controller
304   ));
305
306   sci_base_state_machine_change_state(
307      &fw_controller->parent.state_machine,
308      SCI_BASE_CONTROLLER_STATE_INITIALIZING
309   );
310
311   scif_sas_controller_build_mdl(fw_controller);
312
313   // Perform any domain object initialization that is necessary.
314   for (index = 0; index < SCI_MAX_DOMAINS; index++)
315      scif_sas_domain_initialize(&fw_controller->domains[index]);
316
317   scif_cb_lock_associate(fw_controller, &fw_controller->hprq.lock);
318
319   // Attempt to initialize the core controller.
320   status = scic_controller_initialize(fw_controller->core_object);
321   if (status == SCI_SUCCESS)
322   {
323      sci_base_state_machine_change_state(
324         &fw_controller->parent.state_machine,
325         SCI_BASE_CONTROLLER_STATE_INITIALIZED
326      );
327   }
328
329   if (status != SCI_SUCCESS)
330   {
331      // Initialization failed, Release resources and do not change state
332      scif_sas_controller_release_resource(fw_controller);
333
334      SCIF_LOG_ERROR((
335         sci_base_object_get_logger(fw_controller),
336         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
337         "Controller:0x%x Status:0x%x unable to successfully initialize.\n",
338         fw_controller, status
339      ));
340   }
341
342   return status;
343}
344
345//******************************************************************************
346//* I N I T I A L I Z E D   H A N D L E R S
347//******************************************************************************
348
349/**
350 * @brief This method provides INITIALIZED state specific handling for
351 *        when a user attempts to start a controller.
352 *
353 * @param[in]  controller This parameter specifies the controller object
354 *             on which the user is attempting to perform a start
355 *             operation.
356 * @param[in]  timeout This parameter specifies the timeout value (in
357 *             milliseconds) to be utilized for this operation.
358 *
359 * @return This method returns an indication of whether the start operation
360 *         succeeded.
361 * @retval SCI_SUCCESS This value is returned when the start operation
362 *         begins successfully.
363 */
364static
365SCI_STATUS scif_sas_controller_initialized_start_handler(
366   SCI_BASE_CONTROLLER_T * controller,
367   U32                     timeout
368)
369{
370   SCI_STATUS              status        = SCI_SUCCESS;
371   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
372   U16                     index         = 0;
373
374   SCI_PHYSICAL_MEMORY_DESCRIPTOR_T internal_reqeust_mde =
375      fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO];
376
377   void * internal_request_virtual_address =  internal_reqeust_mde.virtual_address;
378   POINTER_UINT address = (POINTER_UINT)internal_request_virtual_address;
379
380   SCIF_LOG_TRACE((
381      sci_base_object_get_logger(fw_controller),
382      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
383      "scif_sas_controller_initialized_start_handler(0x%x, 0x%x) enter\n",
384      controller, timeout
385   ));
386
387   sci_base_state_machine_change_state(
388      &fw_controller->parent.state_machine,
389      SCI_BASE_CONTROLLER_STATE_STARTING
390   );
391
392   status = scif_sas_controller_validate_mdl(fw_controller);
393
394   // initialization work for internal request path. It must be done before
395   // starting domain.
396   if (status == SCI_SUCCESS)
397   {
398      // fill in the sci_pool for internal requests.
399      sci_pool_initialize(fw_controller->internal_request_memory_pool);
400
401      for (index = 0; index < fw_controller->internal_request_entries; index++)
402      {
403         sci_pool_put(fw_controller->internal_request_memory_pool, address);
404
405         address += scif_sas_internal_request_get_object_size();
406      }
407
408      // Using DPC for starting internal IOs, if yes, we need to intialize
409      // DPC here.
410      scif_cb_start_internal_io_task_create(fw_controller);
411   }
412
413   if (status == SCI_SUCCESS)
414   {
415      // Kick-start the domain state machines and, by association, the
416      // core port's.
417
418      // This will ensure we get valid port objects supplied with link up
419      // messages.
420      for (index = 0;
421           (index < SCI_MAX_DOMAINS) && (status == SCI_SUCCESS);
422           index++)
423      {
424         sci_base_state_machine_change_state(
425            &fw_controller->domains[index].parent.state_machine,
426            SCI_BASE_DOMAIN_STATE_STARTING
427         );
428         status = fw_controller->domains[index].operation.status;
429      }
430   }
431
432   // Validate that all the domain state machines began successfully.
433   if (status != SCI_SUCCESS)
434   {
435      SCIF_LOG_ERROR((
436         sci_base_object_get_logger(fw_controller),
437         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
438         "Controller:0x%x Domain:0x%x Status:0x%x unable to start\n",
439         fw_controller, index, status
440      ));
441
442      return status;
443   }
444
445   // Attempt to start the core controller.
446   status = scic_controller_start(fw_controller->core_object, timeout);
447   if (status != SCI_SUCCESS)
448   {
449      SCIF_LOG_ERROR((
450         sci_base_object_get_logger(fw_controller),
451         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
452         "Controller:0x%x Status:0x%x unable to start controller.\n",
453         fw_controller, status
454      ));
455
456      sci_base_state_machine_change_state(
457         &fw_controller->parent.state_machine,
458         SCI_BASE_CONTROLLER_STATE_FAILED
459      );
460   }
461
462   return status;
463}
464
465//******************************************************************************
466//* R E A D Y   H A N D L E R S
467//******************************************************************************
468
469/**
470 * @brief This method provides READY state specific handling for
471 *        when a user attempts to stop a controller.
472 *
473 * @param[in]  controller This parameter specifies the controller object
474 *             on which the user is attempting to perform a stop
475 *             operation.
476 * @param[in]  timeout This parameter specifies the timeout value (in
477 *             milliseconds) to be utilized for this operation.
478 *
479 * @return This method returns an indication of whether the stop operation
480 *         succeeded.
481 * @retval SCI_SUCCESS This value is returned when the stop operation
482 *         begins successfully.
483 */
484static
485SCI_STATUS scif_sas_controller_ready_stop_handler(
486   SCI_BASE_CONTROLLER_T * controller,
487   U32                     timeout
488)
489{
490   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
491
492   SCIF_LOG_TRACE((
493      sci_base_object_get_logger(fw_controller),
494      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
495      "scif_sas_controller_ready_stop_handler(0x%x, 0x%x) enter\n",
496      controller, timeout
497   ));
498
499   sci_base_state_machine_change_state(
500      &fw_controller->parent.state_machine,
501      SCI_BASE_CONTROLLER_STATE_STOPPING
502   );
503
504   if (fw_controller->user_parameters.sas.clear_affiliation_during_controller_stop)
505   {
506      fw_controller->current_domain_to_clear_affiliation = 0;
507
508      //clear affiliation first. After the last domain finishes clearing
509      //affiliation, it will call back to controller to continue to stop.
510      scif_sas_controller_clear_affiliation(fw_controller);
511   }
512   else
513      scif_sas_controller_continue_to_stop(fw_controller);
514
515   //Must return SUCCESS at this point.
516   return SCI_SUCCESS;
517}
518
519/**
520 * @brief This method provides READY state specific handling for
521 *        when a user attempts to reset a controller.
522 *
523 * @param[in]  controller This parameter specifies the controller object
524 *             on which the user is attempting to perform a reset
525 *             operation.
526 *
527 * @return This method returns an indication of whether the reset operation
528 *         succeeded.
529 * @retval SCI_SUCCESS This value is returned when the reset operation
530 *         completes successfully.
531 */
532static
533SCI_STATUS scif_sas_controller_ready_reset_handler(
534   SCI_BASE_CONTROLLER_T    * controller
535)
536{
537   return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
538}
539
540/**
541 * @brief This method provides READY state specific handling for
542 *        when a user attempts to start an IO request.
543 *
544 * @param[in]  controller This parameter specifies the controller object
545 *             on which the user is attempting to perform a start IO
546 *             operation.
547 * @param[in]  remote_device This parameter specifies the remote deivce
548 *             object on which the user is attempting to perform a start IO
549 *             operation.
550 * @param[in]  io_request This parameter specifies the IO request to be
551 *             started.
552 * @param[in]  io_tag This parameter specifies the optional allocated
553 *             IO tag.  Please reference scif_controller_start_io() for
554 *             more information.
555 *
556 * @return This method returns an indication of whether the start IO
557 *         operation succeeded.
558 * @retval SCI_SUCCESS This value is returned when the start IO operation
559 *         begins successfully.
560 */
561static
562SCI_STATUS scif_sas_controller_ready_start_io_handler(
563   SCI_BASE_CONTROLLER_T    * controller,
564   SCI_BASE_REMOTE_DEVICE_T * remote_device,
565   SCI_BASE_REQUEST_T       * io_request,
566   U16                        io_tag
567)
568{
569   SCI_STATUS                status;
570   SCIF_SAS_IO_REQUEST_T    *fw_io         = (SCIF_SAS_IO_REQUEST_T*)io_request;
571   SCIF_SAS_CONTROLLER_T    *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
572   SCIF_SAS_REMOTE_DEVICE_T *fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
573                                             remote_device;
574
575   SCIF_LOG_TRACE((
576      sci_base_object_get_logger(fw_controller),
577      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
578      "scif_sas_controller_ready_start_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
579      controller, remote_device, io_request, io_tag
580   ));
581
582   status = fw_device->domain->state_handlers->start_io_handler(
583               &fw_device->domain->parent, remote_device, io_request
584            );
585
586   // Check to see that the other objects in the framework allowed
587   // this IO to be started.
588   if (status == SCI_SUCCESS)
589   {
590      // Ask the core to start processing for this IO request.
591      status = (SCI_STATUS)scic_controller_start_io(
592                  fw_controller->core_object,
593                  fw_device->core_object,
594                  fw_io->parent.core_object,
595                  io_tag
596               );
597
598      if (status == SCI_SUCCESS)
599      {
600         // We were able to start the core request. As a result,
601         // commit to starting the request for the framework by changing
602         // the state of the IO request.
603         sci_base_state_machine_change_state(
604            &io_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
605         );
606      }
607      else
608      {
609         // We were unable to start the core IO request. As a result,
610         // back out the start operation for the framework.  It's easier to
611         // back out the framework start operation then to backout the core
612         // start IO operation.
613         fw_device->domain->state_handlers->complete_io_handler(
614            &fw_device->domain->parent, remote_device, io_request
615         );
616
617         // Invoke the IO completion handler.  For most IOs, this does nothing
618         // since we are still in the constructed state.  For NCQ, this will
619         // the return of the NCQ tag back to the remote device free pool.
620         fw_io->parent.state_handlers->complete_handler(io_request);
621
622         SCIF_LOG_WARNING((
623            sci_base_object_get_logger(fw_controller),
624            SCIF_LOG_OBJECT_CONTROLLER,
625            "Controller:0x%x IORequest:0x%x Status:0x%x core IO start failed\n",
626            fw_controller, fw_io, status
627         ));
628      }
629   }
630   else
631   {
632      SCIF_LOG_WARNING((
633         sci_base_object_get_logger(fw_controller),
634         SCIF_LOG_OBJECT_CONTROLLER,
635         "Controller:0x%x IORequest:0x%x Status:0x%x IO start failed\n",
636         fw_controller, fw_io, status
637      ));
638   }
639
640   return status;
641}
642
643/**
644 * @brief This method provides READY state specific handling for
645 *        when a user attempts to complete an IO request.
646 *
647 * @param[in]  controller This parameter specifies the controller object
648 *             on which the user is attempting to perform a complete IO
649 *             operation.
650 * @param[in]  remote_device This parameter specifies the remote deivce
651 *             object on which the user is attempting to perform a start IO
652 *             operation.
653 * @param[in]  io_request This parameter specifies the IO request to be
654 *             started.
655 *
656 * @return This method returns an indication of whether the complete IO
657 *         operation succeeded.
658 * @retval SCI_SUCCESS This value is returned when the complete IO operation
659 *         begins successfully.
660 */
661static
662SCI_STATUS scif_sas_controller_ready_complete_io_handler(
663   SCI_BASE_CONTROLLER_T    * controller,
664   SCI_BASE_REMOTE_DEVICE_T * remote_device,
665   SCI_BASE_REQUEST_T       * io_request
666)
667{
668   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
669                                              controller;
670   SCIF_SAS_REMOTE_DEVICE_T * fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
671                                              remote_device;
672   SCIF_SAS_IO_REQUEST_T    * fw_io         = (SCIF_SAS_IO_REQUEST_T*)
673                                              io_request;
674   SCI_STATUS                 status;
675   SCI_STATUS                 core_status;
676
677   SCIF_LOG_TRACE((
678      sci_base_object_get_logger(fw_controller),
679      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
680      "scif_sas_controller_ready_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
681      controller, remote_device, io_request
682   ));
683
684   fw_io->parent.state_handlers->destruct_handler(&fw_io->parent.parent);
685   status = fw_device->domain->state_handlers->complete_io_handler(
686               &fw_device->domain->parent, remote_device, io_request
687            );
688
689   // Ask the core to finish processing for this IO request.
690   core_status = scic_controller_complete_io(
691                    fw_controller->core_object,
692                    fw_device->core_object,
693                    fw_io->parent.core_object
694                 );
695
696   if (status == SCI_SUCCESS)
697      status = core_status;
698
699   if (status != SCI_SUCCESS)
700   {
701      SCIF_LOG_WARNING((
702         sci_base_object_get_logger(fw_controller),
703         SCIF_LOG_OBJECT_CONTROLLER,
704         "Controller:0x%x IORequest:0x%x Status:0x%x CoreStatus:0x%x "
705         "failure to complete IO\n",
706         fw_controller, fw_io, status, core_status
707      ));
708   }
709
710   return status;
711}
712
713
714/**
715 * @brief This method provides READY state specific handling for
716 *        when a user attempts to complete a high priority IO request.
717 *
718 * @param[in]  controller This parameter specifies the controller object
719 *             on which the user is attempting to perform a complete IO
720 *             operation.
721 * @param[in]  remote_device This parameter specifies the remote deivce
722 *             object on which the user is attempting to perform a start IO
723 *             operation.
724 * @param[in]  io_request This parameter specifies the IO request to be
725 *             started.
726 *
727 * @return This method returns an indication of whether the complete IO
728 *         operation succeeded.
729 * @retval SCI_SUCCESS This value is returned when the complete IO operation
730 *         begins successfully.
731 */
732static
733SCI_STATUS scif_sas_controller_ready_complete_high_priority_io_handler(
734   SCI_BASE_CONTROLLER_T    * controller,
735   SCI_BASE_REMOTE_DEVICE_T * remote_device,
736   SCI_BASE_REQUEST_T       * io_request
737)
738{
739   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
740                                              controller;
741   SCIF_SAS_REMOTE_DEVICE_T * fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
742                                              remote_device;
743   SCIF_SAS_IO_REQUEST_T    * fw_io         = (SCIF_SAS_IO_REQUEST_T*)
744                                              io_request;
745   SCI_IO_STATUS core_completion_status =
746                    scic_request_get_sci_status(fw_io->parent.core_object);
747
748   U8 response_data[SCIF_SAS_RESPONSE_DATA_LENGTH];
749
750   SCI_STATUS                 status;
751   SCI_STATUS                 core_status;
752
753   SCIF_LOG_TRACE((
754      sci_base_object_get_logger(fw_controller),
755      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
756      "scif_sas_controller_ready_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x) enter\n",
757      controller, remote_device, io_request
758   ));
759
760   // In high priority path, we ask the core to finish IO request before framework.
761
762   // retrieve and save io response from core now.
763   memcpy(response_data,
764          scic_io_request_get_response_iu_address(fw_io->parent.core_object),
765          SCIF_SAS_RESPONSE_DATA_LENGTH
766         );
767
768   core_status = scic_controller_complete_io(
769                    fw_controller->core_object,
770                    fw_device->core_object,
771                    fw_io->parent.core_object
772                 );
773
774   fw_io->parent.state_handlers->destruct_handler(&fw_io->parent.parent);
775   status = fw_device->domain->state_handlers->complete_high_priority_io_handler(
776               &fw_device->domain->parent,
777               remote_device,
778               io_request,
779               (void *)response_data,
780               core_completion_status
781            );
782
783   if (status == SCI_SUCCESS)
784      status = core_status;
785
786   if (status == SCI_SUCCESS)
787   {
788       //issue DPC to start next internal io in high prioriy queue.
789      if( !sci_pool_empty(fw_controller->hprq.pool) )
790         scif_cb_start_internal_io_task_schedule(
791            fw_controller,
792            scif_sas_controller_start_high_priority_io,
793            fw_controller
794         );
795   }
796   else
797   {
798      SCIF_LOG_WARNING((
799         sci_base_object_get_logger(fw_controller),
800         SCIF_LOG_OBJECT_CONTROLLER,
801         "Controller:0x%x IORequest:0x%x Status:0x%x CoreStatus:0x%x "
802         "failure to complete IO\n",
803         fw_controller, fw_io, status, core_status
804      ));
805   }
806
807   return status;
808}
809
810/**
811 * @brief This method provides READY state specific handling for
812 *        when a user attempts to continue an IO request.
813 *
814 * @param[in]  controller This parameter specifies the controller object
815 *             on which the user is attempting to perform a continue IO
816 *             operation.
817 * @param[in]  remote_device This parameter specifies the remote deivce
818 *             object on which the user is attempting to perform a start IO
819 *             operation.
820 * @param[in]  io_request This parameter specifies the IO request to be
821 *             started.
822 *
823 * @return This method returns an indication of whether the continue IO
824 *         operation succeeded.
825 * @retval SCI_SUCCESS This value is returned when the continue IO operation
826 *         begins successfully.
827 */
828static
829SCI_STATUS scif_sas_controller_ready_continue_io_handler(
830   SCI_BASE_CONTROLLER_T    * controller,
831   SCI_BASE_REMOTE_DEVICE_T * remote_device,
832   SCI_BASE_REQUEST_T       * io_request
833)
834{
835   SCIF_LOG_TRACE((
836      sci_base_object_get_logger(controller),
837      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
838      "scif_sas_controller_ready_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
839      controller, remote_device, io_request
840   ));
841
842   /// @todo Function unimplemented.  fix return code handling.
843   return SCI_FAILURE;
844}
845
846/**
847 * @brief This method provides READY state specific handling for
848 *        when a user attempts to start a task request.
849 *
850 * @param[in]  controller This parameter specifies the controller object
851 *             on which the user is attempting to perform a start task
852 *             operation.
853 * @param[in]  remote_device This parameter specifies the remote deivce
854 *             object on which the user is attempting to perform a start
855 *             task operation.
856 * @param[in]  task_request This parameter specifies the task management
857 *             request to be started.
858 * @param[in]  io_tag This parameter specifies the optional allocated
859 *             IO tag.  Please reference scif_controller_start_task() for
860 *             more information.
861 *
862 * @return This method returns an indication of whether the start task
863 *         operation succeeded.
864 * @retval SCI_SUCCESS This value is returned when the start task operation
865 *         begins successfully.
866 */
867static
868SCI_STATUS scif_sas_controller_ready_start_task_handler(
869   SCI_BASE_CONTROLLER_T    * controller,
870   SCI_BASE_REMOTE_DEVICE_T * remote_device,
871   SCI_BASE_REQUEST_T       * task_request,
872   U16                        io_tag
873)
874{
875   SCIF_SAS_CONTROLLER_T    * fw_controller = (SCIF_SAS_CONTROLLER_T*)
876                                              controller;
877   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
878                                          remote_device;
879   SCIF_SAS_TASK_REQUEST_T  * fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
880   SCI_STATUS                 status;
881
882   SCIF_LOG_TRACE((
883      sci_base_object_get_logger(fw_controller),
884      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
885      "scif_sas_controller_ready_start_task_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
886      controller, remote_device, task_request, io_tag
887   ));
888
889   status = fw_device->domain->state_handlers->start_task_handler(
890               &fw_device->domain->parent, remote_device, task_request
891            );
892
893   if (status == SCI_SUCCESS)
894   {
895      if (scif_sas_task_request_get_function(fw_task)
896             == SCI_SAS_HARD_RESET)
897      {
898         // Go off to special target reset path. Don't start task to core.
899         scif_sas_remote_device_target_reset(
900            fw_device,
901            (SCIF_SAS_REQUEST_T *)fw_task
902         );
903
904         return SCI_SUCCESS;
905      }
906
907      // Ask the core to start processing for this task request.
908      status = (SCI_STATUS)scic_controller_start_task(
909                  fw_controller->core_object,
910                  fw_device->core_object,
911                  fw_task->parent.core_object,
912                  io_tag
913               );
914
915      if (status == SCI_SUCCESS)
916      {
917         // We were able to start the core request. As a result,
918         // commit to starting the request for the framework by changing
919         // the state of the task request.
920         fw_task->parent.state_handlers->start_handler(&fw_task->parent.parent);
921      }
922      else
923      {
924         // We were unable to start the core task request. As a result,
925         // back out the start operation for the framework.  It's easier to
926         // back out the framework start operation then to backout the core
927         // start task operation.
928         fw_device->domain->state_handlers->complete_task_handler(
929            &fw_device->domain->parent, remote_device, task_request
930         );
931
932         if (status == SCI_SUCCESS)
933         {
934            SCIF_LOG_WARNING((
935               sci_base_object_get_logger(fw_controller),
936               SCIF_LOG_OBJECT_CONTROLLER,
937               "Controller:0x%x TaskRequest:0x%x Status:0x%x core start failed\n",
938               fw_controller, fw_task, status
939            ));
940         }
941      }
942   }
943   else
944   {
945      SCIF_LOG_WARNING((
946         sci_base_object_get_logger(fw_controller),
947         SCIF_LOG_OBJECT_CONTROLLER,
948         "Controller:0x%x TaskRequest:0x%x Status:0x%x Task start failed\n",
949         fw_controller, fw_task, status
950      ));
951   }
952
953   return status;
954}
955
956/**
957 * @brief This method provides READY state specific handling for
958 *        when a user attempts to complete a task request.
959 *
960 * @param[in]  controller This parameter specifies the controller object
961 *             on which the user is attempting to perform a complete task
962 *             operation.
963 * @param[in]  remote_device This parameter specifies the remote deivce
964 *             object on which the user is attempting to perform a start
965 *             task operation.
966 * @param[in]  task_request This parameter specifies the task management
967 *             request to be started.
968 *
969 * @return This method returns an indication of whether the complete task
970 *         operation succeeded.
971 * @retval SCI_SUCCESS This value is returned when the complete task operation
972 *         begins successfully.
973 */
974static
975SCI_STATUS scif_sas_controller_ready_complete_task_handler(
976   SCI_BASE_CONTROLLER_T    * controller,
977   SCI_BASE_REMOTE_DEVICE_T * remote_device,
978   SCI_BASE_REQUEST_T       * task_request
979)
980{
981   SCIF_SAS_CONTROLLER_T    *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
982   SCIF_SAS_REMOTE_DEVICE_T *fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)remote_device;
983   SCIF_SAS_TASK_REQUEST_T  *fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
984   SCI_STATUS                status;
985   SCI_STATUS                core_status;
986
987   SCIF_LOG_TRACE((
988      sci_base_object_get_logger(fw_controller),
989      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
990      "scif_sas_controller_ready_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
991      controller, remote_device, task_request
992   ));
993
994   status = fw_device->domain->state_handlers->complete_task_handler(
995               &fw_device->domain->parent, remote_device, task_request
996            );
997
998   if (scif_sas_task_request_get_function(fw_task)
999          == SCI_SAS_HARD_RESET)
1000   {
1001      //No more things to do in the core, since this task is for Target Reset.
1002      return status;
1003   }
1004
1005   fw_task->parent.state_handlers->destruct_handler(&fw_task->parent.parent);
1006
1007   // Ask the core to finish processing for this task request.
1008   core_status = scic_controller_complete_task(
1009                    fw_controller->core_object,
1010                    fw_device->core_object,
1011                    fw_task->parent.core_object
1012                 );
1013
1014   if (status == SCI_SUCCESS)
1015      status = core_status;
1016
1017   if (status != SCI_SUCCESS)
1018   {
1019      SCIF_LOG_WARNING((
1020         sci_base_object_get_logger(fw_controller),
1021         SCIF_LOG_OBJECT_CONTROLLER,
1022         "Controller:0x%x TaskRequest:0x%x Status:0x%x CoreStatus:0x%x "
1023         "failed to complete\n",
1024         fw_controller, fw_task, status, core_status
1025      ));
1026   }
1027
1028   return status;
1029}
1030
1031
1032
1033/**
1034 * @brief This method provides common handling for several states
1035 *        when a user attempts to start an internal request.
1036 *
1037 * @param[in]  controller This parameter specifies the controller object
1038 *             on which the user is attempting to perform a start IO
1039 *             operation.
1040 * @param[in]  remote_device This parameter specifies the remote deivce
1041 *             object on which the user is attempting to perform a start IO
1042 *             operation.
1043 * @param[in]  io_request This parameter specifies the IO request to be
1044 *             started.
1045 * @param[in]  io_tag This parameter specifies the optional allocated
1046 *             IO tag.  Please reference scif_controller_start_io() for
1047 *             more information.
1048 *
1049 * @return This method returns an indication of whether the start IO
1050 *         operation succeeded.
1051 * @retval SCI_SUCCESS This value is returned when the start IO operation
1052 *         begins successfully.
1053 */
1054static
1055SCI_STATUS scif_sas_controller_common_start_high_priority_io_handler(
1056   SCI_BASE_CONTROLLER_T    * controller,
1057   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1058   SCI_BASE_REQUEST_T       * io_request,
1059   U16                        io_tag
1060)
1061{
1062   SCI_STATUS                status;
1063   SCIF_SAS_IO_REQUEST_T    *fw_io         = (SCIF_SAS_IO_REQUEST_T*)io_request;
1064   SCIF_SAS_CONTROLLER_T    *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
1065   SCIF_SAS_REMOTE_DEVICE_T *fw_device     = (SCIF_SAS_REMOTE_DEVICE_T*)
1066                                             remote_device;
1067
1068   status = fw_device->domain->state_handlers->start_high_priority_io_handler(
1069               &fw_device->domain->parent, remote_device, io_request
1070            );
1071
1072   // Check to see that the other objects in the framework allowed
1073   // this IO to be started.
1074   if (status == SCI_SUCCESS)
1075   {
1076      // Ask the core to start processing for this IO request.
1077      status = (SCI_STATUS)scic_controller_start_io(
1078                  fw_controller->core_object,
1079                  fw_device->core_object,
1080                  fw_io->parent.core_object,
1081                  io_tag
1082               );
1083
1084      if (status == SCI_SUCCESS)
1085      {
1086         // We were able to start the core request. As a result,
1087         // commit to starting the request for the framework by changing
1088         // the state of the IO request.
1089         sci_base_state_machine_change_state(
1090            &io_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
1091         );
1092      }
1093      else
1094      {
1095         // We were unable to start the core IO request. As a result,
1096         // back out the start operation for the framework.  It's easier to
1097         // back out the framework start operation then to backout the core
1098         // start IO operation.
1099         fw_device->domain->state_handlers->complete_io_handler(
1100            &fw_device->domain->parent, remote_device, io_request
1101         );
1102
1103         // Invoke the IO completion handler.  For most IOs, this does nothing
1104         // since we are still in the constructed state.  For NCQ, this will
1105         // the return of the NCQ tag back to the remote device free pool.
1106         fw_io->parent.state_handlers->complete_handler(io_request);
1107
1108         SCIF_LOG_WARNING((
1109            sci_base_object_get_logger(fw_controller),
1110            SCIF_LOG_OBJECT_CONTROLLER,
1111            "Controller:0x%x IORequest:0x%x Status:0x%x core IO start failed\n",
1112            fw_controller, fw_io, status
1113         ));
1114      }
1115   }
1116   else
1117   {
1118      SCIF_LOG_WARNING((
1119         sci_base_object_get_logger(fw_controller),
1120         SCIF_LOG_OBJECT_CONTROLLER,
1121         "Controller:0x%x IORequest:0x%x Status:0x%x IO start failed\n",
1122         fw_controller, fw_io, status
1123      ));
1124
1125      // Invoke the IO completion handler.  For most IOs, this does nothing
1126      // since we are still in the constructed state.  For NCQ, this will
1127      // the return of the NCQ tag back to the remote device free pool.
1128      fw_io->parent.state_handlers->complete_handler(io_request);
1129
1130   }
1131
1132   if (fw_io->parent.is_internal && status != SCI_SUCCESS )
1133   {
1134      SCIC_TRANSPORT_PROTOCOL protocol =
1135         scic_io_request_get_protocol(fw_io->parent.core_object);
1136
1137      U8 retry_count = fw_io->retry_count;
1138
1139      scif_sas_internal_io_request_destruct(
1140         fw_device->domain->controller,
1141         (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io
1142      );
1143
1144      if ( protocol == SCIC_SMP_PROTOCOL )
1145      {
1146         if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL)
1147         {
1148            //destroy the smp_activity_timer
1149            scif_cb_timer_destroy (
1150               fw_controller,
1151               fw_device->protocol_device.smp_device.smp_activity_timer
1152            );
1153
1154            fw_device->protocol_device.smp_device.smp_activity_timer = NULL;
1155         }
1156
1157         //we should retry for finite times
1158         if ( retry_count < SCIF_SAS_IO_RETRY_LIMIT)
1159         {
1160         //An internal smp request failed being started, most likely due to remote device
1161         //is not in ready state, for example, UPDATING_PORT_WIDTH state. In this case,
1162         //we should retry the IO.
1163         scif_sas_smp_remote_device_retry_internal_io(
1164            (SCIF_SAS_REMOTE_DEVICE_T *)remote_device,
1165            retry_count,
1166            SMP_REQUEST_RETRY_WAIT_DURATION
1167         );
1168      }
1169   }
1170   }
1171
1172   return status;
1173}
1174
1175
1176/**
1177 * @brief This method provides READY state specific handling for
1178 *        when a user attempts to start an internal request. If the high
1179 *        priority IO is also internal, this method will schedule its timer.
1180 *
1181 * @param[in]  controller This parameter specifies the controller object
1182 *             on which the user is attempting to perform a start IO
1183 *             operation.
1184 * @param[in]  remote_device This parameter specifies the remote deivce
1185 *             object on which the user is attempting to perform a start IO
1186 *             operation.
1187 * @param[in]  io_request This parameter specifies the IO request to be
1188 *             started.
1189 * @param[in]  io_tag This parameter specifies the optional allocated
1190 *             IO tag.  Please reference scif_controller_start_io() for
1191 *             more information.
1192 *
1193 * @return This method returns an indication of whether the start IO
1194 *         operation succeeded.
1195 * @retval SCI_SUCCESS This value is returned when the start IO operation
1196 *         begins successfully.
1197 */
1198static
1199SCI_STATUS scif_sas_controller_ready_start_high_priority_io_handler(
1200   SCI_BASE_CONTROLLER_T    * controller,
1201   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1202   SCI_BASE_REQUEST_T       * io_request,
1203   U16                        io_tag
1204)
1205{
1206   SCI_STATUS status;
1207   SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)io_request;
1208
1209   SCIF_LOG_TRACE((
1210      sci_base_object_get_logger(controller),
1211      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
1212      "scif_sas_controller_ready_start_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
1213      controller, remote_device, io_request, io_tag
1214   ));
1215
1216   status = scif_sas_controller_common_start_high_priority_io_handler(
1217               controller, remote_device, io_request, io_tag);
1218
1219   if (status == SCI_SUCCESS)
1220   {
1221      //External io could also be put in high priority queue. i.e. the
1222      //smp request for EA Target Reset.
1223      if (fw_io->parent.is_internal)
1224      {
1225         SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io =
1226            (SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io;
1227
1228         //start the timer for internal io
1229         scif_cb_timer_start(
1230            (SCI_CONTROLLER_HANDLE_T)controller,
1231             fw_internal_io->internal_io_timer,
1232             SCIF_SAS_INTERNAL_REQUEST_TIMEOUT
1233         );
1234      }
1235   }
1236   else
1237   {
1238      //If failed to start, most likely the device or domain is not in
1239      //correct state, and the IO has been cleaned up in controller's start
1240      //high priority IO handler. We should just continue to start the next
1241      //IO in the HP queue.
1242
1243      SCIF_LOG_TRACE((
1244         sci_base_object_get_logger(controller),
1245         SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
1246         "scif_controller_start_high_priority_io(0x%x, 0x%x), starting io failed\n",
1247         controller, fw_io
1248      ));
1249   }
1250
1251   return status;
1252}
1253
1254
1255//******************************************************************************
1256//* S T O P P I N G   H A N D L E R S
1257//******************************************************************************
1258/**
1259 * @brief This method provides STOPPING state specific handling for
1260 *        when a user attempts to start an internal request. Note that we don't
1261 *        start the timer for internal IO during controller stopping state.
1262 *
1263 * @param[in]  controller This parameter specifies the controller object
1264 *             on which the user is attempting to perform a start IO
1265 *             operation.
1266 * @param[in]  remote_device This parameter specifies the remote deivce
1267 *             object on which the user is attempting to perform a start IO
1268 *             operation.
1269 * @param[in]  io_request This parameter specifies the IO request to be
1270 *             started.
1271 * @param[in]  io_tag This parameter specifies the optional allocated
1272 *             IO tag.  Please reference scif_controller_start_io() for
1273 *             more information.
1274 *
1275 * @return This method returns an indication of whether the start IO
1276 *         operation succeeded.
1277 * @retval SCI_SUCCESS This value is returned when the start IO operation
1278 *         begins successfully.
1279 */
1280static
1281SCI_STATUS scif_sas_controller_stopping_start_high_priority_io_handler(
1282   SCI_BASE_CONTROLLER_T    * controller,
1283   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1284   SCI_BASE_REQUEST_T       * io_request,
1285   U16                        io_tag
1286)
1287{
1288   SCIF_LOG_TRACE((
1289      sci_base_object_get_logger(controller),
1290      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
1291      "scif_sas_controller_stopping_start_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
1292      controller, remote_device, io_request, io_tag
1293   ));
1294
1295   return scif_sas_controller_common_start_high_priority_io_handler(
1296             controller, remote_device, io_request, io_tag);
1297}
1298
1299
1300//******************************************************************************
1301//* S T O P P E D   H A N D L E R S
1302//******************************************************************************
1303
1304/**
1305 * @brief This method provides STOPPED state specific handling for
1306 *        when a user attempts to reset a controller.
1307 *
1308 * @param[in]  controller This parameter specifies the controller object
1309 *             on which the user is attempting to perform a reset
1310 *             operation.
1311 *
1312 * @return This method returns an indication of whether the reset operation
1313 *         succeeded.
1314 * @retval SCI_SUCCESS This value is returned when the reset operation
1315 *         completes successfully.
1316 */
1317static
1318SCI_STATUS scif_sas_controller_stopped_reset_handler(
1319   SCI_BASE_CONTROLLER_T    * controller
1320)
1321{
1322   return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
1323}
1324
1325
1326//******************************************************************************
1327//* F A I L E D   H A N D L E R S
1328//******************************************************************************
1329
1330/**
1331 * @brief This method provides FAILED state specific handling for
1332 *        when a user attempts to reset a controller.
1333 *
1334 * @param[in]  controller This parameter specifies the controller object
1335 *             on which the user is attempting to perform a reset
1336 *             operation.
1337 *
1338 * @return This method returns an indication of whether the reset operation
1339 *         succeeded.
1340 * @retval SCI_SUCCESS This value is returned when the reset operation
1341 *         completes successfully.
1342 */
1343static
1344SCI_STATUS scif_sas_controller_failed_reset_handler(
1345   SCI_BASE_CONTROLLER_T * controller
1346)
1347{
1348   return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
1349}
1350
1351//******************************************************************************
1352//* D E F A U L T   H A N D L E R S
1353//******************************************************************************
1354
1355/**
1356 * @brief This method provides default handling (i.e. returns an error)
1357 *        when a user attempts to start a controller and a start operation
1358 *        is not allowed.
1359 *
1360 * @param[in]  controller This parameter specifies the controller object
1361 *             on which the user is attempting to perform a start operation.
1362 * @param[in]  timeout This parameter specifies the timeout value (in
1363 *             milliseconds) to be utilized for this operation.
1364 *
1365 * @return This method returns an indication that start operations are not
1366 *         allowed.
1367 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1368 */
1369static
1370SCI_STATUS scif_sas_controller_default_start_handler(
1371   SCI_BASE_CONTROLLER_T * controller,
1372   U32                     timeout
1373)
1374{
1375   SCIF_LOG_WARNING((
1376      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1377      SCIF_LOG_OBJECT_CONTROLLER,
1378      "Controller:0x%x State:0x%x invalid state to start controller.\n",
1379      controller,
1380      sci_base_state_machine_get_state(
1381         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1382   ));
1383
1384   return SCI_FAILURE_INVALID_STATE;
1385}
1386
1387/**
1388 * @brief This method provides default handling (i.e. returns an error)
1389 *        when a user attempts to stop a controller and a stop operation
1390 *        is not allowed.
1391 *
1392 * @param[in]  controller This parameter specifies the controller object
1393 *             on which the user is attempting to perform a stop operation.
1394 * @param[in]  timeout This parameter specifies the timeout value (in
1395 *             milliseconds) to be utilized for this operation.
1396 *
1397 * @return This method returns an indication that stop operations are not
1398 *         allowed.
1399 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1400 */
1401static
1402SCI_STATUS scif_sas_controller_default_stop_handler(
1403   SCI_BASE_CONTROLLER_T * controller,
1404   U32                     timeout
1405)
1406{
1407   SCIF_LOG_WARNING((
1408      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1409      SCIF_LOG_OBJECT_CONTROLLER,
1410      "Controller:0x%x State:0x%x invalid state to stop controller.\n",
1411      controller,
1412      sci_base_state_machine_get_state(
1413         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1414   ));
1415
1416   return SCI_FAILURE_INVALID_STATE;
1417}
1418
1419/**
1420 * @brief This method provides default handling (i.e. returns an error)
1421 *        when a user attempts to reset a controller and a reset operation
1422 *        is not allowed.
1423 *
1424 * @param[in]  controller This parameter specifies the controller object
1425 *             on which the user is attempting to perform a reset operation.
1426 *
1427 * @return This method returns an indication that reset operations are not
1428 *         allowed.
1429 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1430 */
1431static
1432SCI_STATUS scif_sas_controller_default_reset_handler(
1433   SCI_BASE_CONTROLLER_T * controller
1434)
1435{
1436   SCIF_LOG_WARNING((
1437      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1438      SCIF_LOG_OBJECT_CONTROLLER,
1439      "Controller:0x%x State:0x%x invalid state to reset controller.\n",
1440      controller,
1441      sci_base_state_machine_get_state(
1442         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1443   ));
1444
1445   return SCI_FAILURE_INVALID_STATE;
1446}
1447
1448/**
1449 * @brief This method provides default handling (i.e. returns an error)
1450 *        when a user attempts to initialize a controller and an initialize
1451 *        operation is not allowed.
1452 *
1453 * @param[in]  controller This parameter specifies the controller object
1454 *             on which the user is attempting to perform an initialize
1455 *             operation.
1456 *
1457 * @return This method returns an indication that initialize operations
1458 *         are not allowed.
1459 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1460 */
1461static
1462SCI_STATUS scif_sas_controller_default_initialize_handler(
1463   SCI_BASE_CONTROLLER_T * controller
1464)
1465{
1466   SCIF_LOG_WARNING((
1467      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1468      SCIF_LOG_OBJECT_CONTROLLER,
1469      "Controller:0x%x State:0x%x invalid state to initialize controller.\n",
1470      controller,
1471      sci_base_state_machine_get_state(
1472         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1473   ));
1474
1475   return SCI_FAILURE_INVALID_STATE;
1476}
1477
1478/**
1479 * @brief This method provides default handling (i.e. returns an error)
1480 *        when a user attempts to start an IO on a controller and a start
1481 *        IO operation is not allowed.
1482 *
1483 * @param[in]  controller This parameter specifies the controller object
1484 *             on which the user is attempting to perform a start IO
1485 *             operation.
1486 * @param[in]  remote_device This parameter specifies the remote deivce
1487 *             object on which the user is attempting to perform a start IO
1488 *             operation.
1489 * @param[in]  io_request This parameter specifies the IO request to be
1490 *             started.
1491 * @param[in]  io_tag This parameter specifies the optional allocated
1492 *             IO tag.  Please reference scif_controller_start_io() for
1493 *             more information.
1494 *
1495 * @return This method returns an indication that start IO operations
1496 *         are not allowed.
1497 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1498 */
1499static
1500SCI_STATUS scif_sas_controller_default_start_io_handler(
1501   SCI_BASE_CONTROLLER_T    * controller,
1502   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1503   SCI_BASE_REQUEST_T       * io_request,
1504   U16                        io_tag
1505)
1506{
1507   SCIF_LOG_WARNING((
1508      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1509      SCIF_LOG_OBJECT_CONTROLLER,
1510      "Controller:0x%x State:0x%x invalid state to start IO.\n",
1511      controller,
1512      sci_base_state_machine_get_state(
1513         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1514   ));
1515
1516   return SCI_FAILURE_INVALID_STATE;
1517}
1518
1519/**
1520 * @brief This method provides default handling (i.e. returns an error)
1521 *        when a user attempts to complete an IO on a controller and a
1522 *        complete IO operation is not allowed.
1523 *
1524 * @param[in]  controller This parameter specifies the controller object
1525 *             on which the user is attempting to perform a complete IO
1526 *             operation.
1527 * @param[in]  remote_device This parameter specifies the remote deivce
1528 *             object on which the user is attempting to perform a start IO
1529 *             operation.
1530 * @param[in]  io_request This parameter specifies the IO request to be
1531 *             started.
1532 *
1533 * @return This method returns an indication that complete IO operations
1534 *         are not allowed.
1535 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1536 */
1537static
1538SCI_STATUS scif_sas_controller_default_complete_io_handler(
1539   SCI_BASE_CONTROLLER_T    * controller,
1540   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1541   SCI_BASE_REQUEST_T       * io_request
1542)
1543{
1544   SCIF_LOG_WARNING((
1545      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1546      SCIF_LOG_OBJECT_CONTROLLER,
1547      "Controller:0x%x State:0x%x invalid state to complete IO.\n",
1548      controller,
1549      sci_base_state_machine_get_state(
1550         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1551   ));
1552
1553   return SCI_FAILURE_INVALID_STATE;
1554}
1555
1556/**
1557 * @brief This method provides default handling (i.e. returns an error)
1558 *        when a user attempts to continue an IO on a controller and a
1559 *        continue IO operation is not allowed.
1560 *
1561 * @param[in]  controller This parameter specifies the controller object
1562 *             on which the user is attempting to perform a continue IO
1563 *             operation.
1564 * @param[in]  remote_device This parameter specifies the remote deivce
1565 *             object on which the user is attempting to perform a start IO
1566 *             operation.
1567 * @param[in]  io_request This parameter specifies the IO request to be
1568 *             started.
1569 *
1570 * @return This method returns an indication that continue IO operations
1571 *         are not allowed.
1572 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1573 */
1574static
1575SCI_STATUS scif_sas_controller_default_continue_io_handler(
1576   SCI_BASE_CONTROLLER_T    * controller,
1577   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1578   SCI_BASE_REQUEST_T       * io_request
1579)
1580{
1581   SCIF_LOG_WARNING((
1582      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1583      SCIF_LOG_OBJECT_CONTROLLER,
1584      "Controller:0x%x State:0x%x invalid state to continue IO.\n",
1585      controller,
1586      sci_base_state_machine_get_state(
1587         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1588   ));
1589
1590   return SCI_FAILURE_INVALID_STATE;
1591}
1592
1593/**
1594 * @brief This method provides default handling (i.e. returns an error)
1595 *        when a user attempts to start a task on a controller and a start
1596 *        task operation is not allowed.
1597 *
1598 * @param[in]  controller This parameter specifies the controller object
1599 *             on which the user is attempting to perform a start task
1600 *             operation.
1601 * @param[in]  remote_device This parameter specifies the remote deivce
1602 *             object on which the user is attempting to perform a start
1603 *             task operation.
1604 * @param[in]  task_request This parameter specifies the task management
1605 *             request to be started.
1606 * @param[in]  io_tag This parameter specifies the optional allocated
1607 *             IO tag.  Please reference scif_controller_start_task() for
1608 *             more information.
1609 *
1610 * @return This method returns an indication that start task operations
1611 *         are not allowed.
1612 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1613 */
1614static
1615SCI_STATUS scif_sas_controller_default_start_task_handler(
1616   SCI_BASE_CONTROLLER_T    * controller,
1617   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1618   SCI_BASE_REQUEST_T       * task_request,
1619   U16                        io_tag
1620)
1621{
1622   SCIF_LOG_WARNING((
1623      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1624      SCIF_LOG_OBJECT_CONTROLLER,
1625      "Controller:0x%x State:0x%x invalid state to start task mgmt.\n",
1626      controller,
1627      sci_base_state_machine_get_state(
1628         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1629   ));
1630
1631   return SCI_FAILURE_INVALID_STATE;
1632}
1633
1634/**
1635 * @brief This method provides default handling (i.e. returns an error)
1636 *        when a user attempts to complete a task on a controller and a
1637 *        complete task operation is not allowed.
1638 *
1639 * @param[in]  controller This parameter specifies the controller object
1640 *             on which the user is attempting to perform a complete task
1641 *             operation.
1642 * @param[in]  remote_device This parameter specifies the remote deivce
1643 *             object on which the user is attempting to perform a start
1644 *             task operation.
1645 * @param[in]  task_request This parameter specifies the task management
1646 *             request to be started.
1647 *
1648 * @return This method returns an indication that complete task operations
1649 *         are not allowed.
1650 * @retval SCI_FAILURE_INVALID_STATE This value is always returned.
1651 */
1652static
1653SCI_STATUS scif_sas_controller_default_complete_task_handler(
1654   SCI_BASE_CONTROLLER_T    * controller,
1655   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1656   SCI_BASE_REQUEST_T       * task_request
1657)
1658{
1659   SCIF_LOG_WARNING((
1660      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1661      SCIF_LOG_OBJECT_CONTROLLER,
1662      "Controller:0x%x State:0x%x invalid state to complete task mgmt.\n",
1663      controller,
1664      sci_base_state_machine_get_state(
1665         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1666   ));
1667
1668   return SCI_FAILURE_INVALID_STATE;
1669}
1670
1671static
1672SCI_STATUS scif_sas_controller_failed_state_start_io_handler(
1673   SCI_BASE_CONTROLLER_T    * controller,
1674   SCI_BASE_REMOTE_DEVICE_T * remote_device,
1675   SCI_BASE_REQUEST_T       * io_request,
1676   U16                        io_tag
1677)
1678{
1679   SCIF_LOG_WARNING((
1680      sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
1681      SCIF_LOG_OBJECT_CONTROLLER,
1682      "Controller:0x%x State:0x%x invalid state to start IO.\n",
1683      controller,
1684      sci_base_state_machine_get_state(
1685         &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
1686   ));
1687
1688   return SCI_FAILURE;
1689}
1690
1691#define scif_sas_controller_stopping_complete_io_handler   \
1692        scif_sas_controller_ready_complete_io_handler
1693#define scif_sas_controller_stopping_complete_task_handler \
1694        scif_sas_controller_ready_complete_task_handler
1695#define scif_sas_controller_default_start_high_priority_io_handler \
1696        scif_sas_controller_default_start_io_handler
1697#define scif_sas_controller_default_complete_high_priority_io_handler \
1698        scif_sas_controller_default_complete_io_handler
1699#define scif_sas_controller_stopping_complete_high_priority_io_handler \
1700        scif_sas_controller_ready_complete_high_priority_io_handler
1701
1702
1703SCI_BASE_CONTROLLER_STATE_HANDLER_T
1704   scif_sas_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
1705{
1706   // SCI_BASE_CONTROLLER_STATE_INITIAL
1707   {
1708      scif_sas_controller_default_start_handler,
1709      scif_sas_controller_default_stop_handler,
1710      scif_sas_controller_default_reset_handler,
1711      scif_sas_controller_default_initialize_handler,
1712      scif_sas_controller_default_start_io_handler,
1713      scif_sas_controller_default_start_high_priority_io_handler,
1714      scif_sas_controller_default_complete_io_handler,
1715      scif_sas_controller_default_complete_high_priority_io_handler,
1716      scif_sas_controller_default_continue_io_handler,
1717      scif_sas_controller_default_start_task_handler,
1718      scif_sas_controller_default_complete_task_handler
1719   },
1720   // SCI_BASE_CONTROLLER_STATE_RESET
1721   {
1722      scif_sas_controller_default_start_handler,
1723      scif_sas_controller_default_stop_handler,
1724      scif_sas_controller_default_reset_handler,
1725      scif_sas_controller_reset_initialize_handler,
1726      scif_sas_controller_default_start_io_handler,
1727      scif_sas_controller_default_start_high_priority_io_handler,
1728      scif_sas_controller_default_complete_io_handler,
1729      scif_sas_controller_default_complete_high_priority_io_handler,
1730      scif_sas_controller_default_continue_io_handler,
1731      scif_sas_controller_default_start_task_handler,
1732      scif_sas_controller_default_complete_task_handler
1733   },
1734   // SCI_BASE_CONTROLLER_STATE_INITIALIZING
1735   {
1736      scif_sas_controller_default_start_handler,
1737      scif_sas_controller_default_stop_handler,
1738      scif_sas_controller_default_reset_handler,
1739      scif_sas_controller_default_initialize_handler,
1740      scif_sas_controller_default_start_io_handler,
1741      scif_sas_controller_default_start_high_priority_io_handler,
1742      scif_sas_controller_default_complete_io_handler,
1743      scif_sas_controller_default_complete_high_priority_io_handler,
1744      scif_sas_controller_default_continue_io_handler,
1745      scif_sas_controller_default_start_task_handler,
1746      scif_sas_controller_default_complete_task_handler
1747   },
1748   // SCI_BASE_CONTROLLER_STATE_INITIALIZED
1749   {
1750      scif_sas_controller_initialized_start_handler,
1751      scif_sas_controller_default_stop_handler,
1752      scif_sas_controller_default_reset_handler,
1753      scif_sas_controller_default_initialize_handler,
1754      scif_sas_controller_default_start_io_handler,
1755      scif_sas_controller_default_start_high_priority_io_handler,
1756      scif_sas_controller_default_complete_io_handler,
1757      scif_sas_controller_default_complete_high_priority_io_handler,
1758      scif_sas_controller_default_continue_io_handler,
1759      scif_sas_controller_default_start_task_handler,
1760      scif_sas_controller_default_complete_task_handler
1761   },
1762   // SCI_BASE_CONTROLLER_STATE_STARTING
1763   {
1764      scif_sas_controller_default_start_handler,
1765      scif_sas_controller_default_stop_handler,
1766      scif_sas_controller_default_reset_handler,
1767      scif_sas_controller_default_initialize_handler,
1768      scif_sas_controller_default_start_io_handler,
1769      scif_sas_controller_default_start_high_priority_io_handler,
1770      scif_sas_controller_default_complete_io_handler,
1771      scif_sas_controller_default_complete_high_priority_io_handler,
1772      scif_sas_controller_default_continue_io_handler,
1773      scif_sas_controller_default_start_task_handler,
1774      scif_sas_controller_default_complete_task_handler
1775   },
1776   // SCI_BASE_CONTROLLER_STATE_READY
1777   {
1778      scif_sas_controller_default_start_handler,
1779      scif_sas_controller_ready_stop_handler,
1780      scif_sas_controller_ready_reset_handler,
1781      scif_sas_controller_default_initialize_handler,
1782      scif_sas_controller_ready_start_io_handler,
1783      scif_sas_controller_ready_start_high_priority_io_handler,
1784      scif_sas_controller_ready_complete_io_handler,
1785      scif_sas_controller_ready_complete_high_priority_io_handler,
1786      scif_sas_controller_ready_continue_io_handler,
1787      scif_sas_controller_ready_start_task_handler,
1788      scif_sas_controller_ready_complete_task_handler
1789   },
1790   // SCI_BASE_CONTROLLER_STATE_RESETTING
1791   {
1792      scif_sas_controller_default_start_handler,
1793      scif_sas_controller_default_stop_handler,
1794      scif_sas_controller_default_reset_handler,
1795      scif_sas_controller_default_initialize_handler,
1796      scif_sas_controller_default_start_io_handler,
1797      scif_sas_controller_default_start_high_priority_io_handler,
1798      scif_sas_controller_default_complete_io_handler,
1799      scif_sas_controller_default_complete_high_priority_io_handler,
1800      scif_sas_controller_default_continue_io_handler,
1801      scif_sas_controller_default_start_task_handler,
1802      scif_sas_controller_default_complete_task_handler
1803   },
1804   // SCI_BASE_CONTROLLER_STATE_STOPPING
1805   {
1806      scif_sas_controller_default_start_handler,
1807      scif_sas_controller_default_stop_handler,
1808      scif_sas_controller_default_reset_handler,
1809      scif_sas_controller_default_initialize_handler,
1810      scif_sas_controller_default_start_io_handler,
1811      scif_sas_controller_stopping_start_high_priority_io_handler,
1812      scif_sas_controller_stopping_complete_io_handler,
1813      scif_sas_controller_stopping_complete_high_priority_io_handler,
1814      scif_sas_controller_default_continue_io_handler,
1815      scif_sas_controller_default_start_task_handler, /**@todo Allow in core?*/
1816      scif_sas_controller_stopping_complete_task_handler
1817   },
1818   // SCI_BASE_CONTROLLER_STATE_STOPPED
1819   {
1820      scif_sas_controller_default_start_handler,
1821      scif_sas_controller_default_stop_handler,
1822      scif_sas_controller_stopped_reset_handler,
1823      scif_sas_controller_default_initialize_handler,
1824      scif_sas_controller_default_start_io_handler,
1825      scif_sas_controller_default_start_high_priority_io_handler,
1826      scif_sas_controller_default_complete_io_handler,
1827      scif_sas_controller_default_complete_high_priority_io_handler,
1828      scif_sas_controller_default_continue_io_handler,
1829      scif_sas_controller_default_start_task_handler,
1830      scif_sas_controller_default_complete_task_handler
1831   },
1832   // SCI_BASE_CONTROLLER_STATE_FAILED
1833   {
1834      scif_sas_controller_default_start_handler,
1835      scif_sas_controller_default_stop_handler,
1836      scif_sas_controller_failed_reset_handler,
1837      scif_sas_controller_default_initialize_handler,
1838      scif_sas_controller_failed_state_start_io_handler,
1839      scif_sas_controller_failed_state_start_io_handler,
1840      scif_sas_controller_default_complete_io_handler,
1841      scif_sas_controller_default_complete_high_priority_io_handler,
1842      scif_sas_controller_default_continue_io_handler,
1843      scif_sas_controller_default_start_task_handler,
1844      scif_sas_controller_default_complete_task_handler
1845   }
1846};
1847
1848