xref: /freebsd/sys/dev/isci/scil/scic_sds_remote_node_context.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
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