xref: /freebsd/sys/dev/isci/scil/scif_sas_controller_states.c (revision 02e9120893770924227138ba49df1edb3896112a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3  *
4  * This file is provided under a dual BSD/GPLv2 license.  When using or
5  * redistributing this file, you may do so under either license.
6  *
7  * GPL LICENSE SUMMARY
8  *
9  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23  * The full GNU General Public License is included in this distribution
24  * in the file called LICENSE.GPL.
25  *
26  * BSD LICENSE
27  *
28  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  *   * Redistributions of source code must retain the above copyright
36  *     notice, this list of conditions and the following disclaimer.
37  *   * Redistributions in binary form must reproduce the above copyright
38  *     notice, this list of conditions and the following disclaimer in
39  *     the documentation and/or other materials provided with the
40  *     distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 #include <sys/cdefs.h>
56 /**
57  * @file
58  *
59  * @brief This file contains all of the entrance and exit methods for each
60  *        of the controller states defined by the SCI_BASE_CONTROLLER state
61  *        machine.
62  */
63 
64 #include <dev/isci/scil/scic_controller.h>
65 
66 #include <dev/isci/scil/scif_sas_logger.h>
67 #include <dev/isci/scil/scif_sas_controller.h>
68 
69 //******************************************************************************
70 //* P R O T E C T E D    M E T H O D S
71 //******************************************************************************
72 
73 /**
74  * @brief This method implements the actions taken when entering the
75  *        INITIAL state.
76  *
77  * @param[in]  object This parameter specifies the base object for which
78  *             the state transition is occurring.  This is cast into a
79  *             SCIF_SAS_CONTROLLER object in the method implementation.
80  *
81  * @return none
82  */
83 static
84 void scif_sas_controller_initial_state_enter(
85    SCI_BASE_OBJECT_T * object
86 )
87 {
88    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
89 
90    SET_STATE_HANDLER(
91       fw_controller,
92       scif_sas_controller_state_handler_table,
93       SCI_BASE_CONTROLLER_STATE_INITIAL
94    );
95 }
96 
97 /**
98  * @brief This method implements the actions taken when entering the
99  *        RESET state.
100  *
101  * @param[in]  object This parameter specifies the base object for which
102  *             the state transition is occurring.  This is cast into a
103  *             SCIF_SAS_CONTROLLER object in the method implementation.
104  *
105  * @return none
106  */
107 static
108 void scif_sas_controller_reset_state_enter(
109    SCI_BASE_OBJECT_T * object
110 )
111 {
112    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
113    U8 index;
114    U16 smp_phy_index;
115 
116    SET_STATE_HANDLER(
117       fw_controller,
118       scif_sas_controller_state_handler_table,
119       SCI_BASE_CONTROLLER_STATE_RESET
120    );
121 
122    scif_sas_high_priority_request_queue_construct(
123       &fw_controller->hprq, sci_base_object_get_logger(fw_controller)
124    );
125 
126    // Construct the abstract element pool. This pool will store the
127    // references to the framework's remote devices objects.
128    sci_abstract_element_pool_construct(
129       &fw_controller->free_remote_device_pool,
130       fw_controller->remote_device_pool_elements,
131       SCI_MAX_REMOTE_DEVICES
132    );
133 
134    // Construct the domain objects.
135    for (index = 0; index < SCI_MAX_DOMAINS; index++)
136    {
137       scif_sas_domain_construct(
138          &fw_controller->domains[index], index, fw_controller
139       );
140    }
141 
142    //Initialize SMP PHY MEMORY LIST.
143    sci_fast_list_init(&fw_controller->smp_phy_memory_list);
144 
145    for (smp_phy_index = 0;
146         smp_phy_index < SCIF_SAS_SMP_PHY_COUNT;
147         smp_phy_index++)
148    {
149       sci_fast_list_element_init(
150          &fw_controller->smp_phy_array[smp_phy_index],
151          &(fw_controller->smp_phy_array[smp_phy_index].list_element)
152       );
153 
154       //insert to owning device's smp phy list.
155       sci_fast_list_insert_tail(
156          (&(fw_controller->smp_phy_memory_list)),
157          (&(fw_controller->smp_phy_array[smp_phy_index].list_element))
158       );
159    }
160 
161    scif_sas_controller_set_default_config_parameters(fw_controller);
162 
163    fw_controller->internal_request_entries =
164       SCIF_SAS_MAX_INTERNAL_REQUEST_COUNT;
165 
166    //@Todo: may need to verify all timers are released. Including domain's
167    //operation timer and all the Internal IO's timer.
168 
169    //take care of the lock.
170    scif_cb_lock_disassociate(fw_controller, &fw_controller->hprq.lock);
171 }
172 
173 /**
174  * @brief This method implements the actions taken when entering the
175  *        INITIALIZING state.
176  *
177  * @param[in]  object This parameter specifies the base object for which
178  *             the state transition is occurring.  This is cast into a
179  *             SCIF_SAS_CONTROLLER object in the method implementation.
180  *
181  * @return none
182  */
183 static
184 void scif_sas_controller_initializing_state_enter(
185    SCI_BASE_OBJECT_T * object
186 )
187 {
188    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
189 
190    SET_STATE_HANDLER(
191       fw_controller,
192       scif_sas_controller_state_handler_table,
193       SCI_BASE_CONTROLLER_STATE_INITIALIZING
194    );
195 }
196 
197 /**
198  * @brief This method implements the actions taken when entering the
199  *        INITIALIZED state.
200  *
201  * @param[in]  object This parameter specifies the base object for which
202  *             the state transition is occurring.  This is cast into a
203  *             SCIF_SAS_CONTROLLER object in the method implementation.
204  *
205  * @return none
206  */
207 static
208 void scif_sas_controller_initialized_state_enter(
209    SCI_BASE_OBJECT_T * object
210 )
211 {
212    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
213 
214    SET_STATE_HANDLER(
215       fw_controller,
216       scif_sas_controller_state_handler_table,
217       SCI_BASE_CONTROLLER_STATE_INITIALIZED
218    );
219 }
220 
221 /**
222  * @brief This method implements the actions taken when entering the
223  *        STARTING state.
224  *
225  * @param[in]  object This parameter specifies the base object for which
226  *             the state transition is occurring.  This is cast into a
227  *             SCIF_SAS_CONTROLLER object in the method implementation.
228  *
229  * @return none
230  */
231 static
232 void scif_sas_controller_starting_state_enter(
233    SCI_BASE_OBJECT_T * object
234 )
235 {
236    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
237 
238    SET_STATE_HANDLER(
239       fw_controller,
240       scif_sas_controller_state_handler_table,
241       SCI_BASE_CONTROLLER_STATE_STARTING
242    );
243 }
244 
245 /**
246  * @brief This method implements the actions taken when entering the
247  *        READY state.
248  *
249  * @param[in]  object This parameter specifies the base object for which
250  *             the state transition is occurring.  This is cast into a
251  *             SCIF_SAS_CONTROLLER object in the method implementation.
252  *
253  * @return none
254  */
255 static
256 void scif_sas_controller_ready_state_enter(
257    SCI_BASE_OBJECT_T * object
258 )
259 {
260    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
261 
262    SET_STATE_HANDLER(
263       fw_controller,
264       scif_sas_controller_state_handler_table,
265       SCI_BASE_CONTROLLER_STATE_READY
266    );
267 }
268 
269 /**
270  * @brief This method implements the actions taken when entering the
271  *        STOPPING state.
272  *
273  * @param[in]  object This parameter specifies the base object for which
274  *             the state transition is occurring.  This is cast into a
275  *             SCIF_SAS_CONTROLLER object in the method implementation.
276  *
277  * @return none
278  */
279 static
280 void scif_sas_controller_stopping_state_enter(
281    SCI_BASE_OBJECT_T * object
282 )
283 {
284    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
285 
286    SET_STATE_HANDLER(
287       fw_controller,
288       scif_sas_controller_state_handler_table,
289       SCI_BASE_CONTROLLER_STATE_STOPPING
290    );
291 }
292 
293 /**
294  * @brief This method implements the actions taken when entering the
295  *        STOPPED state.
296  *
297  * @param[in]  object This parameter specifies the base object for which
298  *             the state transition is occurring.  This is cast into a
299  *             SCIF_SAS_CONTROLLER object in the method implementation.
300  *
301  * @return none
302  */
303 static
304 void scif_sas_controller_stopped_state_enter(
305    SCI_BASE_OBJECT_T * object
306 )
307 {
308    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
309 
310    SET_STATE_HANDLER(
311       fw_controller,
312       scif_sas_controller_state_handler_table,
313       SCI_BASE_CONTROLLER_STATE_STOPPED
314    );
315 }
316 
317 /**
318  * @brief This method implements the actions taken when entering the
319  *        RESETTING state.
320  *
321  * @param[in]  object This parameter specifies the base object for which
322  *             the state transition is occurring.  This is cast into a
323  *             SCIF_SAS_CONTROLLER object in the method implementation.
324  *
325  * @return none
326  */
327 static
328 void scif_sas_controller_resetting_state_enter(
329    SCI_BASE_OBJECT_T * object
330 )
331 {
332    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
333 
334    SET_STATE_HANDLER(
335       fw_controller,
336       scif_sas_controller_state_handler_table,
337       SCI_BASE_CONTROLLER_STATE_RESETTING
338    );
339 
340    // Attempt to reset the core controller.
341    fw_controller->operation_status = scic_controller_reset(
342                                         fw_controller->core_object
343                                      );
344    if (fw_controller->operation_status == SCI_SUCCESS)
345    {
346       // Reset the framework controller.
347       sci_base_state_machine_change_state(
348          &fw_controller->parent.state_machine,
349          SCI_BASE_CONTROLLER_STATE_RESET
350       );
351    }
352    else
353    {
354       SCIF_LOG_ERROR((
355          sci_base_object_get_logger(fw_controller),
356          SCIF_LOG_OBJECT_CONTROLLER,
357          "Controller: unable to successfully reset controller.\n"
358       ));
359 
360       sci_base_state_machine_change_state(
361          &fw_controller->parent.state_machine,
362          SCI_BASE_CONTROLLER_STATE_FAILED
363       );
364    }
365 }
366 
367 /**
368  * @brief This method implements the actions taken when entering the
369  *        FAILED state.
370  *
371  * @param[in]  object This parameter specifies the base object for which
372  *             the state transition is occurring.  This is cast into a
373  *             SCIF_SAS_CONTROLLER object in the method implementation.
374  *
375  * @return none
376  */
377 static
378 void scif_sas_controller_failed_state_enter(
379    SCI_BASE_OBJECT_T * object
380 )
381 {
382    SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)object;
383 
384    SCIF_LOG_ERROR((
385       sci_base_object_get_logger(fw_controller),
386       SCIF_LOG_OBJECT_CONTROLLER,
387       "Controller: entered FAILED state.\n"
388    ));
389 
390    SET_STATE_HANDLER(
391       fw_controller,
392       scif_sas_controller_state_handler_table,
393       SCI_BASE_CONTROLLER_STATE_FAILED
394    );
395 
396    if (fw_controller->parent.error != SCI_CONTROLLER_FATAL_MEMORY_ERROR)
397    {
398        //clean timers to avoid timer leak.
399        scif_sas_controller_release_resource(fw_controller);
400 
401        //notify user.
402        scif_cb_controller_error(fw_controller, fw_controller->parent.error);
403    }
404 }
405 
406 SCI_BASE_STATE_T
407 scif_sas_controller_state_table[SCI_BASE_CONTROLLER_MAX_STATES] =
408 {
409    {
410       SCI_BASE_CONTROLLER_STATE_INITIAL,
411       scif_sas_controller_initial_state_enter,
412       NULL,
413    },
414    {
415       SCI_BASE_CONTROLLER_STATE_RESET,
416       scif_sas_controller_reset_state_enter,
417       NULL,
418    },
419    {
420       SCI_BASE_CONTROLLER_STATE_INITIALIZING,
421       scif_sas_controller_initializing_state_enter,
422       NULL,
423    },
424    {
425       SCI_BASE_CONTROLLER_STATE_INITIALIZED,
426       scif_sas_controller_initialized_state_enter,
427       NULL,
428    },
429    {
430       SCI_BASE_CONTROLLER_STATE_STARTING,
431       scif_sas_controller_starting_state_enter,
432       NULL,
433    },
434    {
435       SCI_BASE_CONTROLLER_STATE_READY,
436       scif_sas_controller_ready_state_enter,
437       NULL,
438    },
439    {
440       SCI_BASE_CONTROLLER_STATE_RESETTING,
441       scif_sas_controller_resetting_state_enter,
442       NULL,
443    },
444    {
445       SCI_BASE_CONTROLLER_STATE_STOPPING,
446       scif_sas_controller_stopping_state_enter,
447       NULL,
448    },
449    {
450       SCI_BASE_CONTROLLER_STATE_STOPPED,
451       scif_sas_controller_stopped_state_enter,
452       NULL,
453    },
454    {
455       SCI_BASE_CONTROLLER_STATE_FAILED,
456       scif_sas_controller_failed_state_enter,
457       NULL,
458    }
459 };
460 
461