isci: namespacecheck cleanups
[deliverable/linux.git] / drivers / scsi / isci / core / scic_sds_remote_node_context.c
CommitLineData
6f231dda
DW
1/*
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55
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"
66
6f231dda
DW
67
68/**
69 *
70 * @this_rnc: The RNC for which the is posted request is being made.
71 *
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
78 */
79
80/**
81 *
82 * @this_rnc: The state of the remote node context object to check.
83 *
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.
87 */
88bool scic_sds_remote_node_context_is_ready(
89 struct scic_sds_remote_node_context *this_rnc)
90{
91 u32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
92
93 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) {
94 return true;
95 }
96
97 return false;
98}
99
100/**
101 *
102 * @this_device: The remote device to use to construct the RNC buffer.
103 * @rnc: The buffer into which the remote device data will be copied.
104 *
105 * This method will construct the RNC buffer for this remote device object. none
106 */
35173d57 107static void scic_sds_remote_node_context_construct_buffer(
6f231dda
DW
108 struct scic_sds_remote_node_context *this_rnc)
109{
110 union scu_remote_node_context *rnc;
111 struct scic_sds_controller *the_controller;
112
113 the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
114
115 rnc = scic_sds_controller_get_remote_node_context_buffer(
116 the_controller, this_rnc->remote_node_index);
117
118 memset(
119 rnc,
120 0x00,
121 sizeof(union scu_remote_node_context)
122 * scic_sds_remote_device_node_count(this_rnc->device)
123 );
124
125 rnc->ssp.remote_node_index = this_rnc->remote_node_index;
126 rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
127 rnc->ssp.logical_port_index =
128 scic_sds_remote_device_get_port_index(this_rnc->device);
129
130 rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
131 rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
132
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;
138
139 rnc->ssp.arbitration_wait_time = 0;
140
141
142 if (
143 this_rnc->device->target_protocols.u.bits.attached_sata_device
144 || this_rnc->device->target_protocols.u.bits.attached_stp_target
145 ) {
146 rnc->ssp.connection_occupancy_timeout =
147 the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
148 rnc->ssp.connection_inactivity_timeout =
149 the_controller->user_parameters.sds1.stp_inactivity_timeout;
150 } else {
151 rnc->ssp.connection_occupancy_timeout =
152 the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
153 rnc->ssp.connection_inactivity_timeout =
154 the_controller->user_parameters.sds1.ssp_inactivity_timeout;
155 }
156
157 rnc->ssp.initial_arbitration_wait_time = 0;
158
159 /* Open Address Frame Parameters */
160 rnc->ssp.oaf_connection_rate = this_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;
164}
165
166/**
167 *
168 * @this_rnc:
169 * @the_callback:
170 * @callback_parameter:
171 *
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
175 */
176static void scic_sds_remote_node_context_setup_to_resume(
177 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 178 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
179 void *callback_parameter)
180{
181 if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
182 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
183 this_rnc->user_callback = the_callback;
184 this_rnc->user_cookie = callback_parameter;
185 }
186}
187
188/**
189 *
190 * @this_rnc:
191 * @the_callback:
192 * @callback_parameter:
193 *
194 * This method will setup the remote node context object so it will transistion
195 * to its final state. none
196 */
197static void scic_sds_remote_node_context_setup_to_destory(
198 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 199 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
200 void *callback_parameter)
201{
202 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
203 this_rnc->user_callback = the_callback;
204 this_rnc->user_cookie = callback_parameter;
205}
206
207/**
208 *
209 * @this_rnc:
210 * @the_callback:
211 *
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.
214 */
215static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler(
216 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 217 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
218 void *callback_parameter)
219{
220 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
221 this_rnc->user_callback = the_callback;
222 this_rnc->user_cookie = callback_parameter;
223
224 return SCI_SUCCESS;
225 }
226
227 return SCI_FAILURE_INVALID_STATE;
228}
229
230/* --------------------------------------------------------------------------- */
231
232static enum sci_status scic_sds_remote_node_context_default_destruct_handler(
233 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 234 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
235 void *callback_parameter)
236{
237 dev_warn(scirdev_to_dev(this_rnc->device),
238 "%s: SCIC Remote Node Context 0x%p requested to stop while "
239 "in unexpected state %d\n",
240 __func__,
241 this_rnc,
242 sci_base_state_machine_get_state(&this_rnc->state_machine));
243
244 /*
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;
248}
249
250static enum sci_status scic_sds_remote_node_context_default_suspend_handler(
251 struct scic_sds_remote_node_context *this_rnc,
252 u32 suspend_type,
7fbafaa5 253 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
254 void *callback_parameter)
255{
256 dev_warn(scirdev_to_dev(this_rnc->device),
257 "%s: SCIC Remote Node Context 0x%p requested to suspend "
258 "while in wrong state %d\n",
259 __func__,
260 this_rnc,
261 sci_base_state_machine_get_state(&this_rnc->state_machine));
262
263 return SCI_FAILURE_INVALID_STATE;
264}
265
266static enum sci_status scic_sds_remote_node_context_default_resume_handler(
267 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 268 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
269 void *callback_parameter)
270{
271 dev_warn(scirdev_to_dev(this_rnc->device),
272 "%s: SCIC Remote Node Context 0x%p requested to resume "
273 "while in wrong state %d\n",
274 __func__,
275 this_rnc,
276 sci_base_state_machine_get_state(&this_rnc->state_machine));
277
278 return SCI_FAILURE_INVALID_STATE;
279}
280
281static enum sci_status scic_sds_remote_node_context_default_start_io_handler(
282 struct scic_sds_remote_node_context *this_rnc,
283 struct scic_sds_request *the_request)
284{
285 dev_warn(scirdev_to_dev(this_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 this_rnc,
290 the_request,
291 sci_base_state_machine_get_state(&this_rnc->state_machine));
292
293 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
294}
295
296static enum sci_status scic_sds_remote_node_context_default_start_task_handler(
297 struct scic_sds_remote_node_context *this_rnc,
298 struct scic_sds_request *the_request)
299{
300 dev_warn(scirdev_to_dev(this_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 this_rnc,
305 the_request,
306 sci_base_state_machine_get_state(&this_rnc->state_machine));
307
308 return SCI_FAILURE;
309}
310
311static enum sci_status scic_sds_remote_node_context_default_event_handler(
312 struct scic_sds_remote_node_context *this_rnc,
313 u32 event_code)
314{
315 dev_warn(scirdev_to_dev(this_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 this_rnc,
320 event_code,
321 sci_base_state_machine_get_state(&this_rnc->state_machine));
322
323 return SCI_FAILURE_INVALID_STATE;
324}
325
326/**
327 *
328 * @this_rnc: The rnc for which the task request is targeted.
329 * @the_request: The request which is going to be started.
330 *
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
334 */
335static enum sci_status scic_sds_remote_node_context_success_start_task_handler(
336 struct scic_sds_remote_node_context *this_rnc,
337 struct scic_sds_request *the_request)
338{
339 return SCI_SUCCESS;
340}
341
342/**
343 *
344 * @this_rnc:
345 * @the_callback:
346 * @callback_parameter:
347 *
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
352 */
353static enum sci_status scic_sds_remote_node_context_general_destruct_handler(
354 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 355 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
356 void *callback_parameter)
357{
358 scic_sds_remote_node_context_setup_to_destory(
359 this_rnc, the_callback, callback_parameter
360 );
361
362 sci_base_state_machine_change_state(
363 &this_rnc->state_machine,
364 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
365 );
366
367 return SCI_SUCCESS;
368}
369
370/* --------------------------------------------------------------------------- */
371
372static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler(
373 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 374 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
375 void *callback_parameter)
376{
377 if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
378 scic_sds_remote_node_context_setup_to_resume(
379 this_rnc, the_callback, callback_parameter
380 );
381
382 scic_sds_remote_node_context_construct_buffer(this_rnc);
383
384 sci_base_state_machine_change_state(
385 &this_rnc->state_machine,
386 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
387 );
388
389 return SCI_SUCCESS;
390 }
391
392 return SCI_FAILURE_INVALID_STATE;
393}
394
395/* --------------------------------------------------------------------------- */
396
397static enum sci_status scic_sds_remote_node_context_posting_state_event_handler(
398 struct scic_sds_remote_node_context *this_rnc,
399 u32 event_code)
400{
401 enum sci_status status;
402
403 switch (scu_get_event_code(event_code)) {
404 case SCU_EVENT_POST_RNC_COMPLETE:
405 status = SCI_SUCCESS;
406
407 sci_base_state_machine_change_state(
408 &this_rnc->state_machine,
409 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
410 );
411 break;
412
413 default:
414 status = SCI_FAILURE;
415 dev_warn(scirdev_to_dev(this_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 this_rnc,
421 event_code);
422 break;
423 }
424
425 return status;
426}
427
428/* --------------------------------------------------------------------------- */
429
430static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler(
431 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 432 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
433 void *callback_parameter)
434{
435 scic_sds_remote_node_context_setup_to_destory(
436 this_rnc, the_callback, callback_parameter
437 );
438
439 return SCI_SUCCESS;
440}
441
442static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler(
443 struct scic_sds_remote_node_context *this_rnc,
444 u32 event_code)
445{
446 enum sci_status status;
447
448 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
449 status = SCI_SUCCESS;
450
451 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
452 sci_base_state_machine_change_state(
453 &this_rnc->state_machine,
454 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
455 );
456 } else {
457 sci_base_state_machine_change_state(
458 &this_rnc->state_machine,
459 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
460 );
461 }
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:
466 /*
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(this_rnc->device),
470 "%s: SCIC Remote Node Context 0x%p was "
471 "suspeneded by hardware while being "
472 "invalidated.\n",
473 __func__,
474 this_rnc);
475 status = SCI_SUCCESS;
476 break;
477
478 default:
479 dev_warn(scirdev_to_dev(this_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 this_rnc,
485 event_code,
486 sci_base_state_machine_get_state(
487 &this_rnc->state_machine));
488 status = SCI_FAILURE;
489 break;
490 }
491 }
492
493 return status;
494}
495
496/* --------------------------------------------------------------------------- */
497
498
499static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler(
500 struct scic_sds_remote_node_context *this_rnc,
501 u32 event_code)
502{
503 enum sci_status status;
504
505 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
506 status = SCI_SUCCESS;
507
508 sci_base_state_machine_change_state(
509 &this_rnc->state_machine,
510 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
511 );
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:
516 /*
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(this_rnc->device),
520 "%s: SCIC Remote Node Context 0x%p was "
521 "suspeneded by hardware while being resumed.\n",
522 __func__,
523 this_rnc);
524 status = SCI_SUCCESS;
525 break;
526
527 default:
528 dev_warn(scirdev_to_dev(this_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 this_rnc,
533 event_code,
534 sci_base_state_machine_get_state(
535 &this_rnc->state_machine));
536 status = SCI_FAILURE;
537 break;
538 }
539 }
540
541 return status;
542}
543
544/* --------------------------------------------------------------------------- */
545
546/**
547 *
548 * @this_rnc: The remote node context object being suspended.
549 * @the_callback: The callback when the suspension is complete.
550 * @callback_parameter: The parameter that is to be passed into the callback.
551 *
552 * This method will handle the suspend requests from the ready state.
553 * SCI_SUCCESS
554 */
555static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler(
556 struct scic_sds_remote_node_context *this_rnc,
557 u32 suspend_type,
7fbafaa5 558 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
559 void *callback_parameter)
560{
561 this_rnc->user_callback = the_callback;
562 this_rnc->user_cookie = callback_parameter;
563 this_rnc->suspension_code = suspend_type;
564
565 if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
566 scic_sds_remote_device_post_request(
567 this_rnc->device,
568 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
569 );
570 }
571
572 sci_base_state_machine_change_state(
573 &this_rnc->state_machine,
574 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
575 );
576
577 return SCI_SUCCESS;
578}
579
580/**
581 *
582 * @this_rnc: The rnc for which the io request is targeted.
583 * @the_request: The request which is going to be started.
584 *
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
588 */
589static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler(
590 struct scic_sds_remote_node_context *this_rnc,
591 struct scic_sds_request *the_request)
592{
593 return SCI_SUCCESS;
594}
595
596
597static enum sci_status scic_sds_remote_node_context_ready_state_event_handler(
598 struct scic_sds_remote_node_context *this_rnc,
599 u32 event_code)
600{
601 enum sci_status status;
602
603 switch (scu_get_event_type(event_code)) {
604 case SCU_EVENT_TL_RNC_SUSPEND_TX:
605 sci_base_state_machine_change_state(
606 &this_rnc->state_machine,
607 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
608 );
609
610 this_rnc->suspension_code = scu_get_event_specifier(event_code);
611 status = SCI_SUCCESS;
612 break;
613
614 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
615 sci_base_state_machine_change_state(
616 &this_rnc->state_machine,
617 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
618 );
619
620 this_rnc->suspension_code = scu_get_event_specifier(event_code);
621 status = SCI_SUCCESS;
622 break;
623
624 default:
625 dev_warn(scirdev_to_dev(this_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 this_rnc,
630 event_code,
631 sci_base_state_machine_get_state(
632 &this_rnc->state_machine));
633
634 status = SCI_FAILURE;
635 break;
636 }
637
638 return status;
639}
640
641/* --------------------------------------------------------------------------- */
642
643static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler(
644 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 645 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
646 void *callback_parameter)
647{
648 enum sci_status status;
649 struct smp_discover_response_protocols protocols;
650
651 scic_sds_remote_node_context_setup_to_resume(
652 this_rnc, the_callback, callback_parameter
653 );
654
655 /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
656
657 scic_remote_device_get_protocols(this_rnc->device, &protocols);
658
659 if (
660 (protocols.u.bits.attached_ssp_target == 1)
661 || (protocols.u.bits.attached_smp_target == 1)
662 ) {
663 sci_base_state_machine_change_state(
664 &this_rnc->state_machine,
665 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
666 );
667
668 status = SCI_SUCCESS;
669 } else if (protocols.u.bits.attached_stp_target == 1) {
670 if (this_rnc->device->is_direct_attached) {
671 /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
6f231dda
DW
672 sci_base_state_machine_change_state(
673 &this_rnc->state_machine,
674 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
675 );
676 } else {
677 sci_base_state_machine_change_state(
678 &this_rnc->state_machine,
679 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
680 );
681 }
682
683 status = SCI_SUCCESS;
684 } else {
685 status = SCI_FAILURE;
686 }
687
688 return status;
689}
690
691/**
692 *
693 * @this_rnc: The remote node context which is to receive the task request.
694 * @the_request: The task request to be transmitted to to the remote target
695 * device.
696 *
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
701 */
702static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler(
703 struct scic_sds_remote_node_context *this_rnc,
704 struct scic_sds_request *the_request)
705{
706 scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
707
708 return SCI_SUCCESS;
709}
710
711/* --------------------------------------------------------------------------- */
712
713static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
714 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 715 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
716 void *callback_parameter)
717{
718 scic_sds_remote_node_context_setup_to_resume(
719 this_rnc, the_callback, callback_parameter
720 );
721
722 sci_base_state_machine_change_state(
723 &this_rnc->state_machine,
724 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
725 );
726
727 return SCI_FAILURE_INVALID_STATE;
728}
729
730/* --------------------------------------------------------------------------- */
731
732/**
733 *
734 *
735 *
736 */
737static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler(
738 struct scic_sds_remote_node_context *this_rnc,
7fbafaa5 739 scics_sds_remote_node_context_callback the_callback,
6f231dda
DW
740 void *callback_parameter)
741{
742 scic_sds_remote_node_context_setup_to_resume(
743 this_rnc, the_callback, callback_parameter
744 );
745
746 return SCI_SUCCESS;
747}
748
749/**
750 *
751 * @this_rnc: The remote node context which is to receive the task request.
752 * @the_request: The task request to be transmitted to to the remote target
753 * device.
754 *
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
759 */
760static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler(
761 struct scic_sds_remote_node_context *this_rnc,
762 struct scic_sds_request *the_request)
763{
764 return SCI_SUCCESS;
765}
766
767static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler(
768 struct scic_sds_remote_node_context *this_rnc,
769 u32 event_code)
770{
771 enum sci_status status;
772
773 switch (scu_get_event_type(event_code)) {
774 case SCU_EVENT_TL_RNC_SUSPEND_TX:
775 sci_base_state_machine_change_state(
776 &this_rnc->state_machine,
777 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
778 );
779
780 this_rnc->suspension_code = scu_get_event_specifier(event_code);
781 status = SCI_SUCCESS;
782 break;
783
784 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
785 sci_base_state_machine_change_state(
786 &this_rnc->state_machine,
787 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
788 );
789
790 this_rnc->suspension_code = scu_get_event_specifier(event_code);
791 status = SCI_SUCCESS;
792 break;
793
794 default:
795 dev_warn(scirdev_to_dev(this_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 this_rnc,
800 event_code,
801 sci_base_state_machine_get_state(
802 &this_rnc->state_machine));
803
804 status = SCI_FAILURE;
805 break;
806 }
807
808 return status;
809}
810
811/* --------------------------------------------------------------------------- */
812
35173d57 813static struct scic_sds_remote_node_context_handlers
6f231dda
DW
814scic_sds_remote_node_context_state_handler_table[
815 SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
816{
817 /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */
818 {
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
825 },
826 /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */
827 {
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
834 },
835 /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */
836 {
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
843 },
844 /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */
845 {
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
852 },
853 /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */
854 {
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
861 },
862 /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */
863 {
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
870 },
871 /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */
872 {
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
879 },
880 /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */
881 {
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
888 }
889};
890
891/*
892 * *****************************************************************************
893 * * REMOTE NODE CONTEXT PRIVATE METHODS
894 * ***************************************************************************** */
895
896/**
897 *
898 *
899 * This method just calls the user callback function and then resets the
900 * callback.
901 */
902static void scic_sds_remote_node_context_notify_user(
903 struct scic_sds_remote_node_context *rnc)
904{
905 if (rnc->user_callback != NULL) {
906 (*rnc->user_callback)(rnc->user_cookie);
907
908 rnc->user_callback = NULL;
909 rnc->user_cookie = NULL;
910 }
911}
912
913/**
914 *
915 *
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.
919 */
920static void scic_sds_remote_node_context_continue_state_transitions(
921 struct scic_sds_remote_node_context *rnc)
922{
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
926 );
927 }
928}
929
930/**
931 *
932 * @this_rnc: The remote node context object that is to be validated.
933 *
934 * This method will mark the rnc buffer as being valid and post the request to
935 * the hardware. none
936 */
937static void scic_sds_remote_node_context_validate_context_buffer(
938 struct scic_sds_remote_node_context *this_rnc)
939{
940 union scu_remote_node_context *rnc_buffer;
941
942 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
943 scic_sds_remote_device_get_controller(this_rnc->device),
944 this_rnc->remote_node_index
945 );
946
947 rnc_buffer->ssp.is_valid = true;
948
949 if (
950 !this_rnc->device->is_direct_attached
951 && this_rnc->device->target_protocols.u.bits.attached_stp_target
952 ) {
953 scic_sds_remote_device_post_request(
954 this_rnc->device,
955 SCU_CONTEXT_COMMAND_POST_RNC_96
956 );
957 } else {
958 scic_sds_remote_device_post_request(
959 this_rnc->device,
960 SCU_CONTEXT_COMMAND_POST_RNC_32
961 );
962
963 if (this_rnc->device->is_direct_attached) {
24621466 964 scic_sds_port_setup_transports(
6f231dda
DW
965 this_rnc->device->owning_port,
966 this_rnc->remote_node_index
967 );
968 }
969 }
970}
971
972/**
973 *
974 * @this_rnc: The remote node context object that is to be invalidated.
975 *
976 * This method will update the RNC buffer and post the invalidate request. none
977 */
978static void scic_sds_remote_node_context_invalidate_context_buffer(
979 struct scic_sds_remote_node_context *this_rnc)
980{
981 union scu_remote_node_context *rnc_buffer;
982
983 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
984 scic_sds_remote_device_get_controller(this_rnc->device),
985 this_rnc->remote_node_index
986 );
987
988 rnc_buffer->ssp.is_valid = false;
989
990 scic_sds_remote_device_post_request(
991 this_rnc->device,
992 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
993 );
6f231dda
DW
994}
995
996/*
997 * *****************************************************************************
998 * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
999 * ***************************************************************************** */
1000
1001/**
1002 *
1003 *
1004 *
1005 */
1006static void scic_sds_remote_node_context_initial_state_enter(
1007 struct sci_base_object *object)
1008{
1009 struct scic_sds_remote_node_context *rnc;
1010
1011 rnc = (struct scic_sds_remote_node_context *)object;
1012
1013 SET_STATE_HANDLER(
1014 rnc,
1015 scic_sds_remote_node_context_state_handler_table,
1016 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1017 );
1018
1019 /*
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
1025 ) {
1026 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1027
1028 scic_sds_remote_node_context_notify_user(rnc);
1029 }
1030}
1031
1032/**
1033 *
1034 *
1035 *
1036 */
1037static void scic_sds_remote_node_context_posting_state_enter(
1038 struct sci_base_object *object)
1039{
1040 struct scic_sds_remote_node_context *this_rnc;
1041
1042 this_rnc = (struct scic_sds_remote_node_context *)object;
1043
1044 SET_STATE_HANDLER(
1045 this_rnc,
1046 scic_sds_remote_node_context_state_handler_table,
1047 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1048 );
1049
1050 scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1051}
1052
1053/**
1054 *
1055 *
1056 *
1057 */
1058static void scic_sds_remote_node_context_invalidating_state_enter(
1059 struct sci_base_object *object)
1060{
1061 struct scic_sds_remote_node_context *rnc;
1062
1063 rnc = (struct scic_sds_remote_node_context *)object;
1064
1065 SET_STATE_HANDLER(
1066 rnc,
1067 scic_sds_remote_node_context_state_handler_table,
1068 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1069 );
1070
1071 scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1072}
1073
1074/**
1075 *
1076 *
1077 *
1078 */
1079static void scic_sds_remote_node_context_resuming_state_enter(
1080 struct sci_base_object *object)
1081{
1082 struct scic_sds_remote_node_context *rnc;
24621466 1083 struct smp_discover_response_protocols protocols;
6f231dda
DW
1084
1085 rnc = (struct scic_sds_remote_node_context *)object;
1086
1087 SET_STATE_HANDLER(
1088 rnc,
1089 scic_sds_remote_node_context_state_handler_table,
1090 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1091 );
1092
24621466
HD
1093 /*
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
1098 */
1099 scic_remote_device_get_protocols(rnc->device, &protocols);
1100
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);
1105 }
1106
6f231dda
DW
1107 scic_sds_remote_device_post_request(
1108 rnc->device,
1109 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1110 );
1111}
1112
1113/**
1114 *
1115 *
1116 *
1117 */
1118static void scic_sds_remote_node_context_ready_state_enter(
1119 struct sci_base_object *object)
1120{
1121 struct scic_sds_remote_node_context *rnc;
1122
1123 rnc = (struct scic_sds_remote_node_context *)object;
1124
1125 SET_STATE_HANDLER(
1126 rnc,
1127 scic_sds_remote_node_context_state_handler_table,
1128 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1129 );
1130
1131 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1132
1133 if (rnc->user_callback != NULL) {
1134 scic_sds_remote_node_context_notify_user(rnc);
1135 }
1136}
1137
1138/**
1139 *
1140 *
1141 *
1142 */
1143static void scic_sds_remote_node_context_tx_suspended_state_enter(
1144 struct sci_base_object *object)
1145{
1146 struct scic_sds_remote_node_context *rnc;
1147
1148 rnc = (struct scic_sds_remote_node_context *)object;
1149
1150 SET_STATE_HANDLER(
1151 rnc,
1152 scic_sds_remote_node_context_state_handler_table,
1153 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1154 );
1155
1156 scic_sds_remote_node_context_continue_state_transitions(rnc);
1157}
1158
1159/**
1160 *
1161 *
1162 *
1163 */
1164static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1165 struct sci_base_object *object)
1166{
1167 struct scic_sds_remote_node_context *rnc;
1168
1169 rnc = (struct scic_sds_remote_node_context *)object;
1170
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
1175 );
1176
1177 scic_sds_remote_node_context_continue_state_transitions(rnc);
1178}
1179
1180/**
1181 *
1182 *
1183 *
1184 */
1185static void scic_sds_remote_node_context_await_suspension_state_enter(
1186 struct sci_base_object *object)
1187{
1188 struct scic_sds_remote_node_context *rnc;
1189
1190 rnc = (struct scic_sds_remote_node_context *)object;
1191
1192 SET_STATE_HANDLER(
1193 rnc,
1194 scic_sds_remote_node_context_state_handler_table,
1195 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1196 );
1197}
1198
1199/* --------------------------------------------------------------------------- */
1200
35173d57 1201static const struct sci_base_state scic_sds_remote_node_context_state_table[] = {
6f231dda
DW
1202 [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = {
1203 .enter_state = scic_sds_remote_node_context_initial_state_enter,
1204 },
1205 [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = {
1206 .enter_state = scic_sds_remote_node_context_posting_state_enter,
1207 },
1208 [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = {
1209 .enter_state = scic_sds_remote_node_context_invalidating_state_enter,
1210 },
1211 [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = {
1212 .enter_state = scic_sds_remote_node_context_resuming_state_enter,
1213 },
1214 [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = {
1215 .enter_state = scic_sds_remote_node_context_ready_state_enter,
1216 },
1217 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = {
1218 .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter,
1219 },
1220 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = {
1221 .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1222 },
1223 [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = {
1224 .enter_state = scic_sds_remote_node_context_await_suspension_state_enter,
1225 },
1226};
1227
35173d57
DW
1228void 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)
1232{
1233 memset(rnc, 0, sizeof(struct scic_sds_remote_node_context));
1234
1235 rnc->remote_node_index = remote_node_index;
1236 rnc->device = device;
1237 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1238
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
1244 );
1245
1246 sci_base_state_machine_start(&rnc->state_machine);
1247}
This page took 0.076104 seconds and 5 git commands to generate.