isci: replace this_* and the_* variables with more meaningful names
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / scsi / isci / core / scic_sds_remote_node_context.c
blobe329296fa386502a38f358fd9019af482ee1f261
1 /*
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
5 * GPL LICENSE SUMMARY
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.
24 * BSD LICENSE
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
31 * are met:
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
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"
63 #include "sci_util.h"
64 #include "scu_event_codes.h"
65 #include "scu_task_context.h"
68 /**
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
80 /**
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) {
94 return true;
97 return false;
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);
118 memset(
119 rnc,
120 0x00,
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;
142 if (
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;
150 } else {
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;
168 * @sci_rnc:
169 * @callback:
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;
190 * @sci_rnc:
191 * @callback:
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;
209 * @sci_rnc:
210 * @callback:
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;
224 return SCI_SUCCESS;
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",
240 __func__,
241 sci_rnc,
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. */
247 return SCI_SUCCESS;
250 static enum sci_status scic_sds_remote_node_context_default_suspend_handler(
251 struct scic_sds_remote_node_context *sci_rnc,
252 u32 suspend_type,
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",
259 __func__,
260 sci_rnc,
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",
274 __func__,
275 sci_rnc,
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",
288 __func__,
289 sci_rnc,
290 sci_req,
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",
303 __func__,
304 sci_rnc,
305 sci_req,
306 sci_base_state_machine_get_state(&sci_rnc->state_machine));
308 return SCI_FAILURE;
311 static enum sci_status scic_sds_remote_node_context_default_event_handler(
312 struct scic_sds_remote_node_context *sci_rnc,
313 u32 event_code)
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",
318 __func__,
319 sci_rnc,
320 event_code,
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)
339 return SCI_SUCCESS;
344 * @sci_rnc:
345 * @callback:
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
367 return SCI_SUCCESS;
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
389 return SCI_SUCCESS;
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,
399 u32 event_code)
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
411 break;
413 default:
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 "
418 "state\n",
419 __func__,
420 sci_rnc,
421 event_code);
422 break;
425 return status;
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
439 return SCI_SUCCESS;
442 static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler(
443 struct scic_sds_remote_node_context *sci_rnc,
444 u32 event_code)
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
456 } else {
457 sci_base_state_machine_change_state(
458 &sci_rnc->state_machine,
459 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
462 } else {
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 "
472 "invalidated.\n",
473 __func__,
474 sci_rnc);
475 status = SCI_SUCCESS;
476 break;
478 default:
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 "
482 "in state %d.\n",
483 __func__,
484 sci_rnc,
485 event_code,
486 sci_base_state_machine_get_state(
487 &sci_rnc->state_machine));
488 status = SCI_FAILURE;
489 break;
493 return status;
496 /* --------------------------------------------------------------------------- */
499 static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler(
500 struct scic_sds_remote_node_context *sci_rnc,
501 u32 event_code)
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
512 } else {
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",
522 __func__,
523 sci_rnc);
524 status = SCI_SUCCESS;
525 break;
527 default:
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",
531 __func__,
532 sci_rnc,
533 event_code,
534 sci_base_state_machine_get_state(
535 &sci_rnc->state_machine));
536 status = SCI_FAILURE;
537 break;
541 return status;
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.
553 * SCI_SUCCESS
555 static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler(
556 struct scic_sds_remote_node_context *sci_rnc,
557 u32 suspend_type,
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(
567 sci_rnc->device,
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
577 return SCI_SUCCESS;
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
587 * SCI_SUCCESS
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)
593 return SCI_SUCCESS;
597 static enum sci_status scic_sds_remote_node_context_ready_state_event_handler(
598 struct scic_sds_remote_node_context *sci_rnc,
599 u32 event_code)
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;
612 break;
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;
622 break;
624 default:
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",
628 __func__,
629 sci_rnc,
630 event_code,
631 sci_base_state_machine_get_state(
632 &sci_rnc->state_machine));
634 status = SCI_FAILURE;
635 break;
638 return status;
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);
659 if (
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
676 } else {
677 sci_base_state_machine_change_state(
678 &sci_rnc->state_machine,
679 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
683 status = SCI_SUCCESS;
684 } else {
685 status = SCI_FAILURE;
688 return status;
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
695 * device.
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);
708 return SCI_SUCCESS;
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
746 return SCI_SUCCESS;
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
753 * device.
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)
764 return SCI_SUCCESS;
767 static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler(
768 struct scic_sds_remote_node_context *sci_rnc,
769 u32 event_code)
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;
782 break;
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;
792 break;
794 default:
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",
798 __func__,
799 sci_rnc,
800 event_code,
801 sci_base_state_machine_get_state(
802 &sci_rnc->state_machine));
804 status = SCI_FAILURE;
805 break;
808 return status;
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
900 * callback.
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
918 * state.
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
935 * the hardware. none
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;
949 if (
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(
954 sci_rnc->device,
955 SCU_CONTEXT_COMMAND_POST_RNC_96
957 } else {
958 scic_sds_remote_device_post_request(
959 sci_rnc->device,
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(
991 sci_rnc->device,
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;
1013 SET_STATE_HANDLER(
1014 rnc,
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. */
1022 if (
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;
1044 SET_STATE_HANDLER(
1045 sci_rnc,
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;
1065 SET_STATE_HANDLER(
1066 rnc,
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;
1087 SET_STATE_HANDLER(
1088 rnc,
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(
1108 rnc->device,
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;
1125 SET_STATE_HANDLER(
1126 rnc,
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;
1150 SET_STATE_HANDLER(
1151 rnc,
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;
1171 SET_STATE_HANDLER(
1172 rnc,
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;
1192 SET_STATE_HANDLER(
1193 rnc,
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,
1241 &rnc->parent,
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);