2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 #include "sci_base_state_machine.h"
57 #include "scic_remote_device.h"
58 #include "scic_sds_controller.h"
59 #include "scic_sds_port.h"
60 #include "scic_sds_remote_device.h"
61 #include "scic_sds_remote_node_context.h"
62 #include "sci_environment.h"
64 #include "scu_event_codes.h"
65 #include "scu_task_context.h"
70 * @sci_rnc: The RNC for which the is posted request is being made.
72 * This method will return true if the RNC is not in the initial state. In all
73 * other states the RNC is considered active and this will return true. The
74 * destroy request of the state machine drives the RNC back to the initial
75 * state. If the state machine changes then this routine will also have to be
76 * changed. bool true if the state machine is not in the initial state false if
77 * the state machine is in the initial state
82 * @sci_rnc: The state of the remote node context object to check.
84 * This method will return true if the remote node context is in a READY state
85 * otherwise it will return false bool true if the remote node context is in
86 * the ready state. false if the remote node context is not in the ready state.
88 bool scic_sds_remote_node_context_is_ready(
89 struct scic_sds_remote_node_context
*sci_rnc
)
91 u32 current_state
= sci_base_state_machine_get_state(&sci_rnc
->state_machine
);
93 if (current_state
== SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
) {
102 * @sci_dev: The remote device to use to construct the RNC buffer.
103 * @rnc: The buffer into which the remote device data will be copied.
105 * This method will construct the RNC buffer for this remote device object. none
107 static void scic_sds_remote_node_context_construct_buffer(
108 struct scic_sds_remote_node_context
*sci_rnc
)
110 union scu_remote_node_context
*rnc
;
111 struct scic_sds_controller
*scic
;
113 scic
= scic_sds_remote_device_get_controller(sci_rnc
->device
);
115 rnc
= scic_sds_controller_get_remote_node_context_buffer(
116 scic
, sci_rnc
->remote_node_index
);
121 sizeof(union scu_remote_node_context
)
122 * scic_sds_remote_device_node_count(sci_rnc
->device
)
125 rnc
->ssp
.remote_node_index
= sci_rnc
->remote_node_index
;
126 rnc
->ssp
.remote_node_port_width
= sci_rnc
->device
->device_port_width
;
127 rnc
->ssp
.logical_port_index
=
128 scic_sds_remote_device_get_port_index(sci_rnc
->device
);
130 rnc
->ssp
.remote_sas_address_hi
= SCIC_SWAP_DWORD(sci_rnc
->device
->device_address
.high
);
131 rnc
->ssp
.remote_sas_address_lo
= SCIC_SWAP_DWORD(sci_rnc
->device
->device_address
.low
);
133 rnc
->ssp
.nexus_loss_timer_enable
= true;
134 rnc
->ssp
.check_bit
= false;
135 rnc
->ssp
.is_valid
= false;
136 rnc
->ssp
.is_remote_node_context
= true;
137 rnc
->ssp
.function_number
= 0;
139 rnc
->ssp
.arbitration_wait_time
= 0;
143 sci_rnc
->device
->target_protocols
.u
.bits
.attached_sata_device
144 || sci_rnc
->device
->target_protocols
.u
.bits
.attached_stp_target
146 rnc
->ssp
.connection_occupancy_timeout
=
147 scic
->user_parameters
.sds1
.stp_max_occupancy_timeout
;
148 rnc
->ssp
.connection_inactivity_timeout
=
149 scic
->user_parameters
.sds1
.stp_inactivity_timeout
;
151 rnc
->ssp
.connection_occupancy_timeout
=
152 scic
->user_parameters
.sds1
.ssp_max_occupancy_timeout
;
153 rnc
->ssp
.connection_inactivity_timeout
=
154 scic
->user_parameters
.sds1
.ssp_inactivity_timeout
;
157 rnc
->ssp
.initial_arbitration_wait_time
= 0;
159 /* Open Address Frame Parameters */
160 rnc
->ssp
.oaf_connection_rate
= sci_rnc
->device
->connection_rate
;
161 rnc
->ssp
.oaf_features
= 0;
162 rnc
->ssp
.oaf_source_zone_group
= 0;
163 rnc
->ssp
.oaf_more_compatibility_features
= 0;
170 * @callback_parameter:
172 * This method will setup the remote node context object so it will transition
173 * to its ready state. If the remote node context is already setup to
174 * transition to its final state then this function does nothing. none
176 static void scic_sds_remote_node_context_setup_to_resume(
177 struct scic_sds_remote_node_context
*sci_rnc
,
178 scics_sds_remote_node_context_callback callback
,
179 void *callback_parameter
)
181 if (sci_rnc
->destination_state
!= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
) {
182 sci_rnc
->destination_state
= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY
;
183 sci_rnc
->user_callback
= callback
;
184 sci_rnc
->user_cookie
= callback_parameter
;
192 * @callback_parameter:
194 * This method will setup the remote node context object so it will transistion
195 * to its final state. none
197 static void scic_sds_remote_node_context_setup_to_destory(
198 struct scic_sds_remote_node_context
*sci_rnc
,
199 scics_sds_remote_node_context_callback callback
,
200 void *callback_parameter
)
202 sci_rnc
->destination_state
= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
;
203 sci_rnc
->user_callback
= callback
;
204 sci_rnc
->user_cookie
= callback_parameter
;
212 * This method will continue to resume a remote node context. This is used in
213 * the states where a resume is requested while a resume is in progress.
215 static enum sci_status
scic_sds_remote_node_context_continue_to_resume_handler(
216 struct scic_sds_remote_node_context
*sci_rnc
,
217 scics_sds_remote_node_context_callback callback
,
218 void *callback_parameter
)
220 if (sci_rnc
->destination_state
== SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY
) {
221 sci_rnc
->user_callback
= callback
;
222 sci_rnc
->user_cookie
= callback_parameter
;
227 return SCI_FAILURE_INVALID_STATE
;
230 /* --------------------------------------------------------------------------- */
232 static enum sci_status
scic_sds_remote_node_context_default_destruct_handler(
233 struct scic_sds_remote_node_context
*sci_rnc
,
234 scics_sds_remote_node_context_callback callback
,
235 void *callback_parameter
)
237 dev_warn(scirdev_to_dev(sci_rnc
->device
),
238 "%s: SCIC Remote Node Context 0x%p requested to stop while "
239 "in unexpected state %d\n",
242 sci_base_state_machine_get_state(&sci_rnc
->state_machine
));
245 * We have decided that the destruct request on the remote node context can not fail
246 * since it is either in the initial/destroyed state or is can be destroyed. */
250 static enum sci_status
scic_sds_remote_node_context_default_suspend_handler(
251 struct scic_sds_remote_node_context
*sci_rnc
,
253 scics_sds_remote_node_context_callback callback
,
254 void *callback_parameter
)
256 dev_warn(scirdev_to_dev(sci_rnc
->device
),
257 "%s: SCIC Remote Node Context 0x%p requested to suspend "
258 "while in wrong state %d\n",
261 sci_base_state_machine_get_state(&sci_rnc
->state_machine
));
263 return SCI_FAILURE_INVALID_STATE
;
266 static enum sci_status
scic_sds_remote_node_context_default_resume_handler(
267 struct scic_sds_remote_node_context
*sci_rnc
,
268 scics_sds_remote_node_context_callback callback
,
269 void *callback_parameter
)
271 dev_warn(scirdev_to_dev(sci_rnc
->device
),
272 "%s: SCIC Remote Node Context 0x%p requested to resume "
273 "while in wrong state %d\n",
276 sci_base_state_machine_get_state(&sci_rnc
->state_machine
));
278 return SCI_FAILURE_INVALID_STATE
;
281 static enum sci_status
scic_sds_remote_node_context_default_start_io_handler(
282 struct scic_sds_remote_node_context
*sci_rnc
,
283 struct scic_sds_request
*sci_req
)
285 dev_warn(scirdev_to_dev(sci_rnc
->device
),
286 "%s: SCIC Remote Node Context 0x%p requested to start io "
287 "0x%p while in wrong state %d\n",
291 sci_base_state_machine_get_state(&sci_rnc
->state_machine
));
293 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED
;
296 static enum sci_status
scic_sds_remote_node_context_default_start_task_handler(
297 struct scic_sds_remote_node_context
*sci_rnc
,
298 struct scic_sds_request
*sci_req
)
300 dev_warn(scirdev_to_dev(sci_rnc
->device
),
301 "%s: SCIC Remote Node Context 0x%p requested to start "
302 "task 0x%p while in wrong state %d\n",
306 sci_base_state_machine_get_state(&sci_rnc
->state_machine
));
311 static enum sci_status
scic_sds_remote_node_context_default_event_handler(
312 struct scic_sds_remote_node_context
*sci_rnc
,
315 dev_warn(scirdev_to_dev(sci_rnc
->device
),
316 "%s: SCIC Remote Node Context 0x%p requested to process "
317 "event 0x%x while in wrong state %d\n",
321 sci_base_state_machine_get_state(&sci_rnc
->state_machine
));
323 return SCI_FAILURE_INVALID_STATE
;
328 * @sci_rnc: The rnc for which the task request is targeted.
329 * @sci_req: The request which is going to be started.
331 * This method determines if the task request can be started by the SCU
332 * hardware. When the RNC is in the ready state any task can be started.
333 * enum sci_status SCI_SUCCESS
335 static enum sci_status
scic_sds_remote_node_context_success_start_task_handler(
336 struct scic_sds_remote_node_context
*sci_rnc
,
337 struct scic_sds_request
*sci_req
)
346 * @callback_parameter:
348 * This method handles destruct calls from the various state handlers. The
349 * remote node context can be requested to destroy from any state. If there was
350 * a user callback it is always replaced with the request to destroy user
351 * callback. enum sci_status
353 static enum sci_status
scic_sds_remote_node_context_general_destruct_handler(
354 struct scic_sds_remote_node_context
*sci_rnc
,
355 scics_sds_remote_node_context_callback callback
,
356 void *callback_parameter
)
358 scic_sds_remote_node_context_setup_to_destory(
359 sci_rnc
, callback
, callback_parameter
362 sci_base_state_machine_change_state(
363 &sci_rnc
->state_machine
,
364 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
370 /* --------------------------------------------------------------------------- */
372 static enum sci_status
scic_sds_remote_node_context_initial_state_resume_handler(
373 struct scic_sds_remote_node_context
*sci_rnc
,
374 scics_sds_remote_node_context_callback callback
,
375 void *callback_parameter
)
377 if (sci_rnc
->remote_node_index
!= SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX
) {
378 scic_sds_remote_node_context_setup_to_resume(
379 sci_rnc
, callback
, callback_parameter
382 scic_sds_remote_node_context_construct_buffer(sci_rnc
);
384 sci_base_state_machine_change_state(
385 &sci_rnc
->state_machine
,
386 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
392 return SCI_FAILURE_INVALID_STATE
;
395 /* --------------------------------------------------------------------------- */
397 static enum sci_status
scic_sds_remote_node_context_posting_state_event_handler(
398 struct scic_sds_remote_node_context
*sci_rnc
,
401 enum sci_status status
;
403 switch (scu_get_event_code(event_code
)) {
404 case SCU_EVENT_POST_RNC_COMPLETE
:
405 status
= SCI_SUCCESS
;
407 sci_base_state_machine_change_state(
408 &sci_rnc
->state_machine
,
409 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
414 status
= SCI_FAILURE
;
415 dev_warn(scirdev_to_dev(sci_rnc
->device
),
416 "%s: SCIC Remote Node Context 0x%p requested to "
417 "process unexpected event 0x%x while in posting "
428 /* --------------------------------------------------------------------------- */
430 static enum sci_status
scic_sds_remote_node_context_invalidating_state_destruct_handler(
431 struct scic_sds_remote_node_context
*sci_rnc
,
432 scics_sds_remote_node_context_callback callback
,
433 void *callback_parameter
)
435 scic_sds_remote_node_context_setup_to_destory(
436 sci_rnc
, callback
, callback_parameter
442 static enum sci_status
scic_sds_remote_node_context_invalidating_state_event_handler(
443 struct scic_sds_remote_node_context
*sci_rnc
,
446 enum sci_status status
;
448 if (scu_get_event_code(event_code
) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE
) {
449 status
= SCI_SUCCESS
;
451 if (sci_rnc
->destination_state
== SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
) {
452 sci_base_state_machine_change_state(
453 &sci_rnc
->state_machine
,
454 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
457 sci_base_state_machine_change_state(
458 &sci_rnc
->state_machine
,
459 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
463 switch (scu_get_event_type(event_code
)) {
464 case SCU_EVENT_TYPE_RNC_SUSPEND_TX
:
465 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX
:
467 * We really dont care if the hardware is going to suspend
468 * the device since it's being invalidated anyway */
469 dev_dbg(scirdev_to_dev(sci_rnc
->device
),
470 "%s: SCIC Remote Node Context 0x%p was "
471 "suspeneded by hardware while being "
475 status
= SCI_SUCCESS
;
479 dev_warn(scirdev_to_dev(sci_rnc
->device
),
480 "%s: SCIC Remote Node Context 0x%p "
481 "requested to process event 0x%x while "
486 sci_base_state_machine_get_state(
487 &sci_rnc
->state_machine
));
488 status
= SCI_FAILURE
;
496 /* --------------------------------------------------------------------------- */
499 static enum sci_status
scic_sds_remote_node_context_resuming_state_event_handler(
500 struct scic_sds_remote_node_context
*sci_rnc
,
503 enum sci_status status
;
505 if (scu_get_event_code(event_code
) == SCU_EVENT_POST_RCN_RELEASE
) {
506 status
= SCI_SUCCESS
;
508 sci_base_state_machine_change_state(
509 &sci_rnc
->state_machine
,
510 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
513 switch (scu_get_event_type(event_code
)) {
514 case SCU_EVENT_TYPE_RNC_SUSPEND_TX
:
515 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX
:
517 * We really dont care if the hardware is going to suspend
518 * the device since it's being resumed anyway */
519 dev_dbg(scirdev_to_dev(sci_rnc
->device
),
520 "%s: SCIC Remote Node Context 0x%p was "
521 "suspeneded by hardware while being resumed.\n",
524 status
= SCI_SUCCESS
;
528 dev_warn(scirdev_to_dev(sci_rnc
->device
),
529 "%s: SCIC Remote Node Context 0x%p requested "
530 "to process event 0x%x while in state %d.\n",
534 sci_base_state_machine_get_state(
535 &sci_rnc
->state_machine
));
536 status
= SCI_FAILURE
;
544 /* --------------------------------------------------------------------------- */
548 * @sci_rnc: The remote node context object being suspended.
549 * @callback: The callback when the suspension is complete.
550 * @callback_parameter: The parameter that is to be passed into the callback.
552 * This method will handle the suspend requests from the ready state.
555 static enum sci_status
scic_sds_remote_node_context_ready_state_suspend_handler(
556 struct scic_sds_remote_node_context
*sci_rnc
,
558 scics_sds_remote_node_context_callback callback
,
559 void *callback_parameter
)
561 sci_rnc
->user_callback
= callback
;
562 sci_rnc
->user_cookie
= callback_parameter
;
563 sci_rnc
->suspension_code
= suspend_type
;
565 if (suspend_type
== SCI_SOFTWARE_SUSPENSION
) {
566 scic_sds_remote_device_post_request(
568 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
572 sci_base_state_machine_change_state(
573 &sci_rnc
->state_machine
,
574 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
582 * @sci_rnc: The rnc for which the io request is targeted.
583 * @sci_req: The request which is going to be started.
585 * This method determines if the io request can be started by the SCU hardware.
586 * When the RNC is in the ready state any io request can be started. enum sci_status
589 static enum sci_status
scic_sds_remote_node_context_ready_state_start_io_handler(
590 struct scic_sds_remote_node_context
*sci_rnc
,
591 struct scic_sds_request
*sci_req
)
597 static enum sci_status
scic_sds_remote_node_context_ready_state_event_handler(
598 struct scic_sds_remote_node_context
*sci_rnc
,
601 enum sci_status status
;
603 switch (scu_get_event_type(event_code
)) {
604 case SCU_EVENT_TL_RNC_SUSPEND_TX
:
605 sci_base_state_machine_change_state(
606 &sci_rnc
->state_machine
,
607 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
610 sci_rnc
->suspension_code
= scu_get_event_specifier(event_code
);
611 status
= SCI_SUCCESS
;
614 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX
:
615 sci_base_state_machine_change_state(
616 &sci_rnc
->state_machine
,
617 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
620 sci_rnc
->suspension_code
= scu_get_event_specifier(event_code
);
621 status
= SCI_SUCCESS
;
625 dev_warn(scirdev_to_dev(sci_rnc
->device
),
626 "%s: SCIC Remote Node Context 0x%p requested to "
627 "process event 0x%x while in state %d.\n",
631 sci_base_state_machine_get_state(
632 &sci_rnc
->state_machine
));
634 status
= SCI_FAILURE
;
641 /* --------------------------------------------------------------------------- */
643 static enum sci_status
scic_sds_remote_node_context_tx_suspended_state_resume_handler(
644 struct scic_sds_remote_node_context
*sci_rnc
,
645 scics_sds_remote_node_context_callback callback
,
646 void *callback_parameter
)
648 enum sci_status status
;
649 struct smp_discover_response_protocols protocols
;
651 scic_sds_remote_node_context_setup_to_resume(
652 sci_rnc
, callback
, callback_parameter
655 /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
657 scic_remote_device_get_protocols(sci_rnc
->device
, &protocols
);
660 (protocols
.u
.bits
.attached_ssp_target
== 1)
661 || (protocols
.u
.bits
.attached_smp_target
== 1)
663 sci_base_state_machine_change_state(
664 &sci_rnc
->state_machine
,
665 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
668 status
= SCI_SUCCESS
;
669 } else if (protocols
.u
.bits
.attached_stp_target
== 1) {
670 if (sci_rnc
->device
->is_direct_attached
) {
671 /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
672 sci_base_state_machine_change_state(
673 &sci_rnc
->state_machine
,
674 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
677 sci_base_state_machine_change_state(
678 &sci_rnc
->state_machine
,
679 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
683 status
= SCI_SUCCESS
;
685 status
= SCI_FAILURE
;
693 * @sci_rnc: The remote node context which is to receive the task request.
694 * @sci_req: The task request to be transmitted to to the remote target
697 * This method will report a success or failure attempt to start a new task
698 * request to the hardware. Since all task requests are sent on the high
699 * priority queue they can be sent when the RCN is in a TX suspend state.
700 * enum sci_status SCI_SUCCESS
702 static enum sci_status
scic_sds_remote_node_context_suspended_start_task_handler(
703 struct scic_sds_remote_node_context
*sci_rnc
,
704 struct scic_sds_request
*sci_req
)
706 scic_sds_remote_node_context_resume(sci_rnc
, NULL
, NULL
);
711 /* --------------------------------------------------------------------------- */
713 static enum sci_status
scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
714 struct scic_sds_remote_node_context
*sci_rnc
,
715 scics_sds_remote_node_context_callback callback
,
716 void *callback_parameter
)
718 scic_sds_remote_node_context_setup_to_resume(
719 sci_rnc
, callback
, callback_parameter
722 sci_base_state_machine_change_state(
723 &sci_rnc
->state_machine
,
724 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
727 return SCI_FAILURE_INVALID_STATE
;
730 /* --------------------------------------------------------------------------- */
737 static enum sci_status
scic_sds_remote_node_context_await_suspension_state_resume_handler(
738 struct scic_sds_remote_node_context
*sci_rnc
,
739 scics_sds_remote_node_context_callback callback
,
740 void *callback_parameter
)
742 scic_sds_remote_node_context_setup_to_resume(
743 sci_rnc
, callback
, callback_parameter
751 * @sci_rnc: The remote node context which is to receive the task request.
752 * @sci_req: The task request to be transmitted to to the remote target
755 * This method will report a success or failure attempt to start a new task
756 * request to the hardware. Since all task requests are sent on the high
757 * priority queue they can be sent when the RCN is in a TX suspend state.
758 * enum sci_status SCI_SUCCESS
760 static enum sci_status
scic_sds_remote_node_context_await_suspension_state_start_task_handler(
761 struct scic_sds_remote_node_context
*sci_rnc
,
762 struct scic_sds_request
*sci_req
)
767 static enum sci_status
scic_sds_remote_node_context_await_suspension_state_event_handler(
768 struct scic_sds_remote_node_context
*sci_rnc
,
771 enum sci_status status
;
773 switch (scu_get_event_type(event_code
)) {
774 case SCU_EVENT_TL_RNC_SUSPEND_TX
:
775 sci_base_state_machine_change_state(
776 &sci_rnc
->state_machine
,
777 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
780 sci_rnc
->suspension_code
= scu_get_event_specifier(event_code
);
781 status
= SCI_SUCCESS
;
784 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX
:
785 sci_base_state_machine_change_state(
786 &sci_rnc
->state_machine
,
787 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
790 sci_rnc
->suspension_code
= scu_get_event_specifier(event_code
);
791 status
= SCI_SUCCESS
;
795 dev_warn(scirdev_to_dev(sci_rnc
->device
),
796 "%s: SCIC Remote Node Context 0x%p requested to "
797 "process event 0x%x while in state %d.\n",
801 sci_base_state_machine_get_state(
802 &sci_rnc
->state_machine
));
804 status
= SCI_FAILURE
;
811 /* --------------------------------------------------------------------------- */
813 static struct scic_sds_remote_node_context_handlers
814 scic_sds_remote_node_context_state_handler_table
[
815 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES
] =
817 /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */
819 scic_sds_remote_node_context_default_destruct_handler
,
820 scic_sds_remote_node_context_default_suspend_handler
,
821 scic_sds_remote_node_context_initial_state_resume_handler
,
822 scic_sds_remote_node_context_default_start_io_handler
,
823 scic_sds_remote_node_context_default_start_task_handler
,
824 scic_sds_remote_node_context_default_event_handler
826 /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */
828 scic_sds_remote_node_context_general_destruct_handler
,
829 scic_sds_remote_node_context_default_suspend_handler
,
830 scic_sds_remote_node_context_continue_to_resume_handler
,
831 scic_sds_remote_node_context_default_start_io_handler
,
832 scic_sds_remote_node_context_default_start_task_handler
,
833 scic_sds_remote_node_context_posting_state_event_handler
835 /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */
837 scic_sds_remote_node_context_invalidating_state_destruct_handler
,
838 scic_sds_remote_node_context_default_suspend_handler
,
839 scic_sds_remote_node_context_continue_to_resume_handler
,
840 scic_sds_remote_node_context_default_start_io_handler
,
841 scic_sds_remote_node_context_default_start_task_handler
,
842 scic_sds_remote_node_context_invalidating_state_event_handler
844 /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */
846 scic_sds_remote_node_context_general_destruct_handler
,
847 scic_sds_remote_node_context_default_suspend_handler
,
848 scic_sds_remote_node_context_continue_to_resume_handler
,
849 scic_sds_remote_node_context_default_start_io_handler
,
850 scic_sds_remote_node_context_success_start_task_handler
,
851 scic_sds_remote_node_context_resuming_state_event_handler
853 /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */
855 scic_sds_remote_node_context_general_destruct_handler
,
856 scic_sds_remote_node_context_ready_state_suspend_handler
,
857 scic_sds_remote_node_context_default_resume_handler
,
858 scic_sds_remote_node_context_ready_state_start_io_handler
,
859 scic_sds_remote_node_context_success_start_task_handler
,
860 scic_sds_remote_node_context_ready_state_event_handler
862 /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */
864 scic_sds_remote_node_context_general_destruct_handler
,
865 scic_sds_remote_node_context_default_suspend_handler
,
866 scic_sds_remote_node_context_tx_suspended_state_resume_handler
,
867 scic_sds_remote_node_context_default_start_io_handler
,
868 scic_sds_remote_node_context_suspended_start_task_handler
,
869 scic_sds_remote_node_context_default_event_handler
871 /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */
873 scic_sds_remote_node_context_general_destruct_handler
,
874 scic_sds_remote_node_context_default_suspend_handler
,
875 scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler
,
876 scic_sds_remote_node_context_default_start_io_handler
,
877 scic_sds_remote_node_context_suspended_start_task_handler
,
878 scic_sds_remote_node_context_default_event_handler
880 /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */
882 scic_sds_remote_node_context_general_destruct_handler
,
883 scic_sds_remote_node_context_default_suspend_handler
,
884 scic_sds_remote_node_context_await_suspension_state_resume_handler
,
885 scic_sds_remote_node_context_default_start_io_handler
,
886 scic_sds_remote_node_context_await_suspension_state_start_task_handler
,
887 scic_sds_remote_node_context_await_suspension_state_event_handler
892 * *****************************************************************************
893 * * REMOTE NODE CONTEXT PRIVATE METHODS
894 * ***************************************************************************** */
899 * This method just calls the user callback function and then resets the
902 static void scic_sds_remote_node_context_notify_user(
903 struct scic_sds_remote_node_context
*rnc
)
905 if (rnc
->user_callback
!= NULL
) {
906 (*rnc
->user_callback
)(rnc
->user_cookie
);
908 rnc
->user_callback
= NULL
;
909 rnc
->user_cookie
= NULL
;
916 * This method will continue the remote node context state machine by
917 * requesting to resume the remote node context state machine from its current
920 static void scic_sds_remote_node_context_continue_state_transitions(
921 struct scic_sds_remote_node_context
*rnc
)
923 if (rnc
->destination_state
== SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY
) {
924 rnc
->state_handlers
->resume_handler(
925 rnc
, rnc
->user_callback
, rnc
->user_cookie
932 * @sci_rnc: The remote node context object that is to be validated.
934 * This method will mark the rnc buffer as being valid and post the request to
937 static void scic_sds_remote_node_context_validate_context_buffer(
938 struct scic_sds_remote_node_context
*sci_rnc
)
940 union scu_remote_node_context
*rnc_buffer
;
942 rnc_buffer
= scic_sds_controller_get_remote_node_context_buffer(
943 scic_sds_remote_device_get_controller(sci_rnc
->device
),
944 sci_rnc
->remote_node_index
947 rnc_buffer
->ssp
.is_valid
= true;
950 !sci_rnc
->device
->is_direct_attached
951 && sci_rnc
->device
->target_protocols
.u
.bits
.attached_stp_target
953 scic_sds_remote_device_post_request(
955 SCU_CONTEXT_COMMAND_POST_RNC_96
958 scic_sds_remote_device_post_request(
960 SCU_CONTEXT_COMMAND_POST_RNC_32
963 if (sci_rnc
->device
->is_direct_attached
) {
964 scic_sds_port_setup_transports(
965 sci_rnc
->device
->owning_port
,
966 sci_rnc
->remote_node_index
974 * @sci_rnc: The remote node context object that is to be invalidated.
976 * This method will update the RNC buffer and post the invalidate request. none
978 static void scic_sds_remote_node_context_invalidate_context_buffer(
979 struct scic_sds_remote_node_context
*sci_rnc
)
981 union scu_remote_node_context
*rnc_buffer
;
983 rnc_buffer
= scic_sds_controller_get_remote_node_context_buffer(
984 scic_sds_remote_device_get_controller(sci_rnc
->device
),
985 sci_rnc
->remote_node_index
988 rnc_buffer
->ssp
.is_valid
= false;
990 scic_sds_remote_device_post_request(
992 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
997 * *****************************************************************************
998 * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
999 * ***************************************************************************** */
1006 static void scic_sds_remote_node_context_initial_state_enter(
1007 struct sci_base_object
*object
)
1009 struct scic_sds_remote_node_context
*rnc
;
1011 rnc
= (struct scic_sds_remote_node_context
*)object
;
1015 scic_sds_remote_node_context_state_handler_table
,
1016 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1020 * Check to see if we have gotten back to the initial state because someone
1021 * requested to destroy the remote node context object. */
1023 rnc
->state_machine
.previous_state_id
1024 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1026 rnc
->destination_state
= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED
;
1028 scic_sds_remote_node_context_notify_user(rnc
);
1037 static void scic_sds_remote_node_context_posting_state_enter(
1038 struct sci_base_object
*object
)
1040 struct scic_sds_remote_node_context
*sci_rnc
;
1042 sci_rnc
= (struct scic_sds_remote_node_context
*)object
;
1046 scic_sds_remote_node_context_state_handler_table
,
1047 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1050 scic_sds_remote_node_context_validate_context_buffer(sci_rnc
);
1058 static void scic_sds_remote_node_context_invalidating_state_enter(
1059 struct sci_base_object
*object
)
1061 struct scic_sds_remote_node_context
*rnc
;
1063 rnc
= (struct scic_sds_remote_node_context
*)object
;
1067 scic_sds_remote_node_context_state_handler_table
,
1068 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1071 scic_sds_remote_node_context_invalidate_context_buffer(rnc
);
1079 static void scic_sds_remote_node_context_resuming_state_enter(
1080 struct sci_base_object
*object
)
1082 struct scic_sds_remote_node_context
*rnc
;
1083 struct smp_discover_response_protocols protocols
;
1085 rnc
= (struct scic_sds_remote_node_context
*)object
;
1089 scic_sds_remote_node_context_state_handler_table
,
1090 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1094 * For direct attached SATA devices we need to clear the TLCR
1095 * NCQ to TCi tag mapping on the phy and in cases where we
1096 * resume because of a target reset we also need to update
1097 * the STPTLDARNI register with the RNi of the device
1099 scic_remote_device_get_protocols(rnc
->device
, &protocols
);
1101 if ((protocols
.u
.bits
.attached_stp_target
== 1) &&
1102 (rnc
->device
->is_direct_attached
)) {
1103 scic_sds_port_setup_transports(
1104 rnc
->device
->owning_port
, rnc
->remote_node_index
);
1107 scic_sds_remote_device_post_request(
1109 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1118 static void scic_sds_remote_node_context_ready_state_enter(
1119 struct sci_base_object
*object
)
1121 struct scic_sds_remote_node_context
*rnc
;
1123 rnc
= (struct scic_sds_remote_node_context
*)object
;
1127 scic_sds_remote_node_context_state_handler_table
,
1128 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1131 rnc
->destination_state
= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED
;
1133 if (rnc
->user_callback
!= NULL
) {
1134 scic_sds_remote_node_context_notify_user(rnc
);
1143 static void scic_sds_remote_node_context_tx_suspended_state_enter(
1144 struct sci_base_object
*object
)
1146 struct scic_sds_remote_node_context
*rnc
;
1148 rnc
= (struct scic_sds_remote_node_context
*)object
;
1152 scic_sds_remote_node_context_state_handler_table
,
1153 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1156 scic_sds_remote_node_context_continue_state_transitions(rnc
);
1164 static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1165 struct sci_base_object
*object
)
1167 struct scic_sds_remote_node_context
*rnc
;
1169 rnc
= (struct scic_sds_remote_node_context
*)object
;
1173 scic_sds_remote_node_context_state_handler_table
,
1174 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1177 scic_sds_remote_node_context_continue_state_transitions(rnc
);
1185 static void scic_sds_remote_node_context_await_suspension_state_enter(
1186 struct sci_base_object
*object
)
1188 struct scic_sds_remote_node_context
*rnc
;
1190 rnc
= (struct scic_sds_remote_node_context
*)object
;
1194 scic_sds_remote_node_context_state_handler_table
,
1195 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1199 /* --------------------------------------------------------------------------- */
1201 static const struct sci_base_state scic_sds_remote_node_context_state_table
[] = {
1202 [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
] = {
1203 .enter_state
= scic_sds_remote_node_context_initial_state_enter
,
1205 [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
] = {
1206 .enter_state
= scic_sds_remote_node_context_posting_state_enter
,
1208 [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
] = {
1209 .enter_state
= scic_sds_remote_node_context_invalidating_state_enter
,
1211 [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
] = {
1212 .enter_state
= scic_sds_remote_node_context_resuming_state_enter
,
1214 [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
] = {
1215 .enter_state
= scic_sds_remote_node_context_ready_state_enter
,
1217 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
] = {
1218 .enter_state
= scic_sds_remote_node_context_tx_suspended_state_enter
,
1220 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
] = {
1221 .enter_state
= scic_sds_remote_node_context_tx_rx_suspended_state_enter
,
1223 [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
] = {
1224 .enter_state
= scic_sds_remote_node_context_await_suspension_state_enter
,
1228 void scic_sds_remote_node_context_construct(
1229 struct scic_sds_remote_device
*device
,
1230 struct scic_sds_remote_node_context
*rnc
,
1231 u16 remote_node_index
)
1233 memset(rnc
, 0, sizeof(struct scic_sds_remote_node_context
));
1235 rnc
->remote_node_index
= remote_node_index
;
1236 rnc
->device
= device
;
1237 rnc
->destination_state
= SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED
;
1239 sci_base_state_machine_construct(
1240 &rnc
->state_machine
,
1242 scic_sds_remote_node_context_state_table
,
1243 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1246 sci_base_state_machine_start(&rnc
->state_machine
);