xref: /freebsd/sys/dev/isci/scil/scif_sas_domain_states.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1f11c7f63SJim Harris /*-
2*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3*718cf2ccSPedro F. Giffuni  *
4f11c7f63SJim Harris  * This file is provided under a dual BSD/GPLv2 license.  When using or
5f11c7f63SJim Harris  * redistributing this file, you may do so under either license.
6f11c7f63SJim Harris  *
7f11c7f63SJim Harris  * GPL LICENSE SUMMARY
8f11c7f63SJim Harris  *
9f11c7f63SJim Harris  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10f11c7f63SJim Harris  *
11f11c7f63SJim Harris  * This program is free software; you can redistribute it and/or modify
12f11c7f63SJim Harris  * it under the terms of version 2 of the GNU General Public License as
13f11c7f63SJim Harris  * published by the Free Software Foundation.
14f11c7f63SJim Harris  *
15f11c7f63SJim Harris  * This program is distributed in the hope that it will be useful, but
16f11c7f63SJim Harris  * WITHOUT ANY WARRANTY; without even the implied warranty of
17f11c7f63SJim Harris  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18f11c7f63SJim Harris  * General Public License for more details.
19f11c7f63SJim Harris  *
20f11c7f63SJim Harris  * You should have received a copy of the GNU General Public License
21f11c7f63SJim Harris  * along with this program; if not, write to the Free Software
22f11c7f63SJim Harris  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23f11c7f63SJim Harris  * The full GNU General Public License is included in this distribution
24f11c7f63SJim Harris  * in the file called LICENSE.GPL.
25f11c7f63SJim Harris  *
26f11c7f63SJim Harris  * BSD LICENSE
27f11c7f63SJim Harris  *
28f11c7f63SJim Harris  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29f11c7f63SJim Harris  * All rights reserved.
30f11c7f63SJim Harris  *
31f11c7f63SJim Harris  * Redistribution and use in source and binary forms, with or without
32f11c7f63SJim Harris  * modification, are permitted provided that the following conditions
33f11c7f63SJim Harris  * are met:
34f11c7f63SJim Harris  *
35f11c7f63SJim Harris  *   * Redistributions of source code must retain the above copyright
36f11c7f63SJim Harris  *     notice, this list of conditions and the following disclaimer.
37f11c7f63SJim Harris  *   * Redistributions in binary form must reproduce the above copyright
38f11c7f63SJim Harris  *     notice, this list of conditions and the following disclaimer in
39f11c7f63SJim Harris  *     the documentation and/or other materials provided with the
40f11c7f63SJim Harris  *     distribution.
41f11c7f63SJim Harris  *
42f11c7f63SJim Harris  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43f11c7f63SJim Harris  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44f11c7f63SJim Harris  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45f11c7f63SJim Harris  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46f11c7f63SJim Harris  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47f11c7f63SJim Harris  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48f11c7f63SJim Harris  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49f11c7f63SJim Harris  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50f11c7f63SJim Harris  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51f11c7f63SJim Harris  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52f11c7f63SJim Harris  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53f11c7f63SJim Harris  */
54f11c7f63SJim Harris 
55f11c7f63SJim Harris #include <sys/cdefs.h>
56f11c7f63SJim Harris /**
57f11c7f63SJim Harris  * @file
58f11c7f63SJim Harris  *
59f11c7f63SJim Harris  * @brief This file contains all of the entrance and exit methods for each
60f11c7f63SJim Harris  *        of the domain states defined by the SCI_BASE_DOMAIN state
61f11c7f63SJim Harris  *        machine.
62f11c7f63SJim Harris  */
63f11c7f63SJim Harris 
64f11c7f63SJim Harris #include <dev/isci/scil/intel_sas.h>
65f11c7f63SJim Harris #include <dev/isci/scil/scic_port.h>
66f11c7f63SJim Harris 
67f11c7f63SJim Harris #include <dev/isci/scil/scif_sas_logger.h>
68f11c7f63SJim Harris #include <dev/isci/scil/scif_sas_domain.h>
69f11c7f63SJim Harris #include <dev/isci/scil/scif_sas_controller.h>
70f11c7f63SJim Harris #include <dev/isci/scil/scic_controller.h>
71f11c7f63SJim Harris 
72f11c7f63SJim Harris //******************************************************************************
73f11c7f63SJim Harris //* P R O T E C T E D    M E T H O D S
74f11c7f63SJim Harris //******************************************************************************
75f11c7f63SJim Harris 
76f11c7f63SJim Harris /**
77f11c7f63SJim Harris  * @brief This method will attempt to transition to the stopped state.
78f11c7f63SJim Harris  *        The transition will only occur if the criteria for transition is
79f11c7f63SJim Harris  *        met (i.e. all IOs are complete and all devices are stopped).
80f11c7f63SJim Harris  *
81f11c7f63SJim Harris  * @param[in]  fw_domain This parameter specifies the domain in which to
82f11c7f63SJim Harris  *             to attempt to perform the transition.
83f11c7f63SJim Harris  *
84f11c7f63SJim Harris  * @return none
85f11c7f63SJim Harris  */
scif_sas_domain_transition_to_stopped_state(SCIF_SAS_DOMAIN_T * fw_domain)86f11c7f63SJim Harris void scif_sas_domain_transition_to_stopped_state(
87f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain
88f11c7f63SJim Harris )
89f11c7f63SJim Harris {
90f11c7f63SJim Harris    SCIF_LOG_TRACE((
91f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
92f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
93f11c7f63SJim Harris       "scif_sas_domain_transition_to_stopped_state(0x%x) enter\n",
94f11c7f63SJim Harris       fw_domain
95f11c7f63SJim Harris    ));
96f11c7f63SJim Harris 
97f11c7f63SJim Harris    // If IOs are quiesced, and all remote devices are stopped,
98f11c7f63SJim Harris    // then transition directly to the STOPPED state.
99f11c7f63SJim Harris    if (  (fw_domain->request_list.element_count == 0)
100f11c7f63SJim Harris       && (fw_domain->device_start_count == 0) )
101f11c7f63SJim Harris    {
102f11c7f63SJim Harris       SCIF_LOG_INFO((
103f11c7f63SJim Harris          sci_base_object_get_logger(fw_domain),
104f11c7f63SJim Harris          SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
105f11c7f63SJim Harris          "Domain:0x%x immediate transition to STOPPED\n",
106f11c7f63SJim Harris          fw_domain
107f11c7f63SJim Harris       ));
108f11c7f63SJim Harris 
109f11c7f63SJim Harris       sci_base_state_machine_change_state(
110f11c7f63SJim Harris          &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPED
111f11c7f63SJim Harris       );
112f11c7f63SJim Harris    }
113f11c7f63SJim Harris }
114f11c7f63SJim Harris 
115f11c7f63SJim Harris 
116f11c7f63SJim Harris /**
117f11c7f63SJim Harris  * @brief This method is called upon entrance to all states where the
118f11c7f63SJim Harris  *        previous state may have been the DISCOVERING state.
119f11c7f63SJim Harris  *        We issue the scif_cb_domain_discovery_complete() notification
120f11c7f63SJim Harris  *        from this method, assuming pre-requisites are met, as opposed
121f11c7f63SJim Harris  *        to in the exit handler of the DISCOVERING state, so that the
122f11c7f63SJim Harris  *        appropriate state handlers are in place should the user decide
123f11c7f63SJim Harris  *        to call scif_domain_discover() again.
124f11c7f63SJim Harris  *
125f11c7f63SJim Harris  * @param[in]  fw_domain This parameter specifies the domain for which
126f11c7f63SJim Harris  *             the state transition has occurred.
127f11c7f63SJim Harris  *
128f11c7f63SJim Harris  * @return none
129f11c7f63SJim Harris  */
130f11c7f63SJim Harris static
scif_sas_domain_transition_from_discovering_state(SCIF_SAS_DOMAIN_T * fw_domain)131f11c7f63SJim Harris void scif_sas_domain_transition_from_discovering_state(
132f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain
133f11c7f63SJim Harris )
134f11c7f63SJim Harris {
135f11c7f63SJim Harris    SCIF_LOG_TRACE((
136f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
137f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
138f11c7f63SJim Harris       "scif_sas_domain_transition_from_discovering_state(0x%x) enter\n",
139f11c7f63SJim Harris       fw_domain
140f11c7f63SJim Harris    ));
141f11c7f63SJim Harris 
142f11c7f63SJim Harris    if (fw_domain->parent.state_machine.previous_state_id
143f11c7f63SJim Harris        == SCI_BASE_DOMAIN_STATE_DISCOVERING)
144f11c7f63SJim Harris    {
145f11c7f63SJim Harris       scif_sas_controller_restore_interrupt_coalescence(fw_domain->controller);
146f11c7f63SJim Harris 
147f11c7f63SJim Harris       scif_cb_timer_stop(fw_domain->controller, fw_domain->operation.timer);
148f11c7f63SJim Harris 
149f11c7f63SJim Harris       scif_cb_domain_discovery_complete(
150f11c7f63SJim Harris          fw_domain->controller, fw_domain, fw_domain->operation.status
151f11c7f63SJim Harris       );
152f11c7f63SJim Harris    }
153f11c7f63SJim Harris }
154f11c7f63SJim Harris 
155f11c7f63SJim Harris 
156f11c7f63SJim Harris /**
157f11c7f63SJim Harris  * @brief This method is called upon entrance to DISCOVERING state. Right before
158f11c7f63SJim Harris  *           transitioning to DISCOVERING state, we temporarily change interrupt
159f11c7f63SJim Harris  *           coalescence scheme.
160f11c7f63SJim Harris  *
161f11c7f63SJim Harris  * @param[in]  fw_domain This parameter specifies the domain for which
162f11c7f63SJim Harris  *             the state transition has occurred.
163f11c7f63SJim Harris  *
164f11c7f63SJim Harris  * @return none
165f11c7f63SJim Harris  */
scif_sas_domain_transition_to_discovering_state(SCIF_SAS_DOMAIN_T * fw_domain)166f11c7f63SJim Harris void scif_sas_domain_transition_to_discovering_state(
167f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain
168f11c7f63SJim Harris )
169f11c7f63SJim Harris {
170f11c7f63SJim Harris    scif_sas_controller_save_interrupt_coalescence(fw_domain->controller);
171f11c7f63SJim Harris 
172f11c7f63SJim Harris    sci_base_state_machine_change_state(
173f11c7f63SJim Harris       &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING
174f11c7f63SJim Harris    );
175f11c7f63SJim Harris }
176f11c7f63SJim Harris 
177f11c7f63SJim Harris 
178f11c7f63SJim Harris /**
179f11c7f63SJim Harris  * @brief This method implements the actions taken when entering the
180f11c7f63SJim Harris  *        INITIAL state.
181f11c7f63SJim Harris  *
182f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
183f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
184f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
185f11c7f63SJim Harris  *
186f11c7f63SJim Harris  * @return none
187f11c7f63SJim Harris  */
188f11c7f63SJim Harris static
scif_sas_domain_initial_state_enter(SCI_BASE_OBJECT_T * object)189f11c7f63SJim Harris void scif_sas_domain_initial_state_enter(
190f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
191f11c7f63SJim Harris )
192f11c7f63SJim Harris {
193f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
194f11c7f63SJim Harris 
195f11c7f63SJim Harris    SET_STATE_HANDLER(
196f11c7f63SJim Harris       fw_domain,
197f11c7f63SJim Harris       scif_sas_domain_state_handler_table,
198f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_INITIAL
199f11c7f63SJim Harris    );
200f11c7f63SJim Harris 
201f11c7f63SJim Harris    SCIF_LOG_TRACE((
202f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
203f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN,
204f11c7f63SJim Harris       "scif_sas_domain_initial_state_enter(0x%x) enter\n",
205f11c7f63SJim Harris       fw_domain
206f11c7f63SJim Harris    ));
207f11c7f63SJim Harris }
208f11c7f63SJim Harris 
209f11c7f63SJim Harris /**
210f11c7f63SJim Harris  * @brief This method implements the actions taken when entering the
211f11c7f63SJim Harris  *        STARTING state.  This includes setting the state handlers and
212f11c7f63SJim Harris  *        checking to see if the core port has already become READY.
213f11c7f63SJim Harris  *
214f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
215f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
216f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
217f11c7f63SJim Harris  *
218f11c7f63SJim Harris  * @return none
219f11c7f63SJim Harris  */
220f11c7f63SJim Harris static
scif_sas_domain_starting_state_enter(SCI_BASE_OBJECT_T * object)221f11c7f63SJim Harris void scif_sas_domain_starting_state_enter(
222f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
223f11c7f63SJim Harris )
224f11c7f63SJim Harris {
225f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
226f11c7f63SJim Harris 
227f11c7f63SJim Harris    SET_STATE_HANDLER(
228f11c7f63SJim Harris       fw_domain,
229f11c7f63SJim Harris       scif_sas_domain_state_handler_table,
230f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_STARTING
231f11c7f63SJim Harris    );
232f11c7f63SJim Harris 
233f11c7f63SJim Harris    SCIF_LOG_TRACE((
234f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
235f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
236f11c7f63SJim Harris       "scif_sas_domain_starting_state_enter(0x%x) enter\n",
237f11c7f63SJim Harris       fw_domain
238f11c7f63SJim Harris    ));
239f11c7f63SJim Harris 
240f11c7f63SJim Harris    scif_sas_domain_transition_from_discovering_state(fw_domain);
241f11c7f63SJim Harris 
242f11c7f63SJim Harris    // If we entered the STARTING state and the core port is actually ready,
243f11c7f63SJim Harris    // then directly transition into the READY state.  This can occur
244f11c7f63SJim Harris    // if we were in the middle of discovery when the port failed
245f11c7f63SJim Harris    // (causing a transition to STOPPING), then before reaching STOPPED
246f11c7f63SJim Harris    // the port becomes ready again.
247f11c7f63SJim Harris    if (fw_domain->is_port_ready == TRUE)
248f11c7f63SJim Harris    {
249f11c7f63SJim Harris       sci_base_state_machine_change_state(
250f11c7f63SJim Harris          &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_READY
251f11c7f63SJim Harris       );
252f11c7f63SJim Harris    }
253f11c7f63SJim Harris }
254f11c7f63SJim Harris 
255f11c7f63SJim Harris /**
256f11c7f63SJim Harris  * @brief This method implements the actions taken when entering the
257f11c7f63SJim Harris  *        READY state.  If the transition into this state came from:
258f11c7f63SJim Harris  *        - the STARTING state, then alert the user via a
259f11c7f63SJim Harris  *          scif_cb_domain_change_notification() that the domain
260f11c7f63SJim Harris  *          has at least 1 device ready for discovery.
261f11c7f63SJim Harris  *        - the DISCOVERING state, then alert the user that
262f11c7f63SJim Harris  *          discovery is complete via the
263f11c7f63SJim Harris  *          scif_cb_domain_discovery_complete() notification that
264f11c7f63SJim Harris  *          discovery is finished.
265f11c7f63SJim Harris  *
266f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
267f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
268f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
269f11c7f63SJim Harris  *
270f11c7f63SJim Harris  * @return none
271f11c7f63SJim Harris  */
272f11c7f63SJim Harris static
scif_sas_domain_ready_state_enter(SCI_BASE_OBJECT_T * object)273f11c7f63SJim Harris void scif_sas_domain_ready_state_enter(
274f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
275f11c7f63SJim Harris )
276f11c7f63SJim Harris {
277f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
278f11c7f63SJim Harris 
279f11c7f63SJim Harris    SET_STATE_HANDLER(
280f11c7f63SJim Harris       fw_domain,
281f11c7f63SJim Harris       scif_sas_domain_state_handler_table,
282f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_READY
283f11c7f63SJim Harris    );
284f11c7f63SJim Harris 
285f11c7f63SJim Harris    SCIF_LOG_TRACE((
286f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
287f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
288f11c7f63SJim Harris       "scif_sas_domain_ready_state_enter(0x%x) enter\n",
289f11c7f63SJim Harris       fw_domain
290f11c7f63SJim Harris    ));
291f11c7f63SJim Harris 
292f11c7f63SJim Harris    if (fw_domain->parent.state_machine.previous_state_id
293f11c7f63SJim Harris        == SCI_BASE_DOMAIN_STATE_STARTING)
294f11c7f63SJim Harris    {
295f11c7f63SJim Harris       scif_cb_domain_ready(fw_domain->controller, fw_domain);
296f11c7f63SJim Harris 
297f11c7f63SJim Harris       // Only indicate the domain change notification if the previous
298f11c7f63SJim Harris       // state was the STARTING state.  We issue the notification here
299f11c7f63SJim Harris       // as opposed to exit of the STARTING state so that the appropriate
300f11c7f63SJim Harris       // state handlers are in place should the user call
301f11c7f63SJim Harris       // scif_domain_discover() from scif_cb_domain_change_notification()
302f11c7f63SJim Harris       scif_cb_domain_change_notification(fw_domain->controller, fw_domain);
303f11c7f63SJim Harris    }
304f11c7f63SJim Harris    else if (fw_domain->parent.state_machine.previous_state_id
305f11c7f63SJim Harris             == SCI_BASE_DOMAIN_STATE_DISCOVERING)
306f11c7f63SJim Harris    {
307f11c7f63SJim Harris       //if domain discovery timed out, we will NOT go back to discover even
308f11c7f63SJim Harris       //the broadcast change count is not zero. Instead we finish the discovery
309f11c7f63SJim Harris       //back to user. User can check the operation status and decide to
310f11c7f63SJim Harris       //retry discover all over again.
311f11c7f63SJim Harris       if (fw_domain->operation.status == SCI_FAILURE_TIMEOUT)
312f11c7f63SJim Harris          fw_domain->broadcast_change_count = 0;
313f11c7f63SJim Harris 
314f11c7f63SJim Harris       // Check the broadcast change count to determine if discovery
315f11c7f63SJim Harris       // is indeed complete.
316f11c7f63SJim Harris       if (fw_domain->broadcast_change_count == 0)
317f11c7f63SJim Harris       {
318f11c7f63SJim Harris          scif_sas_domain_transition_from_discovering_state(fw_domain);
319f11c7f63SJim Harris          scif_cb_domain_ready(fw_domain->controller, fw_domain);
320f11c7f63SJim Harris       }
321f11c7f63SJim Harris       else
322f11c7f63SJim Harris       {
323f11c7f63SJim Harris          // The broadcast change count indicates something my have
324f11c7f63SJim Harris          // changed in the domain, while a discovery was ongoing.
325f11c7f63SJim Harris          // Thus, we should start discovery over again.
326f11c7f63SJim Harris          sci_base_state_machine_change_state(
327f11c7f63SJim Harris             &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_DISCOVERING
328f11c7f63SJim Harris          );
329f11c7f63SJim Harris       }
330f11c7f63SJim Harris 
331f11c7f63SJim Harris       // Enable the BCN because underneath hardware may disabled any further
332f11c7f63SJim Harris       // BCN.
333f11c7f63SJim Harris       scic_port_enable_broadcast_change_notification(fw_domain->core_object);
334f11c7f63SJim Harris    }
335f11c7f63SJim Harris }
336f11c7f63SJim Harris 
337f11c7f63SJim Harris /**
338f11c7f63SJim Harris  * @brief This method implements the actions taken when exiting the
339f11c7f63SJim Harris  *        READY state.
340f11c7f63SJim Harris  *
341f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
342f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
343f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
344f11c7f63SJim Harris  *
345f11c7f63SJim Harris  * @return none
346f11c7f63SJim Harris  */
347f11c7f63SJim Harris static
scif_sas_domain_ready_state_exit(SCI_BASE_OBJECT_T * object)348f11c7f63SJim Harris void scif_sas_domain_ready_state_exit(
349f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
350f11c7f63SJim Harris )
351f11c7f63SJim Harris {
352f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
353f11c7f63SJim Harris 
354f11c7f63SJim Harris    SCIF_LOG_TRACE((
355f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
356f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
357f11c7f63SJim Harris       "scif_sas_domain_ready_state_exit(0x%x) enter\n",
358f11c7f63SJim Harris       fw_domain
359f11c7f63SJim Harris    ));
360f11c7f63SJim Harris 
361f11c7f63SJim Harris    scif_cb_domain_not_ready(fw_domain->controller, fw_domain);
362f11c7f63SJim Harris }
363f11c7f63SJim Harris 
364f11c7f63SJim Harris /**
365f11c7f63SJim Harris  * @brief This method implements the actions taken when entering the
366f11c7f63SJim Harris  *        STOPPING state.
367f11c7f63SJim Harris  *
368f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
369f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
370f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
371f11c7f63SJim Harris  *
372f11c7f63SJim Harris  * @return none
373f11c7f63SJim Harris  */
374f11c7f63SJim Harris static
scif_sas_domain_stopping_state_enter(SCI_BASE_OBJECT_T * object)375f11c7f63SJim Harris void scif_sas_domain_stopping_state_enter(
376f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
377f11c7f63SJim Harris )
378f11c7f63SJim Harris {
379f11c7f63SJim Harris    SCIF_SAS_REMOTE_DEVICE_T * fw_device;
380f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
381f11c7f63SJim Harris    SCI_ABSTRACT_ELEMENT_T   * element   = sci_abstract_list_get_front(
382f11c7f63SJim Harris                                              &fw_domain->remote_device_list
383f11c7f63SJim Harris                                           );
384f11c7f63SJim Harris 
385f11c7f63SJim Harris    SET_STATE_HANDLER(
386f11c7f63SJim Harris       fw_domain,
387f11c7f63SJim Harris       scif_sas_domain_state_handler_table,
388f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_STOPPING
389f11c7f63SJim Harris    );
390f11c7f63SJim Harris 
391f11c7f63SJim Harris    // This must be invoked after the state handlers are set to ensure
392f11c7f63SJim Harris    // appropriate processing will occur if the user attempts to perform
393f11c7f63SJim Harris    // additional actions.
394f11c7f63SJim Harris    scif_sas_domain_transition_from_discovering_state(fw_domain);
395f11c7f63SJim Harris 
396f11c7f63SJim Harris    SCIF_LOG_TRACE((
397f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
398f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
399f11c7f63SJim Harris       "scif_sas_domain_stopping_state_enter(0x%x) enter\n",
400f11c7f63SJim Harris       fw_domain
401f11c7f63SJim Harris    ));
402f11c7f63SJim Harris 
403f11c7f63SJim Harris    scif_sas_high_priority_request_queue_purge_domain(
404f11c7f63SJim Harris       &fw_domain->controller->hprq, fw_domain
405f11c7f63SJim Harris    );
406f11c7f63SJim Harris 
407f11c7f63SJim Harris    // Search the domain's list of devices and put them all in the STOPPING
408f11c7f63SJim Harris    // state.
409f11c7f63SJim Harris    while (element != NULL)
410f11c7f63SJim Harris    {
411f11c7f63SJim Harris       fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
412f11c7f63SJim Harris                   sci_abstract_list_get_object(element);
413f11c7f63SJim Harris 
414f11c7f63SJim Harris       // This method will stop the core device.  The core will terminate
415f11c7f63SJim Harris       // all IO requests currently outstanding.
416f11c7f63SJim Harris       fw_device->state_handlers->parent.stop_handler(&fw_device->parent);
417f11c7f63SJim Harris 
418f11c7f63SJim Harris       element = sci_abstract_list_get_next(element);
419f11c7f63SJim Harris    }
420f11c7f63SJim Harris 
421f11c7f63SJim Harris    // Attempt to transition to the stopped state.
422f11c7f63SJim Harris    scif_sas_domain_transition_to_stopped_state(fw_domain);
423f11c7f63SJim Harris }
424f11c7f63SJim Harris 
425f11c7f63SJim Harris /**
426f11c7f63SJim Harris  * @brief This method implements the actions taken when entering the
427f11c7f63SJim Harris  *        STOPPED state.
428f11c7f63SJim Harris  *
429f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
430f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
431f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
432f11c7f63SJim Harris  *
433f11c7f63SJim Harris  * @return none
434f11c7f63SJim Harris  */
435f11c7f63SJim Harris static
scif_sas_domain_stopped_state_enter(SCI_BASE_OBJECT_T * object)436f11c7f63SJim Harris void scif_sas_domain_stopped_state_enter(
437f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
438f11c7f63SJim Harris )
439f11c7f63SJim Harris {
440f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
441f11c7f63SJim Harris 
442f11c7f63SJim Harris    SET_STATE_HANDLER(
443f11c7f63SJim Harris       fw_domain,
444f11c7f63SJim Harris       scif_sas_domain_state_handler_table,
445f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_STOPPED
446f11c7f63SJim Harris    );
447f11c7f63SJim Harris 
448f11c7f63SJim Harris    SCIF_LOG_TRACE((
449f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
450f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
451f11c7f63SJim Harris       "scif_sas_domain_stopped_state_enter(0x%x) enter\n",
452f11c7f63SJim Harris       fw_domain
453f11c7f63SJim Harris    ));
454f11c7f63SJim Harris 
455f11c7f63SJim Harris    // A hot unplug of the direct attached device has occurred.  Thus,
456f11c7f63SJim Harris    // notify the user. Note, if the controller is not in READY state,
457f11c7f63SJim Harris    // mostly likely the controller is in STOPPING or STOPPED state,
458f11c7f63SJim Harris    // meaning the controller is in the process of stopping, we should
459f11c7f63SJim Harris    // not call back to user in the middle of controller stopping.
460f11c7f63SJim Harris    if(fw_domain->controller->parent.state_machine.current_state_id
461f11c7f63SJim Harris          == SCI_BASE_CONTROLLER_STATE_READY)
462f11c7f63SJim Harris       scif_cb_domain_change_notification(fw_domain->controller, fw_domain);
463f11c7f63SJim Harris }
464f11c7f63SJim Harris 
465f11c7f63SJim Harris /**
466f11c7f63SJim Harris  * @brief This method implements the actions taken when entering the
467f11c7f63SJim Harris  *        DISCOVERING state.  This includes determining from which
468f11c7f63SJim Harris  *        state we entered.  If we entered from stopping that some sort
469f11c7f63SJim Harris  *        of hot-remove of the port occurred.  In the hot-remove case
470f11c7f63SJim Harris  *        all devices should be in the STOPPED state already and, as
471f11c7f63SJim Harris  *        a result, are removed from the domain with a notification sent
472f11c7f63SJim Harris  *        to the framework user.
473f11c7f63SJim Harris  *
474f11c7f63SJim Harris  * @note This method currently only handles hot-insert/hot-remove of
475f11c7f63SJim Harris  *       direct attached SSP devices.
476f11c7f63SJim Harris  *
477f11c7f63SJim Harris  * @param[in]  object This parameter specifies the base object for which
478f11c7f63SJim Harris  *             the state transition is occurring.  This is cast into a
479f11c7f63SJim Harris  *             SCIF_SAS_DOMAIN object in the method implementation.
480f11c7f63SJim Harris  *
481f11c7f63SJim Harris  * @return none
482f11c7f63SJim Harris  */
483f11c7f63SJim Harris static
scif_sas_domain_discovering_state_enter(SCI_BASE_OBJECT_T * object)484f11c7f63SJim Harris void scif_sas_domain_discovering_state_enter(
485f11c7f63SJim Harris    SCI_BASE_OBJECT_T * object
486f11c7f63SJim Harris )
487f11c7f63SJim Harris {
488f11c7f63SJim Harris    SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T *)object;
489f11c7f63SJim Harris 
490f11c7f63SJim Harris    SET_STATE_HANDLER(
491f11c7f63SJim Harris       fw_domain,
492f11c7f63SJim Harris       scif_sas_domain_state_handler_table,
493f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_DISCOVERING
494f11c7f63SJim Harris    );
495f11c7f63SJim Harris 
496f11c7f63SJim Harris    SCIF_LOG_TRACE((
497f11c7f63SJim Harris       sci_base_object_get_logger(fw_domain),
498f11c7f63SJim Harris       SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
499f11c7f63SJim Harris       "scif_sas_domain_discovering_state_enter(0x%x) enter\n",
500f11c7f63SJim Harris       fw_domain
501f11c7f63SJim Harris    ));
502f11c7f63SJim Harris 
503f11c7f63SJim Harris    fw_domain->broadcast_change_count = 0;
504f11c7f63SJim Harris 
505f11c7f63SJim Harris    // Did the domain just go through a port not ready action?  If it did,
506f11c7f63SJim Harris    // then we will be entering from the STOPPED state.
507f11c7f63SJim Harris    if (fw_domain->parent.state_machine.previous_state_id
508f11c7f63SJim Harris        != SCI_BASE_DOMAIN_STATE_STOPPED)
509f11c7f63SJim Harris    {
510f11c7f63SJim Harris       SCIF_SAS_REMOTE_DEVICE_T * remote_device;
511f11c7f63SJim Harris       SCIC_PORT_PROPERTIES_T     properties;
512f11c7f63SJim Harris 
513f11c7f63SJim Harris       scic_port_get_properties(fw_domain->core_object, &properties);
514f11c7f63SJim Harris 
515f11c7f63SJim Harris       // If the device has not yet been added to the domain, then
516f11c7f63SJim Harris       // inform the user that the device is new.
517f11c7f63SJim Harris       remote_device = (SCIF_SAS_REMOTE_DEVICE_T *)
518f11c7f63SJim Harris                       scif_domain_get_device_by_sas_address(
519f11c7f63SJim Harris                          fw_domain, &properties.remote.sas_address
520f11c7f63SJim Harris                       );
521f11c7f63SJim Harris       if (remote_device == SCI_INVALID_HANDLE)
522f11c7f63SJim Harris       {
523f11c7f63SJim Harris          // simply notify the user of the new DA device and be done
524f11c7f63SJim Harris          // with discovery.
525f11c7f63SJim Harris          scif_cb_domain_da_device_added(
526f11c7f63SJim Harris             fw_domain->controller,
527f11c7f63SJim Harris             fw_domain,
528f11c7f63SJim Harris             &properties.remote.sas_address,
529f11c7f63SJim Harris             &properties.remote.protocols
530f11c7f63SJim Harris          );
531f11c7f63SJim Harris       }
532f11c7f63SJim Harris       else
533f11c7f63SJim Harris       {
534f11c7f63SJim Harris          if(properties.remote.protocols.u.bits.smp_target)
535f11c7f63SJim Harris             //kick off the smp discover process.
536f11c7f63SJim Harris             scif_sas_domain_start_smp_discover(fw_domain, remote_device);
537f11c7f63SJim Harris       }
538f11c7f63SJim Harris    }
539f11c7f63SJim Harris    else  //entered from STOPPED state.
540f11c7f63SJim Harris    {
541f11c7f63SJim Harris       SCI_ABSTRACT_ELEMENT_T * current_element =
542f11c7f63SJim Harris              sci_abstract_list_get_front(&(fw_domain->remote_device_list) );
543f11c7f63SJim Harris 
544f11c7f63SJim Harris       SCIF_SAS_REMOTE_DEVICE_T * fw_device;
545f11c7f63SJim Harris 
546f11c7f63SJim Harris       while (current_element != NULL)
547f11c7f63SJim Harris       {
548f11c7f63SJim Harris          fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)
549f11c7f63SJim Harris                      sci_abstract_list_get_object(current_element);
550f11c7f63SJim Harris 
551f11c7f63SJim Harris          ASSERT(fw_device->parent.state_machine.current_state_id
552f11c7f63SJim Harris                 == SCI_BASE_REMOTE_DEVICE_STATE_STOPPED);
553f11c7f63SJim Harris 
554f11c7f63SJim Harris          current_element =
555f11c7f63SJim Harris             sci_abstract_list_get_next(current_element);
556f11c7f63SJim Harris 
557f11c7f63SJim Harris          SCIF_LOG_INFO((
558f11c7f63SJim Harris             sci_base_object_get_logger(fw_domain),
559f11c7f63SJim Harris             SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
560f11c7f63SJim Harris             "Controller:0x%x Domain:0x%x Device:0x%x removed\n",
561f11c7f63SJim Harris             fw_domain->controller, fw_domain, fw_device
562f11c7f63SJim Harris          ));
563f11c7f63SJim Harris 
564f11c7f63SJim Harris          // Notify the framework user of the device removal.
565f11c7f63SJim Harris          scif_cb_domain_device_removed(
566f11c7f63SJim Harris             fw_domain->controller, fw_domain, fw_device
567f11c7f63SJim Harris          );
568f11c7f63SJim Harris       }
569f11c7f63SJim Harris 
570f11c7f63SJim Harris       ASSERT(fw_domain->request_list.element_count == 0);
571f11c7f63SJim Harris       ASSERT(sci_abstract_list_size(&fw_domain->remote_device_list) == 0);
572f11c7f63SJim Harris 
573f11c7f63SJim Harris       sci_base_state_machine_change_state(
574f11c7f63SJim Harris          &fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STARTING
575f11c7f63SJim Harris       );
576f11c7f63SJim Harris    }
577f11c7f63SJim Harris }
578f11c7f63SJim Harris 
579f11c7f63SJim Harris SCI_BASE_STATE_T scif_sas_domain_state_table[SCI_BASE_DOMAIN_MAX_STATES] =
580f11c7f63SJim Harris {
581f11c7f63SJim Harris    {
582f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_INITIAL,
583f11c7f63SJim Harris       scif_sas_domain_initial_state_enter,
584f11c7f63SJim Harris       NULL,
585f11c7f63SJim Harris    },
586f11c7f63SJim Harris    {
587f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_STARTING,
588f11c7f63SJim Harris       scif_sas_domain_starting_state_enter,
589f11c7f63SJim Harris       NULL,
590f11c7f63SJim Harris    },
591f11c7f63SJim Harris    {
592f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_READY,
593f11c7f63SJim Harris       scif_sas_domain_ready_state_enter,
594f11c7f63SJim Harris       scif_sas_domain_ready_state_exit,
595f11c7f63SJim Harris    },
596f11c7f63SJim Harris    {
597f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_STOPPING,
598f11c7f63SJim Harris       scif_sas_domain_stopping_state_enter,
599f11c7f63SJim Harris       NULL,
600f11c7f63SJim Harris    },
601f11c7f63SJim Harris    {
602f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_STOPPED,
603f11c7f63SJim Harris       scif_sas_domain_stopped_state_enter,
604f11c7f63SJim Harris       NULL,
605f11c7f63SJim Harris    },
606f11c7f63SJim Harris    {
607f11c7f63SJim Harris       SCI_BASE_DOMAIN_STATE_DISCOVERING,
608f11c7f63SJim Harris       scif_sas_domain_discovering_state_enter,
609f11c7f63SJim Harris       NULL,
610f11c7f63SJim Harris    }
611f11c7f63SJim Harris };
612f11c7f63SJim Harris 
613