1 /*-
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 */
52
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
55
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 becasue 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