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 | 56 | #include "intel_sas.h" |
e574a8c1 | 57 | #include "scic_controller.h" |
6f231dda | 58 | #include "scic_phy.h" |
e574a8c1 | 59 | #include "scic_port.h" |
6f231dda | 60 | #include "scic_remote_device.h" |
e574a8c1 | 61 | #include "scic_sds_controller.h" |
6f231dda | 62 | #include "scic_sds_phy.h" |
e574a8c1 | 63 | #include "scic_sds_port.h" |
6f231dda | 64 | #include "scic_sds_remote_device.h" |
e574a8c1 | 65 | #include "scic_sds_remote_node_context.h" |
6f231dda | 66 | #include "scic_sds_request.h" |
e574a8c1 DW |
67 | #include "sci_environment.h" |
68 | #include "sci_util.h" | |
69 | #include "scu_event_codes.h" | |
70 | ||
6f231dda DW |
71 | |
72 | #define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) | |
73 | ||
74 | /* | |
75 | * ***************************************************************************** | |
76 | * * CORE REMOTE DEVICE PRIVATE METHODS | |
77 | * ***************************************************************************** */ | |
78 | ||
79 | /* | |
80 | * ***************************************************************************** | |
81 | * * CORE REMOTE DEVICE PUBLIC METHODS | |
82 | * ***************************************************************************** */ | |
83 | ||
84 | u32 scic_remote_device_get_object_size(void) | |
85 | { | |
86 | return sizeof(struct scic_sds_remote_device) | |
87 | + sizeof(struct scic_sds_remote_node_context); | |
88 | } | |
89 | ||
6f231dda DW |
90 | enum sci_status scic_remote_device_da_construct( |
91 | struct scic_sds_remote_device *sci_dev) | |
92 | { | |
93 | enum sci_status status; | |
94 | u16 remote_node_index; | |
95 | struct sci_sas_identify_address_frame_protocols protocols; | |
96 | ||
97 | /* | |
98 | * This information is request to determine how many remote node context | |
99 | * entries will be needed to store the remote node. | |
100 | */ | |
101 | scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols); | |
102 | sci_dev->target_protocols.u.all = protocols.u.all; | |
103 | sci_dev->is_direct_attached = true; | |
104 | #if !defined(DISABLE_ATAPI) | |
105 | sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev); | |
106 | #endif | |
107 | ||
108 | status = scic_sds_controller_allocate_remote_node_context( | |
109 | sci_dev->owning_port->owning_controller, | |
110 | sci_dev, | |
111 | &remote_node_index); | |
112 | ||
113 | if (status == SCI_SUCCESS) { | |
068b2c03 | 114 | sci_dev->rnc->remote_node_index = remote_node_index; |
6f231dda DW |
115 | |
116 | scic_sds_port_get_attached_sas_address( | |
117 | sci_dev->owning_port, &sci_dev->device_address); | |
118 | ||
119 | if (sci_dev->target_protocols.u.bits.attached_ssp_target) { | |
120 | sci_dev->has_ready_substate_machine = false; | |
121 | } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { | |
122 | sci_dev->has_ready_substate_machine = true; | |
123 | ||
124 | sci_base_state_machine_construct( | |
125 | &sci_dev->ready_substate_machine, | |
126 | &sci_dev->parent.parent, | |
127 | scic_sds_stp_remote_device_ready_substate_table, | |
128 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | |
129 | } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { | |
130 | sci_dev->has_ready_substate_machine = true; | |
131 | ||
132 | /* add the SMP ready substate machine construction here */ | |
133 | sci_base_state_machine_construct( | |
134 | &sci_dev->ready_substate_machine, | |
135 | &sci_dev->parent.parent, | |
136 | scic_sds_smp_remote_device_ready_substate_table, | |
137 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | |
138 | } | |
139 | ||
140 | sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed( | |
141 | sci_dev->owning_port); | |
142 | ||
143 | /* / @todo Should I assign the port width by reading all of the phys on the port? */ | |
144 | sci_dev->device_port_width = 1; | |
145 | } | |
146 | ||
147 | return status; | |
148 | } | |
149 | ||
150 | ||
151 | static void scic_sds_remote_device_get_info_from_smp_discover_response( | |
152 | struct scic_sds_remote_device *this_device, | |
153 | struct smp_response_discover *discover_response) | |
154 | { | |
155 | /* decode discover_response to set sas_address to this_device. */ | |
156 | this_device->device_address.high = | |
157 | discover_response->attached_sas_address.high; | |
158 | ||
159 | this_device->device_address.low = | |
160 | discover_response->attached_sas_address.low; | |
161 | ||
162 | this_device->target_protocols.u.all = discover_response->protocols.u.all; | |
163 | } | |
164 | ||
165 | ||
166 | enum sci_status scic_remote_device_ea_construct( | |
167 | struct scic_sds_remote_device *sci_dev, | |
168 | struct smp_response_discover *discover_response) | |
169 | { | |
170 | enum sci_status status; | |
171 | struct scic_sds_controller *the_controller; | |
172 | ||
173 | the_controller = scic_sds_port_get_controller(sci_dev->owning_port); | |
174 | ||
175 | scic_sds_remote_device_get_info_from_smp_discover_response( | |
176 | sci_dev, discover_response); | |
177 | ||
178 | status = scic_sds_controller_allocate_remote_node_context( | |
179 | the_controller, sci_dev, &sci_dev->rnc->remote_node_index); | |
180 | ||
181 | if (status == SCI_SUCCESS) { | |
182 | if (sci_dev->target_protocols.u.bits.attached_ssp_target) { | |
183 | sci_dev->has_ready_substate_machine = false; | |
184 | } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { | |
185 | sci_dev->has_ready_substate_machine = true; | |
186 | ||
187 | /* add the SMP ready substate machine construction here */ | |
188 | sci_base_state_machine_construct( | |
189 | &sci_dev->ready_substate_machine, | |
190 | &sci_dev->parent.parent, | |
191 | scic_sds_smp_remote_device_ready_substate_table, | |
192 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | |
193 | } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { | |
194 | sci_dev->has_ready_substate_machine = true; | |
195 | ||
196 | sci_base_state_machine_construct( | |
197 | &sci_dev->ready_substate_machine, | |
198 | &sci_dev->parent.parent, | |
199 | scic_sds_stp_remote_device_ready_substate_table, | |
200 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | |
201 | } | |
202 | ||
203 | /* | |
204 | * For SAS-2 the physical link rate is actually a logical link | |
205 | * rate that incorporates multiplexing. The SCU doesn't | |
206 | * incorporate multiplexing and for the purposes of the | |
207 | * connection the logical link rate is that same as the | |
208 | * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay | |
209 | * one another, so this code works for both situations. */ | |
210 | sci_dev->connection_rate = min_t(u16, | |
211 | scic_sds_port_get_max_allowed_speed(sci_dev->owning_port), | |
212 | discover_response->u2.sas1_1.negotiated_physical_link_rate | |
213 | ); | |
214 | ||
215 | /* / @todo Should I assign the port width by reading all of the phys on the port? */ | |
216 | sci_dev->device_port_width = 1; | |
217 | } | |
218 | ||
219 | return status; | |
220 | } | |
221 | ||
222 | enum sci_status scic_remote_device_destruct( | |
223 | struct scic_sds_remote_device *sci_dev) | |
224 | { | |
225 | return sci_dev->state_handlers->parent.destruct_handler(&sci_dev->parent); | |
226 | } | |
227 | ||
228 | ||
229 | enum sci_status scic_remote_device_start( | |
230 | struct scic_sds_remote_device *sci_dev, | |
231 | u32 timeout) | |
232 | { | |
233 | return sci_dev->state_handlers->parent.start_handler(&sci_dev->parent); | |
234 | } | |
235 | ||
236 | ||
237 | enum sci_status scic_remote_device_stop( | |
238 | struct scic_sds_remote_device *sci_dev, | |
239 | u32 timeout) | |
240 | { | |
241 | return sci_dev->state_handlers->parent.stop_handler(&sci_dev->parent); | |
242 | } | |
243 | ||
244 | ||
245 | enum sci_status scic_remote_device_reset( | |
246 | struct scic_sds_remote_device *sci_dev) | |
247 | { | |
248 | return sci_dev->state_handlers->parent.reset_handler(&sci_dev->parent); | |
249 | } | |
250 | ||
251 | ||
252 | enum sci_status scic_remote_device_reset_complete( | |
253 | struct scic_sds_remote_device *sci_dev) | |
254 | { | |
255 | return sci_dev->state_handlers->parent.reset_complete_handler(&sci_dev->parent); | |
256 | } | |
257 | ||
258 | ||
259 | enum sci_sas_link_rate scic_remote_device_get_connection_rate( | |
260 | struct scic_sds_remote_device *sci_dev) | |
261 | { | |
262 | return sci_dev->connection_rate; | |
263 | } | |
264 | ||
265 | ||
266 | void scic_remote_device_get_protocols( | |
267 | struct scic_sds_remote_device *sci_dev, | |
268 | struct smp_discover_response_protocols *pr) | |
269 | { | |
270 | pr->u.all = sci_dev->target_protocols.u.all; | |
271 | } | |
272 | ||
273 | #if !defined(DISABLE_ATAPI) | |
274 | bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) | |
275 | { | |
276 | return sci_dev->is_atapi; | |
277 | } | |
278 | #endif | |
279 | ||
280 | ||
281 | /* | |
282 | * ***************************************************************************** | |
283 | * * SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS | |
284 | * ***************************************************************************** */ | |
285 | ||
286 | /** | |
287 | * | |
288 | * | |
289 | * Remote device timer requirements | |
290 | */ | |
291 | #define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) | |
292 | #define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) | |
293 | ||
294 | ||
295 | /** | |
296 | * | |
297 | * @this_device: The remote device for which the suspend is being requested. | |
298 | * | |
299 | * This method invokes the remote device suspend state handler. enum sci_status | |
300 | */ | |
301 | enum sci_status scic_sds_remote_device_suspend( | |
302 | struct scic_sds_remote_device *this_device, | |
303 | u32 suspend_type) | |
304 | { | |
305 | return this_device->state_handlers->suspend_handler(this_device, suspend_type); | |
306 | } | |
307 | ||
308 | /** | |
309 | * | |
310 | * @this_device: The remote device for which the resume is being requested. | |
311 | * | |
312 | * This method invokes the remote device resume state handler. enum sci_status | |
313 | */ | |
314 | enum sci_status scic_sds_remote_device_resume( | |
315 | struct scic_sds_remote_device *this_device) | |
316 | { | |
317 | return this_device->state_handlers->resume_handler(this_device); | |
318 | } | |
319 | ||
320 | /** | |
321 | * | |
322 | * @this_device: The remote device for which the event handling is being | |
323 | * requested. | |
324 | * @frame_index: This is the frame index that is being processed. | |
325 | * | |
326 | * This method invokes the frame handler for the remote device state machine | |
327 | * enum sci_status | |
328 | */ | |
329 | enum sci_status scic_sds_remote_device_frame_handler( | |
330 | struct scic_sds_remote_device *this_device, | |
331 | u32 frame_index) | |
332 | { | |
333 | return this_device->state_handlers->frame_handler(this_device, frame_index); | |
334 | } | |
335 | ||
336 | /** | |
337 | * | |
338 | * @this_device: The remote device for which the event handling is being | |
339 | * requested. | |
340 | * @event_code: This is the event code that is to be processed. | |
341 | * | |
342 | * This method invokes the remote device event handler. enum sci_status | |
343 | */ | |
344 | enum sci_status scic_sds_remote_device_event_handler( | |
345 | struct scic_sds_remote_device *this_device, | |
346 | u32 event_code) | |
347 | { | |
348 | return this_device->state_handlers->event_handler(this_device, event_code); | |
349 | } | |
350 | ||
351 | /** | |
352 | * | |
353 | * @controller: The controller that is starting the io request. | |
354 | * @this_device: The remote device for which the start io handling is being | |
355 | * requested. | |
356 | * @io_request: The io request that is being started. | |
357 | * | |
358 | * This method invokes the remote device start io handler. enum sci_status | |
359 | */ | |
360 | enum sci_status scic_sds_remote_device_start_io( | |
361 | struct scic_sds_controller *controller, | |
362 | struct scic_sds_remote_device *this_device, | |
363 | struct scic_sds_request *io_request) | |
364 | { | |
365 | return this_device->state_handlers->parent.start_io_handler( | |
366 | &this_device->parent, &io_request->parent); | |
367 | } | |
368 | ||
369 | /** | |
370 | * | |
371 | * @controller: The controller that is completing the io request. | |
372 | * @this_device: The remote device for which the complete io handling is being | |
373 | * requested. | |
374 | * @io_request: The io request that is being completed. | |
375 | * | |
376 | * This method invokes the remote device complete io handler. enum sci_status | |
377 | */ | |
378 | enum sci_status scic_sds_remote_device_complete_io( | |
379 | struct scic_sds_controller *controller, | |
380 | struct scic_sds_remote_device *this_device, | |
381 | struct scic_sds_request *io_request) | |
382 | { | |
383 | return this_device->state_handlers->parent.complete_io_handler( | |
384 | &this_device->parent, &io_request->parent); | |
385 | } | |
386 | ||
387 | /** | |
388 | * | |
389 | * @controller: The controller that is starting the task request. | |
390 | * @this_device: The remote device for which the start task handling is being | |
391 | * requested. | |
392 | * @io_request: The task request that is being started. | |
393 | * | |
394 | * This method invokes the remote device start task handler. enum sci_status | |
395 | */ | |
396 | enum sci_status scic_sds_remote_device_start_task( | |
397 | struct scic_sds_controller *controller, | |
398 | struct scic_sds_remote_device *this_device, | |
399 | struct scic_sds_request *io_request) | |
400 | { | |
401 | return this_device->state_handlers->parent.start_task_handler( | |
402 | &this_device->parent, &io_request->parent); | |
403 | } | |
404 | ||
405 | /** | |
406 | * | |
407 | * @controller: The controller that is completing the task request. | |
408 | * @this_device: The remote device for which the complete task handling is | |
409 | * being requested. | |
410 | * @io_request: The task request that is being completed. | |
411 | * | |
412 | * This method invokes the remote device complete task handler. enum sci_status | |
413 | */ | |
414 | ||
415 | /** | |
416 | * | |
417 | * @this_device: | |
418 | * @request: | |
419 | * | |
420 | * This method takes the request and bulids an appropriate SCU context for the | |
421 | * request and then requests the controller to post the request. none | |
422 | */ | |
423 | void scic_sds_remote_device_post_request( | |
424 | struct scic_sds_remote_device *this_device, | |
425 | u32 request) | |
426 | { | |
427 | u32 context; | |
428 | ||
429 | context = scic_sds_remote_device_build_command_context(this_device, request); | |
430 | ||
431 | scic_sds_controller_post_request( | |
432 | scic_sds_remote_device_get_controller(this_device), | |
433 | context | |
434 | ); | |
435 | } | |
436 | ||
437 | #if !defined(DISABLE_ATAPI) | |
438 | /** | |
439 | * | |
440 | * @this_device: The device to be checked. | |
441 | * | |
442 | * This method check the signature fis of a stp device to decide whether a | |
443 | * device is atapi or not. true if a device is atapi device. False if a device | |
444 | * is not atapi. | |
445 | */ | |
446 | bool scic_sds_remote_device_is_atapi( | |
447 | struct scic_sds_remote_device *this_device) | |
448 | { | |
449 | if (!this_device->target_protocols.u.bits.attached_stp_target) | |
450 | return false; | |
451 | else if (this_device->is_direct_attached) { | |
452 | struct scic_sds_phy *phy; | |
453 | struct scic_sata_phy_properties properties; | |
454 | struct sata_fis_reg_d2h *signature_fis; | |
455 | phy = scic_sds_port_get_a_connected_phy(this_device->owning_port); | |
456 | scic_sata_phy_get_properties(phy, &properties); | |
457 | ||
458 | /* decode the signature fis. */ | |
459 | signature_fis = &(properties.signature_fis); | |
460 | ||
461 | if ((signature_fis->sector_count == 0x01) | |
462 | && (signature_fis->lba_low == 0x01) | |
463 | && (signature_fis->lba_mid == 0x14) | |
464 | && (signature_fis->lba_high == 0xEB) | |
465 | && ((signature_fis->device & 0x5F) == 0x00) | |
466 | ) { | |
467 | /* An ATA device supporting the PACKET command set. */ | |
468 | return true; | |
469 | } else | |
470 | return false; | |
471 | } else { | |
472 | /* Expander supported ATAPI device is not currently supported. */ | |
473 | return false; | |
474 | } | |
475 | } | |
476 | #endif | |
6f231dda DW |
477 | |
478 | /** | |
479 | * | |
480 | * @user_parameter: This is cast to a remote device object. | |
481 | * | |
482 | * This method is called once the remote node context is ready to be freed. | |
483 | * The remote device can now report that its stop operation is complete. none | |
484 | */ | |
485 | static void scic_sds_cb_remote_device_rnc_destruct_complete( | |
486 | void *user_parameter) | |
487 | { | |
068b2c03 | 488 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 489 | |
068b2c03 | 490 | sci_dev = (struct scic_sds_remote_device *)user_parameter; |
6f231dda | 491 | |
068b2c03 | 492 | BUG_ON(sci_dev->started_request_count != 0); |
6f231dda | 493 | |
068b2c03 DW |
494 | sci_base_state_machine_change_state(&sci_dev->parent.state_machine, |
495 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); | |
6f231dda DW |
496 | } |
497 | ||
498 | /** | |
499 | * | |
500 | * @user_parameter: This is cast to a remote device object. | |
501 | * | |
502 | * This method is called once the remote node context has transisitioned to a | |
503 | * ready state. This is the indication that the remote device object can also | |
504 | * transition to ready. none | |
505 | */ | |
506 | static void scic_sds_remote_device_resume_complete_handler( | |
507 | void *user_parameter) | |
508 | { | |
509 | struct scic_sds_remote_device *this_device; | |
510 | ||
511 | this_device = (struct scic_sds_remote_device *)user_parameter; | |
512 | ||
513 | if ( | |
514 | sci_base_state_machine_get_state(&this_device->parent.state_machine) | |
515 | != SCI_BASE_REMOTE_DEVICE_STATE_READY | |
516 | ) { | |
517 | sci_base_state_machine_change_state( | |
518 | &this_device->parent.state_machine, | |
519 | SCI_BASE_REMOTE_DEVICE_STATE_READY | |
520 | ); | |
521 | } | |
522 | } | |
523 | ||
524 | /** | |
525 | * | |
526 | * @device: This parameter specifies the device for which the request is being | |
527 | * started. | |
528 | * @request: This parameter specifies the request being started. | |
529 | * @status: This parameter specifies the current start operation status. | |
530 | * | |
531 | * This method will perform the STP request start processing common to IO | |
532 | * requests and task requests of all types. none | |
533 | */ | |
534 | void scic_sds_remote_device_start_request( | |
535 | struct scic_sds_remote_device *this_device, | |
536 | struct scic_sds_request *the_request, | |
537 | enum sci_status status) | |
538 | { | |
539 | /* We still have a fault in starting the io complete it on the port */ | |
540 | if (status == SCI_SUCCESS) | |
541 | scic_sds_remote_device_increment_request_count(this_device); | |
542 | else{ | |
543 | this_device->owning_port->state_handlers->complete_io_handler( | |
544 | this_device->owning_port, this_device, the_request | |
545 | ); | |
546 | } | |
547 | } | |
548 | ||
549 | ||
550 | /** | |
551 | * | |
552 | * @request: This parameter specifies the request being continued. | |
553 | * | |
554 | * This method will continue to post tc for a STP request. This method usually | |
555 | * serves as a callback when RNC gets resumed during a task management | |
556 | * sequence. none | |
557 | */ | |
f7d36e18 | 558 | void scic_sds_remote_device_continue_request(void *dev) |
6f231dda | 559 | { |
f7d36e18 DW |
560 | struct scic_sds_remote_device *sci_dev = dev; |
561 | struct scic_sds_request *sci_req = sci_dev->working_request; | |
562 | ||
6f231dda | 563 | /* we need to check if this request is still valid to continue. */ |
f7d36e18 DW |
564 | if (sci_req) { |
565 | struct scic_sds_controller *scic = sci_req->owning_controller; | |
6f231dda DW |
566 | u32 state = scic->parent.state_machine.current_state_id; |
567 | sci_base_controller_request_handler_t continue_io; | |
568 | ||
569 | continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; | |
f7d36e18 DW |
570 | continue_io(&scic->parent, &sci_req->target_device->parent, |
571 | &sci_req->parent); | |
6f231dda DW |
572 | } |
573 | } | |
574 | ||
575 | /** | |
576 | * | |
577 | * @user_parameter: This is cast to a remote device object. | |
578 | * | |
579 | * This method is called once the remote node context has reached a suspended | |
580 | * state. The remote device can now report that its suspend operation is | |
581 | * complete. none | |
582 | */ | |
583 | ||
584 | /** | |
585 | * This method will terminate all of the IO requests in the controllers IO | |
586 | * request table that were targeted for this device. | |
587 | * @this_device: This parameter specifies the remote device for which to | |
588 | * attempt to terminate all requests. | |
589 | * | |
590 | * This method returns an indication as to whether all requests were | |
591 | * successfully terminated. If a single request fails to be terminated, then | |
592 | * this method will return the failure. | |
593 | */ | |
594 | static enum sci_status scic_sds_remote_device_terminate_requests( | |
595 | struct scic_sds_remote_device *this_device) | |
596 | { | |
597 | enum sci_status status = SCI_SUCCESS; | |
598 | enum sci_status terminate_status = SCI_SUCCESS; | |
599 | struct scic_sds_request *the_request; | |
600 | u32 index; | |
601 | u32 request_count = this_device->started_request_count; | |
602 | ||
603 | for (index = 0; | |
604 | (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); | |
605 | index++) { | |
606 | the_request = this_device->owning_port->owning_controller->io_request_table[index]; | |
607 | ||
608 | if ((the_request != NULL) && (the_request->target_device == this_device)) { | |
609 | terminate_status = scic_controller_terminate_request( | |
610 | this_device->owning_port->owning_controller, | |
611 | this_device, | |
612 | the_request | |
613 | ); | |
614 | ||
615 | if (terminate_status != SCI_SUCCESS) | |
616 | status = terminate_status; | |
617 | ||
618 | request_count--; | |
619 | } | |
620 | } | |
621 | ||
622 | return status; | |
623 | } | |
624 | ||
068b2c03 DW |
625 | static enum sci_status default_device_handler(struct sci_base_remote_device *base_dev, |
626 | const char *func) | |
6f231dda | 627 | { |
068b2c03 | 628 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 629 | |
068b2c03 DW |
630 | sci_dev = container_of(base_dev, typeof(*sci_dev), parent); |
631 | dev_warn(scirdev_to_dev(sci_dev), | |
632 | "%s: in wrong state: %d\n", func, | |
633 | sci_base_state_machine_get_state(&base_dev->state_machine)); | |
6f231dda DW |
634 | return SCI_FAILURE_INVALID_STATE; |
635 | } | |
636 | ||
068b2c03 DW |
637 | enum sci_status scic_sds_remote_device_default_start_handler( |
638 | struct sci_base_remote_device *base_dev) | |
6f231dda | 639 | { |
068b2c03 DW |
640 | return default_device_handler(base_dev, __func__); |
641 | } | |
6f231dda | 642 | |
068b2c03 DW |
643 | static enum sci_status scic_sds_remote_device_default_stop_handler( |
644 | struct sci_base_remote_device *base_dev) | |
645 | { | |
646 | return default_device_handler(base_dev, __func__); | |
6f231dda DW |
647 | } |
648 | ||
6f231dda | 649 | enum sci_status scic_sds_remote_device_default_fail_handler( |
068b2c03 | 650 | struct sci_base_remote_device *base_dev) |
6f231dda | 651 | { |
068b2c03 | 652 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
653 | } |
654 | ||
6f231dda | 655 | enum sci_status scic_sds_remote_device_default_destruct_handler( |
068b2c03 | 656 | struct sci_base_remote_device *base_dev) |
6f231dda | 657 | { |
068b2c03 | 658 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
659 | } |
660 | ||
6f231dda | 661 | enum sci_status scic_sds_remote_device_default_reset_handler( |
068b2c03 | 662 | struct sci_base_remote_device *base_dev) |
6f231dda | 663 | { |
068b2c03 | 664 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
665 | } |
666 | ||
6f231dda | 667 | enum sci_status scic_sds_remote_device_default_reset_complete_handler( |
068b2c03 | 668 | struct sci_base_remote_device *base_dev) |
6f231dda | 669 | { |
068b2c03 | 670 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
671 | } |
672 | ||
6f231dda | 673 | enum sci_status scic_sds_remote_device_default_suspend_handler( |
068b2c03 | 674 | struct scic_sds_remote_device *sci_dev, u32 suspend_type) |
6f231dda | 675 | { |
068b2c03 | 676 | return default_device_handler(&sci_dev->parent, __func__); |
6f231dda DW |
677 | } |
678 | ||
6f231dda | 679 | enum sci_status scic_sds_remote_device_default_resume_handler( |
068b2c03 | 680 | struct scic_sds_remote_device *sci_dev) |
6f231dda | 681 | { |
068b2c03 | 682 | return default_device_handler(&sci_dev->parent, __func__); |
6f231dda DW |
683 | } |
684 | ||
685 | /** | |
686 | * | |
687 | * @device: The struct sci_base_remote_device which is then cast into a | |
688 | * struct scic_sds_remote_device. | |
689 | * @event_code: The event code that the struct scic_sds_controller wants the device | |
690 | * object to process. | |
691 | * | |
692 | * This method is the default event handler. It will call the RNC state | |
693 | * machine handler for any RNC events otherwise it will log a warning and | |
694 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | |
695 | */ | |
696 | static enum sci_status scic_sds_remote_device_core_event_handler( | |
697 | struct scic_sds_remote_device *this_device, | |
698 | u32 event_code, | |
699 | bool is_ready_state) | |
700 | { | |
701 | enum sci_status status; | |
702 | ||
703 | switch (scu_get_event_type(event_code)) { | |
704 | case SCU_EVENT_TYPE_RNC_OPS_MISC: | |
705 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX: | |
706 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: | |
707 | status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code); | |
708 | break; | |
709 | case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: | |
710 | ||
711 | if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { | |
712 | status = SCI_SUCCESS; | |
713 | ||
714 | /* Suspend the associated RNC */ | |
715 | scic_sds_remote_node_context_suspend(this_device->rnc, | |
716 | SCI_SOFTWARE_SUSPENSION, | |
717 | NULL, NULL); | |
718 | ||
719 | dev_dbg(scirdev_to_dev(this_device), | |
720 | "%s: device: %p event code: %x: %s\n", | |
721 | __func__, this_device, event_code, | |
722 | (is_ready_state) | |
723 | ? "I_T_Nexus_Timeout event" | |
724 | : "I_T_Nexus_Timeout event in wrong state"); | |
725 | ||
726 | break; | |
727 | } | |
728 | /* Else, fall through and treat as unhandled... */ | |
729 | ||
730 | default: | |
731 | dev_dbg(scirdev_to_dev(this_device), | |
732 | "%s: device: %p event code: %x: %s\n", | |
733 | __func__, this_device, event_code, | |
734 | (is_ready_state) | |
735 | ? "unexpected event" | |
736 | : "unexpected event in wrong state"); | |
737 | status = SCI_FAILURE_INVALID_STATE; | |
738 | break; | |
739 | } | |
740 | ||
741 | return status; | |
742 | } | |
743 | /** | |
744 | * | |
745 | * @device: The struct sci_base_remote_device which is then cast into a | |
746 | * struct scic_sds_remote_device. | |
747 | * @event_code: The event code that the struct scic_sds_controller wants the device | |
748 | * object to process. | |
749 | * | |
750 | * This method is the default event handler. It will call the RNC state | |
751 | * machine handler for any RNC events otherwise it will log a warning and | |
752 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | |
753 | */ | |
754 | static enum sci_status scic_sds_remote_device_default_event_handler( | |
755 | struct scic_sds_remote_device *this_device, | |
756 | u32 event_code) | |
757 | { | |
758 | return scic_sds_remote_device_core_event_handler(this_device, | |
759 | event_code, | |
760 | false); | |
761 | } | |
762 | ||
763 | /** | |
764 | * | |
765 | * @device: The struct sci_base_remote_device which is then cast into a | |
766 | * struct scic_sds_remote_device. | |
767 | * @frame_index: The frame index for which the struct scic_sds_controller wants this | |
768 | * device object to process. | |
769 | * | |
770 | * This method is the default unsolicited frame handler. It logs a warning, | |
771 | * releases the frame and returns a failure. enum sci_status | |
772 | * SCI_FAILURE_INVALID_STATE | |
773 | */ | |
774 | enum sci_status scic_sds_remote_device_default_frame_handler( | |
775 | struct scic_sds_remote_device *this_device, | |
776 | u32 frame_index) | |
777 | { | |
778 | dev_warn(scirdev_to_dev(this_device), | |
779 | "%s: SCIC Remote Device requested to handle frame %x " | |
780 | "while in wrong state %d\n", | |
781 | __func__, | |
782 | frame_index, | |
783 | sci_base_state_machine_get_state( | |
784 | &this_device->parent.state_machine)); | |
785 | ||
786 | /* Return the frame back to the controller */ | |
787 | scic_sds_controller_release_frame( | |
788 | scic_sds_remote_device_get_controller(this_device), frame_index | |
789 | ); | |
790 | ||
791 | return SCI_FAILURE_INVALID_STATE; | |
792 | } | |
793 | ||
6f231dda | 794 | enum sci_status scic_sds_remote_device_default_start_request_handler( |
068b2c03 | 795 | struct sci_base_remote_device *base_dev, |
6f231dda DW |
796 | struct sci_base_request *request) |
797 | { | |
068b2c03 | 798 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
799 | } |
800 | ||
6f231dda | 801 | enum sci_status scic_sds_remote_device_default_complete_request_handler( |
068b2c03 | 802 | struct sci_base_remote_device *base_dev, |
6f231dda DW |
803 | struct sci_base_request *request) |
804 | { | |
068b2c03 | 805 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
806 | } |
807 | ||
6f231dda | 808 | enum sci_status scic_sds_remote_device_default_continue_request_handler( |
068b2c03 | 809 | struct sci_base_remote_device *base_dev, |
6f231dda DW |
810 | struct sci_base_request *request) |
811 | { | |
068b2c03 | 812 | return default_device_handler(base_dev, __func__); |
6f231dda DW |
813 | } |
814 | ||
6f231dda DW |
815 | /** |
816 | * | |
817 | * @device: The struct sci_base_remote_device which is then cast into a | |
818 | * struct scic_sds_remote_device. | |
819 | * @frame_index: The frame index for which the struct scic_sds_controller wants this | |
820 | * device object to process. | |
821 | * | |
822 | * This method is a general ssp frame handler. In most cases the device object | |
823 | * needs to route the unsolicited frame processing to the io request object. | |
824 | * This method decodes the tag for the io request object and routes the | |
825 | * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE | |
826 | */ | |
827 | enum sci_status scic_sds_remote_device_general_frame_handler( | |
828 | struct scic_sds_remote_device *this_device, | |
829 | u32 frame_index) | |
830 | { | |
831 | enum sci_status result; | |
832 | struct sci_ssp_frame_header *frame_header; | |
833 | struct scic_sds_request *io_request; | |
834 | ||
835 | result = scic_sds_unsolicited_frame_control_get_header( | |
836 | &(scic_sds_remote_device_get_controller(this_device)->uf_control), | |
837 | frame_index, | |
838 | (void **)&frame_header | |
839 | ); | |
840 | ||
841 | if (SCI_SUCCESS == result) { | |
842 | io_request = scic_sds_controller_get_io_request_from_tag( | |
843 | scic_sds_remote_device_get_controller(this_device), frame_header->tag); | |
844 | ||
a7e536c7 | 845 | if ((io_request == NULL) |
6f231dda DW |
846 | || (io_request->target_device != this_device)) { |
847 | /* | |
848 | * We could not map this tag to a valid IO request | |
849 | * Just toss the frame and continue */ | |
850 | scic_sds_controller_release_frame( | |
851 | scic_sds_remote_device_get_controller(this_device), frame_index | |
852 | ); | |
853 | } else { | |
854 | /* The IO request is now in charge of releasing the frame */ | |
855 | result = io_request->state_handlers->frame_handler( | |
856 | io_request, frame_index); | |
857 | } | |
858 | } | |
859 | ||
860 | return result; | |
861 | } | |
862 | ||
863 | /** | |
864 | * | |
865 | * @[in]: this_device This is the device object that is receiving the event. | |
866 | * @[in]: event_code The event code to process. | |
867 | * | |
868 | * This is a common method for handling events reported to the remote device | |
869 | * from the controller object. enum sci_status | |
870 | */ | |
871 | enum sci_status scic_sds_remote_device_general_event_handler( | |
872 | struct scic_sds_remote_device *this_device, | |
873 | u32 event_code) | |
874 | { | |
875 | return scic_sds_remote_device_core_event_handler(this_device, | |
876 | event_code, | |
877 | true); | |
878 | } | |
879 | ||
880 | /* | |
881 | * ***************************************************************************** | |
882 | * * STOPPED STATE HANDLERS | |
883 | * ***************************************************************************** */ | |
884 | ||
885 | /** | |
886 | * | |
887 | * @device: | |
888 | * | |
889 | * This method takes the struct scic_sds_remote_device from a stopped state and | |
890 | * attempts to start it. The RNC buffer for the device is constructed and the | |
891 | * device state machine is transitioned to the | |
892 | * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is | |
893 | * an RNC buffer available to construct the remote device. | |
894 | * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in | |
895 | * which to construct the remote device. | |
896 | */ | |
897 | static enum sci_status scic_sds_remote_device_stopped_state_start_handler( | |
068b2c03 | 898 | struct sci_base_remote_device *base_dev) |
6f231dda DW |
899 | { |
900 | enum sci_status status; | |
068b2c03 | 901 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 902 | |
068b2c03 | 903 | sci_dev = container_of(base_dev, typeof(*sci_dev), parent); |
6f231dda | 904 | |
068b2c03 DW |
905 | status = scic_sds_remote_node_context_resume(sci_dev->rnc, |
906 | scic_sds_remote_device_resume_complete_handler, sci_dev); | |
907 | ||
908 | if (status == SCI_SUCCESS) | |
909 | sci_base_state_machine_change_state(&base_dev->state_machine, | |
910 | SCI_BASE_REMOTE_DEVICE_STATE_STARTING); | |
6f231dda DW |
911 | |
912 | return status; | |
913 | } | |
914 | ||
6f231dda | 915 | static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( |
068b2c03 | 916 | struct sci_base_remote_device *base_dev) |
6f231dda DW |
917 | { |
918 | return SCI_SUCCESS; | |
919 | } | |
920 | ||
921 | /** | |
922 | * | |
068b2c03 | 923 | * @sci_dev: The struct sci_base_remote_device which is cast into a |
6f231dda DW |
924 | * struct scic_sds_remote_device. |
925 | * | |
926 | * This method will destruct a struct scic_sds_remote_device that is in a stopped | |
927 | * state. This is the only state from which a destruct request will succeed. | |
928 | * The RNi for this struct scic_sds_remote_device is returned to the free pool and the | |
929 | * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. | |
930 | * enum sci_status SCI_SUCCESS | |
931 | */ | |
932 | static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( | |
068b2c03 | 933 | struct sci_base_remote_device *base_dev) |
6f231dda | 934 | { |
068b2c03 DW |
935 | struct scic_sds_remote_device *sci_dev; |
936 | struct scic_sds_controller *scic; | |
6f231dda | 937 | |
068b2c03 DW |
938 | sci_dev = container_of(base_dev, typeof(*sci_dev), parent); |
939 | scic = scic_sds_remote_device_get_controller(sci_dev); | |
940 | scic_sds_controller_free_remote_node_context(scic, sci_dev, | |
941 | sci_dev->rnc->remote_node_index); | |
942 | sci_dev->rnc->remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; | |
6f231dda | 943 | |
068b2c03 DW |
944 | sci_base_state_machine_change_state(&base_dev->state_machine, |
945 | SCI_BASE_REMOTE_DEVICE_STATE_FINAL); | |
6f231dda DW |
946 | |
947 | return SCI_SUCCESS; | |
948 | } | |
949 | ||
950 | /* | |
951 | * ***************************************************************************** | |
952 | * * STARTING STATE HANDLERS | |
953 | * ***************************************************************************** */ | |
954 | ||
955 | static enum sci_status scic_sds_remote_device_starting_state_stop_handler( | |
068b2c03 | 956 | struct sci_base_remote_device *base_dev) |
6f231dda | 957 | { |
068b2c03 | 958 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 959 | |
068b2c03 | 960 | sci_dev = container_of(base_dev, typeof(*sci_dev), parent); |
6f231dda DW |
961 | /* |
962 | * This device has not yet started so there had better be no IO requests | |
963 | */ | |
068b2c03 | 964 | BUG_ON(sci_dev->started_request_count != 0); |
6f231dda DW |
965 | |
966 | /* | |
967 | * Destroy the remote node context | |
968 | */ | |
068b2c03 DW |
969 | scic_sds_remote_node_context_destruct(sci_dev->rnc, |
970 | scic_sds_cb_remote_device_rnc_destruct_complete, sci_dev); | |
6f231dda DW |
971 | |
972 | /* | |
973 | * Transition to the stopping state and wait for the remote node to | |
974 | * complete being posted and invalidated. | |
975 | */ | |
068b2c03 DW |
976 | sci_base_state_machine_change_state(&base_dev->state_machine, |
977 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); | |
6f231dda DW |
978 | |
979 | return SCI_SUCCESS; | |
980 | } | |
981 | ||
6f231dda | 982 | enum sci_status scic_sds_remote_device_ready_state_stop_handler( |
068b2c03 | 983 | struct sci_base_remote_device *base_dev) |
6f231dda | 984 | { |
068b2c03 DW |
985 | struct scic_sds_remote_device *sci_dev; |
986 | enum sci_status status = SCI_SUCCESS; | |
6f231dda | 987 | |
068b2c03 | 988 | sci_dev = container_of(base_dev, typeof(*sci_dev), parent); |
6f231dda | 989 | /* Request the parent state machine to transition to the stopping state */ |
068b2c03 DW |
990 | sci_base_state_machine_change_state(&base_dev->state_machine, |
991 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING); | |
6f231dda | 992 | |
068b2c03 DW |
993 | if (sci_dev->started_request_count == 0) { |
994 | scic_sds_remote_node_context_destruct(sci_dev->rnc, | |
6f231dda | 995 | scic_sds_cb_remote_device_rnc_destruct_complete, |
068b2c03 | 996 | sci_dev); |
6f231dda | 997 | } else |
068b2c03 | 998 | status = scic_sds_remote_device_terminate_requests(sci_dev); |
6f231dda DW |
999 | |
1000 | return status; | |
1001 | } | |
1002 | ||
1003 | /** | |
1004 | * | |
1005 | * @device: The struct sci_base_remote_device object which is cast to a | |
1006 | * struct scic_sds_remote_device object. | |
1007 | * | |
1008 | * This is the ready state device reset handler enum sci_status | |
1009 | */ | |
1010 | enum sci_status scic_sds_remote_device_ready_state_reset_handler( | |
068b2c03 | 1011 | struct sci_base_remote_device *base_dev) |
6f231dda | 1012 | { |
068b2c03 | 1013 | struct scic_sds_remote_device *sci_dev; |
6f231dda | 1014 | |
068b2c03 | 1015 | sci_dev = container_of(base_dev, typeof(*sci_dev), parent); |
6f231dda | 1016 | /* Request the parent state machine to transition to the stopping state */ |
068b2c03 DW |
1017 | sci_base_state_machine_change_state(&base_dev->state_machine, |
1018 | SCI_BASE_REMOTE_DEVICE_STATE_RESETTING); | |
6f231dda DW |
1019 | |
1020 | return SCI_SUCCESS; | |
1021 | } | |
1022 | ||
6f231dda DW |
1023 | /** |
1024 | * | |
1025 | * @device: The struct sci_base_remote_device which is cast to a | |
1026 | * struct scic_sds_remote_device for which the request is to be started. | |
1027 | * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that | |
1028 | * is to be started. | |
1029 | * | |
1030 | * This method will attempt to start a task request for this device object. The | |
1031 | * remote device object will issue the start request for the task and if | |
1032 | * successful it will start the request for the port object then increment its | |
1033 | * own requet count. enum sci_status SCI_SUCCESS if the task request is started for | |
1034 | * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request | |
1035 | * object could not get the resources to start. | |
1036 | */ | |
1037 | static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( | |
1038 | struct sci_base_remote_device *device, | |
1039 | struct sci_base_request *request) | |
1040 | { | |
1041 | enum sci_status result; | |
1042 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1043 | struct scic_sds_request *task_request = (struct scic_sds_request *)request; | |
1044 | ||
1045 | /* See if the port is in a state where we can start the IO request */ | |
1046 | result = scic_sds_port_start_io( | |
1047 | scic_sds_remote_device_get_port(this_device), this_device, task_request); | |
1048 | ||
1049 | if (result == SCI_SUCCESS) { | |
1050 | result = scic_sds_remote_node_context_start_task( | |
1051 | this_device->rnc, task_request | |
1052 | ); | |
1053 | ||
1054 | if (result == SCI_SUCCESS) { | |
1055 | result = scic_sds_request_start(task_request); | |
1056 | } | |
1057 | ||
1058 | scic_sds_remote_device_start_request(this_device, task_request, result); | |
1059 | } | |
1060 | ||
1061 | return result; | |
1062 | } | |
1063 | ||
1064 | /** | |
1065 | * | |
1066 | * @device: The struct sci_base_remote_device which is cast to a | |
1067 | * struct scic_sds_remote_device for which the request is to be started. | |
1068 | * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that | |
1069 | * is to be started. | |
1070 | * | |
1071 | * This method will attempt to start an io request for this device object. The | |
1072 | * remote device object will issue the start request for the io and if | |
1073 | * successful it will start the request for the port object then increment its | |
1074 | * own requet count. enum sci_status SCI_SUCCESS if the io request is started for | |
1075 | * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request | |
1076 | * object could not get the resources to start. | |
1077 | */ | |
1078 | static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( | |
1079 | struct sci_base_remote_device *device, | |
1080 | struct sci_base_request *request) | |
1081 | { | |
1082 | enum sci_status result; | |
1083 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1084 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | |
1085 | ||
1086 | /* See if the port is in a state where we can start the IO request */ | |
1087 | result = scic_sds_port_start_io( | |
1088 | scic_sds_remote_device_get_port(this_device), this_device, io_request); | |
1089 | ||
1090 | if (result == SCI_SUCCESS) { | |
1091 | result = scic_sds_remote_node_context_start_io( | |
1092 | this_device->rnc, io_request | |
1093 | ); | |
1094 | ||
1095 | if (result == SCI_SUCCESS) { | |
1096 | result = scic_sds_request_start(io_request); | |
1097 | } | |
1098 | ||
1099 | scic_sds_remote_device_start_request(this_device, io_request, result); | |
1100 | } | |
1101 | ||
1102 | return result; | |
1103 | } | |
1104 | ||
1105 | /** | |
1106 | * | |
1107 | * @device: The struct sci_base_remote_device which is cast to a | |
1108 | * struct scic_sds_remote_device for which the request is to be completed. | |
1109 | * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that | |
1110 | * is to be completed. | |
1111 | * | |
1112 | * This method will complete the request for the remote device object. The | |
1113 | * method will call the completion handler for the request object and if | |
1114 | * successful it will complete the request on the port object then decrement | |
1115 | * its own started_request_count. enum sci_status | |
1116 | */ | |
1117 | static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( | |
1118 | struct sci_base_remote_device *device, | |
1119 | struct sci_base_request *request) | |
1120 | { | |
1121 | enum sci_status result; | |
1122 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1123 | struct scic_sds_request *the_request = (struct scic_sds_request *)request; | |
1124 | ||
1125 | result = scic_sds_request_complete(the_request); | |
1126 | ||
1127 | if (result == SCI_SUCCESS) { | |
1128 | /* See if the port is in a state where we can start the IO request */ | |
1129 | result = scic_sds_port_complete_io( | |
1130 | scic_sds_remote_device_get_port(this_device), this_device, the_request); | |
1131 | ||
1132 | if (result == SCI_SUCCESS) { | |
1133 | scic_sds_remote_device_decrement_request_count(this_device); | |
1134 | } | |
1135 | } | |
1136 | ||
1137 | return result; | |
1138 | } | |
1139 | ||
1140 | /* | |
1141 | * ***************************************************************************** | |
1142 | * * STOPPING STATE HANDLERS | |
1143 | * ***************************************************************************** */ | |
1144 | ||
1145 | /** | |
1146 | * | |
1147 | * @this_device: The struct sci_base_remote_device which is cast into a | |
1148 | * struct scic_sds_remote_device. | |
1149 | * | |
1150 | * This method will stop a struct scic_sds_remote_device that is already in the | |
1151 | * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error | |
1152 | * since we allow a stop request on a device that is alreay stopping or | |
1153 | * stopped. enum sci_status SCI_SUCCESS | |
1154 | */ | |
1155 | static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( | |
1156 | struct sci_base_remote_device *device) | |
1157 | { | |
1158 | /* | |
1159 | * All requests should have been terminated, but if there is an | |
1160 | * attempt to stop a device already in the stopping state, then | |
1161 | * try again to terminate. */ | |
1162 | return scic_sds_remote_device_terminate_requests( | |
1163 | (struct scic_sds_remote_device *)device); | |
1164 | } | |
1165 | ||
1166 | ||
1167 | /** | |
1168 | * | |
1169 | * @device: The device object for which the request is completing. | |
1170 | * @request: The task request that is being completed. | |
1171 | * | |
1172 | * This method completes requests for this struct scic_sds_remote_device while it is | |
1173 | * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the | |
1174 | * complete method for the request object and if that is successful the port | |
1175 | * object is called to complete the task request. Then the device object itself | |
1176 | * completes the task request. If struct scic_sds_remote_device started_request_count | |
1177 | * goes to 0 and the invalidate RNC request has completed the device object can | |
1178 | * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status | |
1179 | */ | |
1180 | static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( | |
1181 | struct sci_base_remote_device *device, | |
1182 | struct sci_base_request *request) | |
1183 | { | |
1184 | enum sci_status status = SCI_SUCCESS; | |
1185 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | |
1186 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1187 | ||
1188 | status = scic_sds_request_complete(this_request); | |
1189 | if (status == SCI_SUCCESS) { | |
1190 | status = scic_sds_port_complete_io( | |
1191 | scic_sds_remote_device_get_port(this_device), | |
1192 | this_device, | |
1193 | this_request | |
1194 | ); | |
1195 | ||
1196 | if (status == SCI_SUCCESS) { | |
1197 | scic_sds_remote_device_decrement_request_count(this_device); | |
1198 | ||
1199 | if (scic_sds_remote_device_get_request_count(this_device) == 0) { | |
1200 | scic_sds_remote_node_context_destruct( | |
1201 | this_device->rnc, | |
1202 | scic_sds_cb_remote_device_rnc_destruct_complete, | |
1203 | this_device | |
1204 | ); | |
1205 | } | |
1206 | } | |
1207 | } | |
1208 | ||
1209 | return status; | |
1210 | } | |
1211 | ||
1212 | /* | |
1213 | * ***************************************************************************** | |
1214 | * * RESETTING STATE HANDLERS | |
1215 | * ***************************************************************************** */ | |
1216 | ||
1217 | /** | |
1218 | * | |
1219 | * @device: The struct sci_base_remote_device which is to be cast into a | |
1220 | * struct scic_sds_remote_device object. | |
1221 | * | |
1222 | * This method will complete the reset operation when the device is in the | |
1223 | * resetting state. enum sci_status | |
1224 | */ | |
1225 | static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( | |
1226 | struct sci_base_remote_device *device) | |
1227 | { | |
1228 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1229 | ||
1230 | sci_base_state_machine_change_state( | |
1231 | &this_device->parent.state_machine, | |
1232 | SCI_BASE_REMOTE_DEVICE_STATE_READY | |
1233 | ); | |
1234 | ||
1235 | return SCI_SUCCESS; | |
1236 | } | |
1237 | ||
1238 | /** | |
1239 | * | |
1240 | * @device: The struct sci_base_remote_device which is to be cast into a | |
1241 | * struct scic_sds_remote_device object. | |
1242 | * | |
1243 | * This method will stop the remote device while in the resetting state. | |
1244 | * enum sci_status | |
1245 | */ | |
1246 | static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( | |
1247 | struct sci_base_remote_device *device) | |
1248 | { | |
1249 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1250 | ||
1251 | sci_base_state_machine_change_state( | |
1252 | &this_device->parent.state_machine, | |
1253 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING | |
1254 | ); | |
1255 | ||
1256 | return SCI_SUCCESS; | |
1257 | } | |
1258 | ||
1259 | /** | |
1260 | * | |
1261 | * @device: The device object for which the request is completing. | |
1262 | * @request: The task request that is being completed. | |
1263 | * | |
1264 | * This method completes requests for this struct scic_sds_remote_device while it is | |
1265 | * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the | |
1266 | * complete method for the request object and if that is successful the port | |
1267 | * object is called to complete the task request. Then the device object itself | |
1268 | * completes the task request. enum sci_status | |
1269 | */ | |
1270 | static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( | |
1271 | struct sci_base_remote_device *device, | |
1272 | struct sci_base_request *request) | |
1273 | { | |
1274 | enum sci_status status = SCI_SUCCESS; | |
1275 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | |
1276 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | |
1277 | ||
1278 | status = scic_sds_request_complete(this_request); | |
1279 | ||
1280 | if (status == SCI_SUCCESS) { | |
1281 | status = scic_sds_port_complete_io( | |
1282 | scic_sds_remote_device_get_port(this_device), this_device, this_request); | |
1283 | ||
1284 | if (status == SCI_SUCCESS) { | |
1285 | scic_sds_remote_device_decrement_request_count(this_device); | |
1286 | } | |
1287 | } | |
1288 | ||
1289 | return status; | |
1290 | } | |
1291 | ||
1292 | /* | |
1293 | * ***************************************************************************** | |
1294 | * * FAILED STATE HANDLERS | |
1295 | * ***************************************************************************** */ | |
1296 | ||
1297 | /** | |
1298 | * | |
1299 | * @device: The struct sci_base_remote_device which is to be cast into a | |
1300 | * struct scic_sds_remote_device object. | |
1301 | * | |
1302 | * This method handles the remove request for a failed struct scic_sds_remote_device | |
1303 | * object. The method will transition the device object to the | |
1304 | * SCIC_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status SCI_SUCCESS | |
1305 | */ | |
1306 | ||
1307 | /* --------------------------------------------------------------------------- */ | |
1308 | ||
35173d57 | 1309 | static const struct scic_sds_remote_device_state_handler scic_sds_remote_device_state_handler_table[] = { |
7fbafaa5 HD |
1310 | [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { |
1311 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1312 | .parent.stop_handler = scic_sds_remote_device_default_stop_handler, | |
1313 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1314 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1315 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1316 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1317 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1318 | .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
1319 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1320 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1321 | .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
1322 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1323 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1324 | .event_handler = scic_sds_remote_device_default_event_handler, | |
1325 | .frame_handler = scic_sds_remote_device_default_frame_handler | |
6f231dda | 1326 | }, |
7fbafaa5 HD |
1327 | [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { |
1328 | .parent.start_handler = scic_sds_remote_device_stopped_state_start_handler, | |
1329 | .parent.stop_handler = scic_sds_remote_device_stopped_state_stop_handler, | |
1330 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1331 | .parent.destruct_handler = scic_sds_remote_device_stopped_state_destruct_handler, | |
1332 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1333 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1334 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1335 | .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
1336 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1337 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1338 | .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
1339 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1340 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1341 | .event_handler = scic_sds_remote_device_default_event_handler, | |
1342 | .frame_handler = scic_sds_remote_device_default_frame_handler | |
6f231dda | 1343 | }, |
7fbafaa5 HD |
1344 | [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { |
1345 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1346 | .parent.stop_handler = scic_sds_remote_device_starting_state_stop_handler, | |
1347 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1348 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1349 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1350 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1351 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1352 | .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
1353 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1354 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1355 | .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
1356 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1357 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1358 | .event_handler = scic_sds_remote_device_general_event_handler, | |
1359 | .frame_handler = scic_sds_remote_device_default_frame_handler | |
6f231dda | 1360 | }, |
7fbafaa5 HD |
1361 | [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { |
1362 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1363 | .parent.stop_handler = scic_sds_remote_device_ready_state_stop_handler, | |
1364 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1365 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1366 | .parent.reset_handler = scic_sds_remote_device_ready_state_reset_handler, | |
1367 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1368 | .parent.start_io_handler = scic_sds_remote_device_ready_state_start_io_handler, | |
1369 | .parent.complete_io_handler = scic_sds_remote_device_ready_state_complete_request_handler, | |
1370 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1371 | .parent.start_task_handler = scic_sds_remote_device_ready_state_start_task_handler, | |
1372 | .parent.complete_task_handler = scic_sds_remote_device_ready_state_complete_request_handler, | |
1373 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1374 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1375 | .event_handler = scic_sds_remote_device_general_event_handler, | |
1376 | .frame_handler = scic_sds_remote_device_general_frame_handler, | |
6f231dda | 1377 | }, |
7fbafaa5 HD |
1378 | [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { |
1379 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1380 | .parent.stop_handler = scic_sds_remote_device_stopping_state_stop_handler, | |
1381 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1382 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1383 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1384 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1385 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1386 | .parent.complete_io_handler = scic_sds_remote_device_stopping_state_complete_request_handler, | |
1387 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1388 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1389 | .parent.complete_task_handler = scic_sds_remote_device_stopping_state_complete_request_handler, | |
1390 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1391 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1392 | .event_handler = scic_sds_remote_device_general_event_handler, | |
1393 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda | 1394 | }, |
7fbafaa5 HD |
1395 | [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { |
1396 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1397 | .parent.stop_handler = scic_sds_remote_device_default_stop_handler, | |
1398 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1399 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1400 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1401 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1402 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1403 | .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
1404 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1405 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1406 | .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
1407 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1408 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1409 | .event_handler = scic_sds_remote_device_default_event_handler, | |
1410 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda | 1411 | }, |
7fbafaa5 HD |
1412 | [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { |
1413 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1414 | .parent.stop_handler = scic_sds_remote_device_resetting_state_stop_handler, | |
1415 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1416 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1417 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1418 | .parent.reset_complete_handler = scic_sds_remote_device_resetting_state_reset_complete_handler, | |
1419 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1420 | .parent.complete_io_handler = scic_sds_remote_device_resetting_state_complete_request_handler, | |
1421 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1422 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1423 | .parent.complete_task_handler = scic_sds_remote_device_resetting_state_complete_request_handler, | |
1424 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1425 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1426 | .event_handler = scic_sds_remote_device_default_event_handler, | |
1427 | .frame_handler = scic_sds_remote_device_general_frame_handler | |
6f231dda | 1428 | }, |
7fbafaa5 HD |
1429 | [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { |
1430 | .parent.start_handler = scic_sds_remote_device_default_start_handler, | |
1431 | .parent.stop_handler = scic_sds_remote_device_default_stop_handler, | |
1432 | .parent.fail_handler = scic_sds_remote_device_default_fail_handler, | |
1433 | .parent.destruct_handler = scic_sds_remote_device_default_destruct_handler, | |
1434 | .parent.reset_handler = scic_sds_remote_device_default_reset_handler, | |
1435 | .parent.reset_complete_handler = scic_sds_remote_device_default_reset_complete_handler, | |
1436 | .parent.start_io_handler = scic_sds_remote_device_default_start_request_handler, | |
1437 | .parent.complete_io_handler = scic_sds_remote_device_default_complete_request_handler, | |
1438 | .parent.continue_io_handler = scic_sds_remote_device_default_continue_request_handler, | |
1439 | .parent.start_task_handler = scic_sds_remote_device_default_start_request_handler, | |
1440 | .parent.complete_task_handler = scic_sds_remote_device_default_complete_request_handler, | |
1441 | .suspend_handler = scic_sds_remote_device_default_suspend_handler, | |
1442 | .resume_handler = scic_sds_remote_device_default_resume_handler, | |
1443 | .event_handler = scic_sds_remote_device_default_event_handler, | |
1444 | .frame_handler = scic_sds_remote_device_default_frame_handler | |
6f231dda DW |
1445 | } |
1446 | }; | |
6f231dda DW |
1447 | |
1448 | /** | |
1449 | * | |
1450 | * @object: This is the struct sci_base_object that is cast into a | |
1451 | * struct scic_sds_remote_device. | |
1452 | * | |
1453 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it | |
1454 | * immediatly transitions the remote device object to the stopped state. none | |
1455 | */ | |
1456 | static void scic_sds_remote_device_initial_state_enter( | |
1457 | struct sci_base_object *object) | |
1458 | { | |
068b2c03 | 1459 | struct scic_sds_remote_device *sci_dev = (struct scic_sds_remote_device *)object; |
6f231dda | 1460 | |
068b2c03 DW |
1461 | sci_dev = container_of(object, typeof(*sci_dev), parent.parent); |
1462 | SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, | |
1463 | SCI_BASE_REMOTE_DEVICE_STATE_INITIAL); | |
6f231dda DW |
1464 | |
1465 | /* Initial state is a transitional state to the stopped state */ | |
068b2c03 DW |
1466 | sci_base_state_machine_change_state(&sci_dev->parent.state_machine, |
1467 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); | |
6f231dda DW |
1468 | } |
1469 | ||
1470 | /** | |
1471 | * | |
1472 | * @object: This is the struct sci_base_object that is cast into a | |
1473 | * struct scic_sds_remote_device. | |
1474 | * | |
09d7da13 | 1475 | * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it |
6f231dda DW |
1476 | * sets the stopped state handlers and if this state is entered from the |
1477 | * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that the | |
1478 | * device stop is complete. none | |
1479 | */ | |
1480 | static void scic_sds_remote_device_stopped_state_enter( | |
1481 | struct sci_base_object *object) | |
1482 | { | |
068b2c03 DW |
1483 | struct scic_sds_remote_device *sci_dev; |
1484 | struct scic_sds_controller *scic; | |
1485 | struct isci_remote_device *idev; | |
1486 | struct isci_host *ihost; | |
1487 | u32 prev_state; | |
1488 | ||
1489 | sci_dev = container_of(object, typeof(*sci_dev), parent.parent); | |
1490 | scic = scic_sds_remote_device_get_controller(sci_dev); | |
1491 | ihost = sci_object_get_association(scic); | |
1492 | idev = sci_object_get_association(sci_dev); | |
1493 | ||
1494 | SET_STATE_HANDLER(sci_dev, scic_sds_remote_device_state_handler_table, | |
09d7da13 | 1495 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED); |
6f231dda | 1496 | |
068b2c03 | 1497 | /* If we are entering from the stopping state let the SCI User know that |
09d7da13 DJ |
1498 | * the stop operation has completed. |
1499 | */ | |
068b2c03 DW |
1500 | prev_state = sci_dev->parent.state_machine.previous_state_id; |
1501 | if (prev_state == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) | |
09d7da13 | 1502 | isci_remote_device_stop_complete(ihost, idev, SCI_SUCCESS); |
c658b109 | 1503 | |
068b2c03 | 1504 | scic_sds_controller_remote_device_stopped(scic, sci_dev); |
6f231dda DW |
1505 | } |
1506 | ||
1507 | /** | |
1508 | * | |
1509 | * @object: This is the struct sci_base_object that is cast into a | |
1510 | * struct scic_sds_remote_device. | |
1511 | * | |
09d7da13 | 1512 | * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it |
6f231dda DW |
1513 | * sets the starting state handlers, sets the device not ready, and posts the |
1514 | * remote node context to the hardware. none | |
1515 | */ | |
1516 | static void scic_sds_remote_device_starting_state_enter( | |
1517 | struct sci_base_object *object) | |
1518 | { | |
09d7da13 DJ |
1519 | struct scic_sds_controller *scic; |
1520 | struct scic_sds_remote_device *sci_dev = | |
1521 | (struct scic_sds_remote_device *)object; | |
1522 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); | |
6f231dda | 1523 | |
09d7da13 | 1524 | scic = scic_sds_remote_device_get_controller(sci_dev); |
6f231dda DW |
1525 | |
1526 | SET_STATE_HANDLER( | |
09d7da13 DJ |
1527 | sci_dev, |
1528 | scic_sds_remote_device_state_handler_table, | |
1529 | SCI_BASE_REMOTE_DEVICE_STATE_STARTING); | |
6f231dda | 1530 | |
09d7da13 DJ |
1531 | isci_remote_device_not_ready( |
1532 | idev, | |
1533 | SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED); | |
6f231dda DW |
1534 | } |
1535 | ||
1536 | /** | |
1537 | * | |
1538 | * @object: This is the struct sci_base_object that is cast into a | |
1539 | * struct scic_sds_remote_device. | |
1540 | * | |
09d7da13 | 1541 | * This is the exit function for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it |
6f231dda DW |
1542 | * reports that the device start is complete. none |
1543 | */ | |
1544 | static void scic_sds_remote_device_starting_state_exit( | |
1545 | struct sci_base_object *object) | |
1546 | { | |
09d7da13 DJ |
1547 | struct scic_sds_remote_device *sci_dev = |
1548 | (struct scic_sds_remote_device *)object; | |
1549 | struct scic_sds_controller *scic = | |
1550 | scic_sds_remote_device_get_controller(sci_dev); | |
1551 | struct isci_host *ihost = sci_object_get_association(scic); | |
1552 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); | |
1553 | ||
6f231dda DW |
1554 | |
1555 | /* | |
09d7da13 DJ |
1556 | * @todo Check the device object for the proper return code for this |
1557 | * callback | |
1558 | */ | |
1559 | isci_remote_device_start_complete(ihost, idev, SCI_SUCCESS); | |
c658b109 PM |
1560 | |
1561 | scic_sds_controller_remote_device_started( | |
09d7da13 DJ |
1562 | scic_sds_remote_device_get_controller(sci_dev), |
1563 | sci_dev); | |
6f231dda DW |
1564 | } |
1565 | ||
1566 | /** | |
1567 | * | |
1568 | * @object: This is the struct sci_base_object that is cast into a | |
1569 | * struct scic_sds_remote_device. | |
1570 | * | |
09d7da13 | 1571 | * This is the enter function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets |
6f231dda DW |
1572 | * the ready state handlers, and starts the ready substate machine. none |
1573 | */ | |
1574 | static void scic_sds_remote_device_ready_state_enter( | |
1575 | struct sci_base_object *object) | |
1576 | { | |
09d7da13 DJ |
1577 | struct scic_sds_remote_device *sci_dev = |
1578 | (struct scic_sds_remote_device *)object; | |
1579 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); | |
1580 | struct scic_sds_controller *scic | |
1581 | = scic_sds_remote_device_get_controller(sci_dev); | |
6f231dda | 1582 | |
09d7da13 DJ |
1583 | SET_STATE_HANDLER(sci_dev, |
1584 | scic_sds_remote_device_state_handler_table, | |
1585 | SCI_BASE_REMOTE_DEVICE_STATE_READY); | |
6f231dda | 1586 | |
09d7da13 | 1587 | scic->remote_device_sequence[sci_dev->rnc->remote_node_index]++; |
6f231dda | 1588 | |
09d7da13 DJ |
1589 | if (sci_dev->has_ready_substate_machine) |
1590 | sci_base_state_machine_start(&sci_dev->ready_substate_machine); | |
1591 | else | |
1592 | isci_remote_device_ready(idev); | |
6f231dda DW |
1593 | } |
1594 | ||
1595 | /** | |
1596 | * | |
1597 | * @object: This is the struct sci_base_object that is cast into a | |
1598 | * struct scic_sds_remote_device. | |
1599 | * | |
09d7da13 | 1600 | * This is the exit function for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does |
6f231dda DW |
1601 | * nothing. none |
1602 | */ | |
1603 | static void scic_sds_remote_device_ready_state_exit( | |
1604 | struct sci_base_object *object) | |
1605 | { | |
09d7da13 DJ |
1606 | struct scic_sds_remote_device *sci_dev = |
1607 | (struct scic_sds_remote_device *)object; | |
1608 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); | |
6f231dda | 1609 | |
09d7da13 DJ |
1610 | if (sci_dev->has_ready_substate_machine) |
1611 | sci_base_state_machine_stop(&sci_dev->ready_substate_machine); | |
1612 | else | |
1613 | isci_remote_device_not_ready( | |
1614 | idev, | |
1615 | SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED); | |
6f231dda DW |
1616 | } |
1617 | ||
1618 | /** | |
1619 | * | |
1620 | * @object: This is the struct sci_base_object that is cast into a | |
1621 | * struct scic_sds_remote_device. | |
1622 | * | |
1623 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it | |
1624 | * sets the stopping state handlers and posts an RNC invalidate request to the | |
1625 | * SCU hardware. none | |
1626 | */ | |
1627 | static void scic_sds_remote_device_stopping_state_enter( | |
1628 | struct sci_base_object *object) | |
1629 | { | |
1630 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | |
1631 | ||
1632 | SET_STATE_HANDLER( | |
1633 | this_device, | |
1634 | scic_sds_remote_device_state_handler_table, | |
1635 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING | |
1636 | ); | |
1637 | } | |
1638 | ||
1639 | /** | |
1640 | * | |
1641 | * @object: This is the struct sci_base_object that is cast into a | |
1642 | * struct scic_sds_remote_device. | |
1643 | * | |
1644 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it sets | |
1645 | * the stopping state handlers. none | |
1646 | */ | |
1647 | static void scic_sds_remote_device_failed_state_enter( | |
1648 | struct sci_base_object *object) | |
1649 | { | |
1650 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | |
1651 | ||
1652 | SET_STATE_HANDLER( | |
1653 | this_device, | |
1654 | scic_sds_remote_device_state_handler_table, | |
1655 | SCI_BASE_REMOTE_DEVICE_STATE_FAILED | |
1656 | ); | |
1657 | } | |
1658 | ||
1659 | /** | |
1660 | * | |
1661 | * @object: This is the struct sci_base_object that is cast into a | |
1662 | * struct scic_sds_remote_device. | |
1663 | * | |
1664 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it | |
1665 | * sets the resetting state handlers. none | |
1666 | */ | |
1667 | static void scic_sds_remote_device_resetting_state_enter( | |
1668 | struct sci_base_object *object) | |
1669 | { | |
1670 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | |
1671 | ||
1672 | SET_STATE_HANDLER( | |
1673 | this_device, | |
1674 | scic_sds_remote_device_state_handler_table, | |
1675 | SCI_BASE_REMOTE_DEVICE_STATE_RESETTING | |
1676 | ); | |
1677 | ||
1678 | scic_sds_remote_node_context_suspend( | |
1679 | this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); | |
1680 | } | |
1681 | ||
1682 | /** | |
1683 | * | |
1684 | * @object: This is the struct sci_base_object that is cast into a | |
1685 | * struct scic_sds_remote_device. | |
1686 | * | |
1687 | * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it | |
1688 | * does nothing. none | |
1689 | */ | |
1690 | static void scic_sds_remote_device_resetting_state_exit( | |
1691 | struct sci_base_object *object) | |
1692 | { | |
1693 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | |
1694 | ||
6f231dda DW |
1695 | scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); |
1696 | } | |
1697 | ||
1698 | /** | |
1699 | * | |
1700 | * @object: This is the struct sci_base_object that is cast into a | |
1701 | * struct scic_sds_remote_device. | |
1702 | * | |
1703 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets | |
1704 | * the final state handlers. none | |
1705 | */ | |
1706 | static void scic_sds_remote_device_final_state_enter( | |
1707 | struct sci_base_object *object) | |
1708 | { | |
1709 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | |
1710 | ||
1711 | SET_STATE_HANDLER( | |
1712 | this_device, | |
1713 | scic_sds_remote_device_state_handler_table, | |
1714 | SCI_BASE_REMOTE_DEVICE_STATE_FINAL | |
1715 | ); | |
1716 | } | |
1717 | ||
1718 | /* --------------------------------------------------------------------------- */ | |
1719 | ||
35173d57 | 1720 | static const struct sci_base_state scic_sds_remote_device_state_table[] = { |
6f231dda DW |
1721 | [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { |
1722 | .enter_state = scic_sds_remote_device_initial_state_enter, | |
1723 | }, | |
1724 | [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { | |
1725 | .enter_state = scic_sds_remote_device_stopped_state_enter, | |
1726 | }, | |
1727 | [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { | |
1728 | .enter_state = scic_sds_remote_device_starting_state_enter, | |
1729 | .exit_state = scic_sds_remote_device_starting_state_exit | |
1730 | }, | |
1731 | [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { | |
1732 | .enter_state = scic_sds_remote_device_ready_state_enter, | |
1733 | .exit_state = scic_sds_remote_device_ready_state_exit | |
1734 | }, | |
1735 | [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { | |
1736 | .enter_state = scic_sds_remote_device_stopping_state_enter, | |
1737 | }, | |
1738 | [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { | |
1739 | .enter_state = scic_sds_remote_device_failed_state_enter, | |
1740 | }, | |
1741 | [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { | |
1742 | .enter_state = scic_sds_remote_device_resetting_state_enter, | |
1743 | .exit_state = scic_sds_remote_device_resetting_state_exit | |
1744 | }, | |
1745 | [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { | |
1746 | .enter_state = scic_sds_remote_device_final_state_enter, | |
1747 | }, | |
1748 | }; | |
1749 | ||
35173d57 DW |
1750 | void scic_remote_device_construct(struct scic_sds_port *sci_port, |
1751 | struct scic_sds_remote_device *sci_dev) | |
1752 | { | |
1753 | sci_dev->owning_port = sci_port; | |
1754 | sci_dev->started_request_count = 0; | |
1755 | sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; | |
1756 | ||
1757 | sci_base_remote_device_construct( | |
1758 | &sci_dev->parent, | |
1759 | scic_sds_remote_device_state_table | |
1760 | ); | |
1761 | ||
1762 | scic_sds_remote_node_context_construct( | |
1763 | sci_dev, | |
1764 | sci_dev->rnc, | |
1765 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | |
1766 | ); | |
1767 | ||
1768 | sci_object_set_association(sci_dev->rnc, sci_dev); | |
1769 | } |