1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 * * Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * * Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in
39 * the documentation and/or other materials provided with the
40 * distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55 #include <sys/cdefs.h>
56 /**
57 * @file
58 *
59 * @brief This file contains the structures, constants, and prototypes
60 * associated with the remote node context in the silicon. It
61 * exists to model and manage the remote node context in the silicon.
62 */
63
64 #include <dev/isci/scil/sci_util.h>
65 #include <dev/isci/scil/scic_sds_logger.h>
66 #include <dev/isci/scil/scic_sds_controller.h>
67 #include <dev/isci/scil/scic_sds_remote_device.h>
68 #include <dev/isci/scil/scic_sds_remote_node_context.h>
69 #include <dev/isci/scil/sci_base_state_machine.h>
70 #include <dev/isci/scil/scic_remote_device.h>
71 #include <dev/isci/scil/scic_sds_port.h>
72 #include <dev/isci/scil/scu_event_codes.h>
73 #include <dev/isci/scil/scu_task_context.h>
74
75 /**
76 * @brief
77 */
scic_sds_remote_node_context_construct(SCIC_SDS_REMOTE_DEVICE_T * device,SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,U16 remote_node_index)78 void scic_sds_remote_node_context_construct(
79 SCIC_SDS_REMOTE_DEVICE_T * device,
80 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc,
81 U16 remote_node_index
82 )
83 {
84 memset (rnc, 0, sizeof(SCIC_SDS_REMOTE_NODE_CONTEXT_T) );
85
86 rnc->remote_node_index = remote_node_index;
87 rnc->device = device;
88 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
89
90 rnc->parent.logger = device->parent.parent.logger;
91
92 sci_base_state_machine_construct(
93 &rnc->state_machine,
94 &rnc->parent,
95 scic_sds_remote_node_context_state_table,
96 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
97 );
98
99 sci_base_state_machine_start(&rnc->state_machine);
100
101 // State logging initialization takes place late for the remote node context
102 // see the resume state handler for the initial state.
103 }
104
105 /**
106 * This method will return TRUE if the RNC is not in the initial state. In
107 * all other states the RNC is considered active and this will return TRUE.
108 *
109 * @note The destroy request of the state machine drives the RNC back to the
110 * initial state. If the state machine changes then this routine will
111 * also have to be changed.
112 *
113 * @param[in] this_rnc The RNC for which the is posted request is being made.
114 *
115 * @return BOOL
116 * @retval TRUE if the state machine is not in the initial state
117 * @retval FALSE if the state machine is in the initial state
118 */
scic_sds_remote_node_context_is_initialized(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)119 BOOL scic_sds_remote_node_context_is_initialized(
120 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
121 )
122 {
123 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
124
125 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE)
126 {
127 return FALSE;
128 }
129
130 return TRUE;
131 }
132
133 /**
134 * This method will return TRUE if the remote node context is in a READY state
135 * otherwise it will return FALSE
136 *
137 * @param[in] this_rnc The state of the remote node context object to check.
138 *
139 * @return BOOL
140 * @retval TRUE if the remote node context is in the ready state.
141 * @retval FALSE if the remote node context is not in the ready state.
142 */
scic_sds_remote_node_context_is_ready(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)143 BOOL scic_sds_remote_node_context_is_ready(
144 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
145 )
146 {
147 U32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
148
149 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE)
150 {
151 return TRUE;
152 }
153
154 return FALSE;
155 }
156
157 /**
158 * This method will construct the RNC buffer for this remote device object.
159 *
160 * @param[in] this_device The remote device to use to construct the RNC
161 * buffer.
162 * @param[in] rnc The buffer into which the remote device data will be copied.
163 *
164 * @return none
165 */
scic_sds_remote_node_context_construct_buffer(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)166 void scic_sds_remote_node_context_construct_buffer(
167 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
168 )
169 {
170 SCU_REMOTE_NODE_CONTEXT_T * rnc;
171 SCIC_SDS_CONTROLLER_T * the_controller;
172
173 the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
174
175 rnc = scic_sds_controller_get_remote_node_context_buffer(
176 the_controller, this_rnc->remote_node_index);
177
178 memset(
179 rnc,
180 0x00,
181 sizeof(SCU_REMOTE_NODE_CONTEXT_T)
182 * scic_sds_remote_device_node_count(this_rnc->device)
183 );
184
185 rnc->ssp.remote_node_index = this_rnc->remote_node_index;
186 rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
187 rnc->ssp.logical_port_index =
188 scic_sds_remote_device_get_port_index(this_rnc->device);
189
190 rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
191 rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
192
193 rnc->ssp.nexus_loss_timer_enable = TRUE;
194 rnc->ssp.check_bit = FALSE;
195 rnc->ssp.is_valid = FALSE;
196 rnc->ssp.is_remote_node_context = TRUE;
197 rnc->ssp.function_number = 0;
198
199 rnc->ssp.arbitration_wait_time = 0;
200
201
202 if (
203 this_rnc->device->target_protocols.u.bits.attached_sata_device
204 || this_rnc->device->target_protocols.u.bits.attached_stp_target
205 )
206 {
207 rnc->ssp.connection_occupancy_timeout =
208 the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
209 rnc->ssp.connection_inactivity_timeout =
210 the_controller->user_parameters.sds1.stp_inactivity_timeout;
211 }
212 else
213 {
214 rnc->ssp.connection_occupancy_timeout =
215 the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
216 rnc->ssp.connection_inactivity_timeout =
217 the_controller->user_parameters.sds1.ssp_inactivity_timeout;
218 }
219
220 rnc->ssp.initial_arbitration_wait_time = 0;
221
222 // Open Address Frame Parameters
223 rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
224 rnc->ssp.oaf_features = 0;
225 rnc->ssp.oaf_source_zone_group = 0;
226 rnc->ssp.oaf_more_compatibility_features = 0;
227 }
228
229 // ---------------------------------------------------------------------------
230
231 #ifdef SCI_LOGGING
232 /**
233 * This method will enable and turn on state transition logging for the remote
234 * node context object.
235 *
236 * @param[in] this_rnc The remote node context for which state transition
237 * logging is to be enabled.
238 *
239 * @return none
240 */
scic_sds_remote_node_context_initialize_state_logging(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)241 void scic_sds_remote_node_context_initialize_state_logging(
242 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
243 )
244 {
245 sci_base_state_machine_logger_initialize(
246 &this_rnc->state_machine_logger,
247 &this_rnc->state_machine,
248 &this_rnc->parent,
249 scic_cb_logger_log_states,
250 "SCIC_SDS_REMOTE_NODE_CONTEXT_T", "state machine",
251 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
252 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
253 SCIC_LOG_OBJECT_STP_REMOTE_TARGET
254 );
255 }
256
257 /**
258 * This method will stop the state machine logging for this object and should
259 * be called before the object is destroyed.
260 *
261 * @param[in] this_rnc The remote node context on which to stop logging state
262 * transitions.
263 *
264 * @return none
265 */
scic_sds_remote_node_context_deinitialize_state_logging(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)266 void scic_sds_remote_node_context_deinitialize_state_logging(
267 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
268 )
269 {
270 sci_base_state_machine_logger_deinitialize(
271 &this_rnc->state_machine_logger,
272 &this_rnc->state_machine
273 );
274 }
275 #endif
276
277 /**
278 * This method will setup the remote node context object so it will transition
279 * to its ready state. If the remote node context is already setup to
280 * transition to its final state then this function does nothing.
281 *
282 * @param[in] this_rnc
283 * @param[in] the_callback
284 * @param[in] callback_parameter
285 *
286 * @return none
287 */
288 static
scic_sds_remote_node_context_setup_to_resume(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)289 void scic_sds_remote_node_context_setup_to_resume(
290 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
291 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
292 void * callback_parameter
293 )
294 {
295 if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
296 {
297 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
298 this_rnc->user_callback = the_callback;
299 this_rnc->user_cookie = callback_parameter;
300 }
301 }
302
303 /**
304 * This method will setup the remote node context object so it will
305 * transition to its final state.
306 *
307 * @param[in] this_rnc
308 * @param[in] the_callback
309 * @param[in] callback_parameter
310 *
311 * @return none
312 */
313 static
scic_sds_remote_node_context_setup_to_destory(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)314 void scic_sds_remote_node_context_setup_to_destory(
315 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
316 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
317 void * callback_parameter
318 )
319 {
320 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
321 this_rnc->user_callback = the_callback;
322 this_rnc->user_cookie = callback_parameter;
323 }
324
325 /**
326 * This method will continue to resume a remote node context. This is used
327 * in the states where a resume is requested while a resume is in progress.
328 *
329 * @param[in] this_rnc
330 * @param[in] the_callback
331 * @param[in] callback_parameter
332 */
333 static
scic_sds_remote_node_context_continue_to_resume_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)334 SCI_STATUS scic_sds_remote_node_context_continue_to_resume_handler(
335 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
336 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
337 void * callback_parameter
338 )
339 {
340 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
341 {
342 this_rnc->user_callback = the_callback;
343 this_rnc->user_cookie = callback_parameter;
344
345 return SCI_SUCCESS;
346 }
347
348 return SCI_FAILURE_INVALID_STATE;
349 }
350
351 //******************************************************************************
352 //* REMOTE NODE CONTEXT STATE MACHINE
353 //******************************************************************************
354
355 static
scic_sds_remote_node_context_default_destruct_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)356 SCI_STATUS scic_sds_remote_node_context_default_destruct_handler(
357 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
358 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
359 void * callback_parameter
360 )
361 {
362 SCIC_LOG_WARNING((
363 sci_base_object_get_logger(this_rnc->device),
364 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
365 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
366 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
367 "SCIC Remote Node Context 0x%x requested to stop while in unexpected state %d\n",
368 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
369 ));
370
371 // We have decided that the destruct request on the remote node context can not fail
372 // since it is either in the initial/destroyed state or is can be destroyed.
373 return SCI_SUCCESS;
374 }
375
376 static
scic_sds_remote_node_context_default_suspend_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,U32 suspend_type,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)377 SCI_STATUS scic_sds_remote_node_context_default_suspend_handler(
378 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
379 U32 suspend_type,
380 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
381 void * callback_parameter
382 )
383 {
384 SCIC_LOG_WARNING((
385 sci_base_object_get_logger(this_rnc->device),
386 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
387 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
388 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
389 "SCIC Remote Node Context 0x%x requested to suspend while in wrong state %d\n",
390 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
391 ));
392
393 return SCI_FAILURE_INVALID_STATE;
394 }
395
396 static
scic_sds_remote_node_context_default_resume_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)397 SCI_STATUS scic_sds_remote_node_context_default_resume_handler(
398 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
399 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
400 void * callback_parameter
401 )
402 {
403 SCIC_LOG_WARNING((
404 sci_base_object_get_logger(this_rnc->device),
405 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
406 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
407 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
408 "SCIC Remote Node Context 0x%x requested to resume while in wrong state %d\n",
409 this_rnc, sci_base_state_machine_get_state(&this_rnc->state_machine)
410 ));
411
412 return SCI_FAILURE_INVALID_STATE;
413 }
414
415 static
scic_sds_remote_node_context_default_start_io_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)416 SCI_STATUS scic_sds_remote_node_context_default_start_io_handler(
417 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
418 struct SCIC_SDS_REQUEST * the_request
419 )
420 {
421 SCIC_LOG_WARNING((
422 sci_base_object_get_logger(this_rnc->device),
423 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
424 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
425 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
426 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
427 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
428 ));
429
430 return SCI_FAILURE_INVALID_STATE;
431 }
432
433 static
scic_sds_remote_node_context_default_start_task_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)434 SCI_STATUS scic_sds_remote_node_context_default_start_task_handler(
435 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
436 struct SCIC_SDS_REQUEST * the_request
437 )
438 {
439 SCIC_LOG_WARNING((
440 sci_base_object_get_logger(this_rnc->device),
441 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
442 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
443 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
444 "SCIC Remote Node Context 0x%x requested to start task 0x%x while in wrong state %d\n",
445 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
446 ));
447
448 return SCI_FAILURE;
449 }
450
451 static
scic_sds_remote_node_context_default_event_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,U32 event_code)452 SCI_STATUS scic_sds_remote_node_context_default_event_handler(
453 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
454 U32 event_code
455 )
456 {
457 SCIC_LOG_WARNING((
458 sci_base_object_get_logger(this_rnc->device),
459 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
460 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
461 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
462 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in wrong state %d\n",
463 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
464 ));
465
466 return SCI_FAILURE_INVALID_STATE;
467 }
468
469 /**
470 * This method determines if the task request can be started by the SCU
471 * hardware. When the RNC is in the ready state any task can be started.
472 *
473 * @param[in] this_rnc The rnc for which the task request is targeted.
474 * @param[in] the_request The request which is going to be started.
475 *
476 * @return SCI_STATUS
477 * @retval SCI_SUCCESS
478 */
479 static
scic_sds_remote_node_context_success_start_task_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)480 SCI_STATUS scic_sds_remote_node_context_success_start_task_handler(
481 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
482 struct SCIC_SDS_REQUEST * the_request
483 )
484 {
485 return SCI_SUCCESS;
486 }
487
488 /**
489 * This method handles destruct calls from the various state handlers. The
490 * remote node context can be requested to destroy from any state. If there
491 * was a user callback it is always replaced with the request to destroy user
492 * callback.
493 *
494 * @param[in] this_rnc
495 * @param[in] the_callback
496 * @param[in] callback_parameter
497 *
498 * @return SCI_STATUS
499 */
500 static
scic_sds_remote_node_context_general_destruct_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)501 SCI_STATUS scic_sds_remote_node_context_general_destruct_handler(
502 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
503 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
504 void * callback_parameter
505 )
506 {
507 scic_sds_remote_node_context_setup_to_destory(
508 this_rnc, the_callback, callback_parameter
509 );
510
511 sci_base_state_machine_change_state(
512 &this_rnc->state_machine,
513 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
514 );
515
516 return SCI_SUCCESS;
517 }
518 // ---------------------------------------------------------------------------
519 static
scic_sds_remote_node_context_reset_required_start_io_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)520 SCI_STATUS scic_sds_remote_node_context_reset_required_start_io_handler(
521 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
522 struct SCIC_SDS_REQUEST * the_request
523 )
524 {
525 SCIC_LOG_WARNING((
526 sci_base_object_get_logger(this_rnc->device),
527 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
528 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
529 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
530 "SCIC Remote Node Context 0x%x requested to start io 0x%x while in wrong state %d\n",
531 this_rnc, the_request, sci_base_state_machine_get_state(&this_rnc->state_machine)
532 ));
533
534 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
535 }
536
537 // ---------------------------------------------------------------------------
538
539 static
scic_sds_remote_node_context_initial_state_resume_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)540 SCI_STATUS scic_sds_remote_node_context_initial_state_resume_handler(
541 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
542 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
543 void * callback_parameter
544 )
545 {
546 if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
547 {
548 scic_sds_remote_node_context_setup_to_resume(
549 this_rnc, the_callback, callback_parameter
550 );
551
552 scic_sds_remote_node_context_construct_buffer(this_rnc);
553
554 #if defined (SCI_LOGGING)
555 // If a remote node context has a logger already, don't work on its state
556 // logging.
557 if (this_rnc->state_machine.previous_state_id
558 != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE)
559 scic_sds_remote_node_context_initialize_state_logging(this_rnc);
560 #endif
561
562 sci_base_state_machine_change_state(
563 &this_rnc->state_machine,
564 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
565 );
566
567 return SCI_SUCCESS;
568 }
569
570 return SCI_FAILURE_INVALID_STATE;
571 }
572
573 // ---------------------------------------------------------------------------
574
575 static
scic_sds_remote_node_context_posting_state_event_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,U32 event_code)576 SCI_STATUS scic_sds_remote_node_context_posting_state_event_handler(
577 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
578 U32 event_code
579 )
580 {
581 SCI_STATUS status;
582
583 switch (scu_get_event_code(event_code))
584 {
585 case SCU_EVENT_POST_RNC_COMPLETE:
586 status = SCI_SUCCESS;
587
588 sci_base_state_machine_change_state(
589 &this_rnc->state_machine,
590 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
591 );
592 break;
593
594 default:
595 status = SCI_FAILURE;
596 SCIC_LOG_WARNING((
597 sci_base_object_get_logger(this_rnc->device),
598 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
599 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
600 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
601 "SCIC Remote Node Context 0x%x requested to process unexpected event 0x%x while in posting state\n",
602 this_rnc, event_code
603 ));
604 break;
605 }
606
607 return status;
608 }
609
610 // ---------------------------------------------------------------------------
611
612 static
scic_sds_remote_node_context_invalidating_state_destruct_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)613 SCI_STATUS scic_sds_remote_node_context_invalidating_state_destruct_handler(
614 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
615 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
616 void * callback_parameter
617 )
618 {
619 scic_sds_remote_node_context_setup_to_destory(
620 this_rnc, the_callback, callback_parameter
621 );
622
623 return SCI_SUCCESS;
624 }
625
626 static
scic_sds_remote_node_context_invalidating_state_event_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,U32 event_code)627 SCI_STATUS scic_sds_remote_node_context_invalidating_state_event_handler(
628 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
629 U32 event_code
630 )
631 {
632 SCI_STATUS status;
633
634 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE)
635 {
636 status = SCI_SUCCESS;
637
638 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
639 {
640 sci_base_state_machine_change_state(
641 &this_rnc->state_machine,
642 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
643 );
644 }
645 else
646 {
647 sci_base_state_machine_change_state(
648 &this_rnc->state_machine,
649 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
650 );
651 }
652 }
653 else
654 {
655 switch (scu_get_event_type(event_code))
656 {
657 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
658 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
659 // We really dont care if the hardware is going to suspend
660 // the device since it's being invalidated anyway
661 SCIC_LOG_INFO((
662 sci_base_object_get_logger(this_rnc->device),
663 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
664 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
665 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
666 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being invalidated.\n",
667 this_rnc
668 ));
669 status = SCI_SUCCESS;
670 break;
671
672 default:
673 SCIC_LOG_WARNING((
674 sci_base_object_get_logger(this_rnc->device),
675 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
676 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
677 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
678 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
679 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
680 ));
681 status = SCI_FAILURE;
682 break;
683 }
684 }
685
686 return status;
687 }
688
689 // ---------------------------------------------------------------------------
690
691 static
scic_sds_remote_node_context_resuming_state_event_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,U32 event_code)692 SCI_STATUS scic_sds_remote_node_context_resuming_state_event_handler(
693 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
694 U32 event_code
695 )
696 {
697 SCI_STATUS status;
698
699 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE)
700 {
701 status = SCI_SUCCESS;
702
703 sci_base_state_machine_change_state(
704 &this_rnc->state_machine,
705 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
706 );
707 }
708 else
709 {
710 switch (scu_get_event_type(event_code))
711 {
712 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
713 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
714 // We really dont care if the hardware is going to suspend
715 // the device since it's being resumed anyway
716 SCIC_LOG_INFO((
717 sci_base_object_get_logger(this_rnc->device),
718 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
719 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
720 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
721 "SCIC Remote Node Context 0x%x was suspeneded by hardware while being resumed.\n",
722 this_rnc
723 ));
724 status = SCI_SUCCESS;
725 break;
726
727 default:
728 SCIC_LOG_WARNING((
729 sci_base_object_get_logger(this_rnc->device),
730 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
731 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
732 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
733 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
734 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
735 ));
736 status = SCI_FAILURE;
737 break;
738 }
739 }
740
741 return status;
742 }
743
744 // ---------------------------------------------------------------------------
745
746 /**
747 * This method will handle the suspend requests from the ready state.
748 *
749 * @param[in] this_rnc The remote node context object being suspended.
750 * @param[in] the_callback The callback when the suspension is complete.
751 * @param[in] callback_parameter The parameter that is to be passed into the
752 * callback.
753 *
754 * @return SCI_SUCCESS
755 */
756 static
scic_sds_remote_node_context_ready_state_suspend_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,U32 suspend_type,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)757 SCI_STATUS scic_sds_remote_node_context_ready_state_suspend_handler(
758 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
759 U32 suspend_type,
760 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
761 void * callback_parameter
762 )
763 {
764 this_rnc->user_callback = the_callback;
765 this_rnc->user_cookie = callback_parameter;
766 this_rnc->suspension_code = suspend_type;
767
768 if (suspend_type == SCI_SOFTWARE_SUSPENSION)
769 {
770 scic_sds_remote_device_post_request(
771 this_rnc->device,
772 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
773 );
774 }
775
776 sci_base_state_machine_change_state(
777 &this_rnc->state_machine,
778 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
779 );
780
781 return SCI_SUCCESS;
782 }
783
784 /**
785 * This method determines if the io request can be started by the SCU
786 * hardware. When the RNC is in the ready state any io request can be started.
787 *
788 * @param[in] this_rnc The rnc for which the io request is targeted.
789 * @param[in] the_request The request which is going to be started.
790 *
791 * @return SCI_STATUS
792 * @retval SCI_SUCCESS
793 */
794 static
scic_sds_remote_node_context_ready_state_start_io_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)795 SCI_STATUS scic_sds_remote_node_context_ready_state_start_io_handler(
796 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
797 struct SCIC_SDS_REQUEST * the_request
798 )
799 {
800 return SCI_SUCCESS;
801 }
802
803
804 static
scic_sds_remote_node_context_ready_state_event_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,U32 event_code)805 SCI_STATUS scic_sds_remote_node_context_ready_state_event_handler(
806 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
807 U32 event_code
808 )
809 {
810 SCI_STATUS status;
811
812 switch (scu_get_event_type(event_code))
813 {
814 case SCU_EVENT_TL_RNC_SUSPEND_TX:
815 sci_base_state_machine_change_state(
816 &this_rnc->state_machine,
817 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
818 );
819
820 this_rnc->suspension_code = scu_get_event_specifier(event_code);
821 status = SCI_SUCCESS;
822 break;
823
824 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
825 sci_base_state_machine_change_state(
826 &this_rnc->state_machine,
827 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
828 );
829
830 this_rnc->suspension_code = scu_get_event_specifier(event_code);
831 status = SCI_SUCCESS;
832 break;
833
834 default:
835 SCIC_LOG_WARNING((
836 sci_base_object_get_logger(this_rnc->device),
837 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
838 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
839 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
840 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
841 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
842 ));
843
844 status = SCI_FAILURE;
845 break;
846 }
847
848 return status;
849 }
850
851 // ---------------------------------------------------------------------------
852
853 static
scic_sds_remote_node_context_tx_suspended_state_resume_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)854 SCI_STATUS scic_sds_remote_node_context_tx_suspended_state_resume_handler(
855 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
856 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
857 void * callback_parameter
858 )
859 {
860 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
861
862 scic_sds_remote_node_context_setup_to_resume(
863 this_rnc, the_callback, callback_parameter
864 );
865
866 // If this is an expander attached SATA device we must invalidate
867 // and repost the RNC since this is the only way to clear the
868 // TCi to NCQ tag mapping table for the RNi
869 // All other device types we can just resume.
870 scic_remote_device_get_protocols(this_rnc->device, &protocols);
871
872 if (
873 (protocols.u.bits.attached_stp_target == 1)
874 && !(this_rnc->device->is_direct_attached)
875 )
876 {
877 sci_base_state_machine_change_state(
878 &this_rnc->state_machine,
879 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
880 );
881 }
882 else
883 {
884 sci_base_state_machine_change_state(
885 &this_rnc->state_machine,
886 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
887 );
888 }
889
890 return SCI_SUCCESS;
891 }
892
893 /**
894 * This method will report a success or failure attempt to start a new task
895 * request to the hardware. Since all task requests are sent on the high
896 * priority queue they can be sent when the RCN is in a TX suspend state.
897 *
898 * @param[in] this_rnc The remote node context which is to receive the task
899 * request.
900 * @param[in] the_request The task request to be transmitted to the remote
901 * target device.
902 *
903 * @return SCI_STATUS
904 * @retval SCI_SUCCESS
905 */
906 static
scic_sds_remote_node_context_suspended_start_task_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)907 SCI_STATUS scic_sds_remote_node_context_suspended_start_task_handler(
908 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
909 struct SCIC_SDS_REQUEST * the_request
910 )
911 {
912 scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
913
914 return SCI_SUCCESS;
915 }
916
917 // ---------------------------------------------------------------------------
918
919 static
scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)920 SCI_STATUS scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
921 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
922 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
923 void * callback_parameter
924 )
925 {
926 scic_sds_remote_node_context_setup_to_resume(
927 this_rnc, the_callback, callback_parameter
928 );
929
930 sci_base_state_machine_change_state(
931 &this_rnc->state_machine,
932 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
933 );
934
935 return SCI_FAILURE_INVALID_STATE;
936 }
937
938 // ---------------------------------------------------------------------------
939
940 /**
941 *
942 */
943 static
scic_sds_remote_node_context_await_suspension_state_resume_handler(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,void * callback_parameter)944 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_resume_handler(
945 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc,
946 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
947 void * callback_parameter
948 )
949 {
950 scic_sds_remote_node_context_setup_to_resume(
951 this_rnc, the_callback, callback_parameter
952 );
953
954 return SCI_SUCCESS;
955 }
956
957 /**
958 * This method will report a success or failure attempt to start a new task
959 * request to the hardware. Since all task requests are sent on the high
960 * priority queue they can be sent when the RCN is in a TX suspend state.
961 *
962 * @param[in] this_rnc The remote node context which is to receive the task
963 * request.
964 * @param[in] the_request The task request to be transmitted to the remote
965 * target device.
966 *
967 * @return SCI_STATUS
968 * @retval SCI_SUCCESS
969 */
970 static
scic_sds_remote_node_context_await_suspension_state_start_task_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,struct SCIC_SDS_REQUEST * the_request)971 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_start_task_handler(
972 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
973 struct SCIC_SDS_REQUEST * the_request
974 )
975 {
976 return SCI_SUCCESS;
977 }
978
979 static
scic_sds_remote_node_context_await_suspension_state_event_handler(struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,U32 event_code)980 SCI_STATUS scic_sds_remote_node_context_await_suspension_state_event_handler(
981 struct SCIC_SDS_REMOTE_NODE_CONTEXT * this_rnc,
982 U32 event_code
983 )
984 {
985 SCI_STATUS status;
986
987 switch (scu_get_event_type(event_code))
988 {
989 case SCU_EVENT_TL_RNC_SUSPEND_TX:
990 sci_base_state_machine_change_state(
991 &this_rnc->state_machine,
992 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
993 );
994
995 this_rnc->suspension_code = scu_get_event_specifier(event_code);
996 status = SCI_SUCCESS;
997 break;
998
999 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
1000 sci_base_state_machine_change_state(
1001 &this_rnc->state_machine,
1002 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1003 );
1004
1005 this_rnc->suspension_code = scu_get_event_specifier(event_code);
1006 status = SCI_SUCCESS;
1007 break;
1008
1009 default:
1010 SCIC_LOG_WARNING((
1011 sci_base_object_get_logger(this_rnc->device),
1012 SCIC_LOG_OBJECT_SSP_REMOTE_TARGET |
1013 SCIC_LOG_OBJECT_SMP_REMOTE_TARGET |
1014 SCIC_LOG_OBJECT_STP_REMOTE_TARGET,
1015 "SCIC Remote Node Context 0x%x requested to process event 0x%x while in state %d.\n",
1016 this_rnc, event_code, sci_base_state_machine_get_state(&this_rnc->state_machine)
1017 ));
1018
1019 status = SCI_FAILURE;
1020 break;
1021 }
1022
1023 return status;
1024 }
1025
1026 // ---------------------------------------------------------------------------
1027
1028 SCIC_SDS_REMOTE_NODE_CONTEXT_HANDLERS
1029 scic_sds_remote_node_context_state_handler_table[
1030 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1031 {
1032 // SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1033 {
1034 scic_sds_remote_node_context_default_destruct_handler,
1035 scic_sds_remote_node_context_default_suspend_handler,
1036 scic_sds_remote_node_context_initial_state_resume_handler,
1037 scic_sds_remote_node_context_default_start_io_handler,
1038 scic_sds_remote_node_context_default_start_task_handler,
1039 scic_sds_remote_node_context_default_event_handler
1040 },
1041 // SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1042 {
1043 scic_sds_remote_node_context_general_destruct_handler,
1044 scic_sds_remote_node_context_default_suspend_handler,
1045 scic_sds_remote_node_context_continue_to_resume_handler,
1046 scic_sds_remote_node_context_default_start_io_handler,
1047 scic_sds_remote_node_context_default_start_task_handler,
1048 scic_sds_remote_node_context_posting_state_event_handler
1049 },
1050 // SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1051 {
1052 scic_sds_remote_node_context_invalidating_state_destruct_handler,
1053 scic_sds_remote_node_context_default_suspend_handler,
1054 scic_sds_remote_node_context_continue_to_resume_handler,
1055 scic_sds_remote_node_context_default_start_io_handler,
1056 scic_sds_remote_node_context_default_start_task_handler,
1057 scic_sds_remote_node_context_invalidating_state_event_handler
1058 },
1059 // SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1060 {
1061 scic_sds_remote_node_context_general_destruct_handler,
1062 scic_sds_remote_node_context_default_suspend_handler,
1063 scic_sds_remote_node_context_continue_to_resume_handler,
1064 scic_sds_remote_node_context_default_start_io_handler,
1065 scic_sds_remote_node_context_success_start_task_handler,
1066 scic_sds_remote_node_context_resuming_state_event_handler
1067 },
1068 // SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1069 {
1070 scic_sds_remote_node_context_general_destruct_handler,
1071 scic_sds_remote_node_context_ready_state_suspend_handler,
1072 scic_sds_remote_node_context_default_resume_handler,
1073 scic_sds_remote_node_context_ready_state_start_io_handler,
1074 scic_sds_remote_node_context_success_start_task_handler,
1075 scic_sds_remote_node_context_ready_state_event_handler
1076 },
1077 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1078 {
1079 scic_sds_remote_node_context_general_destruct_handler,
1080 scic_sds_remote_node_context_default_suspend_handler,
1081 scic_sds_remote_node_context_tx_suspended_state_resume_handler,
1082 scic_sds_remote_node_context_reset_required_start_io_handler,
1083 scic_sds_remote_node_context_suspended_start_task_handler,
1084 scic_sds_remote_node_context_default_event_handler
1085 },
1086 // SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1087 {
1088 scic_sds_remote_node_context_general_destruct_handler,
1089 scic_sds_remote_node_context_default_suspend_handler,
1090 scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
1091 scic_sds_remote_node_context_reset_required_start_io_handler,
1092 scic_sds_remote_node_context_suspended_start_task_handler,
1093 scic_sds_remote_node_context_default_event_handler
1094 },
1095 // SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1096 {
1097 scic_sds_remote_node_context_general_destruct_handler,
1098 scic_sds_remote_node_context_default_suspend_handler,
1099 scic_sds_remote_node_context_await_suspension_state_resume_handler,
1100 scic_sds_remote_node_context_reset_required_start_io_handler,
1101 scic_sds_remote_node_context_await_suspension_state_start_task_handler,
1102 scic_sds_remote_node_context_await_suspension_state_event_handler
1103 }
1104 };
1105
1106 //*****************************************************************************
1107 //* REMOTE NODE CONTEXT PRIVATE METHODS
1108 //*****************************************************************************
1109
1110 /**
1111 * This method just calls the user callback function and then resets the
1112 * callback.
1113 *
1114 * @param[in out] rnc
1115 */
1116 static
scic_sds_remote_node_context_notify_user(SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc)1117 void scic_sds_remote_node_context_notify_user(
1118 SCIC_SDS_REMOTE_NODE_CONTEXT_T *rnc
1119 )
1120 {
1121 SCIC_SDS_REMOTE_NODE_CONTEXT_CALLBACK local_user_callback = rnc->user_callback;
1122 void * local_user_cookie = rnc->user_cookie;
1123
1124 //we need to set the user_callback to NULL before it is called, because
1125 //the user callback's stack may eventually also set up a new set of
1126 //user callback. If we nullify the user_callback after it is called,
1127 //we are in the risk to lose the freshly set user callback.
1128 rnc->user_callback = NULL;
1129 rnc->user_cookie = NULL;
1130
1131 if (local_user_callback != NULL)
1132 {
1133 (*local_user_callback)(local_user_cookie);
1134 }
1135 }
1136
1137 /**
1138 * This method will continue the remote node context state machine by
1139 * requesting to resume the remote node context state machine from its current
1140 * state.
1141 *
1142 * @param[in] rnc
1143 */
1144 static
scic_sds_remote_node_context_continue_state_transitions(SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc)1145 void scic_sds_remote_node_context_continue_state_transitions(
1146 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc
1147 )
1148 {
1149 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY)
1150 {
1151 rnc->state_handlers->resume_handler(
1152 rnc, rnc->user_callback, rnc->user_cookie
1153 );
1154 }
1155 }
1156
1157 /**
1158 * This method will mark the rnc buffer as being valid and post the request to
1159 * the hardware.
1160 *
1161 * @param[in] this_rnc The remote node context object that is to be
1162 * validated.
1163 *
1164 * @return none
1165 */
1166 static
scic_sds_remote_node_context_validate_context_buffer(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)1167 void scic_sds_remote_node_context_validate_context_buffer(
1168 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1169 )
1170 {
1171 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1172
1173 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1174 scic_sds_remote_device_get_controller(this_rnc->device),
1175 this_rnc->remote_node_index
1176 );
1177
1178 rnc_buffer->ssp.is_valid = TRUE;
1179
1180 if (
1181 !this_rnc->device->is_direct_attached
1182 && this_rnc->device->target_protocols.u.bits.attached_stp_target
1183 )
1184 {
1185 scic_sds_remote_device_post_request(
1186 this_rnc->device,
1187 SCU_CONTEXT_COMMAND_POST_RNC_96
1188 );
1189 }
1190 else
1191 {
1192 scic_sds_remote_device_post_request(
1193 this_rnc->device,
1194 SCU_CONTEXT_COMMAND_POST_RNC_32
1195 );
1196
1197 if (this_rnc->device->is_direct_attached)
1198 {
1199 scic_sds_port_setup_transports(
1200 this_rnc->device->owning_port,
1201 this_rnc->remote_node_index
1202 );
1203 }
1204 }
1205 }
1206
1207 /**
1208 * This method will update the RNC buffer and post the invalidate request.
1209 *
1210 * @param[in] this_rnc The remote node context object that is to be
1211 * invalidated.
1212 *
1213 * @return none
1214 */
1215 static
scic_sds_remote_node_context_invalidate_context_buffer(SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc)1216 void scic_sds_remote_node_context_invalidate_context_buffer(
1217 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc
1218 )
1219 {
1220 SCU_REMOTE_NODE_CONTEXT_T *rnc_buffer;
1221
1222 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1223 scic_sds_remote_device_get_controller(this_rnc->device),
1224 this_rnc->remote_node_index
1225 );
1226
1227 rnc_buffer->ssp.is_valid = FALSE;
1228
1229 scic_sds_remote_device_post_request(
1230 this_rnc->device,
1231 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
1232 );
1233 }
1234
1235 //*****************************************************************************
1236 //* REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
1237 //*****************************************************************************
1238
1239 /**
1240 *
1241 *
1242 * @param[in] object
1243 */
1244 static
scic_sds_remote_node_context_initial_state_enter(SCI_BASE_OBJECT_T * object)1245 void scic_sds_remote_node_context_initial_state_enter(
1246 SCI_BASE_OBJECT_T * object
1247 )
1248 {
1249 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1250 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1251
1252 SET_STATE_HANDLER(
1253 rnc,
1254 scic_sds_remote_node_context_state_handler_table,
1255 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1256 );
1257
1258 // Check to see if we have gotten back to the initial state because someone
1259 // requested to destroy the remote node context object.
1260 if (
1261 rnc->state_machine.previous_state_id
1262 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1263 )
1264 {
1265 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1266
1267 scic_sds_remote_node_context_notify_user(rnc);
1268
1269 // Since we are destroying the remote node context deinitialize the state logging
1270 // should we resume the remote node context the state logging will be reinitialized
1271 // on the resume handler.
1272 scic_sds_remote_node_context_deinitialize_state_logging(rnc);
1273 }
1274 }
1275
1276 /**
1277 *
1278 *
1279 * @param[in] object
1280 */
1281 static
scic_sds_remote_node_context_posting_state_enter(SCI_BASE_OBJECT_T * object)1282 void scic_sds_remote_node_context_posting_state_enter(
1283 SCI_BASE_OBJECT_T * object
1284 )
1285 {
1286 SCIC_SDS_REMOTE_NODE_CONTEXT_T * this_rnc;
1287 this_rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1288
1289 SET_STATE_HANDLER(
1290 this_rnc,
1291 scic_sds_remote_node_context_state_handler_table,
1292 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1293 );
1294
1295 scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1296 }
1297
1298 /**
1299 *
1300 *
1301 * @param[in] object
1302 */
1303 static
scic_sds_remote_node_context_invalidating_state_enter(SCI_BASE_OBJECT_T * object)1304 void scic_sds_remote_node_context_invalidating_state_enter(
1305 SCI_BASE_OBJECT_T * object
1306 )
1307 {
1308 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1309 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1310
1311 SET_STATE_HANDLER(
1312 rnc,
1313 scic_sds_remote_node_context_state_handler_table,
1314 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1315 );
1316
1317 scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1318 }
1319
1320 /**
1321 *
1322 *
1323 * @param[in] object
1324 */
1325 static
scic_sds_remote_node_context_resuming_state_enter(SCI_BASE_OBJECT_T * object)1326 void scic_sds_remote_node_context_resuming_state_enter(
1327 SCI_BASE_OBJECT_T * object
1328 )
1329 {
1330 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1331 SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
1332 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1333
1334 SET_STATE_HANDLER(
1335 rnc,
1336 scic_sds_remote_node_context_state_handler_table,
1337 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1338 );
1339
1340 // For direct attached SATA devices we need to clear the TLCR
1341 // NCQ to TCi tag mapping on the phy and in cases where we
1342 // resume because of a target reset we also need to update
1343 // the STPTLDARNI register with the RNi of the device
1344 scic_remote_device_get_protocols(rnc->device, &protocols);
1345
1346 if (
1347 (protocols.u.bits.attached_stp_target == 1)
1348 && (rnc->device->is_direct_attached)
1349 )
1350 {
1351 scic_sds_port_setup_transports(
1352 rnc->device->owning_port, rnc->remote_node_index
1353 );
1354 }
1355
1356 scic_sds_remote_device_post_request(
1357 rnc->device,
1358 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1359 );
1360 }
1361
1362 /**
1363 *
1364 *
1365 * @param[in] object
1366 */
1367 static
scic_sds_remote_node_context_ready_state_enter(SCI_BASE_OBJECT_T * object)1368 void scic_sds_remote_node_context_ready_state_enter(
1369 SCI_BASE_OBJECT_T * object
1370 )
1371 {
1372 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1373 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1374
1375 SET_STATE_HANDLER(
1376 rnc,
1377 scic_sds_remote_node_context_state_handler_table,
1378 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1379 );
1380
1381 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1382
1383 if (rnc->user_callback != NULL)
1384 {
1385 scic_sds_remote_node_context_notify_user(rnc);
1386 }
1387 }
1388
1389 /**
1390 *
1391 *
1392 * @param[in] object
1393 */
1394 static
scic_sds_remote_node_context_tx_suspended_state_enter(SCI_BASE_OBJECT_T * object)1395 void scic_sds_remote_node_context_tx_suspended_state_enter(
1396 SCI_BASE_OBJECT_T * object
1397 )
1398 {
1399 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1400 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1401
1402 SET_STATE_HANDLER(
1403 rnc,
1404 scic_sds_remote_node_context_state_handler_table,
1405 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1406 );
1407
1408 scic_sds_remote_node_context_continue_state_transitions(rnc);
1409 }
1410
1411 /**
1412 *
1413 *
1414 * @param[in] object
1415 */
1416 static
scic_sds_remote_node_context_tx_rx_suspended_state_enter(SCI_BASE_OBJECT_T * object)1417 void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1418 SCI_BASE_OBJECT_T * object
1419 )
1420 {
1421 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1422 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1423
1424 SET_STATE_HANDLER(
1425 rnc,
1426 scic_sds_remote_node_context_state_handler_table,
1427 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1428 );
1429
1430 scic_sds_remote_node_context_continue_state_transitions(rnc);
1431 }
1432
1433 /**
1434 *
1435 *
1436 * @param[in] object
1437 */
1438 static
scic_sds_remote_node_context_await_suspension_state_enter(SCI_BASE_OBJECT_T * object)1439 void scic_sds_remote_node_context_await_suspension_state_enter(
1440 SCI_BASE_OBJECT_T * object
1441 )
1442 {
1443 SCIC_SDS_REMOTE_NODE_CONTEXT_T * rnc;
1444 rnc = (SCIC_SDS_REMOTE_NODE_CONTEXT_T *)object;
1445
1446 SET_STATE_HANDLER(
1447 rnc,
1448 scic_sds_remote_node_context_state_handler_table,
1449 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1450 );
1451 }
1452
1453 // ---------------------------------------------------------------------------
1454
1455 SCI_BASE_STATE_T
1456 scic_sds_remote_node_context_state_table[
1457 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
1458 {
1459 {
1460 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
1461 scic_sds_remote_node_context_initial_state_enter,
1462 NULL
1463 },
1464 {
1465 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
1466 scic_sds_remote_node_context_posting_state_enter,
1467 NULL
1468 },
1469 {
1470 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
1471 scic_sds_remote_node_context_invalidating_state_enter,
1472 NULL
1473 },
1474 {
1475 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
1476 scic_sds_remote_node_context_resuming_state_enter,
1477 NULL
1478 },
1479 {
1480 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
1481 scic_sds_remote_node_context_ready_state_enter,
1482 NULL
1483 },
1484 {
1485 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
1486 scic_sds_remote_node_context_tx_suspended_state_enter,
1487 NULL
1488 },
1489 {
1490 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
1491 scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1492 NULL
1493 },
1494 {
1495 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
1496 scic_sds_remote_node_context_await_suspension_state_enter,
1497 NULL
1498 }
1499 };
1500
1501