Commit | Line | Data |
---|---|---|
6f231dda DW |
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 | * * Neither the name of Intel Corporation nor the names of its | |
40 | * contributors may be used to endorse or promote products derived | |
41 | * from this software without specific prior written permission. | |
42 | * | |
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
54 | */ | |
55 | ||
6f231dda DW |
56 | #include "intel_ata.h" |
57 | #include "intel_sata.h" | |
e574a8c1 DW |
58 | #include "intel_sat.h" |
59 | #include "sci_base_state.h" | |
6f231dda DW |
60 | #include "scic_sds_controller.h" |
61 | #include "scic_sds_port.h" | |
88f3b62a | 62 | #include "remote_device.h" |
6f231dda | 63 | #include "scic_sds_request.h" |
e574a8c1 DW |
64 | #include "sci_environment.h" |
65 | #include "sci_util.h" | |
6f231dda DW |
66 | #include "scu_event_codes.h" |
67 | ||
68 | /** | |
69 | * This method will perform the STP request completion processing common to IO | |
70 | * requests and task requests of all types | |
71 | * @device: This parameter specifies the device for which the request is being | |
72 | * completed. | |
73 | * @request: This parameter specifies the request being completed. | |
74 | * | |
75 | * This method returns an indication as to whether the request processing | |
76 | * completed successfully. | |
77 | */ | |
78 | static enum sci_status scic_sds_stp_remote_device_complete_request( | |
0ea99d52 | 79 | struct scic_sds_remote_device *device, |
38aa74eb | 80 | struct scic_sds_request *request) |
6f231dda | 81 | { |
6f231dda DW |
82 | enum sci_status status; |
83 | ||
38aa74eb | 84 | status = scic_sds_io_request_complete(request); |
6f231dda DW |
85 | |
86 | if (status == SCI_SUCCESS) { | |
87 | status = scic_sds_port_complete_io( | |
0ea99d52 | 88 | device->owning_port, device, request); |
6f231dda DW |
89 | |
90 | if (status == SCI_SUCCESS) { | |
0ea99d52 | 91 | scic_sds_remote_device_decrement_request_count(device); |
38aa74eb | 92 | if (request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { |
6f231dda DW |
93 | /* |
94 | * This request causes hardware error, device needs to be Lun Reset. | |
95 | * So here we force the state machine to IDLE state so the rest IOs | |
96 | * can reach RNC state handler, these IOs will be completed by RNC with | |
97 | * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ | |
98 | sci_base_state_machine_change_state( | |
0ea99d52 | 99 | &device->ready_substate_machine, |
6f231dda DW |
100 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET |
101 | ); | |
0ea99d52 | 102 | } else if (scic_sds_remote_device_get_request_count(device) == 0) { |
6f231dda | 103 | sci_base_state_machine_change_state( |
0ea99d52 | 104 | &device->ready_substate_machine, |
6f231dda DW |
105 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE |
106 | ); | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | if (status != SCI_SUCCESS) | |
0ea99d52 | 112 | dev_err(scirdev_to_dev(device), |
6f231dda DW |
113 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " |
114 | "could not complete\n", | |
115 | __func__, | |
0ea99d52 MT |
116 | device->owning_port, |
117 | device, | |
38aa74eb | 118 | request, |
6f231dda DW |
119 | status); |
120 | ||
121 | return status; | |
122 | } | |
123 | ||
124 | /* | |
125 | * ***************************************************************************** | |
126 | * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS | |
127 | * ***************************************************************************** */ | |
128 | ||
129 | /** | |
130 | * This is the READY NCQ substate handler to start task management request. In | |
131 | * this routine, we suspend and resume the RNC. | |
132 | * @device: The target device a task management request towards to. | |
133 | * @request: The task request. | |
134 | * | |
135 | * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to | |
136 | * let controller_start_task_handler know that the controller can't post TC for | |
137 | * task request yet, instead, when RNC gets resumed, a controller_continue_task | |
138 | * callback will be called. | |
139 | */ | |
140 | static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( | |
0ea99d52 | 141 | struct scic_sds_remote_device *device, |
38aa74eb | 142 | struct scic_sds_request *request) |
6f231dda DW |
143 | { |
144 | enum sci_status status; | |
6f231dda DW |
145 | |
146 | /* Will the port allow the io request to start? */ | |
0ea99d52 MT |
147 | status = device->owning_port->state_handlers->start_io_handler( |
148 | device->owning_port, device, request); | |
38aa74eb CH |
149 | if (status != SCI_SUCCESS) |
150 | return status; | |
6f231dda | 151 | |
7ab92c9e | 152 | status = scic_sds_remote_node_context_start_task(&device->rnc, request); |
38aa74eb CH |
153 | if (status != SCI_SUCCESS) |
154 | goto out; | |
6f231dda | 155 | |
38aa74eb CH |
156 | status = request->state_handlers->start_handler(request); |
157 | if (status != SCI_SUCCESS) | |
158 | goto out; | |
6f231dda | 159 | |
38aa74eb CH |
160 | /* |
161 | * Note: If the remote device state is not IDLE this will replace | |
162 | * the request that probably resulted in the task management request. | |
163 | */ | |
0ea99d52 MT |
164 | device->working_request = request; |
165 | sci_base_state_machine_change_state(&device->ready_substate_machine, | |
38aa74eb | 166 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); |
6f231dda | 167 | |
38aa74eb CH |
168 | /* |
169 | * The remote node context must cleanup the TCi to NCQ mapping table. | |
170 | * The only way to do this correctly is to either write to the TLCR | |
171 | * register or to invalidate and repost the RNC. In either case the | |
172 | * remote node context state machine will take the correct action when | |
173 | * the remote node context is suspended and later resumed. | |
174 | */ | |
7ab92c9e | 175 | scic_sds_remote_node_context_suspend(&device->rnc, |
38aa74eb | 176 | SCI_SOFTWARE_SUSPENSION, NULL, NULL); |
7ab92c9e | 177 | scic_sds_remote_node_context_resume(&device->rnc, |
38aa74eb | 178 | scic_sds_remote_device_continue_request, |
0ea99d52 | 179 | device); |
38aa74eb CH |
180 | |
181 | out: | |
0ea99d52 | 182 | scic_sds_remote_device_start_request(device, request, status); |
38aa74eb CH |
183 | /* |
184 | * We need to let the controller start request handler know that it can't | |
185 | * post TC yet. We will provide a callback function to post TC when RNC gets | |
186 | * resumed. | |
187 | */ | |
188 | return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; | |
6f231dda DW |
189 | } |
190 | ||
191 | /* | |
192 | * ***************************************************************************** | |
193 | * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS | |
194 | * ***************************************************************************** */ | |
195 | ||
196 | /** | |
197 | * This method will handle the start io operation for a sata device that is in | |
198 | * the command idle state. - Evalute the type of IO request to be started - | |
199 | * If its an NCQ request change to NCQ substate - If its any other command | |
200 | * change to the CMD substate | |
201 | * @device: | |
202 | * @request: | |
203 | * | |
7392d275 DJ |
204 | * If this is a softreset we may want to have a different substate. |
205 | * enum sci_status | |
6f231dda DW |
206 | */ |
207 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( | |
0ea99d52 | 208 | struct scic_sds_remote_device *sci_dev, |
38aa74eb | 209 | struct scic_sds_request *request) |
6f231dda DW |
210 | { |
211 | enum sci_status status; | |
890cae9b | 212 | struct isci_request *isci_request = request->ireq; |
6f231dda DW |
213 | |
214 | ||
215 | /* Will the port allow the io request to start? */ | |
0ea99d52 MT |
216 | status = sci_dev->owning_port->state_handlers->start_io_handler( |
217 | sci_dev->owning_port, sci_dev, request); | |
38aa74eb CH |
218 | if (status != SCI_SUCCESS) |
219 | return status; | |
6f231dda | 220 | |
7ab92c9e | 221 | status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); |
38aa74eb CH |
222 | if (status != SCI_SUCCESS) |
223 | goto out; | |
6f231dda | 224 | |
38aa74eb CH |
225 | status = request->state_handlers->start_handler(request); |
226 | if (status != SCI_SUCCESS) | |
227 | goto out; | |
6f231dda | 228 | |
38aa74eb | 229 | if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { |
0ea99d52 | 230 | sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, |
38aa74eb CH |
231 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); |
232 | } else { | |
0ea99d52 MT |
233 | sci_dev->working_request = request; |
234 | sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, | |
38aa74eb | 235 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); |
6f231dda | 236 | } |
38aa74eb | 237 | out: |
0ea99d52 | 238 | scic_sds_remote_device_start_request(sci_dev, request, status); |
6f231dda DW |
239 | return status; |
240 | } | |
241 | ||
242 | ||
243 | /** | |
244 | * | |
245 | * @[in]: device The device received event. | |
246 | * @[in]: event_code The event code. | |
247 | * | |
248 | * This method will handle the event for a sata device that is in the idle | |
249 | * state. We pick up suspension events to handle specifically to this state. We | |
250 | * resume the RNC right away. enum sci_status | |
251 | */ | |
252 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( | |
e2023b87 | 253 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
254 | u32 event_code) |
255 | { | |
256 | enum sci_status status; | |
257 | ||
e2023b87 | 258 | status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); |
6f231dda DW |
259 | |
260 | if (status == SCI_SUCCESS) { | |
261 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX | |
262 | || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | |
263 | status = scic_sds_remote_node_context_resume( | |
7ab92c9e | 264 | &sci_dev->rnc, NULL, NULL); |
6f231dda DW |
265 | } |
266 | } | |
267 | ||
268 | return status; | |
269 | } | |
270 | ||
271 | ||
272 | /* | |
273 | * ***************************************************************************** | |
274 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | |
275 | * ***************************************************************************** */ | |
276 | ||
277 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( | |
0ea99d52 | 278 | struct scic_sds_remote_device *sci_dev, |
38aa74eb | 279 | struct scic_sds_request *request) |
6f231dda DW |
280 | { |
281 | enum sci_status status; | |
890cae9b | 282 | struct isci_request *isci_request = request->ireq; |
7392d275 DJ |
283 | |
284 | if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { | |
0ea99d52 MT |
285 | status = sci_dev->owning_port->state_handlers->start_io_handler( |
286 | sci_dev->owning_port, | |
287 | sci_dev, | |
38aa74eb | 288 | request); |
7ab92c9e DW |
289 | if (status != SCI_SUCCESS) |
290 | return status; | |
6f231dda | 291 | |
7ab92c9e DW |
292 | status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); |
293 | if (status != SCI_SUCCESS) | |
294 | return status; | |
6f231dda | 295 | |
7ab92c9e | 296 | status = request->state_handlers->start_handler(request); |
6f231dda | 297 | |
7ab92c9e | 298 | scic_sds_remote_device_start_request(sci_dev, request, status); |
7392d275 | 299 | } else |
6f231dda | 300 | status = SCI_FAILURE_INVALID_STATE; |
6f231dda DW |
301 | |
302 | return status; | |
303 | } | |
304 | ||
305 | ||
306 | /** | |
307 | * This method will handle events received while the STP device is in the ready | |
308 | * command substate. | |
e2023b87 | 309 | * @sci_dev: This is the device object that is receiving the event. |
6f231dda DW |
310 | * @event_code: The event code to process. |
311 | * | |
312 | * enum sci_status | |
313 | */ | |
314 | ||
315 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( | |
e2023b87 | 316 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
317 | u32 frame_index) |
318 | { | |
319 | enum sci_status status; | |
320 | struct sata_fis_header *frame_header; | |
321 | ||
322 | status = scic_sds_unsolicited_frame_control_get_header( | |
e2023b87 | 323 | &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), |
6f231dda DW |
324 | frame_index, |
325 | (void **)&frame_header | |
326 | ); | |
327 | ||
328 | if (status == SCI_SUCCESS) { | |
3ff0121a PS |
329 | if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && |
330 | (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { | |
e2023b87 | 331 | sci_dev->not_ready_reason = |
3ff0121a PS |
332 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; |
333 | ||
334 | /* | |
335 | * / @todo Check sactive and complete associated IO | |
336 | * if any. | |
337 | */ | |
338 | ||
339 | sci_base_state_machine_change_state( | |
e2023b87 | 340 | &sci_dev->ready_substate_machine, |
3ff0121a PS |
341 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR |
342 | ); | |
343 | } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && | |
344 | (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { | |
345 | ||
346 | /* | |
347 | * Some devices return D2H FIS when an NCQ error is detected. | |
348 | * Treat this like an SDB error FIS ready reason. | |
349 | */ | |
e2023b87 | 350 | sci_dev->not_ready_reason = |
6f231dda DW |
351 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; |
352 | ||
353 | sci_base_state_machine_change_state( | |
e2023b87 | 354 | &sci_dev->ready_substate_machine, |
6f231dda DW |
355 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR |
356 | ); | |
357 | } else { | |
358 | status = SCI_FAILURE; | |
359 | } | |
360 | ||
361 | scic_sds_controller_release_frame( | |
e2023b87 | 362 | scic_sds_remote_device_get_controller(sci_dev), frame_index |
6f231dda DW |
363 | ); |
364 | } | |
365 | ||
366 | return status; | |
367 | } | |
368 | ||
369 | /* | |
370 | * ***************************************************************************** | |
371 | * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS | |
372 | * ***************************************************************************** */ | |
373 | ||
374 | /** | |
375 | * This device is already handling a command it can not accept new commands | |
376 | * until this one is complete. | |
377 | * @device: | |
378 | * @request: | |
379 | * | |
380 | * enum sci_status | |
381 | */ | |
382 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( | |
0ea99d52 | 383 | struct scic_sds_remote_device *device, |
38aa74eb | 384 | struct scic_sds_request *request) |
6f231dda DW |
385 | { |
386 | return SCI_FAILURE_INVALID_STATE; | |
387 | } | |
388 | ||
389 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( | |
e2023b87 | 390 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
391 | u32 suspend_type) |
392 | { | |
393 | enum sci_status status; | |
394 | ||
7ab92c9e DW |
395 | status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, |
396 | suspend_type, NULL, NULL); | |
6f231dda DW |
397 | |
398 | return status; | |
399 | } | |
400 | ||
401 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( | |
e2023b87 | 402 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
403 | u32 frame_index) |
404 | { | |
405 | enum sci_status status; | |
406 | ||
407 | /* | |
408 | * / The device doe not process any UF received from the hardware while | |
409 | * / in this state. All unsolicited frames are forwarded to the io request | |
410 | * / object. */ | |
411 | status = scic_sds_io_request_frame_handler( | |
e2023b87 | 412 | sci_dev->working_request, |
6f231dda DW |
413 | frame_index |
414 | ); | |
415 | ||
416 | return status; | |
417 | } | |
418 | ||
419 | ||
420 | /* | |
421 | * ***************************************************************************** | |
422 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | |
423 | * ***************************************************************************** */ | |
424 | ||
425 | /* | |
426 | * ***************************************************************************** | |
427 | * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS | |
428 | * ***************************************************************************** */ | |
429 | ||
430 | /* | |
431 | * ***************************************************************************** | |
432 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS | |
433 | * ***************************************************************************** */ | |
434 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( | |
0ea99d52 | 435 | struct scic_sds_remote_device *device, |
38aa74eb | 436 | struct scic_sds_request *request) |
6f231dda DW |
437 | { |
438 | return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; | |
439 | } | |
440 | ||
441 | ||
442 | ||
443 | /** | |
444 | * This method will perform the STP request (both io or task) completion | |
445 | * processing for await reset state. | |
446 | * @device: This parameter specifies the device for which the request is being | |
447 | * completed. | |
448 | * @request: This parameter specifies the request being completed. | |
449 | * | |
450 | * This method returns an indication as to whether the request processing | |
451 | * completed successfully. | |
452 | */ | |
453 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( | |
0ea99d52 | 454 | struct scic_sds_remote_device *device, |
38aa74eb | 455 | struct scic_sds_request *request) |
6f231dda | 456 | { |
e2023b87 | 457 | struct scic_sds_request *sci_req = (struct scic_sds_request *)request; |
6f231dda DW |
458 | enum sci_status status; |
459 | ||
e2023b87 | 460 | status = scic_sds_io_request_complete(sci_req); |
6f231dda DW |
461 | |
462 | if (status == SCI_SUCCESS) { | |
463 | status = scic_sds_port_complete_io( | |
e2023b87 | 464 | device->owning_port, device, sci_req |
6f231dda DW |
465 | ); |
466 | ||
467 | if (status == SCI_SUCCESS) | |
0ea99d52 | 468 | scic_sds_remote_device_decrement_request_count(device); |
6f231dda DW |
469 | } |
470 | ||
471 | if (status != SCI_SUCCESS) | |
0ea99d52 | 472 | dev_err(scirdev_to_dev(device), |
6f231dda DW |
473 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " |
474 | "could not complete\n", | |
475 | __func__, | |
0ea99d52 MT |
476 | device->owning_port, |
477 | device, | |
e2023b87 | 478 | sci_req, |
6f231dda DW |
479 | status); |
480 | ||
481 | return status; | |
482 | } | |
483 | ||
35173d57 | 484 | static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { |
db48255b | 485 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { |
0ea99d52 MT |
486 | .start_handler = scic_sds_remote_device_default_start_handler, |
487 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
488 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
489 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
490 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
491 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
492 | .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, | |
493 | .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
494 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
495 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
496 | .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
db48255b HD |
497 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
498 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
499 | .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, | |
500 | .frame_handler = scic_sds_remote_device_default_frame_handler | |
6f231dda | 501 | }, |
db48255b | 502 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { |
0ea99d52 MT |
503 | .start_handler = scic_sds_remote_device_default_start_handler, |
504 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
505 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
506 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
507 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
508 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
509 | .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, | |
510 | .complete_io_handler = scic_sds_stp_remote_device_complete_request, | |
511 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
512 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
513 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
514 | .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, |
515 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
516 | .event_handler = scic_sds_remote_device_general_event_handler, | |
517 | .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler | |
6f231dda | 518 | }, |
db48255b | 519 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { |
0ea99d52 MT |
520 | .start_handler = scic_sds_remote_device_default_start_handler, |
521 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
522 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
523 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
524 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
525 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
526 | .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, | |
527 | .complete_io_handler = scic_sds_stp_remote_device_complete_request, | |
528 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
529 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
530 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
531 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
532 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
533 | .event_handler = scic_sds_remote_device_general_event_handler, | |
534 | .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler | |
6f231dda | 535 | }, |
db48255b | 536 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { |
0ea99d52 MT |
537 | .start_handler = scic_sds_remote_device_default_start_handler, |
538 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
539 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
540 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
541 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
542 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
543 | .start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
544 | .complete_io_handler = scic_sds_stp_remote_device_complete_request, | |
545 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
546 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
547 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
548 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
549 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
550 | .event_handler = scic_sds_remote_device_general_event_handler, | |
551 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda | 552 | }, |
db48255b | 553 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { |
0ea99d52 MT |
554 | .start_handler = scic_sds_remote_device_default_start_handler, |
555 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
556 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
557 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
558 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
559 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
560 | .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, | |
561 | .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, | |
562 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
563 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
564 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
565 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
566 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
567 | .event_handler = scic_sds_remote_device_general_event_handler, | |
568 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda DW |
569 | } |
570 | }; | |
571 | ||
6f231dda DW |
572 | /* |
573 | * ***************************************************************************** | |
574 | * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS | |
575 | * ***************************************************************************** */ | |
576 | ||
037afc78 DW |
577 | static void |
578 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) | |
6f231dda | 579 | { |
037afc78 | 580 | struct scic_sds_remote_device *sci_dev = user_cookie; |
5d937e96 | 581 | struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); |
037afc78 | 582 | struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); |
d3757c3a | 583 | struct isci_host *ihost = scic->ihost; |
6f231dda DW |
584 | |
585 | /* | |
586 | * For NCQ operation we do not issue a | |
587 | * scic_cb_remote_device_not_ready(). As a result, avoid sending | |
09d7da13 DJ |
588 | * the ready notification. |
589 | */ | |
590 | if (sci_dev->ready_substate_machine.previous_state_id != | |
591 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) | |
037afc78 | 592 | isci_remote_device_ready(ihost, idev); |
6f231dda DW |
593 | } |
594 | ||
595 | /* | |
596 | * ***************************************************************************** | |
597 | * * STP REMOTE DEVICE READY IDLE SUBSTATE | |
598 | * ***************************************************************************** */ | |
599 | ||
600 | /** | |
601 | * | |
9a0fff7b | 602 | * @device: This is the object which is cast into a |
6f231dda DW |
603 | * struct scic_sds_remote_device object. |
604 | * | |
605 | */ | |
9a0fff7b | 606 | static void scic_sds_stp_remote_device_ready_idle_substate_enter(void *device) |
6f231dda | 607 | { |
5d937e96 | 608 | struct scic_sds_remote_device *sci_dev = device; |
6f231dda DW |
609 | |
610 | SET_STATE_HANDLER( | |
e2023b87 | 611 | sci_dev, |
6f231dda DW |
612 | scic_sds_stp_remote_device_ready_substate_handler_table, |
613 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | |
614 | ); | |
615 | ||
e2023b87 | 616 | sci_dev->working_request = NULL; |
6f231dda | 617 | |
7ab92c9e | 618 | if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { |
6f231dda DW |
619 | /* |
620 | * Since the RNC is ready, it's alright to finish completion | |
621 | * processing (e.g. signal the remote device is ready). */ | |
622 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( | |
e2023b87 | 623 | sci_dev |
6f231dda DW |
624 | ); |
625 | } else { | |
626 | scic_sds_remote_node_context_resume( | |
7ab92c9e | 627 | &sci_dev->rnc, |
6f231dda | 628 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, |
7ab92c9e | 629 | sci_dev); |
6f231dda DW |
630 | } |
631 | } | |
632 | ||
9a0fff7b | 633 | static void scic_sds_stp_remote_device_ready_cmd_substate_enter(void *object) |
6f231dda | 634 | { |
5d937e96 | 635 | struct scic_sds_remote_device *sci_dev = object; |
037afc78 | 636 | struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); |
d3757c3a | 637 | struct isci_host *ihost = scic->ihost; |
5d937e96 | 638 | struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); |
6f231dda | 639 | |
09d7da13 | 640 | BUG_ON(sci_dev->working_request == NULL); |
6f231dda | 641 | |
037afc78 DW |
642 | SET_STATE_HANDLER(sci_dev, |
643 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
644 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); | |
6f231dda | 645 | |
037afc78 DW |
646 | isci_remote_device_not_ready(ihost, idev, |
647 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); | |
6f231dda DW |
648 | } |
649 | ||
9a0fff7b | 650 | static void scic_sds_stp_remote_device_ready_ncq_substate_enter(void *object) |
6f231dda | 651 | { |
5d937e96 | 652 | struct scic_sds_remote_device *sci_dev = object; |
037afc78 DW |
653 | SET_STATE_HANDLER(sci_dev, |
654 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
655 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); | |
6f231dda DW |
656 | } |
657 | ||
9a0fff7b MP |
658 | static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( |
659 | void *object) | |
6f231dda | 660 | { |
5d937e96 | 661 | struct scic_sds_remote_device *sci_dev = object; |
037afc78 | 662 | struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); |
d3757c3a | 663 | struct isci_host *ihost = scic->ihost; |
5d937e96 | 664 | struct isci_remote_device *idev = sci_dev_to_idev(sci_dev); |
6f231dda | 665 | |
037afc78 DW |
666 | SET_STATE_HANDLER(sci_dev, |
667 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
668 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); | |
6f231dda | 669 | |
09d7da13 DJ |
670 | if (sci_dev->not_ready_reason == |
671 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) | |
037afc78 | 672 | isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason); |
6f231dda DW |
673 | } |
674 | ||
675 | /* | |
676 | * ***************************************************************************** | |
677 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE | |
678 | * ***************************************************************************** */ | |
679 | ||
680 | /** | |
681 | * The enter routine to READY AWAIT RESET substate. | |
9a0fff7b | 682 | * @device: This is the object which is cast into a |
6f231dda DW |
683 | * struct scic_sds_remote_device object. |
684 | * | |
685 | */ | |
686 | static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( | |
9a0fff7b | 687 | void *device) |
6f231dda | 688 | { |
e2023b87 | 689 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 690 | |
e2023b87 | 691 | sci_dev = (struct scic_sds_remote_device *)device; |
6f231dda DW |
692 | |
693 | SET_STATE_HANDLER( | |
e2023b87 | 694 | sci_dev, |
6f231dda DW |
695 | scic_sds_stp_remote_device_ready_substate_handler_table, |
696 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET | |
697 | ); | |
698 | } | |
699 | ||
6f231dda DW |
700 | const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { |
701 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { | |
702 | .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, | |
703 | }, | |
704 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { | |
705 | .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, | |
706 | }, | |
707 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { | |
708 | .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, | |
709 | }, | |
710 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { | |
711 | .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, | |
712 | }, | |
6f231dda DW |
713 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { |
714 | .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, | |
715 | }, | |
716 | }; |