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