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