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; | |
7392d275 | 212 | struct isci_request *isci_request = |
38aa74eb | 213 | (struct isci_request *)sci_object_get_association(request); |
6f231dda DW |
214 | |
215 | ||
216 | /* Will the port allow the io request to start? */ | |
0ea99d52 MT |
217 | status = sci_dev->owning_port->state_handlers->start_io_handler( |
218 | sci_dev->owning_port, sci_dev, request); | |
38aa74eb CH |
219 | if (status != SCI_SUCCESS) |
220 | return status; | |
6f231dda | 221 | |
7ab92c9e | 222 | status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); |
38aa74eb CH |
223 | if (status != SCI_SUCCESS) |
224 | goto out; | |
6f231dda | 225 | |
38aa74eb CH |
226 | status = request->state_handlers->start_handler(request); |
227 | if (status != SCI_SUCCESS) | |
228 | goto out; | |
6f231dda | 229 | |
38aa74eb | 230 | if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { |
0ea99d52 | 231 | sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, |
38aa74eb CH |
232 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); |
233 | } else { | |
0ea99d52 MT |
234 | sci_dev->working_request = request; |
235 | sci_base_state_machine_change_state(&sci_dev->ready_substate_machine, | |
38aa74eb | 236 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); |
6f231dda | 237 | } |
38aa74eb | 238 | out: |
0ea99d52 | 239 | scic_sds_remote_device_start_request(sci_dev, request, status); |
6f231dda DW |
240 | return status; |
241 | } | |
242 | ||
243 | ||
244 | /** | |
245 | * | |
246 | * @[in]: device The device received event. | |
247 | * @[in]: event_code The event code. | |
248 | * | |
249 | * This method will handle the event for a sata device that is in the idle | |
250 | * state. We pick up suspension events to handle specifically to this state. We | |
251 | * resume the RNC right away. enum sci_status | |
252 | */ | |
253 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( | |
e2023b87 | 254 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
255 | u32 event_code) |
256 | { | |
257 | enum sci_status status; | |
258 | ||
e2023b87 | 259 | status = scic_sds_remote_device_general_event_handler(sci_dev, event_code); |
6f231dda DW |
260 | |
261 | if (status == SCI_SUCCESS) { | |
262 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX | |
263 | || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | |
264 | status = scic_sds_remote_node_context_resume( | |
7ab92c9e | 265 | &sci_dev->rnc, NULL, NULL); |
6f231dda DW |
266 | } |
267 | } | |
268 | ||
269 | return status; | |
270 | } | |
271 | ||
272 | ||
273 | /* | |
274 | * ***************************************************************************** | |
275 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | |
276 | * ***************************************************************************** */ | |
277 | ||
278 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( | |
0ea99d52 | 279 | struct scic_sds_remote_device *sci_dev, |
38aa74eb | 280 | struct scic_sds_request *request) |
6f231dda DW |
281 | { |
282 | enum sci_status status; | |
7392d275 | 283 | struct isci_request *isci_request = |
38aa74eb | 284 | (struct isci_request *)sci_object_get_association(request); |
7392d275 DJ |
285 | |
286 | if (isci_sata_get_sat_protocol(isci_request) == SAT_PROTOCOL_FPDMA) { | |
0ea99d52 MT |
287 | status = sci_dev->owning_port->state_handlers->start_io_handler( |
288 | sci_dev->owning_port, | |
289 | sci_dev, | |
38aa74eb | 290 | request); |
7ab92c9e DW |
291 | if (status != SCI_SUCCESS) |
292 | return status; | |
6f231dda | 293 | |
7ab92c9e DW |
294 | status = scic_sds_remote_node_context_start_io(&sci_dev->rnc, request); |
295 | if (status != SCI_SUCCESS) | |
296 | return status; | |
6f231dda | 297 | |
7ab92c9e | 298 | status = request->state_handlers->start_handler(request); |
6f231dda | 299 | |
7ab92c9e | 300 | scic_sds_remote_device_start_request(sci_dev, request, status); |
7392d275 | 301 | } else |
6f231dda | 302 | status = SCI_FAILURE_INVALID_STATE; |
6f231dda DW |
303 | |
304 | return status; | |
305 | } | |
306 | ||
307 | ||
308 | /** | |
309 | * This method will handle events received while the STP device is in the ready | |
310 | * command substate. | |
e2023b87 | 311 | * @sci_dev: This is the device object that is receiving the event. |
6f231dda DW |
312 | * @event_code: The event code to process. |
313 | * | |
314 | * enum sci_status | |
315 | */ | |
316 | ||
317 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( | |
e2023b87 | 318 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
319 | u32 frame_index) |
320 | { | |
321 | enum sci_status status; | |
322 | struct sata_fis_header *frame_header; | |
323 | ||
324 | status = scic_sds_unsolicited_frame_control_get_header( | |
e2023b87 | 325 | &(scic_sds_remote_device_get_controller(sci_dev)->uf_control), |
6f231dda DW |
326 | frame_index, |
327 | (void **)&frame_header | |
328 | ); | |
329 | ||
330 | if (status == SCI_SUCCESS) { | |
3ff0121a PS |
331 | if (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS && |
332 | (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { | |
e2023b87 | 333 | sci_dev->not_ready_reason = |
3ff0121a PS |
334 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; |
335 | ||
336 | /* | |
337 | * / @todo Check sactive and complete associated IO | |
338 | * if any. | |
339 | */ | |
340 | ||
341 | sci_base_state_machine_change_state( | |
e2023b87 | 342 | &sci_dev->ready_substate_machine, |
3ff0121a PS |
343 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR |
344 | ); | |
345 | } else if (frame_header->fis_type == SATA_FIS_TYPE_REGD2H && | |
346 | (frame_header->status & ATA_STATUS_REG_ERROR_BIT)) { | |
347 | ||
348 | /* | |
349 | * Some devices return D2H FIS when an NCQ error is detected. | |
350 | * Treat this like an SDB error FIS ready reason. | |
351 | */ | |
e2023b87 | 352 | sci_dev->not_ready_reason = |
6f231dda DW |
353 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; |
354 | ||
355 | sci_base_state_machine_change_state( | |
e2023b87 | 356 | &sci_dev->ready_substate_machine, |
6f231dda DW |
357 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR |
358 | ); | |
359 | } else { | |
360 | status = SCI_FAILURE; | |
361 | } | |
362 | ||
363 | scic_sds_controller_release_frame( | |
e2023b87 | 364 | scic_sds_remote_device_get_controller(sci_dev), frame_index |
6f231dda DW |
365 | ); |
366 | } | |
367 | ||
368 | return status; | |
369 | } | |
370 | ||
371 | /* | |
372 | * ***************************************************************************** | |
373 | * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS | |
374 | * ***************************************************************************** */ | |
375 | ||
376 | /** | |
377 | * This device is already handling a command it can not accept new commands | |
378 | * until this one is complete. | |
379 | * @device: | |
380 | * @request: | |
381 | * | |
382 | * enum sci_status | |
383 | */ | |
384 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( | |
0ea99d52 | 385 | struct scic_sds_remote_device *device, |
38aa74eb | 386 | struct scic_sds_request *request) |
6f231dda DW |
387 | { |
388 | return SCI_FAILURE_INVALID_STATE; | |
389 | } | |
390 | ||
391 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( | |
e2023b87 | 392 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
393 | u32 suspend_type) |
394 | { | |
395 | enum sci_status status; | |
396 | ||
7ab92c9e DW |
397 | status = scic_sds_remote_node_context_suspend(&sci_dev->rnc, |
398 | suspend_type, NULL, NULL); | |
6f231dda DW |
399 | |
400 | return status; | |
401 | } | |
402 | ||
403 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( | |
e2023b87 | 404 | struct scic_sds_remote_device *sci_dev, |
6f231dda DW |
405 | u32 frame_index) |
406 | { | |
407 | enum sci_status status; | |
408 | ||
409 | /* | |
410 | * / The device doe not process any UF received from the hardware while | |
411 | * / in this state. All unsolicited frames are forwarded to the io request | |
412 | * / object. */ | |
413 | status = scic_sds_io_request_frame_handler( | |
e2023b87 | 414 | sci_dev->working_request, |
6f231dda DW |
415 | frame_index |
416 | ); | |
417 | ||
418 | return status; | |
419 | } | |
420 | ||
421 | ||
422 | /* | |
423 | * ***************************************************************************** | |
424 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | |
425 | * ***************************************************************************** */ | |
426 | ||
427 | /* | |
428 | * ***************************************************************************** | |
429 | * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS | |
430 | * ***************************************************************************** */ | |
431 | ||
432 | /* | |
433 | * ***************************************************************************** | |
434 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS | |
435 | * ***************************************************************************** */ | |
436 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( | |
0ea99d52 | 437 | struct scic_sds_remote_device *device, |
38aa74eb | 438 | struct scic_sds_request *request) |
6f231dda DW |
439 | { |
440 | return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; | |
441 | } | |
442 | ||
443 | ||
444 | ||
445 | /** | |
446 | * This method will perform the STP request (both io or task) completion | |
447 | * processing for await reset state. | |
448 | * @device: This parameter specifies the device for which the request is being | |
449 | * completed. | |
450 | * @request: This parameter specifies the request being completed. | |
451 | * | |
452 | * This method returns an indication as to whether the request processing | |
453 | * completed successfully. | |
454 | */ | |
455 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( | |
0ea99d52 | 456 | struct scic_sds_remote_device *device, |
38aa74eb | 457 | struct scic_sds_request *request) |
6f231dda | 458 | { |
e2023b87 | 459 | struct scic_sds_request *sci_req = (struct scic_sds_request *)request; |
6f231dda DW |
460 | enum sci_status status; |
461 | ||
e2023b87 | 462 | status = scic_sds_io_request_complete(sci_req); |
6f231dda DW |
463 | |
464 | if (status == SCI_SUCCESS) { | |
465 | status = scic_sds_port_complete_io( | |
e2023b87 | 466 | device->owning_port, device, sci_req |
6f231dda DW |
467 | ); |
468 | ||
469 | if (status == SCI_SUCCESS) | |
0ea99d52 | 470 | scic_sds_remote_device_decrement_request_count(device); |
6f231dda DW |
471 | } |
472 | ||
473 | if (status != SCI_SUCCESS) | |
0ea99d52 | 474 | dev_err(scirdev_to_dev(device), |
6f231dda DW |
475 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " |
476 | "could not complete\n", | |
477 | __func__, | |
0ea99d52 MT |
478 | device->owning_port, |
479 | device, | |
e2023b87 | 480 | sci_req, |
6f231dda DW |
481 | status); |
482 | ||
483 | return status; | |
484 | } | |
485 | ||
35173d57 | 486 | static const struct scic_sds_remote_device_state_handler scic_sds_stp_remote_device_ready_substate_handler_table[] = { |
db48255b | 487 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { |
0ea99d52 MT |
488 | .start_handler = scic_sds_remote_device_default_start_handler, |
489 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
490 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
491 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
492 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
493 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
494 | .start_io_handler = scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, | |
495 | .complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
496 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
497 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
498 | .complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
db48255b HD |
499 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
500 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
501 | .event_handler = scic_sds_stp_remote_device_ready_idle_substate_event_handler, | |
502 | .frame_handler = scic_sds_remote_device_default_frame_handler | |
6f231dda | 503 | }, |
db48255b | 504 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { |
0ea99d52 MT |
505 | .start_handler = scic_sds_remote_device_default_start_handler, |
506 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
507 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
508 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
509 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
510 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
511 | .start_io_handler = scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, | |
512 | .complete_io_handler = scic_sds_stp_remote_device_complete_request, | |
513 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
514 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
515 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
516 | .suspend_handler = scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, |
517 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
518 | .event_handler = scic_sds_remote_device_general_event_handler, | |
519 | .frame_handler = scic_sds_stp_remote_device_ready_cmd_substate_frame_handler | |
6f231dda | 520 | }, |
db48255b | 521 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { |
0ea99d52 MT |
522 | .start_handler = scic_sds_remote_device_default_start_handler, |
523 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
524 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
525 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
526 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
527 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
528 | .start_io_handler = scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, | |
529 | .complete_io_handler = scic_sds_stp_remote_device_complete_request, | |
530 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
531 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
532 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
533 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
534 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
535 | .event_handler = scic_sds_remote_device_general_event_handler, | |
536 | .frame_handler = scic_sds_stp_remote_device_ready_ncq_substate_frame_handler | |
6f231dda | 537 | }, |
db48255b | 538 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { |
0ea99d52 MT |
539 | .start_handler = scic_sds_remote_device_default_start_handler, |
540 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
541 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
542 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
543 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
544 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
545 | .start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
546 | .complete_io_handler = scic_sds_stp_remote_device_complete_request, | |
547 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
548 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
549 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
550 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
551 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
552 | .event_handler = scic_sds_remote_device_general_event_handler, | |
553 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda | 554 | }, |
db48255b | 555 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { |
0ea99d52 MT |
556 | .start_handler = scic_sds_remote_device_default_start_handler, |
557 | .stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
558 | .fail_handler = scic_sds_remote_device_default_fail_handler, | |
559 | .destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
560 | .reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
561 | .reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
562 | .start_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, | |
563 | .complete_io_handler = scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, | |
564 | .continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
565 | .start_task_handler = scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
566 | .complete_task_handler = scic_sds_stp_remote_device_complete_request, | |
db48255b HD |
567 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, |
568 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
569 | .event_handler = scic_sds_remote_device_general_event_handler, | |
570 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda DW |
571 | } |
572 | }; | |
573 | ||
6f231dda DW |
574 | /* |
575 | * ***************************************************************************** | |
576 | * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS | |
577 | * ***************************************************************************** */ | |
578 | ||
037afc78 DW |
579 | static void |
580 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(void *user_cookie) | |
6f231dda | 581 | { |
037afc78 | 582 | struct scic_sds_remote_device *sci_dev = user_cookie; |
09d7da13 | 583 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); |
037afc78 DW |
584 | struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); |
585 | struct isci_host *ihost = sci_object_get_association(scic); | |
6f231dda DW |
586 | |
587 | /* | |
588 | * For NCQ operation we do not issue a | |
589 | * scic_cb_remote_device_not_ready(). As a result, avoid sending | |
09d7da13 DJ |
590 | * the ready notification. |
591 | */ | |
592 | if (sci_dev->ready_substate_machine.previous_state_id != | |
593 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) | |
037afc78 | 594 | isci_remote_device_ready(ihost, idev); |
6f231dda DW |
595 | } |
596 | ||
597 | /* | |
598 | * ***************************************************************************** | |
599 | * * STP REMOTE DEVICE READY IDLE SUBSTATE | |
600 | * ***************************************************************************** */ | |
601 | ||
602 | /** | |
603 | * | |
604 | * @device: This is the SCI base object which is cast into a | |
605 | * struct scic_sds_remote_device object. | |
606 | * | |
607 | */ | |
608 | static void scic_sds_stp_remote_device_ready_idle_substate_enter( | |
609 | struct sci_base_object *device) | |
610 | { | |
e2023b87 | 611 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 612 | |
e2023b87 | 613 | sci_dev = (struct scic_sds_remote_device *)device; |
6f231dda DW |
614 | |
615 | SET_STATE_HANDLER( | |
e2023b87 | 616 | sci_dev, |
6f231dda DW |
617 | scic_sds_stp_remote_device_ready_substate_handler_table, |
618 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | |
619 | ); | |
620 | ||
e2023b87 | 621 | sci_dev->working_request = NULL; |
6f231dda | 622 | |
7ab92c9e | 623 | if (scic_sds_remote_node_context_is_ready(&sci_dev->rnc)) { |
6f231dda DW |
624 | /* |
625 | * Since the RNC is ready, it's alright to finish completion | |
626 | * processing (e.g. signal the remote device is ready). */ | |
627 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( | |
e2023b87 | 628 | sci_dev |
6f231dda DW |
629 | ); |
630 | } else { | |
631 | scic_sds_remote_node_context_resume( | |
7ab92c9e | 632 | &sci_dev->rnc, |
6f231dda | 633 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, |
7ab92c9e | 634 | sci_dev); |
6f231dda DW |
635 | } |
636 | } | |
637 | ||
037afc78 | 638 | static void scic_sds_stp_remote_device_ready_cmd_substate_enter(struct sci_base_object *object) |
6f231dda | 639 | { |
037afc78 | 640 | struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), |
0ea99d52 | 641 | parent); |
037afc78 DW |
642 | struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); |
643 | struct isci_host *ihost = sci_object_get_association(scic); | |
09d7da13 | 644 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); |
6f231dda | 645 | |
09d7da13 | 646 | BUG_ON(sci_dev->working_request == NULL); |
6f231dda | 647 | |
037afc78 DW |
648 | SET_STATE_HANDLER(sci_dev, |
649 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
650 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD); | |
6f231dda | 651 | |
037afc78 DW |
652 | isci_remote_device_not_ready(ihost, idev, |
653 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED); | |
6f231dda DW |
654 | } |
655 | ||
037afc78 | 656 | static void scic_sds_stp_remote_device_ready_ncq_substate_enter(struct sci_base_object *object) |
6f231dda | 657 | { |
037afc78 | 658 | struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), |
0ea99d52 | 659 | parent); |
037afc78 DW |
660 | SET_STATE_HANDLER(sci_dev, |
661 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
662 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ); | |
6f231dda DW |
663 | } |
664 | ||
037afc78 | 665 | static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_object *object) |
6f231dda | 666 | { |
037afc78 | 667 | struct scic_sds_remote_device *sci_dev = container_of(object, typeof(*sci_dev), |
0ea99d52 | 668 | parent); |
037afc78 DW |
669 | struct scic_sds_controller *scic = scic_sds_remote_device_get_controller(sci_dev); |
670 | struct isci_host *ihost = sci_object_get_association(scic); | |
09d7da13 | 671 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); |
6f231dda | 672 | |
037afc78 DW |
673 | SET_STATE_HANDLER(sci_dev, |
674 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
675 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR); | |
6f231dda | 676 | |
09d7da13 DJ |
677 | if (sci_dev->not_ready_reason == |
678 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) | |
037afc78 | 679 | isci_remote_device_not_ready(ihost, idev, sci_dev->not_ready_reason); |
6f231dda DW |
680 | } |
681 | ||
682 | /* | |
683 | * ***************************************************************************** | |
684 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE | |
685 | * ***************************************************************************** */ | |
686 | ||
687 | /** | |
688 | * The enter routine to READY AWAIT RESET substate. | |
689 | * @device: This is the SCI base object which is cast into a | |
690 | * struct scic_sds_remote_device object. | |
691 | * | |
692 | */ | |
693 | static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( | |
694 | struct sci_base_object *device) | |
695 | { | |
e2023b87 | 696 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 697 | |
e2023b87 | 698 | sci_dev = (struct scic_sds_remote_device *)device; |
6f231dda DW |
699 | |
700 | SET_STATE_HANDLER( | |
e2023b87 | 701 | sci_dev, |
6f231dda DW |
702 | scic_sds_stp_remote_device_ready_substate_handler_table, |
703 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET | |
704 | ); | |
705 | } | |
706 | ||
6f231dda DW |
707 | const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { |
708 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { | |
709 | .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, | |
710 | }, | |
711 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { | |
712 | .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, | |
713 | }, | |
714 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { | |
715 | .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, | |
716 | }, | |
717 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { | |
718 | .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, | |
719 | }, | |
6f231dda DW |
720 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { |
721 | .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, | |
722 | }, | |
723 | }; |