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 the entrance and exit methods for the ready
60 * sub-state machine states (OPERATIONAL, TASK_MGMT).
61 */
62
63 #include <dev/isci/scil/scif_sas_remote_device.h>
64 #include <dev/isci/scil/scif_sas_domain.h>
65 #include <dev/isci/scil/scif_sas_logger.h>
66 #include <dev/isci/scil/scif_sas_internal_io_request.h>
67 #include <dev/isci/scil/scif_sas_controller.h>
68 #include <dev/isci/scil/sci_controller.h>
69
70 //******************************************************************************
71 //* P R O T E C T E D M E T H O D S
72 //******************************************************************************
73
74 /**
75 * @brief This method implements the actions taken when entering the
76 * READY OPERATIONAL substate. This includes setting the state
77 * handler methods and issuing a scif_cb_remote_device_ready()
78 * notification to the user.
79 *
80 * @param[in] object This parameter specifies the base object for which
81 * the state transition is occurring. This is cast into a
82 * SCIF_SAS_REMOTE_DEVICE object in the method implementation.
83 *
84 * @return none
85 */
86 static
scif_sas_remote_device_ready_operational_substate_enter(SCI_BASE_OBJECT_T * object)87 void scif_sas_remote_device_ready_operational_substate_enter(
88 SCI_BASE_OBJECT_T *object
89 )
90 {
91 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
92
93 SET_STATE_HANDLER(
94 fw_device,
95 scif_sas_remote_device_ready_substate_handler_table,
96 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
97 );
98
99 SCIF_LOG_INFO((
100 sci_base_object_get_logger(fw_device),
101 SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
102 "Domain:0x%x Device:0x%x device ready\n",
103 fw_device->domain, fw_device
104 ));
105
106 // Notify the user that the device has become ready.
107 scif_cb_remote_device_ready(
108 fw_device->domain->controller, fw_device->domain, fw_device
109 );
110 }
111
112 /**
113 * @brief This method implements the actions taken when exiting the
114 * READY OPERATIONAL substate. This method issues a
115 * scif_cb_remote_device_not_ready() notification to the framework
116 * user.
117 *
118 * @param[in] object This parameter specifies the base object for which
119 * the state transition is occurring. This is cast into a
120 * SCIF_SAS_REMOTE_DEVICE object in the method implementation.
121 *
122 * @return none
123 */
124 static
scif_sas_remote_device_ready_operational_substate_exit(SCI_BASE_OBJECT_T * object)125 void scif_sas_remote_device_ready_operational_substate_exit(
126 SCI_BASE_OBJECT_T *object
127 )
128 {
129 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
130
131 // Notify the user that the device has become ready.
132 scif_cb_remote_device_not_ready(
133 fw_device->domain->controller, fw_device->domain, fw_device
134 );
135 }
136
137 /**
138 * @brief This method implements the actions taken when entering the
139 * READY SUSPENDED substate. This includes setting the state
140 * handler methods.
141 *
142 * @param[in] object This parameter specifies the base object for which
143 * the state transition is occurring. This is cast into a
144 * SCIF_SAS_REMOTE_DEVICE object in the method implementation.
145 *
146 * @return none
147 */
148 static
scif_sas_remote_device_ready_suspended_substate_enter(SCI_BASE_OBJECT_T * object)149 void scif_sas_remote_device_ready_suspended_substate_enter(
150 SCI_BASE_OBJECT_T *object
151 )
152 {
153 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
154
155 SET_STATE_HANDLER(
156 fw_device,
157 scif_sas_remote_device_ready_substate_handler_table,
158 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
159 );
160 }
161
162 /**
163 * @brief This method implements the actions taken when entering the
164 * READY TASK MGMT substate. This includes setting the state
165 * handler methods.
166 *
167 * @param[in] object This parameter specifies the base object for which
168 * the state transition is occurring. This is cast into a
169 * SCIF_SAS_REMOTE_DEVICE object in the method implementation.
170 *
171 * @return none
172 */
173 static
scif_sas_remote_device_ready_taskmgmt_substate_enter(SCI_BASE_OBJECT_T * object)174 void scif_sas_remote_device_ready_taskmgmt_substate_enter(
175 SCI_BASE_OBJECT_T *object
176 )
177 {
178 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
179
180 SET_STATE_HANDLER(
181 fw_device,
182 scif_sas_remote_device_ready_substate_handler_table,
183 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
184 );
185 }
186
187 /**
188 * @brief This method implements the actions taken when entering the
189 * READY NCQ ERROR substate. This includes setting the state
190 * handler methods.
191 *
192 * @param[in] object This parameter specifies the base object for which
193 * the state transition is occurring. This is cast into a
194 * SCIF_SAS_REMOTE_DEVICE object in the method implementation.
195 *
196 * @return none
197 */
198 static
scif_sas_remote_device_ready_ncq_error_substate_enter(SCI_BASE_OBJECT_T * object)199 void scif_sas_remote_device_ready_ncq_error_substate_enter(
200 SCI_BASE_OBJECT_T *object
201 )
202 {
203 SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
204 SCI_STATUS status = SCI_SUCCESS;
205 SCI_TASK_REQUEST_HANDLE_T handle;
206 SCIF_SAS_CONTROLLER_T * fw_controller = fw_device->domain->controller;
207 SCIF_SAS_TASK_REQUEST_T * fw_task_request;
208 SCIF_SAS_REQUEST_T * fw_request;
209 void * internal_task_memory;
210 SCIF_SAS_DOMAIN_T * fw_domain = fw_device->domain;
211 SCI_FAST_LIST_ELEMENT_T * pending_request_element;
212 SCIF_SAS_REQUEST_T * pending_request = NULL;
213
214 SET_STATE_HANDLER(
215 fw_device,
216 scif_sas_remote_device_ready_substate_handler_table,
217 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
218 );
219
220 internal_task_memory = scif_sas_controller_allocate_internal_request(fw_controller);
221 ASSERT(internal_task_memory != NULL);
222
223 fw_task_request = (SCIF_SAS_TASK_REQUEST_T*)internal_task_memory;
224
225 fw_request = &fw_task_request->parent;
226
227 //construct the scif io request
228 status = scif_sas_internal_task_request_construct(
229 fw_controller,
230 fw_device,
231 SCI_CONTROLLER_INVALID_IO_TAG,
232 (void *)fw_task_request,
233 &handle,
234 SCI_SAS_ABORT_TASK_SET
235 );
236
237 pending_request_element = fw_domain->request_list.list_head;
238
239 // Cycle through the fast list of IO requests. Mark each request
240 // pending to this remote device so that they are not completed
241 // to the operating system when the request is terminated, but
242 // rather when the abort task set completes.
243 while (pending_request_element != NULL)
244 {
245 pending_request =
246 (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);
247
248 // The current element may be deleted from the list because of
249 // IO completion so advance to the next element early
250 pending_request_element = sci_fast_list_get_next(pending_request_element);
251
252 if (pending_request->device == fw_device)
253 {
254 pending_request->is_waiting_for_abort_task_set = TRUE;
255 }
256 }
257
258 scif_controller_start_task(
259 fw_controller,
260 fw_device,
261 fw_request,
262 SCI_CONTROLLER_INVALID_IO_TAG
263 );
264 }
265
266 SCI_BASE_STATE_T scif_sas_remote_device_ready_substate_table
267 [SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_MAX_STATES] =
268 {
269 {
270 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
271 scif_sas_remote_device_ready_operational_substate_enter,
272 scif_sas_remote_device_ready_operational_substate_exit
273 },
274 {
275 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
276 scif_sas_remote_device_ready_suspended_substate_enter,
277 NULL
278 },
279 {
280 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT,
281 scif_sas_remote_device_ready_taskmgmt_substate_enter,
282 NULL
283 },
284 {
285 SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
286 scif_sas_remote_device_ready_ncq_error_substate_enter,
287 NULL
288 }
289 };
290
291