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 | ||
56 | /** | |
57 | * This file contains the ready substate handlers for an STP device. | |
58 | * | |
59 | * | |
60 | */ | |
61 | ||
62 | #include "intel_sat.h" | |
63 | #include "intel_ata.h" | |
64 | #include "intel_sata.h" | |
65 | #include "sci_environment.h" | |
66 | #include "scic_remote_device.h" | |
67 | #include "scic_user_callback.h" | |
68 | #include "scic_sds_controller.h" | |
69 | #include "scic_sds_port.h" | |
70 | #include "scic_sds_remote_device.h" | |
71 | #include "scic_sds_request.h" | |
72 | #include "scu_event_codes.h" | |
73 | ||
74 | /** | |
75 | * This method will perform the STP request completion processing common to IO | |
76 | * requests and task requests of all types | |
77 | * @device: This parameter specifies the device for which the request is being | |
78 | * completed. | |
79 | * @request: This parameter specifies the request being completed. | |
80 | * | |
81 | * This method returns an indication as to whether the request processing | |
82 | * completed successfully. | |
83 | */ | |
84 | static enum sci_status scic_sds_stp_remote_device_complete_request( | |
85 | struct sci_base_remote_device *device, | |
86 | struct sci_base_request *request) | |
87 | { | |
88 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
89 | struct scic_sds_request *the_request = (struct scic_sds_request *)request; | |
90 | enum sci_status status; | |
91 | ||
92 | status = scic_sds_io_request_complete(the_request); | |
93 | ||
94 | if (status == SCI_SUCCESS) { | |
95 | status = scic_sds_port_complete_io( | |
96 | this_device->owning_port, this_device, the_request | |
97 | ); | |
98 | ||
99 | if (status == SCI_SUCCESS) { | |
100 | scic_sds_remote_device_decrement_request_count(this_device); | |
101 | if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { | |
102 | /* | |
103 | * This request causes hardware error, device needs to be Lun Reset. | |
104 | * So here we force the state machine to IDLE state so the rest IOs | |
105 | * can reach RNC state handler, these IOs will be completed by RNC with | |
106 | * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ | |
107 | sci_base_state_machine_change_state( | |
108 | &this_device->ready_substate_machine, | |
109 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET | |
110 | ); | |
111 | } else if (scic_sds_remote_device_get_request_count(this_device) == 0) { | |
112 | sci_base_state_machine_change_state( | |
113 | &this_device->ready_substate_machine, | |
114 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | |
115 | ); | |
116 | } | |
117 | } | |
118 | } | |
119 | ||
120 | if (status != SCI_SUCCESS) | |
121 | dev_err(scirdev_to_dev(this_device), | |
122 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " | |
123 | "could not complete\n", | |
124 | __func__, | |
125 | this_device->owning_port, | |
126 | this_device, | |
127 | the_request, | |
128 | status); | |
129 | ||
130 | return status; | |
131 | } | |
132 | ||
133 | /* | |
134 | * ***************************************************************************** | |
135 | * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS | |
136 | * ***************************************************************************** */ | |
137 | ||
138 | /** | |
139 | * This is the READY NCQ substate handler to start task management request. In | |
140 | * this routine, we suspend and resume the RNC. | |
141 | * @device: The target device a task management request towards to. | |
142 | * @request: The task request. | |
143 | * | |
144 | * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to | |
145 | * let controller_start_task_handler know that the controller can't post TC for | |
146 | * task request yet, instead, when RNC gets resumed, a controller_continue_task | |
147 | * callback will be called. | |
148 | */ | |
149 | static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( | |
150 | struct sci_base_remote_device *device, | |
151 | struct sci_base_request *request) | |
152 | { | |
153 | enum sci_status status; | |
154 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
155 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | |
156 | ||
157 | /* Will the port allow the io request to start? */ | |
158 | status = this_device->owning_port->state_handlers->start_io_handler( | |
159 | this_device->owning_port, | |
160 | this_device, | |
161 | this_request | |
162 | ); | |
163 | ||
164 | if (SCI_SUCCESS == status) { | |
165 | status = | |
166 | scic_sds_remote_node_context_start_task(this_device->rnc, this_request); | |
167 | ||
168 | if (SCI_SUCCESS == status) { | |
169 | status = this_request->state_handlers->parent.start_handler(request); | |
170 | } | |
171 | ||
172 | if (status == SCI_SUCCESS) { | |
173 | /* | |
174 | * / @note If the remote device state is not IDLE this will replace | |
175 | * / the request that probably resulted in the task management | |
176 | * / request. */ | |
177 | this_device->working_request = this_request; | |
178 | ||
179 | sci_base_state_machine_change_state( | |
180 | &this_device->ready_substate_machine, | |
181 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD | |
182 | ); | |
183 | ||
184 | /* | |
185 | * The remote node context must cleanup the TCi to NCQ mapping table. | |
186 | * The only way to do this correctly is to either write to the TLCR | |
187 | * register or to invalidate and repost the RNC. In either case the | |
188 | * remote node context state machine will take the correct action when | |
189 | * the remote node context is suspended and later resumed. */ | |
190 | scic_sds_remote_node_context_suspend( | |
191 | this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); | |
192 | ||
193 | scic_sds_remote_node_context_resume( | |
194 | this_device->rnc, | |
7fbafaa5 | 195 | (scics_sds_remote_node_context_callback) |
6f231dda DW |
196 | scic_sds_remote_device_continue_request, |
197 | this_device); | |
198 | } | |
199 | ||
200 | scic_sds_remote_device_start_request(this_device, this_request, status); | |
201 | ||
202 | /* | |
203 | * We need to let the controller start request handler know that it can't | |
204 | * post TC yet. We will provide a callback function to post TC when RNC gets | |
205 | * resumed. */ | |
206 | return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; | |
207 | } | |
208 | ||
209 | return status; | |
210 | } | |
211 | ||
212 | /* | |
213 | * ***************************************************************************** | |
214 | * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS | |
215 | * ***************************************************************************** */ | |
216 | ||
217 | /** | |
218 | * This method will handle the start io operation for a sata device that is in | |
219 | * the command idle state. - Evalute the type of IO request to be started - | |
220 | * If its an NCQ request change to NCQ substate - If its any other command | |
221 | * change to the CMD substate | |
222 | * @device: | |
223 | * @request: | |
224 | * | |
225 | * If this is a softreset we may want to have a different substate. enum sci_status | |
226 | */ | |
227 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( | |
228 | struct sci_base_remote_device *device, | |
229 | struct sci_base_request *request) | |
230 | { | |
231 | enum sci_status status; | |
232 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
233 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | |
234 | ||
235 | ||
236 | /* Will the port allow the io request to start? */ | |
237 | status = this_device->owning_port->state_handlers->start_io_handler( | |
238 | this_device->owning_port, | |
239 | this_device, | |
240 | io_request | |
241 | ); | |
242 | ||
243 | if (status == SCI_SUCCESS) { | |
244 | status = | |
245 | scic_sds_remote_node_context_start_io(this_device->rnc, io_request); | |
246 | ||
247 | if (status == SCI_SUCCESS) { | |
248 | status = io_request->state_handlers->parent.start_handler(request); | |
249 | } | |
250 | ||
251 | if (status == SCI_SUCCESS) { | |
252 | if ( | |
253 | scic_cb_request_get_sat_protocol(io_request->user_request) | |
254 | == SAT_PROTOCOL_FPDMA | |
255 | ) { | |
256 | sci_base_state_machine_change_state( | |
257 | &this_device->ready_substate_machine, | |
258 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ | |
259 | ); | |
260 | } else { | |
261 | this_device->working_request = io_request; | |
262 | ||
263 | sci_base_state_machine_change_state( | |
264 | &this_device->ready_substate_machine, | |
265 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD | |
266 | ); | |
267 | } | |
268 | } | |
269 | ||
270 | scic_sds_remote_device_start_request(this_device, io_request, status); | |
271 | } | |
272 | ||
273 | return status; | |
274 | } | |
275 | ||
276 | ||
277 | /** | |
278 | * | |
279 | * @[in]: device The device received event. | |
280 | * @[in]: event_code The event code. | |
281 | * | |
282 | * This method will handle the event for a sata device that is in the idle | |
283 | * state. We pick up suspension events to handle specifically to this state. We | |
284 | * resume the RNC right away. enum sci_status | |
285 | */ | |
286 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( | |
287 | struct scic_sds_remote_device *this_device, | |
288 | u32 event_code) | |
289 | { | |
290 | enum sci_status status; | |
291 | ||
292 | status = scic_sds_remote_device_general_event_handler(this_device, event_code); | |
293 | ||
294 | if (status == SCI_SUCCESS) { | |
295 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX | |
296 | || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | |
297 | status = scic_sds_remote_node_context_resume( | |
298 | this_device->rnc, NULL, NULL); | |
299 | } | |
300 | } | |
301 | ||
302 | return status; | |
303 | } | |
304 | ||
305 | ||
306 | /* | |
307 | * ***************************************************************************** | |
308 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | |
309 | * ***************************************************************************** */ | |
310 | ||
311 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( | |
312 | struct sci_base_remote_device *device, | |
313 | struct sci_base_request *request) | |
314 | { | |
315 | enum sci_status status; | |
316 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
317 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | |
318 | ||
319 | if ( | |
320 | scic_cb_request_get_sat_protocol(io_request->user_request) | |
321 | == SAT_PROTOCOL_FPDMA | |
322 | ) { | |
323 | status = this_device->owning_port->state_handlers->start_io_handler( | |
324 | this_device->owning_port, | |
325 | this_device, | |
326 | io_request | |
327 | ); | |
328 | ||
329 | if (status == SCI_SUCCESS) { | |
330 | status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request); | |
331 | ||
332 | if (status == SCI_SUCCESS) { | |
333 | status = io_request->state_handlers->parent.start_handler(request); | |
334 | } | |
335 | ||
336 | scic_sds_remote_device_start_request(this_device, io_request, status); | |
337 | } | |
338 | } else { | |
339 | status = SCI_FAILURE_INVALID_STATE; | |
340 | } | |
341 | ||
342 | return status; | |
343 | } | |
344 | ||
345 | ||
346 | /** | |
347 | * This method will handle events received while the STP device is in the ready | |
348 | * command substate. | |
349 | * @this_device: This is the device object that is receiving the event. | |
350 | * @event_code: The event code to process. | |
351 | * | |
352 | * enum sci_status | |
353 | */ | |
354 | ||
355 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( | |
356 | struct scic_sds_remote_device *this_device, | |
357 | u32 frame_index) | |
358 | { | |
359 | enum sci_status status; | |
360 | struct sata_fis_header *frame_header; | |
361 | ||
362 | status = scic_sds_unsolicited_frame_control_get_header( | |
363 | &(scic_sds_remote_device_get_controller(this_device)->uf_control), | |
364 | frame_index, | |
365 | (void **)&frame_header | |
366 | ); | |
367 | ||
368 | if (status == SCI_SUCCESS) { | |
369 | if ( | |
370 | (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) | |
371 | && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) | |
372 | ) { | |
373 | this_device->not_ready_reason = | |
374 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; | |
375 | ||
376 | sci_base_state_machine_change_state( | |
377 | &this_device->ready_substate_machine, | |
378 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR | |
379 | ); | |
380 | } else { | |
381 | status = SCI_FAILURE; | |
382 | } | |
383 | ||
384 | scic_sds_controller_release_frame( | |
385 | scic_sds_remote_device_get_controller(this_device), frame_index | |
386 | ); | |
387 | } | |
388 | ||
389 | return status; | |
390 | } | |
391 | ||
392 | /* | |
393 | * ***************************************************************************** | |
394 | * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS | |
395 | * ***************************************************************************** */ | |
396 | ||
397 | /** | |
398 | * This device is already handling a command it can not accept new commands | |
399 | * until this one is complete. | |
400 | * @device: | |
401 | * @request: | |
402 | * | |
403 | * enum sci_status | |
404 | */ | |
405 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( | |
406 | struct sci_base_remote_device *device, | |
407 | struct sci_base_request *request) | |
408 | { | |
409 | return SCI_FAILURE_INVALID_STATE; | |
410 | } | |
411 | ||
412 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( | |
413 | struct scic_sds_remote_device *this_device, | |
414 | u32 suspend_type) | |
415 | { | |
416 | enum sci_status status; | |
417 | ||
418 | status = scic_sds_remote_node_context_suspend( | |
419 | this_device->rnc, suspend_type, NULL, NULL | |
420 | ); | |
421 | ||
422 | return status; | |
423 | } | |
424 | ||
425 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( | |
426 | struct scic_sds_remote_device *this_device, | |
427 | u32 frame_index) | |
428 | { | |
429 | enum sci_status status; | |
430 | ||
431 | /* | |
432 | * / The device doe not process any UF received from the hardware while | |
433 | * / in this state. All unsolicited frames are forwarded to the io request | |
434 | * / object. */ | |
435 | status = scic_sds_io_request_frame_handler( | |
436 | this_device->working_request, | |
437 | frame_index | |
438 | ); | |
439 | ||
440 | return status; | |
441 | } | |
442 | ||
443 | ||
444 | /* | |
445 | * ***************************************************************************** | |
446 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | |
447 | * ***************************************************************************** */ | |
448 | ||
449 | /* | |
450 | * ***************************************************************************** | |
451 | * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS | |
452 | * ***************************************************************************** */ | |
453 | ||
454 | /* | |
455 | * ***************************************************************************** | |
456 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS | |
457 | * ***************************************************************************** */ | |
458 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( | |
459 | struct sci_base_remote_device *device, | |
460 | struct sci_base_request *request) | |
461 | { | |
462 | return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; | |
463 | } | |
464 | ||
465 | ||
466 | ||
467 | /** | |
468 | * This method will perform the STP request (both io or task) completion | |
469 | * processing for await reset state. | |
470 | * @device: This parameter specifies the device for which the request is being | |
471 | * completed. | |
472 | * @request: This parameter specifies the request being completed. | |
473 | * | |
474 | * This method returns an indication as to whether the request processing | |
475 | * completed successfully. | |
476 | */ | |
477 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( | |
478 | struct sci_base_remote_device *device, | |
479 | struct sci_base_request *request) | |
480 | { | |
481 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
482 | struct scic_sds_request *the_request = (struct scic_sds_request *)request; | |
483 | enum sci_status status; | |
484 | ||
485 | status = scic_sds_io_request_complete(the_request); | |
486 | ||
487 | if (status == SCI_SUCCESS) { | |
488 | status = scic_sds_port_complete_io( | |
489 | this_device->owning_port, this_device, the_request | |
490 | ); | |
491 | ||
492 | if (status == SCI_SUCCESS) | |
493 | scic_sds_remote_device_decrement_request_count(this_device); | |
494 | } | |
495 | ||
496 | if (status != SCI_SUCCESS) | |
497 | dev_err(scirdev_to_dev(this_device), | |
498 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " | |
499 | "could not complete\n", | |
500 | __func__, | |
501 | this_device->owning_port, | |
502 | this_device, | |
503 | the_request, | |
504 | status); | |
505 | ||
506 | return status; | |
507 | } | |
508 | ||
509 | #if !defined(DISABLE_ATAPI) | |
510 | /* | |
511 | * ***************************************************************************** | |
512 | * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS | |
513 | * ***************************************************************************** */ | |
514 | ||
515 | /** | |
516 | * | |
517 | * @[in]: device The device received event. | |
518 | * @[in]: event_code The event code. | |
519 | * | |
520 | * This method will handle the event for a ATAPI device that is in the ATAPI | |
521 | * ERROR state. We pick up suspension events to handle specifically to this | |
522 | * state. We resume the RNC right away. We then complete the outstanding IO to | |
523 | * this device. enum sci_status | |
524 | */ | |
525 | enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( | |
526 | struct scic_sds_remote_device *this_device, | |
527 | u32 event_code) | |
528 | { | |
529 | enum sci_status status; | |
530 | ||
531 | status = scic_sds_remote_device_general_event_handler(this_device, event_code); | |
532 | ||
533 | if (status == SCI_SUCCESS) { | |
534 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX | |
535 | || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | |
536 | status = scic_sds_remote_node_context_resume( | |
537 | this_device->rnc, | |
538 | this_device->working_request->state_handlers->parent.complete_handler, | |
539 | (void *)this_device->working_request | |
540 | ); | |
541 | } | |
542 | } | |
543 | ||
544 | return status; | |
545 | } | |
546 | #endif /* !defined(DISABLE_ATAPI) */ | |
547 | ||
548 | /* --------------------------------------------------------------------------- */ | |
549 | ||
550 | struct scic_sds_remote_device_state_handler | |
551 | scic_sds_stp_remote_device_ready_substate_handler_table[ | |
552 | SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = | |
553 | { | |
554 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ | |
555 | { | |
556 | { | |
557 | scic_sds_remote_device_default_start_handler, | |
558 | scic_sds_remote_device_ready_state_stop_handler, | |
559 | scic_sds_remote_device_default_fail_handler, | |
560 | scic_sds_remote_device_default_destruct_handler, | |
561 | scic_sds_remote_device_ready_state_reset_handler, | |
562 | scic_sds_remote_device_default_reset_complete_handler, | |
563 | scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, | |
564 | scic_sds_remote_device_default_complete_request_handler, | |
565 | scic_sds_remote_device_default_continue_request_handler, | |
566 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
567 | scic_sds_remote_device_default_complete_request_handler | |
568 | }, | |
569 | scic_sds_remote_device_default_suspend_handler, | |
570 | scic_sds_remote_device_default_resume_handler, | |
571 | scic_sds_stp_remote_device_ready_idle_substate_event_handler, | |
572 | scic_sds_remote_device_default_frame_handler | |
573 | }, | |
574 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ | |
575 | { | |
576 | { | |
577 | scic_sds_remote_device_default_start_handler, | |
578 | scic_sds_remote_device_ready_state_stop_handler, | |
579 | scic_sds_remote_device_default_fail_handler, | |
580 | scic_sds_remote_device_default_destruct_handler, | |
581 | scic_sds_remote_device_ready_state_reset_handler, | |
582 | scic_sds_remote_device_default_reset_complete_handler, | |
583 | scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, | |
584 | scic_sds_stp_remote_device_complete_request, | |
585 | scic_sds_remote_device_default_continue_request_handler, | |
586 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
587 | scic_sds_stp_remote_device_complete_request, | |
588 | }, | |
589 | scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, | |
590 | scic_sds_remote_device_default_resume_handler, | |
591 | scic_sds_remote_device_general_event_handler, | |
592 | scic_sds_stp_remote_device_ready_cmd_substate_frame_handler | |
593 | }, | |
594 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */ | |
595 | { | |
596 | { | |
597 | scic_sds_remote_device_default_start_handler, | |
598 | scic_sds_remote_device_ready_state_stop_handler, | |
599 | scic_sds_remote_device_default_fail_handler, | |
600 | scic_sds_remote_device_default_destruct_handler, | |
601 | scic_sds_remote_device_ready_state_reset_handler, | |
602 | scic_sds_remote_device_default_reset_complete_handler, | |
603 | scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, | |
604 | scic_sds_stp_remote_device_complete_request, | |
605 | scic_sds_remote_device_default_continue_request_handler, | |
606 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
607 | scic_sds_stp_remote_device_complete_request | |
608 | }, | |
609 | scic_sds_remote_device_default_suspend_handler, | |
610 | scic_sds_remote_device_default_resume_handler, | |
611 | scic_sds_remote_device_general_event_handler, | |
612 | scic_sds_stp_remote_device_ready_ncq_substate_frame_handler | |
613 | }, | |
614 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */ | |
615 | { | |
616 | { | |
617 | scic_sds_remote_device_default_start_handler, | |
618 | scic_sds_remote_device_ready_state_stop_handler, | |
619 | scic_sds_remote_device_default_fail_handler, | |
620 | scic_sds_remote_device_default_destruct_handler, | |
621 | scic_sds_remote_device_ready_state_reset_handler, | |
622 | scic_sds_remote_device_default_reset_complete_handler, | |
623 | scic_sds_remote_device_default_start_request_handler, | |
624 | scic_sds_stp_remote_device_complete_request, | |
625 | scic_sds_remote_device_default_continue_request_handler, | |
626 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
627 | scic_sds_stp_remote_device_complete_request | |
628 | }, | |
629 | scic_sds_remote_device_default_suspend_handler, | |
630 | scic_sds_remote_device_default_resume_handler, | |
631 | scic_sds_remote_device_general_event_handler, | |
632 | scic_sds_remote_device_general_frame_handler | |
633 | }, | |
634 | #if !defined(DISABLE_ATAPI) | |
635 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */ | |
636 | { | |
637 | { | |
638 | scic_sds_remote_device_default_start_handler, | |
639 | scic_sds_remote_device_ready_state_stop_handler, | |
640 | scic_sds_remote_device_default_fail_handler, | |
641 | scic_sds_remote_device_default_destruct_handler, | |
642 | scic_sds_remote_device_ready_state_reset_handler, | |
643 | scic_sds_remote_device_default_reset_complete_handler, | |
644 | scic_sds_remote_device_default_start_request_handler, | |
645 | scic_sds_stp_remote_device_complete_request, | |
646 | scic_sds_remote_device_default_continue_request_handler, | |
647 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
648 | scic_sds_stp_remote_device_complete_request | |
649 | }, | |
650 | scic_sds_remote_device_default_suspend_handler, | |
651 | scic_sds_remote_device_default_resume_handler, | |
652 | scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, | |
653 | scic_sds_remote_device_general_frame_handler | |
654 | }, | |
655 | #endif | |
656 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */ | |
657 | { | |
658 | { | |
659 | scic_sds_remote_device_default_start_handler, | |
660 | scic_sds_remote_device_ready_state_stop_handler, | |
661 | scic_sds_remote_device_default_fail_handler, | |
662 | scic_sds_remote_device_default_destruct_handler, | |
663 | scic_sds_remote_device_ready_state_reset_handler, | |
664 | scic_sds_remote_device_default_reset_complete_handler, | |
665 | scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, | |
666 | scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, | |
667 | scic_sds_remote_device_default_continue_request_handler, | |
668 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | |
669 | scic_sds_stp_remote_device_complete_request | |
670 | }, | |
671 | scic_sds_remote_device_default_suspend_handler, | |
672 | scic_sds_remote_device_default_resume_handler, | |
673 | scic_sds_remote_device_general_event_handler, | |
674 | scic_sds_remote_device_general_frame_handler | |
675 | } | |
676 | }; | |
677 | ||
678 | /* | |
679 | * This file is provided under a dual BSD/GPLv2 license. When using or | |
680 | * redistributing this file, you may do so under either license. | |
681 | * | |
682 | * GPL LICENSE SUMMARY | |
683 | * | |
684 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | |
685 | * | |
686 | * This program is free software; you can redistribute it and/or modify | |
687 | * it under the terms of version 2 of the GNU General Public License as | |
688 | * published by the Free Software Foundation. | |
689 | * | |
690 | * This program is distributed in the hope that it will be useful, but | |
691 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
692 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
693 | * General Public License for more details. | |
694 | * | |
695 | * You should have received a copy of the GNU General Public License | |
696 | * along with this program; if not, write to the Free Software | |
697 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
698 | * The full GNU General Public License is included in this distribution | |
699 | * in the file called LICENSE.GPL. | |
700 | * | |
701 | * BSD LICENSE | |
702 | * | |
703 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | |
704 | * All rights reserved. | |
705 | * | |
706 | * Redistribution and use in source and binary forms, with or without | |
707 | * modification, are permitted provided that the following conditions | |
708 | * are met: | |
709 | * | |
710 | * * Redistributions of source code must retain the above copyright | |
711 | * notice, this list of conditions and the following disclaimer. | |
712 | * * Redistributions in binary form must reproduce the above copyright | |
713 | * notice, this list of conditions and the following disclaimer in | |
714 | * the documentation and/or other materials provided with the | |
715 | * distribution. | |
716 | * * Neither the name of Intel Corporation nor the names of its | |
717 | * contributors may be used to endorse or promote products derived | |
718 | * from this software without specific prior written permission. | |
719 | * | |
720 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
721 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
722 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
723 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
724 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
725 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
726 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
727 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
728 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
729 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
730 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
731 | */ | |
732 | ||
733 | #include "sci_base_state.h" | |
734 | #include "scic_remote_device.h" | |
735 | #include "scic_user_callback.h" | |
736 | #include "scic_sds_controller.h" | |
737 | #include "scic_sds_port.h" | |
738 | #include "scic_sds_remote_device.h" | |
739 | #include "sci_util.h" | |
740 | #include "sci_environment.h" | |
741 | ||
742 | /* | |
743 | * ***************************************************************************** | |
744 | * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS | |
745 | * ***************************************************************************** */ | |
746 | ||
747 | static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( | |
748 | void *user_cookie) | |
749 | { | |
750 | struct scic_sds_remote_device *this_device; | |
751 | ||
752 | this_device = (struct scic_sds_remote_device *)user_cookie; | |
753 | ||
754 | /* | |
755 | * For NCQ operation we do not issue a | |
756 | * scic_cb_remote_device_not_ready(). As a result, avoid sending | |
757 | * the ready notification. */ | |
758 | if (this_device->ready_substate_machine.previous_state_id | |
759 | != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) { | |
760 | scic_cb_remote_device_ready( | |
761 | scic_sds_remote_device_get_controller(this_device), this_device | |
762 | ); | |
763 | } | |
764 | } | |
765 | ||
766 | /* | |
767 | * ***************************************************************************** | |
768 | * * STP REMOTE DEVICE READY IDLE SUBSTATE | |
769 | * ***************************************************************************** */ | |
770 | ||
771 | /** | |
772 | * | |
773 | * @device: This is the SCI base object which is cast into a | |
774 | * struct scic_sds_remote_device object. | |
775 | * | |
776 | */ | |
777 | static void scic_sds_stp_remote_device_ready_idle_substate_enter( | |
778 | struct sci_base_object *device) | |
779 | { | |
780 | struct scic_sds_remote_device *this_device; | |
781 | ||
782 | this_device = (struct scic_sds_remote_device *)device; | |
783 | ||
784 | SET_STATE_HANDLER( | |
785 | this_device, | |
786 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
787 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | |
788 | ); | |
789 | ||
790 | this_device->working_request = NULL; | |
791 | ||
792 | if (scic_sds_remote_node_context_is_ready(this_device->rnc)) { | |
793 | /* | |
794 | * Since the RNC is ready, it's alright to finish completion | |
795 | * processing (e.g. signal the remote device is ready). */ | |
796 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( | |
797 | this_device | |
798 | ); | |
799 | } else { | |
800 | scic_sds_remote_node_context_resume( | |
801 | this_device->rnc, | |
802 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, | |
803 | this_device | |
804 | ); | |
805 | } | |
806 | } | |
807 | ||
808 | /* | |
809 | * ***************************************************************************** | |
810 | * * STP REMOTE DEVICE READY CMD SUBSTATE | |
811 | * ***************************************************************************** */ | |
812 | ||
813 | /** | |
814 | * | |
815 | * @device: This is the SCI base object which is cast into a | |
816 | * struct scic_sds_remote_device object. | |
817 | * | |
818 | */ | |
819 | static void scic_sds_stp_remote_device_ready_cmd_substate_enter( | |
820 | struct sci_base_object *device) | |
821 | { | |
822 | struct scic_sds_remote_device *this_device; | |
823 | ||
824 | this_device = (struct scic_sds_remote_device *)device; | |
825 | ||
826 | BUG_ON(this_device->working_request == NULL); | |
827 | ||
828 | SET_STATE_HANDLER( | |
829 | this_device, | |
830 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
831 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD | |
832 | ); | |
833 | ||
834 | scic_cb_remote_device_not_ready( | |
835 | scic_sds_remote_device_get_controller(this_device), | |
836 | this_device, | |
837 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED | |
838 | ); | |
839 | } | |
840 | ||
841 | /* | |
842 | * ***************************************************************************** | |
843 | * * STP REMOTE DEVICE READY NCQ SUBSTATE | |
844 | * ***************************************************************************** */ | |
845 | ||
846 | /** | |
847 | * | |
848 | * @device: This is the SCI base object which is cast into a | |
849 | * struct scic_sds_remote_device object. | |
850 | * | |
851 | */ | |
852 | static void scic_sds_stp_remote_device_ready_ncq_substate_enter( | |
853 | struct sci_base_object *device) | |
854 | { | |
855 | struct scic_sds_remote_device *this_device; | |
856 | ||
857 | this_device = (struct scic_sds_remote_device *)device; | |
858 | ||
859 | SET_STATE_HANDLER( | |
860 | this_device, | |
861 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
862 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ | |
863 | ); | |
864 | } | |
865 | ||
866 | /* | |
867 | * ***************************************************************************** | |
868 | * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE | |
869 | * ***************************************************************************** */ | |
870 | ||
871 | /** | |
872 | * | |
873 | * @device: This is the SCI base object which is cast into a | |
874 | * struct scic_sds_remote_device object. | |
875 | * | |
876 | */ | |
877 | static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( | |
878 | struct sci_base_object *device) | |
879 | { | |
880 | struct scic_sds_remote_device *this_device; | |
881 | ||
882 | this_device = (struct scic_sds_remote_device *)device; | |
883 | ||
884 | SET_STATE_HANDLER( | |
885 | this_device, | |
886 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
887 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR | |
888 | ); | |
889 | ||
890 | if (this_device->not_ready_reason == | |
891 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) { | |
892 | scic_cb_remote_device_not_ready( | |
893 | scic_sds_remote_device_get_controller(this_device), | |
894 | this_device, | |
895 | this_device->not_ready_reason | |
896 | ); | |
897 | } | |
898 | } | |
899 | ||
900 | /* | |
901 | * ***************************************************************************** | |
902 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE | |
903 | * ***************************************************************************** */ | |
904 | ||
905 | /** | |
906 | * The enter routine to READY AWAIT RESET substate. | |
907 | * @device: This is the SCI base object which is cast into a | |
908 | * struct scic_sds_remote_device object. | |
909 | * | |
910 | */ | |
911 | static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( | |
912 | struct sci_base_object *device) | |
913 | { | |
914 | struct scic_sds_remote_device *this_device; | |
915 | ||
916 | this_device = (struct scic_sds_remote_device *)device; | |
917 | ||
918 | SET_STATE_HANDLER( | |
919 | this_device, | |
920 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
921 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET | |
922 | ); | |
923 | } | |
924 | ||
925 | #if !defined(DISABLE_ATAPI) | |
926 | /* | |
927 | * ***************************************************************************** | |
928 | * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE | |
929 | * ***************************************************************************** */ | |
930 | ||
931 | /** | |
932 | * The enter routine to READY ATAPI ERROR substate. | |
933 | * @device: This is the SCI base object which is cast into a | |
934 | * struct scic_sds_remote_device object. | |
935 | * | |
936 | */ | |
937 | void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( | |
938 | struct sci_base_object *device) | |
939 | { | |
940 | struct scic_sds_remote_device *this_device; | |
941 | ||
942 | this_device = (struct scic_sds_remote_device *)device; | |
943 | ||
944 | SET_STATE_HANDLER( | |
945 | this_device, | |
946 | scic_sds_stp_remote_device_ready_substate_handler_table, | |
947 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR | |
948 | ); | |
949 | } | |
950 | #endif /* !defined(DISABLE_ATAPI) */ | |
951 | ||
952 | /* --------------------------------------------------------------------------- */ | |
953 | ||
954 | const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { | |
955 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { | |
956 | .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, | |
957 | }, | |
958 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { | |
959 | .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, | |
960 | }, | |
961 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { | |
962 | .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, | |
963 | }, | |
964 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { | |
965 | .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, | |
966 | }, | |
967 | #if !defined(DISABLE_ATAPI) | |
968 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { | |
969 | .enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter, | |
970 | }, | |
971 | #endif | |
972 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { | |
973 | .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, | |
974 | }, | |
975 | }; |