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