isci: Move transport layer registers from port to phy
[pandora-kernel.git] / drivers / scsi / isci / core / scic_sds_remote_node_context.c
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
67 void scic_sds_remote_node_context_construct(
68         struct scic_sds_remote_device *device,
69         struct scic_sds_remote_node_context *rnc,
70         u16 remote_node_index)
71 {
72         memset(rnc, 0, sizeof(struct scic_sds_remote_node_context));
73
74         rnc->remote_node_index = remote_node_index;
75         rnc->device            = device;
76         rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
77
78         sci_base_state_machine_construct(
79                 &rnc->state_machine,
80                 &rnc->parent,
81                 scic_sds_remote_node_context_state_table,
82                 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
83                 );
84
85         sci_base_state_machine_start(&rnc->state_machine);
86 }
87
88 /**
89  *
90  * @this_rnc: The RNC for which the is posted request is being made.
91  *
92  * This method will return true if the RNC is not in the initial state.  In all
93  * other states the RNC is considered active and this will return true. The
94  * destroy request of the state machine drives the RNC back to the initial
95  * state.  If the state machine changes then this routine will also have to be
96  * changed. bool true if the state machine is not in the initial state false if
97  * the state machine is in the initial state
98  */
99
100 /**
101  *
102  * @this_rnc: The state of the remote node context object to check.
103  *
104  * This method will return true if the remote node context is in a READY state
105  * otherwise it will return false bool true if the remote node context is in
106  * the ready state. false if the remote node context is not in the ready state.
107  */
108 bool scic_sds_remote_node_context_is_ready(
109         struct scic_sds_remote_node_context *this_rnc)
110 {
111         u32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine);
112
113         if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) {
114                 return true;
115         }
116
117         return false;
118 }
119
120 /**
121  *
122  * @this_device: The remote device to use to construct the RNC buffer.
123  * @rnc: The buffer into which the remote device data will be copied.
124  *
125  * This method will construct the RNC buffer for this remote device object. none
126  */
127 void scic_sds_remote_node_context_construct_buffer(
128         struct scic_sds_remote_node_context *this_rnc)
129 {
130         union scu_remote_node_context *rnc;
131         struct scic_sds_controller *the_controller;
132
133         the_controller = scic_sds_remote_device_get_controller(this_rnc->device);
134
135         rnc = scic_sds_controller_get_remote_node_context_buffer(
136                 the_controller, this_rnc->remote_node_index);
137
138         memset(
139                 rnc,
140                 0x00,
141                 sizeof(union scu_remote_node_context)
142                 * scic_sds_remote_device_node_count(this_rnc->device)
143                 );
144
145         rnc->ssp.remote_node_index = this_rnc->remote_node_index;
146         rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width;
147         rnc->ssp.logical_port_index =
148                 scic_sds_remote_device_get_port_index(this_rnc->device);
149
150         rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high);
151         rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low);
152
153         rnc->ssp.nexus_loss_timer_enable = true;
154         rnc->ssp.check_bit               = false;
155         rnc->ssp.is_valid                = false;
156         rnc->ssp.is_remote_node_context  = true;
157         rnc->ssp.function_number         = 0;
158
159         rnc->ssp.arbitration_wait_time = 0;
160
161
162         if (
163                 this_rnc->device->target_protocols.u.bits.attached_sata_device
164                 || this_rnc->device->target_protocols.u.bits.attached_stp_target
165                 ) {
166                 rnc->ssp.connection_occupancy_timeout =
167                         the_controller->user_parameters.sds1.stp_max_occupancy_timeout;
168                 rnc->ssp.connection_inactivity_timeout =
169                         the_controller->user_parameters.sds1.stp_inactivity_timeout;
170         } else {
171                 rnc->ssp.connection_occupancy_timeout  =
172                         the_controller->user_parameters.sds1.ssp_max_occupancy_timeout;
173                 rnc->ssp.connection_inactivity_timeout =
174                         the_controller->user_parameters.sds1.ssp_inactivity_timeout;
175         }
176
177         rnc->ssp.initial_arbitration_wait_time = 0;
178
179         /* Open Address Frame Parameters */
180         rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate;
181         rnc->ssp.oaf_features = 0;
182         rnc->ssp.oaf_source_zone_group = 0;
183         rnc->ssp.oaf_more_compatibility_features = 0;
184 }
185
186 /**
187  *
188  * @this_rnc:
189  * @the_callback:
190  * @callback_parameter:
191  *
192  * This method will setup the remote node context object so it will transition
193  * to its ready state.  If the remote node context is already setup to
194  * transition to its final state then this function does nothing. none
195  */
196 static void scic_sds_remote_node_context_setup_to_resume(
197         struct scic_sds_remote_node_context *this_rnc,
198         scics_sds_remote_node_context_callback the_callback,
199         void *callback_parameter)
200 {
201         if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
202                 this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
203                 this_rnc->user_callback     = the_callback;
204                 this_rnc->user_cookie       = callback_parameter;
205         }
206 }
207
208 /**
209  *
210  * @this_rnc:
211  * @the_callback:
212  * @callback_parameter:
213  *
214  * This method will setup the remote node context object so it will transistion
215  * to its final state. none
216  */
217 static void scic_sds_remote_node_context_setup_to_destory(
218         struct scic_sds_remote_node_context *this_rnc,
219         scics_sds_remote_node_context_callback the_callback,
220         void *callback_parameter)
221 {
222         this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
223         this_rnc->user_callback     = the_callback;
224         this_rnc->user_cookie       = callback_parameter;
225 }
226
227 /**
228  *
229  * @this_rnc:
230  * @the_callback:
231  *
232  * This method will continue to resume a remote node context.  This is used in
233  * the states where a resume is requested while a resume is in progress.
234  */
235 static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler(
236         struct scic_sds_remote_node_context *this_rnc,
237         scics_sds_remote_node_context_callback the_callback,
238         void *callback_parameter)
239 {
240         if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
241                 this_rnc->user_callback = the_callback;
242                 this_rnc->user_cookie   = callback_parameter;
243
244                 return SCI_SUCCESS;
245         }
246
247         return SCI_FAILURE_INVALID_STATE;
248 }
249
250 /* --------------------------------------------------------------------------- */
251
252 static enum sci_status scic_sds_remote_node_context_default_destruct_handler(
253         struct scic_sds_remote_node_context *this_rnc,
254         scics_sds_remote_node_context_callback the_callback,
255         void *callback_parameter)
256 {
257         dev_warn(scirdev_to_dev(this_rnc->device),
258                  "%s: SCIC Remote Node Context 0x%p requested to stop while "
259                  "in unexpected state %d\n",
260                  __func__,
261                  this_rnc,
262                  sci_base_state_machine_get_state(&this_rnc->state_machine));
263
264         /*
265          * We have decided that the destruct request on the remote node context can not fail
266          * since it is either in the initial/destroyed state or is can be destroyed. */
267         return SCI_SUCCESS;
268 }
269
270 static enum sci_status scic_sds_remote_node_context_default_suspend_handler(
271         struct scic_sds_remote_node_context *this_rnc,
272         u32 suspend_type,
273         scics_sds_remote_node_context_callback the_callback,
274         void *callback_parameter)
275 {
276         dev_warn(scirdev_to_dev(this_rnc->device),
277                  "%s: SCIC Remote Node Context 0x%p requested to suspend "
278                  "while in wrong state %d\n",
279                  __func__,
280                  this_rnc,
281                  sci_base_state_machine_get_state(&this_rnc->state_machine));
282
283         return SCI_FAILURE_INVALID_STATE;
284 }
285
286 static enum sci_status scic_sds_remote_node_context_default_resume_handler(
287         struct scic_sds_remote_node_context *this_rnc,
288         scics_sds_remote_node_context_callback the_callback,
289         void *callback_parameter)
290 {
291         dev_warn(scirdev_to_dev(this_rnc->device),
292                  "%s: SCIC Remote Node Context 0x%p requested to resume "
293                  "while in wrong state %d\n",
294                  __func__,
295                  this_rnc,
296                  sci_base_state_machine_get_state(&this_rnc->state_machine));
297
298         return SCI_FAILURE_INVALID_STATE;
299 }
300
301 static enum sci_status scic_sds_remote_node_context_default_start_io_handler(
302         struct scic_sds_remote_node_context *this_rnc,
303         struct scic_sds_request *the_request)
304 {
305         dev_warn(scirdev_to_dev(this_rnc->device),
306                  "%s: SCIC Remote Node Context 0x%p requested to start io "
307                  "0x%p while in wrong state %d\n",
308                  __func__,
309                  this_rnc,
310                  the_request,
311                  sci_base_state_machine_get_state(&this_rnc->state_machine));
312
313         return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
314 }
315
316 static enum sci_status scic_sds_remote_node_context_default_start_task_handler(
317         struct scic_sds_remote_node_context *this_rnc,
318         struct scic_sds_request *the_request)
319 {
320         dev_warn(scirdev_to_dev(this_rnc->device),
321                  "%s: SCIC Remote Node Context 0x%p requested to start "
322                  "task 0x%p while in wrong state %d\n",
323                  __func__,
324                  this_rnc,
325                  the_request,
326                  sci_base_state_machine_get_state(&this_rnc->state_machine));
327
328         return SCI_FAILURE;
329 }
330
331 static enum sci_status scic_sds_remote_node_context_default_event_handler(
332         struct scic_sds_remote_node_context *this_rnc,
333         u32 event_code)
334 {
335         dev_warn(scirdev_to_dev(this_rnc->device),
336                  "%s: SCIC Remote Node Context 0x%p requested to process "
337                  "event 0x%x while in wrong state %d\n",
338                  __func__,
339                  this_rnc,
340                  event_code,
341                  sci_base_state_machine_get_state(&this_rnc->state_machine));
342
343         return SCI_FAILURE_INVALID_STATE;
344 }
345
346 /**
347  *
348  * @this_rnc: The rnc for which the task request is targeted.
349  * @the_request: The request which is going to be started.
350  *
351  * This method determines if the task request can be started by the SCU
352  * hardware. When the RNC is in the ready state any task can be started.
353  * enum sci_status SCI_SUCCESS
354  */
355 static enum sci_status scic_sds_remote_node_context_success_start_task_handler(
356         struct scic_sds_remote_node_context *this_rnc,
357         struct scic_sds_request *the_request)
358 {
359         return SCI_SUCCESS;
360 }
361
362 /**
363  *
364  * @this_rnc:
365  * @the_callback:
366  * @callback_parameter:
367  *
368  * This method handles destruct calls from the various state handlers.  The
369  * remote node context can be requested to destroy from any state. If there was
370  * a user callback it is always replaced with the request to destroy user
371  * callback. enum sci_status
372  */
373 static enum sci_status scic_sds_remote_node_context_general_destruct_handler(
374         struct scic_sds_remote_node_context *this_rnc,
375         scics_sds_remote_node_context_callback the_callback,
376         void *callback_parameter)
377 {
378         scic_sds_remote_node_context_setup_to_destory(
379                 this_rnc, the_callback, callback_parameter
380                 );
381
382         sci_base_state_machine_change_state(
383                 &this_rnc->state_machine,
384                 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
385                 );
386
387         return SCI_SUCCESS;
388 }
389
390 /* --------------------------------------------------------------------------- */
391
392 static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler(
393         struct scic_sds_remote_node_context *this_rnc,
394         scics_sds_remote_node_context_callback the_callback,
395         void *callback_parameter)
396 {
397         if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
398                 scic_sds_remote_node_context_setup_to_resume(
399                         this_rnc, the_callback, callback_parameter
400                         );
401
402                 scic_sds_remote_node_context_construct_buffer(this_rnc);
403
404                 sci_base_state_machine_change_state(
405                         &this_rnc->state_machine,
406                         SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
407                         );
408
409                 return SCI_SUCCESS;
410         }
411
412         return SCI_FAILURE_INVALID_STATE;
413 }
414
415 /* --------------------------------------------------------------------------- */
416
417 static enum sci_status scic_sds_remote_node_context_posting_state_event_handler(
418         struct scic_sds_remote_node_context *this_rnc,
419         u32 event_code)
420 {
421         enum sci_status status;
422
423         switch (scu_get_event_code(event_code)) {
424         case SCU_EVENT_POST_RNC_COMPLETE:
425                 status = SCI_SUCCESS;
426
427                 sci_base_state_machine_change_state(
428                         &this_rnc->state_machine,
429                         SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
430                         );
431                 break;
432
433         default:
434                 status = SCI_FAILURE;
435                 dev_warn(scirdev_to_dev(this_rnc->device),
436                          "%s: SCIC Remote Node Context 0x%p requested to "
437                          "process unexpected event 0x%x while in posting "
438                          "state\n",
439                          __func__,
440                          this_rnc,
441                          event_code);
442                 break;
443         }
444
445         return status;
446 }
447
448 /* --------------------------------------------------------------------------- */
449
450 static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler(
451         struct scic_sds_remote_node_context *this_rnc,
452         scics_sds_remote_node_context_callback the_callback,
453         void *callback_parameter)
454 {
455         scic_sds_remote_node_context_setup_to_destory(
456                 this_rnc, the_callback, callback_parameter
457                 );
458
459         return SCI_SUCCESS;
460 }
461
462 static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler(
463         struct scic_sds_remote_node_context *this_rnc,
464         u32 event_code)
465 {
466         enum sci_status status;
467
468         if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
469                 status = SCI_SUCCESS;
470
471                 if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
472                         sci_base_state_machine_change_state(
473                                 &this_rnc->state_machine,
474                                 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
475                                 );
476                 } else {
477                         sci_base_state_machine_change_state(
478                                 &this_rnc->state_machine,
479                                 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
480                                 );
481                 }
482         } else {
483                 switch (scu_get_event_type(event_code)) {
484                 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
485                 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
486                         /*
487                          * We really dont care if the hardware is going to suspend
488                          * the device since it's being invalidated anyway */
489                         dev_dbg(scirdev_to_dev(this_rnc->device),
490                                 "%s: SCIC Remote Node Context 0x%p was "
491                                 "suspeneded by hardware while being "
492                                 "invalidated.\n",
493                                 __func__,
494                                 this_rnc);
495                         status = SCI_SUCCESS;
496                         break;
497
498                 default:
499                         dev_warn(scirdev_to_dev(this_rnc->device),
500                                  "%s: SCIC Remote Node Context 0x%p "
501                                  "requested to process event 0x%x while "
502                                  "in state %d.\n",
503                                  __func__,
504                                  this_rnc,
505                                  event_code,
506                                  sci_base_state_machine_get_state(
507                                          &this_rnc->state_machine));
508                         status = SCI_FAILURE;
509                         break;
510                 }
511         }
512
513         return status;
514 }
515
516 /* --------------------------------------------------------------------------- */
517
518
519 static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler(
520         struct scic_sds_remote_node_context *this_rnc,
521         u32 event_code)
522 {
523         enum sci_status status;
524
525         if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
526                 status = SCI_SUCCESS;
527
528                 sci_base_state_machine_change_state(
529                         &this_rnc->state_machine,
530                         SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
531                         );
532         } else {
533                 switch (scu_get_event_type(event_code)) {
534                 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
535                 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
536                         /*
537                          * We really dont care if the hardware is going to suspend
538                          * the device since it's being resumed anyway */
539                         dev_dbg(scirdev_to_dev(this_rnc->device),
540                                 "%s: SCIC Remote Node Context 0x%p was "
541                                 "suspeneded by hardware while being resumed.\n",
542                                 __func__,
543                                 this_rnc);
544                         status = SCI_SUCCESS;
545                         break;
546
547                 default:
548                         dev_warn(scirdev_to_dev(this_rnc->device),
549                                  "%s: SCIC Remote Node Context 0x%p requested "
550                                  "to process event 0x%x while in state %d.\n",
551                                  __func__,
552                                  this_rnc,
553                                  event_code,
554                                  sci_base_state_machine_get_state(
555                                          &this_rnc->state_machine));
556                         status = SCI_FAILURE;
557                         break;
558                 }
559         }
560
561         return status;
562 }
563
564 /* --------------------------------------------------------------------------- */
565
566 /**
567  *
568  * @this_rnc: The remote node context object being suspended.
569  * @the_callback: The callback when the suspension is complete.
570  * @callback_parameter: The parameter that is to be passed into the callback.
571  *
572  * This method will handle the suspend requests from the ready state.
573  * SCI_SUCCESS
574  */
575 static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler(
576         struct scic_sds_remote_node_context *this_rnc,
577         u32 suspend_type,
578         scics_sds_remote_node_context_callback the_callback,
579         void *callback_parameter)
580 {
581         this_rnc->user_callback   = the_callback;
582         this_rnc->user_cookie     = callback_parameter;
583         this_rnc->suspension_code = suspend_type;
584
585         if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
586                 scic_sds_remote_device_post_request(
587                         this_rnc->device,
588                         SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX
589                         );
590         }
591
592         sci_base_state_machine_change_state(
593                 &this_rnc->state_machine,
594                 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
595                 );
596
597         return SCI_SUCCESS;
598 }
599
600 /**
601  *
602  * @this_rnc: The rnc for which the io request is targeted.
603  * @the_request: The request which is going to be started.
604  *
605  * This method determines if the io request can be started by the SCU hardware.
606  * When the RNC is in the ready state any io request can be started. enum sci_status
607  * SCI_SUCCESS
608  */
609 static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler(
610         struct scic_sds_remote_node_context *this_rnc,
611         struct scic_sds_request *the_request)
612 {
613         return SCI_SUCCESS;
614 }
615
616
617 static enum sci_status scic_sds_remote_node_context_ready_state_event_handler(
618         struct scic_sds_remote_node_context *this_rnc,
619         u32 event_code)
620 {
621         enum sci_status status;
622
623         switch (scu_get_event_type(event_code)) {
624         case SCU_EVENT_TL_RNC_SUSPEND_TX:
625                 sci_base_state_machine_change_state(
626                         &this_rnc->state_machine,
627                         SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
628                         );
629
630                 this_rnc->suspension_code = scu_get_event_specifier(event_code);
631                 status = SCI_SUCCESS;
632                 break;
633
634         case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
635                 sci_base_state_machine_change_state(
636                         &this_rnc->state_machine,
637                         SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
638                         );
639
640                 this_rnc->suspension_code = scu_get_event_specifier(event_code);
641                 status = SCI_SUCCESS;
642                 break;
643
644         default:
645                 dev_warn(scirdev_to_dev(this_rnc->device),
646                         "%s: SCIC Remote Node Context 0x%p requested to "
647                         "process event 0x%x while in state %d.\n",
648                         __func__,
649                         this_rnc,
650                         event_code,
651                         sci_base_state_machine_get_state(
652                                 &this_rnc->state_machine));
653
654                 status = SCI_FAILURE;
655                 break;
656         }
657
658         return status;
659 }
660
661 /* --------------------------------------------------------------------------- */
662
663 static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler(
664         struct scic_sds_remote_node_context *this_rnc,
665         scics_sds_remote_node_context_callback the_callback,
666         void *callback_parameter)
667 {
668         enum sci_status status;
669         struct smp_discover_response_protocols protocols;
670
671         scic_sds_remote_node_context_setup_to_resume(
672                 this_rnc, the_callback, callback_parameter
673                 );
674
675         /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
676
677         scic_remote_device_get_protocols(this_rnc->device, &protocols);
678
679         if (
680                 (protocols.u.bits.attached_ssp_target == 1)
681                 || (protocols.u.bits.attached_smp_target == 1)
682                 ) {
683                 sci_base_state_machine_change_state(
684                         &this_rnc->state_machine,
685                         SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
686                         );
687
688                 status = SCI_SUCCESS;
689         } else if (protocols.u.bits.attached_stp_target == 1) {
690                 if (this_rnc->device->is_direct_attached) {
691                         /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
692                         sci_base_state_machine_change_state(
693                                 &this_rnc->state_machine,
694                                 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
695                                 );
696                 } else {
697                         sci_base_state_machine_change_state(
698                                 &this_rnc->state_machine,
699                                 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
700                                 );
701                 }
702
703                 status = SCI_SUCCESS;
704         } else {
705                 status = SCI_FAILURE;
706         }
707
708         return status;
709 }
710
711 /**
712  *
713  * @this_rnc: The remote node context which is to receive the task request.
714  * @the_request: The task request to be transmitted to to the remote target
715  *    device.
716  *
717  * This method will report a success or failure attempt to start a new task
718  * request to the hardware.  Since all task requests are sent on the high
719  * priority queue they can be sent when the RCN is in a TX suspend state.
720  * enum sci_status SCI_SUCCESS
721  */
722 static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler(
723         struct scic_sds_remote_node_context *this_rnc,
724         struct scic_sds_request *the_request)
725 {
726         scic_sds_remote_node_context_resume(this_rnc, NULL, NULL);
727
728         return SCI_SUCCESS;
729 }
730
731 /* --------------------------------------------------------------------------- */
732
733 static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
734         struct scic_sds_remote_node_context *this_rnc,
735         scics_sds_remote_node_context_callback the_callback,
736         void *callback_parameter)
737 {
738         scic_sds_remote_node_context_setup_to_resume(
739                 this_rnc, the_callback, callback_parameter
740                 );
741
742         sci_base_state_machine_change_state(
743                 &this_rnc->state_machine,
744                 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
745                 );
746
747         return SCI_FAILURE_INVALID_STATE;
748 }
749
750 /* --------------------------------------------------------------------------- */
751
752 /**
753  *
754  *
755  *
756  */
757 static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler(
758         struct scic_sds_remote_node_context *this_rnc,
759         scics_sds_remote_node_context_callback the_callback,
760         void *callback_parameter)
761 {
762         scic_sds_remote_node_context_setup_to_resume(
763                 this_rnc, the_callback, callback_parameter
764                 );
765
766         return SCI_SUCCESS;
767 }
768
769 /**
770  *
771  * @this_rnc: The remote node context which is to receive the task request.
772  * @the_request: The task request to be transmitted to to the remote target
773  *    device.
774  *
775  * This method will report a success or failure attempt to start a new task
776  * request to the hardware.  Since all task requests are sent on the high
777  * priority queue they can be sent when the RCN is in a TX suspend state.
778  * enum sci_status SCI_SUCCESS
779  */
780 static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler(
781         struct scic_sds_remote_node_context *this_rnc,
782         struct scic_sds_request *the_request)
783 {
784         return SCI_SUCCESS;
785 }
786
787 static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler(
788         struct scic_sds_remote_node_context *this_rnc,
789         u32 event_code)
790 {
791         enum sci_status status;
792
793         switch (scu_get_event_type(event_code)) {
794         case SCU_EVENT_TL_RNC_SUSPEND_TX:
795                 sci_base_state_machine_change_state(
796                         &this_rnc->state_machine,
797                         SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
798                         );
799
800                 this_rnc->suspension_code = scu_get_event_specifier(event_code);
801                 status = SCI_SUCCESS;
802                 break;
803
804         case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
805                 sci_base_state_machine_change_state(
806                         &this_rnc->state_machine,
807                         SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
808                         );
809
810                 this_rnc->suspension_code = scu_get_event_specifier(event_code);
811                 status = SCI_SUCCESS;
812                 break;
813
814         default:
815                 dev_warn(scirdev_to_dev(this_rnc->device),
816                          "%s: SCIC Remote Node Context 0x%p requested to "
817                          "process event 0x%x while in state %d.\n",
818                          __func__,
819                          this_rnc,
820                          event_code,
821                          sci_base_state_machine_get_state(
822                                  &this_rnc->state_machine));
823
824                 status = SCI_FAILURE;
825                 break;
826         }
827
828         return status;
829 }
830
831 /* --------------------------------------------------------------------------- */
832
833 struct scic_sds_remote_node_context_handlers
834 scic_sds_remote_node_context_state_handler_table[
835         SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] =
836 {
837         /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */
838         {
839                 scic_sds_remote_node_context_default_destruct_handler,
840                 scic_sds_remote_node_context_default_suspend_handler,
841                 scic_sds_remote_node_context_initial_state_resume_handler,
842                 scic_sds_remote_node_context_default_start_io_handler,
843                 scic_sds_remote_node_context_default_start_task_handler,
844                 scic_sds_remote_node_context_default_event_handler
845         },
846         /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */
847         {
848                 scic_sds_remote_node_context_general_destruct_handler,
849                 scic_sds_remote_node_context_default_suspend_handler,
850                 scic_sds_remote_node_context_continue_to_resume_handler,
851                 scic_sds_remote_node_context_default_start_io_handler,
852                 scic_sds_remote_node_context_default_start_task_handler,
853                 scic_sds_remote_node_context_posting_state_event_handler
854         },
855         /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */
856         {
857                 scic_sds_remote_node_context_invalidating_state_destruct_handler,
858                 scic_sds_remote_node_context_default_suspend_handler,
859                 scic_sds_remote_node_context_continue_to_resume_handler,
860                 scic_sds_remote_node_context_default_start_io_handler,
861                 scic_sds_remote_node_context_default_start_task_handler,
862                 scic_sds_remote_node_context_invalidating_state_event_handler
863         },
864         /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */
865         {
866                 scic_sds_remote_node_context_general_destruct_handler,
867                 scic_sds_remote_node_context_default_suspend_handler,
868                 scic_sds_remote_node_context_continue_to_resume_handler,
869                 scic_sds_remote_node_context_default_start_io_handler,
870                 scic_sds_remote_node_context_success_start_task_handler,
871                 scic_sds_remote_node_context_resuming_state_event_handler
872         },
873         /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */
874         {
875                 scic_sds_remote_node_context_general_destruct_handler,
876                 scic_sds_remote_node_context_ready_state_suspend_handler,
877                 scic_sds_remote_node_context_default_resume_handler,
878                 scic_sds_remote_node_context_ready_state_start_io_handler,
879                 scic_sds_remote_node_context_success_start_task_handler,
880                 scic_sds_remote_node_context_ready_state_event_handler
881         },
882         /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */
883         {
884                 scic_sds_remote_node_context_general_destruct_handler,
885                 scic_sds_remote_node_context_default_suspend_handler,
886                 scic_sds_remote_node_context_tx_suspended_state_resume_handler,
887                 scic_sds_remote_node_context_default_start_io_handler,
888                 scic_sds_remote_node_context_suspended_start_task_handler,
889                 scic_sds_remote_node_context_default_event_handler
890         },
891         /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */
892         {
893                 scic_sds_remote_node_context_general_destruct_handler,
894                 scic_sds_remote_node_context_default_suspend_handler,
895                 scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
896                 scic_sds_remote_node_context_default_start_io_handler,
897                 scic_sds_remote_node_context_suspended_start_task_handler,
898                 scic_sds_remote_node_context_default_event_handler
899         },
900         /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */
901         {
902                 scic_sds_remote_node_context_general_destruct_handler,
903                 scic_sds_remote_node_context_default_suspend_handler,
904                 scic_sds_remote_node_context_await_suspension_state_resume_handler,
905                 scic_sds_remote_node_context_default_start_io_handler,
906                 scic_sds_remote_node_context_await_suspension_state_start_task_handler,
907                 scic_sds_remote_node_context_await_suspension_state_event_handler
908         }
909 };
910
911 /*
912  * *****************************************************************************
913  * * REMOTE NODE CONTEXT PRIVATE METHODS
914  * ***************************************************************************** */
915
916 /**
917  *
918  *
919  * This method just calls the user callback function and then resets the
920  * callback.
921  */
922 static void scic_sds_remote_node_context_notify_user(
923         struct scic_sds_remote_node_context *rnc)
924 {
925         if (rnc->user_callback != NULL) {
926                 (*rnc->user_callback)(rnc->user_cookie);
927
928                 rnc->user_callback = NULL;
929                 rnc->user_cookie = NULL;
930         }
931 }
932
933 /**
934  *
935  *
936  * This method will continue the remote node context state machine by
937  * requesting to resume the remote node context state machine from its current
938  * state.
939  */
940 static void scic_sds_remote_node_context_continue_state_transitions(
941         struct scic_sds_remote_node_context *rnc)
942 {
943         if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
944                 rnc->state_handlers->resume_handler(
945                         rnc, rnc->user_callback, rnc->user_cookie
946                         );
947         }
948 }
949
950 /**
951  *
952  * @this_rnc: The remote node context object that is to be validated.
953  *
954  * This method will mark the rnc buffer as being valid and post the request to
955  * the hardware. none
956  */
957 static void scic_sds_remote_node_context_validate_context_buffer(
958         struct scic_sds_remote_node_context *this_rnc)
959 {
960         union scu_remote_node_context *rnc_buffer;
961
962         rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
963                 scic_sds_remote_device_get_controller(this_rnc->device),
964                 this_rnc->remote_node_index
965                 );
966
967         rnc_buffer->ssp.is_valid = true;
968
969         if (
970                 !this_rnc->device->is_direct_attached
971                 && this_rnc->device->target_protocols.u.bits.attached_stp_target
972                 ) {
973                 scic_sds_remote_device_post_request(
974                         this_rnc->device,
975                         SCU_CONTEXT_COMMAND_POST_RNC_96
976                         );
977         } else {
978                 scic_sds_remote_device_post_request(
979                         this_rnc->device,
980                         SCU_CONTEXT_COMMAND_POST_RNC_32
981                         );
982
983                 if (this_rnc->device->is_direct_attached) {
984                         scic_sds_port_setup_transports(
985                                 this_rnc->device->owning_port,
986                                 this_rnc->remote_node_index
987                                 );
988                 }
989         }
990 }
991
992 /**
993  *
994  * @this_rnc: The remote node context object that is to be invalidated.
995  *
996  * This method will update the RNC buffer and post the invalidate request. none
997  */
998 static void scic_sds_remote_node_context_invalidate_context_buffer(
999         struct scic_sds_remote_node_context *this_rnc)
1000 {
1001         union scu_remote_node_context *rnc_buffer;
1002
1003         rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
1004                 scic_sds_remote_device_get_controller(this_rnc->device),
1005                 this_rnc->remote_node_index
1006                 );
1007
1008         rnc_buffer->ssp.is_valid = false;
1009
1010         scic_sds_remote_device_post_request(
1011                 this_rnc->device,
1012                 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE
1013                 );
1014 }
1015
1016 /*
1017  * *****************************************************************************
1018  * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
1019  * ***************************************************************************** */
1020
1021 /**
1022  *
1023  *
1024  *
1025  */
1026 static void scic_sds_remote_node_context_initial_state_enter(
1027         struct sci_base_object *object)
1028 {
1029         struct scic_sds_remote_node_context *rnc;
1030
1031         rnc = (struct scic_sds_remote_node_context *)object;
1032
1033         SET_STATE_HANDLER(
1034                 rnc,
1035                 scic_sds_remote_node_context_state_handler_table,
1036                 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
1037                 );
1038
1039         /*
1040          * Check to see if we have gotten back to the initial state because someone
1041          * requested to destroy the remote node context object. */
1042         if (
1043                 rnc->state_machine.previous_state_id
1044                 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1045                 ) {
1046                 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1047
1048                 scic_sds_remote_node_context_notify_user(rnc);
1049         }
1050 }
1051
1052 /**
1053  *
1054  *
1055  *
1056  */
1057 static void scic_sds_remote_node_context_posting_state_enter(
1058         struct sci_base_object *object)
1059 {
1060         struct scic_sds_remote_node_context *this_rnc;
1061
1062         this_rnc = (struct scic_sds_remote_node_context *)object;
1063
1064         SET_STATE_HANDLER(
1065                 this_rnc,
1066                 scic_sds_remote_node_context_state_handler_table,
1067                 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
1068                 );
1069
1070         scic_sds_remote_node_context_validate_context_buffer(this_rnc);
1071 }
1072
1073 /**
1074  *
1075  *
1076  *
1077  */
1078 static void scic_sds_remote_node_context_invalidating_state_enter(
1079         struct sci_base_object *object)
1080 {
1081         struct scic_sds_remote_node_context *rnc;
1082
1083         rnc = (struct scic_sds_remote_node_context *)object;
1084
1085         SET_STATE_HANDLER(
1086                 rnc,
1087                 scic_sds_remote_node_context_state_handler_table,
1088                 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
1089                 );
1090
1091         scic_sds_remote_node_context_invalidate_context_buffer(rnc);
1092 }
1093
1094 /**
1095  *
1096  *
1097  *
1098  */
1099 static void scic_sds_remote_node_context_resuming_state_enter(
1100         struct sci_base_object *object)
1101 {
1102         struct scic_sds_remote_node_context *rnc;
1103         struct smp_discover_response_protocols protocols;
1104
1105         rnc = (struct scic_sds_remote_node_context *)object;
1106
1107         SET_STATE_HANDLER(
1108                 rnc,
1109                 scic_sds_remote_node_context_state_handler_table,
1110                 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
1111                 );
1112
1113         /*
1114          * For direct attached SATA devices we need to clear the TLCR
1115          * NCQ to TCi tag mapping on the phy and in cases where we
1116          * resume because of a target reset we also need to update
1117          * the STPTLDARNI register with the RNi of the device
1118          */
1119         scic_remote_device_get_protocols(rnc->device, &protocols);
1120
1121         if ((protocols.u.bits.attached_stp_target == 1) &&
1122             (rnc->device->is_direct_attached)) {
1123                 scic_sds_port_setup_transports(
1124                         rnc->device->owning_port, rnc->remote_node_index);
1125         }
1126
1127         scic_sds_remote_device_post_request(
1128                 rnc->device,
1129                 SCU_CONTEXT_COMMAND_POST_RNC_RESUME
1130                 );
1131 }
1132
1133 /**
1134  *
1135  *
1136  *
1137  */
1138 static void scic_sds_remote_node_context_ready_state_enter(
1139         struct sci_base_object *object)
1140 {
1141         struct scic_sds_remote_node_context *rnc;
1142
1143         rnc = (struct scic_sds_remote_node_context *)object;
1144
1145         SET_STATE_HANDLER(
1146                 rnc,
1147                 scic_sds_remote_node_context_state_handler_table,
1148                 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
1149                 );
1150
1151         rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
1152
1153         if (rnc->user_callback != NULL) {
1154                 scic_sds_remote_node_context_notify_user(rnc);
1155         }
1156 }
1157
1158 /**
1159  *
1160  *
1161  *
1162  */
1163 static void scic_sds_remote_node_context_tx_suspended_state_enter(
1164         struct sci_base_object *object)
1165 {
1166         struct scic_sds_remote_node_context *rnc;
1167
1168         rnc = (struct scic_sds_remote_node_context *)object;
1169
1170         SET_STATE_HANDLER(
1171                 rnc,
1172                 scic_sds_remote_node_context_state_handler_table,
1173                 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
1174                 );
1175
1176         scic_sds_remote_node_context_continue_state_transitions(rnc);
1177 }
1178
1179 /**
1180  *
1181  *
1182  *
1183  */
1184 static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
1185         struct sci_base_object *object)
1186 {
1187         struct scic_sds_remote_node_context *rnc;
1188
1189         rnc = (struct scic_sds_remote_node_context *)object;
1190
1191         SET_STATE_HANDLER(
1192                 rnc,
1193                 scic_sds_remote_node_context_state_handler_table,
1194                 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
1195                 );
1196
1197         scic_sds_remote_node_context_continue_state_transitions(rnc);
1198 }
1199
1200 /**
1201  *
1202  *
1203  *
1204  */
1205 static void scic_sds_remote_node_context_await_suspension_state_enter(
1206         struct sci_base_object *object)
1207 {
1208         struct scic_sds_remote_node_context *rnc;
1209
1210         rnc = (struct scic_sds_remote_node_context *)object;
1211
1212         SET_STATE_HANDLER(
1213                 rnc,
1214                 scic_sds_remote_node_context_state_handler_table,
1215                 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
1216                 );
1217 }
1218
1219 /* --------------------------------------------------------------------------- */
1220
1221 const struct sci_base_state scic_sds_remote_node_context_state_table[] = {
1222         [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = {
1223                 .enter_state = scic_sds_remote_node_context_initial_state_enter,
1224         },
1225         [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = {
1226                 .enter_state = scic_sds_remote_node_context_posting_state_enter,
1227         },
1228         [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = {
1229                 .enter_state = scic_sds_remote_node_context_invalidating_state_enter,
1230         },
1231         [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = {
1232                 .enter_state = scic_sds_remote_node_context_resuming_state_enter,
1233         },
1234         [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = {
1235                 .enter_state = scic_sds_remote_node_context_ready_state_enter,
1236         },
1237         [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = {
1238                 .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter,
1239         },
1240         [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = {
1241                 .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter,
1242         },
1243         [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = {
1244                 .enter_state = scic_sds_remote_node_context_await_suspension_state_enter,
1245         },
1246 };
1247