blob: 769a3fc6ec4b868ffda1ca72f4fabece82ef8a06 [file] [log] [blame]
Dan Williams6f231dd2011-07-02 22:56:22 -07001/*
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
Dan Williamscc9203b2011-05-08 17:34:44 -070056#include "host.h"
Dan Williams3bff9d52011-05-08 22:15:10 -070057#include "state_machine.h"
Dan Williams88f3b622011-04-22 19:18:03 -070058#include "remote_device.h"
59#include "remote_node_context.h"
Dan Williams6f231dd2011-07-02 22:56:22 -070060#include "scu_event_codes.h"
61#include "scu_task_context.h"
62
Dan Williams6f231dd2011-07-02 22:56:22 -070063
64/**
65 *
Dave Jiange2023b82011-04-21 05:34:49 +000066 * @sci_rnc: The RNC for which the is posted request is being made.
Dan Williams6f231dd2011-07-02 22:56:22 -070067 *
68 * This method will return true if the RNC is not in the initial state. In all
69 * other states the RNC is considered active and this will return true. The
70 * destroy request of the state machine drives the RNC back to the initial
71 * state. If the state machine changes then this routine will also have to be
72 * changed. bool true if the state machine is not in the initial state false if
73 * the state machine is in the initial state
74 */
75
76/**
77 *
Dave Jiange2023b82011-04-21 05:34:49 +000078 * @sci_rnc: The state of the remote node context object to check.
Dan Williams6f231dd2011-07-02 22:56:22 -070079 *
80 * This method will return true if the remote node context is in a READY state
81 * otherwise it will return false bool true if the remote node context is in
82 * the ready state. false if the remote node context is not in the ready state.
83 */
84bool scic_sds_remote_node_context_is_ready(
Dave Jiange2023b82011-04-21 05:34:49 +000085 struct scic_sds_remote_node_context *sci_rnc)
Dan Williams6f231dd2011-07-02 22:56:22 -070086{
Dave Jiange2023b82011-04-21 05:34:49 +000087 u32 current_state = sci_base_state_machine_get_state(&sci_rnc->state_machine);
Dan Williams6f231dd2011-07-02 22:56:22 -070088
89 if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) {
90 return true;
91 }
92
93 return false;
94}
95
96/**
97 *
Dave Jiange2023b82011-04-21 05:34:49 +000098 * @sci_dev: The remote device to use to construct the RNC buffer.
Dan Williams6f231dd2011-07-02 22:56:22 -070099 * @rnc: The buffer into which the remote device data will be copied.
100 *
101 * This method will construct the RNC buffer for this remote device object. none
102 */
Dan Williams35173d52011-03-26 16:43:01 -0700103static void scic_sds_remote_node_context_construct_buffer(
Dave Jiange2023b82011-04-21 05:34:49 +0000104 struct scic_sds_remote_node_context *sci_rnc)
Dan Williams6f231dd2011-07-02 22:56:22 -0700105{
Dan Williams96143952011-04-19 18:35:58 -0700106 struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
Dan Williamsa1a113b2011-04-21 18:44:45 -0700107 struct domain_device *dev = sci_dev_to_domain(sci_dev);
Dan Williams1f4fa1f2011-04-26 11:44:06 -0700108 int rni = sci_rnc->remote_node_index;
Dan Williamsa1a113b2011-04-21 18:44:45 -0700109 union scu_remote_node_context *rnc;
Dave Jiange2023b82011-04-21 05:34:49 +0000110 struct scic_sds_controller *scic;
Dan Williamsa3d568f02011-04-26 09:41:52 -0700111 __le64 sas_addr;
Dan Williams6f231dd2011-07-02 22:56:22 -0700112
Dan Williams96143952011-04-19 18:35:58 -0700113 scic = scic_sds_remote_device_get_controller(sci_dev);
Dan Williams1f4fa1f2011-04-26 11:44:06 -0700114 rnc = scic_sds_controller_get_remote_node_context_buffer(scic, rni);
Dan Williams6f231dd2011-07-02 22:56:22 -0700115
Dan Williams96143952011-04-19 18:35:58 -0700116 memset(rnc, 0, sizeof(union scu_remote_node_context)
117 * scic_sds_remote_device_node_count(sci_dev));
Dan Williams6f231dd2011-07-02 22:56:22 -0700118
Dan Williams1f4fa1f2011-04-26 11:44:06 -0700119 rnc->ssp.remote_node_index = rni;
Dan Williams96143952011-04-19 18:35:58 -0700120 rnc->ssp.remote_node_port_width = sci_dev->device_port_width;
Dan Williams1f4fa1f2011-04-26 11:44:06 -0700121 rnc->ssp.logical_port_index = sci_dev->owning_port->physical_port_index;
Dan Williams6f231dd2011-07-02 22:56:22 -0700122
Dan Williamsa3d568f02011-04-26 09:41:52 -0700123 /* sas address is __be64, context ram format is __le64 */
124 sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr));
125 rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr);
126 rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr);
Dan Williams6f231dd2011-07-02 22:56:22 -0700127
128 rnc->ssp.nexus_loss_timer_enable = true;
129 rnc->ssp.check_bit = false;
130 rnc->ssp.is_valid = false;
131 rnc->ssp.is_remote_node_context = true;
132 rnc->ssp.function_number = 0;
133
134 rnc->ssp.arbitration_wait_time = 0;
135
Dan Williamsa1a113b2011-04-21 18:44:45 -0700136 if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700137 rnc->ssp.connection_occupancy_timeout =
Dave Jiange2023b82011-04-21 05:34:49 +0000138 scic->user_parameters.sds1.stp_max_occupancy_timeout;
Dan Williams6f231dd2011-07-02 22:56:22 -0700139 rnc->ssp.connection_inactivity_timeout =
Dave Jiange2023b82011-04-21 05:34:49 +0000140 scic->user_parameters.sds1.stp_inactivity_timeout;
Dan Williams6f231dd2011-07-02 22:56:22 -0700141 } else {
142 rnc->ssp.connection_occupancy_timeout =
Dave Jiange2023b82011-04-21 05:34:49 +0000143 scic->user_parameters.sds1.ssp_max_occupancy_timeout;
Dan Williams6f231dd2011-07-02 22:56:22 -0700144 rnc->ssp.connection_inactivity_timeout =
Dave Jiange2023b82011-04-21 05:34:49 +0000145 scic->user_parameters.sds1.ssp_inactivity_timeout;
Dan Williams6f231dd2011-07-02 22:56:22 -0700146 }
147
148 rnc->ssp.initial_arbitration_wait_time = 0;
149
150 /* Open Address Frame Parameters */
Dan Williams96143952011-04-19 18:35:58 -0700151 rnc->ssp.oaf_connection_rate = sci_dev->connection_rate;
Dan Williams6f231dd2011-07-02 22:56:22 -0700152 rnc->ssp.oaf_features = 0;
153 rnc->ssp.oaf_source_zone_group = 0;
154 rnc->ssp.oaf_more_compatibility_features = 0;
155}
156
157/**
158 *
Dave Jiange2023b82011-04-21 05:34:49 +0000159 * @sci_rnc:
160 * @callback:
Dan Williams6f231dd2011-07-02 22:56:22 -0700161 * @callback_parameter:
162 *
163 * This method will setup the remote node context object so it will transition
164 * to its ready state. If the remote node context is already setup to
165 * transition to its final state then this function does nothing. none
166 */
167static void scic_sds_remote_node_context_setup_to_resume(
Dave Jiange2023b82011-04-21 05:34:49 +0000168 struct scic_sds_remote_node_context *sci_rnc,
169 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700170 void *callback_parameter)
171{
Dave Jiange2023b82011-04-21 05:34:49 +0000172 if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) {
173 sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY;
174 sci_rnc->user_callback = callback;
175 sci_rnc->user_cookie = callback_parameter;
Dan Williams6f231dd2011-07-02 22:56:22 -0700176 }
177}
178
179/**
180 *
Dave Jiange2023b82011-04-21 05:34:49 +0000181 * @sci_rnc:
182 * @callback:
Dan Williams6f231dd2011-07-02 22:56:22 -0700183 * @callback_parameter:
184 *
185 * This method will setup the remote node context object so it will transistion
186 * to its final state. none
187 */
188static void scic_sds_remote_node_context_setup_to_destory(
Dave Jiange2023b82011-04-21 05:34:49 +0000189 struct scic_sds_remote_node_context *sci_rnc,
190 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700191 void *callback_parameter)
192{
Dave Jiange2023b82011-04-21 05:34:49 +0000193 sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL;
194 sci_rnc->user_callback = callback;
195 sci_rnc->user_cookie = callback_parameter;
Dan Williams6f231dd2011-07-02 22:56:22 -0700196}
197
198/**
199 *
Dave Jiange2023b82011-04-21 05:34:49 +0000200 * @sci_rnc:
201 * @callback:
Dan Williams6f231dd2011-07-02 22:56:22 -0700202 *
203 * This method will continue to resume a remote node context. This is used in
204 * the states where a resume is requested while a resume is in progress.
205 */
206static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000207 struct scic_sds_remote_node_context *sci_rnc,
208 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700209 void *callback_parameter)
210{
Dave Jiange2023b82011-04-21 05:34:49 +0000211 if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
212 sci_rnc->user_callback = callback;
213 sci_rnc->user_cookie = callback_parameter;
Dan Williams6f231dd2011-07-02 22:56:22 -0700214
215 return SCI_SUCCESS;
216 }
217
218 return SCI_FAILURE_INVALID_STATE;
219}
220
Dan Williams6f231dd2011-07-02 22:56:22 -0700221static enum sci_status scic_sds_remote_node_context_default_suspend_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000222 struct scic_sds_remote_node_context *sci_rnc,
Dan Williams6f231dd2011-07-02 22:56:22 -0700223 u32 suspend_type,
Dave Jiange2023b82011-04-21 05:34:49 +0000224 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700225 void *callback_parameter)
226{
Dan Williams96143952011-04-19 18:35:58 -0700227 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
Dan Williams6f231dd2011-07-02 22:56:22 -0700228 "%s: SCIC Remote Node Context 0x%p requested to suspend "
229 "while in wrong state %d\n",
230 __func__,
Dave Jiange2023b82011-04-21 05:34:49 +0000231 sci_rnc,
232 sci_base_state_machine_get_state(&sci_rnc->state_machine));
Dan Williams6f231dd2011-07-02 22:56:22 -0700233
234 return SCI_FAILURE_INVALID_STATE;
235}
236
237static enum sci_status scic_sds_remote_node_context_default_resume_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000238 struct scic_sds_remote_node_context *sci_rnc,
239 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700240 void *callback_parameter)
241{
Dan Williams96143952011-04-19 18:35:58 -0700242 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
Dan Williams6f231dd2011-07-02 22:56:22 -0700243 "%s: SCIC Remote Node Context 0x%p requested to resume "
244 "while in wrong state %d\n",
245 __func__,
Dave Jiange2023b82011-04-21 05:34:49 +0000246 sci_rnc,
247 sci_base_state_machine_get_state(&sci_rnc->state_machine));
Dan Williams6f231dd2011-07-02 22:56:22 -0700248
249 return SCI_FAILURE_INVALID_STATE;
250}
251
252static enum sci_status scic_sds_remote_node_context_default_start_io_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000253 struct scic_sds_remote_node_context *sci_rnc,
254 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700255{
Dan Williams96143952011-04-19 18:35:58 -0700256 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
Dan Williams6f231dd2011-07-02 22:56:22 -0700257 "%s: SCIC Remote Node Context 0x%p requested to start io "
258 "0x%p while in wrong state %d\n",
259 __func__,
Dave Jiange2023b82011-04-21 05:34:49 +0000260 sci_rnc,
261 sci_req,
262 sci_base_state_machine_get_state(&sci_rnc->state_machine));
Dan Williams6f231dd2011-07-02 22:56:22 -0700263
264 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
265}
266
267static enum sci_status scic_sds_remote_node_context_default_start_task_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000268 struct scic_sds_remote_node_context *sci_rnc,
269 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700270{
Dan Williams96143952011-04-19 18:35:58 -0700271 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
Dan Williams6f231dd2011-07-02 22:56:22 -0700272 "%s: SCIC Remote Node Context 0x%p requested to start "
273 "task 0x%p while in wrong state %d\n",
274 __func__,
Dave Jiange2023b82011-04-21 05:34:49 +0000275 sci_rnc,
276 sci_req,
277 sci_base_state_machine_get_state(&sci_rnc->state_machine));
Dan Williams6f231dd2011-07-02 22:56:22 -0700278
279 return SCI_FAILURE;
280}
281
Dan Williams6f231dd2011-07-02 22:56:22 -0700282/**
283 *
Dave Jiange2023b82011-04-21 05:34:49 +0000284 * @sci_rnc: The rnc for which the task request is targeted.
285 * @sci_req: The request which is going to be started.
Dan Williams6f231dd2011-07-02 22:56:22 -0700286 *
287 * This method determines if the task request can be started by the SCU
288 * hardware. When the RNC is in the ready state any task can be started.
289 * enum sci_status SCI_SUCCESS
290 */
291static enum sci_status scic_sds_remote_node_context_success_start_task_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000292 struct scic_sds_remote_node_context *sci_rnc,
293 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700294{
295 return SCI_SUCCESS;
296}
297
Dan Williams6f231dd2011-07-02 22:56:22 -0700298static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000299 struct scic_sds_remote_node_context *sci_rnc,
300 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700301 void *callback_parameter)
302{
Dave Jiange2023b82011-04-21 05:34:49 +0000303 if (sci_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700304 scic_sds_remote_node_context_setup_to_resume(
Dave Jiange2023b82011-04-21 05:34:49 +0000305 sci_rnc, callback, callback_parameter
Dan Williams6f231dd2011-07-02 22:56:22 -0700306 );
307
Dave Jiange2023b82011-04-21 05:34:49 +0000308 scic_sds_remote_node_context_construct_buffer(sci_rnc);
Dan Williams6f231dd2011-07-02 22:56:22 -0700309
310 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000311 &sci_rnc->state_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700312 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
313 );
314
315 return SCI_SUCCESS;
316 }
317
318 return SCI_FAILURE_INVALID_STATE;
319}
320
Dan Williams6f231dd2011-07-02 22:56:22 -0700321/**
322 *
Dave Jiange2023b82011-04-21 05:34:49 +0000323 * @sci_rnc: The remote node context object being suspended.
324 * @callback: The callback when the suspension is complete.
Dan Williams6f231dd2011-07-02 22:56:22 -0700325 * @callback_parameter: The parameter that is to be passed into the callback.
326 *
327 * This method will handle the suspend requests from the ready state.
328 * SCI_SUCCESS
329 */
330static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000331 struct scic_sds_remote_node_context *sci_rnc,
Dan Williams6f231dd2011-07-02 22:56:22 -0700332 u32 suspend_type,
Dave Jiange2023b82011-04-21 05:34:49 +0000333 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700334 void *callback_parameter)
335{
Dave Jiange2023b82011-04-21 05:34:49 +0000336 sci_rnc->user_callback = callback;
337 sci_rnc->user_cookie = callback_parameter;
338 sci_rnc->suspension_code = suspend_type;
Dan Williams6f231dd2011-07-02 22:56:22 -0700339
340 if (suspend_type == SCI_SOFTWARE_SUSPENSION) {
Dan Williams96143952011-04-19 18:35:58 -0700341 scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc),
342 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX);
Dan Williams6f231dd2011-07-02 22:56:22 -0700343 }
344
345 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000346 &sci_rnc->state_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700347 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
348 );
349
350 return SCI_SUCCESS;
351}
352
353/**
354 *
Dave Jiange2023b82011-04-21 05:34:49 +0000355 * @sci_rnc: The rnc for which the io request is targeted.
356 * @sci_req: The request which is going to be started.
Dan Williams6f231dd2011-07-02 22:56:22 -0700357 *
358 * This method determines if the io request can be started by the SCU hardware.
359 * When the RNC is in the ready state any io request can be started. enum sci_status
360 * SCI_SUCCESS
361 */
362static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000363 struct scic_sds_remote_node_context *sci_rnc,
364 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700365{
366 return SCI_SUCCESS;
367}
368
Dan Williams6f231dd2011-07-02 22:56:22 -0700369static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000370 struct scic_sds_remote_node_context *sci_rnc,
371 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700372 void *callback_parameter)
373{
Dan Williamsa1a113b2011-04-21 18:44:45 -0700374 struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
375 struct domain_device *dev = sci_dev_to_domain(sci_dev);
376 enum sci_status status = SCI_SUCCESS;
Dan Williams6f231dd2011-07-02 22:56:22 -0700377
Dan Williamsa1a113b2011-04-21 18:44:45 -0700378 scic_sds_remote_node_context_setup_to_resume(sci_rnc, callback,
379 callback_parameter);
Dan Williams6f231dd2011-07-02 22:56:22 -0700380
381 /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */
Dan Williamsa1a113b2011-04-21 18:44:45 -0700382 if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev))
383 sci_base_state_machine_change_state(&sci_rnc->state_machine,
384 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
385 else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) {
386 if (sci_dev->is_direct_attached) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700387 /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */
Dan Williams6f231dd2011-07-02 22:56:22 -0700388 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000389 &sci_rnc->state_machine,
Dan Williamsa1a113b2011-04-21 18:44:45 -0700390 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE);
Dan Williams6f231dd2011-07-02 22:56:22 -0700391 } else {
392 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000393 &sci_rnc->state_machine,
Dan Williamsa1a113b2011-04-21 18:44:45 -0700394 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE);
Dan Williams6f231dd2011-07-02 22:56:22 -0700395 }
Dan Williamsa1a113b2011-04-21 18:44:45 -0700396 } else
Dan Williams6f231dd2011-07-02 22:56:22 -0700397 status = SCI_FAILURE;
Dan Williams6f231dd2011-07-02 22:56:22 -0700398
399 return status;
400}
401
402/**
403 *
Dave Jiange2023b82011-04-21 05:34:49 +0000404 * @sci_rnc: The remote node context which is to receive the task request.
405 * @sci_req: The task request to be transmitted to to the remote target
Dan Williams6f231dd2011-07-02 22:56:22 -0700406 * device.
407 *
408 * This method will report a success or failure attempt to start a new task
409 * request to the hardware. Since all task requests are sent on the high
410 * priority queue they can be sent when the RCN is in a TX suspend state.
411 * enum sci_status SCI_SUCCESS
412 */
413static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000414 struct scic_sds_remote_node_context *sci_rnc,
415 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700416{
Dave Jiange2023b82011-04-21 05:34:49 +0000417 scic_sds_remote_node_context_resume(sci_rnc, NULL, NULL);
Dan Williams6f231dd2011-07-02 22:56:22 -0700418
419 return SCI_SUCCESS;
420}
421
422/* --------------------------------------------------------------------------- */
423
424static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000425 struct scic_sds_remote_node_context *sci_rnc,
426 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700427 void *callback_parameter)
428{
429 scic_sds_remote_node_context_setup_to_resume(
Dave Jiange2023b82011-04-21 05:34:49 +0000430 sci_rnc, callback, callback_parameter
Dan Williams6f231dd2011-07-02 22:56:22 -0700431 );
432
433 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000434 &sci_rnc->state_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700435 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
436 );
437
438 return SCI_FAILURE_INVALID_STATE;
439}
440
441/* --------------------------------------------------------------------------- */
442
443/**
444 *
445 *
446 *
447 */
448static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000449 struct scic_sds_remote_node_context *sci_rnc,
450 scics_sds_remote_node_context_callback callback,
Dan Williams6f231dd2011-07-02 22:56:22 -0700451 void *callback_parameter)
452{
453 scic_sds_remote_node_context_setup_to_resume(
Dave Jiange2023b82011-04-21 05:34:49 +0000454 sci_rnc, callback, callback_parameter
Dan Williams6f231dd2011-07-02 22:56:22 -0700455 );
456
457 return SCI_SUCCESS;
458}
459
460/**
461 *
Dave Jiange2023b82011-04-21 05:34:49 +0000462 * @sci_rnc: The remote node context which is to receive the task request.
463 * @sci_req: The task request to be transmitted to to the remote target
Dan Williams6f231dd2011-07-02 22:56:22 -0700464 * device.
465 *
466 * This method will report a success or failure attempt to start a new task
467 * request to the hardware. Since all task requests are sent on the high
468 * priority queue they can be sent when the RCN is in a TX suspend state.
469 * enum sci_status SCI_SUCCESS
470 */
471static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000472 struct scic_sds_remote_node_context *sci_rnc,
473 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700474{
475 return SCI_SUCCESS;
476}
477
Dan Williams338e3862011-05-12 07:46:59 -0700478static struct scic_sds_remote_node_context_handlers scic_sds_remote_node_context_state_handler_table[] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000479 [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000480 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
481 .resume_handler = scic_sds_remote_node_context_initial_state_resume_handler,
482 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
483 .start_task_handler = scic_sds_remote_node_context_default_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700484 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000485 [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000486 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
487 .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler,
488 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
489 .start_task_handler = scic_sds_remote_node_context_default_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700490 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000491 [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000492 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
493 .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler,
494 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
495 .start_task_handler = scic_sds_remote_node_context_default_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700496 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000497 [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000498 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
499 .resume_handler = scic_sds_remote_node_context_continue_to_resume_handler,
500 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
501 .start_task_handler = scic_sds_remote_node_context_success_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700502 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000503 [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000504 .suspend_handler = scic_sds_remote_node_context_ready_state_suspend_handler,
505 .resume_handler = scic_sds_remote_node_context_default_resume_handler,
506 .start_io_handler = scic_sds_remote_node_context_ready_state_start_io_handler,
507 .start_task_handler = scic_sds_remote_node_context_success_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700508 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000509 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000510 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
511 .resume_handler = scic_sds_remote_node_context_tx_suspended_state_resume_handler,
512 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
513 .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700514 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000515 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000516 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
517 .resume_handler = scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler,
518 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
519 .start_task_handler = scic_sds_remote_node_context_suspended_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700520 },
Jacek Daneckia98a7422011-05-03 04:21:07 +0000521 [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = {
Jacek Daneckia98a7422011-05-03 04:21:07 +0000522 .suspend_handler = scic_sds_remote_node_context_default_suspend_handler,
523 .resume_handler = scic_sds_remote_node_context_await_suspension_state_resume_handler,
524 .start_io_handler = scic_sds_remote_node_context_default_start_io_handler,
525 .start_task_handler = scic_sds_remote_node_context_await_suspension_state_start_task_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700526 }
527};
528
529/*
530 * *****************************************************************************
531 * * REMOTE NODE CONTEXT PRIVATE METHODS
532 * ***************************************************************************** */
533
534/**
535 *
536 *
537 * This method just calls the user callback function and then resets the
538 * callback.
539 */
540static void scic_sds_remote_node_context_notify_user(
541 struct scic_sds_remote_node_context *rnc)
542{
543 if (rnc->user_callback != NULL) {
544 (*rnc->user_callback)(rnc->user_cookie);
545
546 rnc->user_callback = NULL;
547 rnc->user_cookie = NULL;
548 }
549}
550
551/**
552 *
553 *
554 * This method will continue the remote node context state machine by
555 * requesting to resume the remote node context state machine from its current
556 * state.
557 */
558static void scic_sds_remote_node_context_continue_state_transitions(
559 struct scic_sds_remote_node_context *rnc)
560{
561 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) {
562 rnc->state_handlers->resume_handler(
563 rnc, rnc->user_callback, rnc->user_cookie
564 );
565 }
566}
567
568/**
569 *
Dave Jiange2023b82011-04-21 05:34:49 +0000570 * @sci_rnc: The remote node context object that is to be validated.
Dan Williams6f231dd2011-07-02 22:56:22 -0700571 *
572 * This method will mark the rnc buffer as being valid and post the request to
573 * the hardware. none
574 */
575static void scic_sds_remote_node_context_validate_context_buffer(
Dave Jiange2023b82011-04-21 05:34:49 +0000576 struct scic_sds_remote_node_context *sci_rnc)
Dan Williams6f231dd2011-07-02 22:56:22 -0700577{
Dan Williams96143952011-04-19 18:35:58 -0700578 struct scic_sds_remote_device *sci_dev = rnc_to_dev(sci_rnc);
Dan Williamsa1a113b2011-04-21 18:44:45 -0700579 struct domain_device *dev = sci_dev_to_domain(sci_dev);
Dan Williams6f231dd2011-07-02 22:56:22 -0700580 union scu_remote_node_context *rnc_buffer;
581
582 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
Dan Williams96143952011-04-19 18:35:58 -0700583 scic_sds_remote_device_get_controller(sci_dev),
Dave Jiange2023b82011-04-21 05:34:49 +0000584 sci_rnc->remote_node_index
Dan Williams6f231dd2011-07-02 22:56:22 -0700585 );
586
587 rnc_buffer->ssp.is_valid = true;
588
Dan Williams96143952011-04-19 18:35:58 -0700589 if (!sci_dev->is_direct_attached &&
Dan Williamsa1a113b2011-04-21 18:44:45 -0700590 (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) {
Dan Williams96143952011-04-19 18:35:58 -0700591 scic_sds_remote_device_post_request(sci_dev,
592 SCU_CONTEXT_COMMAND_POST_RNC_96);
Dan Williams6f231dd2011-07-02 22:56:22 -0700593 } else {
Dan Williams96143952011-04-19 18:35:58 -0700594 scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_32);
Dan Williams6f231dd2011-07-02 22:56:22 -0700595
Dan Williams96143952011-04-19 18:35:58 -0700596 if (sci_dev->is_direct_attached) {
597 scic_sds_port_setup_transports(sci_dev->owning_port,
598 sci_rnc->remote_node_index);
Dan Williams6f231dd2011-07-02 22:56:22 -0700599 }
600 }
601}
602
603/**
604 *
Dave Jiange2023b82011-04-21 05:34:49 +0000605 * @sci_rnc: The remote node context object that is to be invalidated.
Dan Williams6f231dd2011-07-02 22:56:22 -0700606 *
607 * This method will update the RNC buffer and post the invalidate request. none
608 */
609static void scic_sds_remote_node_context_invalidate_context_buffer(
Dave Jiange2023b82011-04-21 05:34:49 +0000610 struct scic_sds_remote_node_context *sci_rnc)
Dan Williams6f231dd2011-07-02 22:56:22 -0700611{
612 union scu_remote_node_context *rnc_buffer;
613
614 rnc_buffer = scic_sds_controller_get_remote_node_context_buffer(
Dan Williams96143952011-04-19 18:35:58 -0700615 scic_sds_remote_device_get_controller(rnc_to_dev(sci_rnc)),
616 sci_rnc->remote_node_index);
Dan Williams6f231dd2011-07-02 22:56:22 -0700617
618 rnc_buffer->ssp.is_valid = false;
619
Dan Williams96143952011-04-19 18:35:58 -0700620 scic_sds_remote_device_post_request(rnc_to_dev(sci_rnc),
621 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE);
Dan Williams6f231dd2011-07-02 22:56:22 -0700622}
623
624/*
625 * *****************************************************************************
626 * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS
627 * ***************************************************************************** */
628
629/**
630 *
631 *
632 *
633 */
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000634static void scic_sds_remote_node_context_initial_state_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700635{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000636 struct scic_sds_remote_node_context *rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700637
638 SET_STATE_HANDLER(
639 rnc,
640 scic_sds_remote_node_context_state_handler_table,
641 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
642 );
643
644 /*
645 * Check to see if we have gotten back to the initial state because someone
646 * requested to destroy the remote node context object. */
647 if (
648 rnc->state_machine.previous_state_id
649 == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
650 ) {
651 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
652
653 scic_sds_remote_node_context_notify_user(rnc);
654 }
655}
656
657/**
658 *
659 *
660 *
661 */
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000662static void scic_sds_remote_node_context_posting_state_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700663{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000664 struct scic_sds_remote_node_context *sci_rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700665
666 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +0000667 sci_rnc,
Dan Williams6f231dd2011-07-02 22:56:22 -0700668 scic_sds_remote_node_context_state_handler_table,
669 SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE
670 );
671
Dave Jiange2023b82011-04-21 05:34:49 +0000672 scic_sds_remote_node_context_validate_context_buffer(sci_rnc);
Dan Williams6f231dd2011-07-02 22:56:22 -0700673}
674
675/**
676 *
677 *
678 *
679 */
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000680static void scic_sds_remote_node_context_invalidating_state_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700681{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000682 struct scic_sds_remote_node_context *rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700683
684 SET_STATE_HANDLER(
685 rnc,
686 scic_sds_remote_node_context_state_handler_table,
687 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE
688 );
689
690 scic_sds_remote_node_context_invalidate_context_buffer(rnc);
691}
692
693/**
694 *
695 *
696 *
697 */
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000698static void scic_sds_remote_node_context_resuming_state_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700699{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000700 struct scic_sds_remote_node_context *rnc = object;
Dan Williams96143952011-04-19 18:35:58 -0700701 struct scic_sds_remote_device *sci_dev;
Dan Williamsa1a113b2011-04-21 18:44:45 -0700702 struct domain_device *dev;
Dan Williams6f231dd2011-07-02 22:56:22 -0700703
Dan Williams96143952011-04-19 18:35:58 -0700704 sci_dev = rnc_to_dev(rnc);
Dan Williamsa1a113b2011-04-21 18:44:45 -0700705 dev = sci_dev_to_domain(sci_dev);
Dan Williams6f231dd2011-07-02 22:56:22 -0700706
707 SET_STATE_HANDLER(
708 rnc,
709 scic_sds_remote_node_context_state_handler_table,
710 SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE
711 );
712
Henryk Dembkowski24621462011-02-23 00:08:52 -0800713 /*
714 * For direct attached SATA devices we need to clear the TLCR
715 * NCQ to TCi tag mapping on the phy and in cases where we
716 * resume because of a target reset we also need to update
717 * the STPTLDARNI register with the RNi of the device
718 */
Dan Williamsa1a113b2011-04-21 18:44:45 -0700719 if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
720 sci_dev->is_direct_attached)
Dan Williams96143952011-04-19 18:35:58 -0700721 scic_sds_port_setup_transports(sci_dev->owning_port,
722 rnc->remote_node_index);
Henryk Dembkowski24621462011-02-23 00:08:52 -0800723
Dan Williams96143952011-04-19 18:35:58 -0700724 scic_sds_remote_device_post_request(sci_dev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME);
Dan Williams6f231dd2011-07-02 22:56:22 -0700725}
726
727/**
728 *
729 *
730 *
731 */
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000732static void scic_sds_remote_node_context_ready_state_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700733{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000734 struct scic_sds_remote_node_context *rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700735
736 SET_STATE_HANDLER(
737 rnc,
738 scic_sds_remote_node_context_state_handler_table,
739 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE
740 );
741
742 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
743
744 if (rnc->user_callback != NULL) {
745 scic_sds_remote_node_context_notify_user(rnc);
746 }
747}
748
749/**
750 *
751 *
752 *
753 */
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000754static void scic_sds_remote_node_context_tx_suspended_state_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700755{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000756 struct scic_sds_remote_node_context *rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700757
758 SET_STATE_HANDLER(
759 rnc,
760 scic_sds_remote_node_context_state_handler_table,
761 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE
762 );
763
764 scic_sds_remote_node_context_continue_state_transitions(rnc);
765}
766
767/**
768 *
769 *
770 *
771 */
772static void scic_sds_remote_node_context_tx_rx_suspended_state_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000773 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700774{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000775 struct scic_sds_remote_node_context *rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700776
777 SET_STATE_HANDLER(
778 rnc,
779 scic_sds_remote_node_context_state_handler_table,
780 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE
781 );
782
783 scic_sds_remote_node_context_continue_state_transitions(rnc);
784}
785
786/**
787 *
788 *
789 *
790 */
791static void scic_sds_remote_node_context_await_suspension_state_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000792 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700793{
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000794 struct scic_sds_remote_node_context *rnc = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700795
796 SET_STATE_HANDLER(
797 rnc,
798 scic_sds_remote_node_context_state_handler_table,
799 SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE
800 );
801}
802
803/* --------------------------------------------------------------------------- */
804
Dan Williams35173d52011-03-26 16:43:01 -0700805static const struct sci_base_state scic_sds_remote_node_context_state_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -0700806 [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = {
807 .enter_state = scic_sds_remote_node_context_initial_state_enter,
808 },
809 [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = {
810 .enter_state = scic_sds_remote_node_context_posting_state_enter,
811 },
812 [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = {
813 .enter_state = scic_sds_remote_node_context_invalidating_state_enter,
814 },
815 [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = {
816 .enter_state = scic_sds_remote_node_context_resuming_state_enter,
817 },
818 [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = {
819 .enter_state = scic_sds_remote_node_context_ready_state_enter,
820 },
821 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = {
822 .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter,
823 },
824 [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = {
825 .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter,
826 },
827 [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = {
828 .enter_state = scic_sds_remote_node_context_await_suspension_state_enter,
829 },
830};
831
Dan Williams96143952011-04-19 18:35:58 -0700832void scic_sds_remote_node_context_construct(struct scic_sds_remote_node_context *rnc,
833 u16 remote_node_index)
Dan Williams35173d52011-03-26 16:43:01 -0700834{
835 memset(rnc, 0, sizeof(struct scic_sds_remote_node_context));
836
837 rnc->remote_node_index = remote_node_index;
Dan Williams35173d52011-03-26 16:43:01 -0700838 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED;
839
840 sci_base_state_machine_construct(
841 &rnc->state_machine,
Maciej Patelczykaf23e852011-04-28 22:06:26 +0000842 rnc,
Dan Williams35173d52011-03-26 16:43:01 -0700843 scic_sds_remote_node_context_state_table,
844 SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE
845 );
846
847 sci_base_state_machine_start(&rnc->state_machine);
848}
Dan Williams338e3862011-05-12 07:46:59 -0700849
850enum sci_status scic_sds_remote_node_context_event_handler(struct scic_sds_remote_node_context *sci_rnc,
851 u32 event_code)
852{
853 enum scis_sds_remote_node_context_states state;
854
855 state = sci_rnc->state_machine.current_state_id;
856 switch (state) {
857 case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE:
858 switch (scu_get_event_code(event_code)) {
859 case SCU_EVENT_POST_RNC_COMPLETE:
860 sci_base_state_machine_change_state(&sci_rnc->state_machine,
861 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE);
862 break;
863 default:
864 goto out;
865 }
866 break;
867 case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE:
868 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
869 if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL)
870 state = SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE;
871 else
872 state = SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE;
873 sci_base_state_machine_change_state(&sci_rnc->state_machine,
874 state);
875 } else {
876 switch (scu_get_event_type(event_code)) {
877 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
878 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
879 /* We really dont care if the hardware is going to suspend
880 * the device since it's being invalidated anyway */
881 dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
882 "%s: SCIC Remote Node Context 0x%p was "
883 "suspeneded by hardware while being "
884 "invalidated.\n", __func__, sci_rnc);
885 break;
886 default:
887 goto out;
888 }
889 }
890 break;
891 case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE:
892 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
893 sci_base_state_machine_change_state(&sci_rnc->state_machine,
894 SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE);
895 } else {
896 switch (scu_get_event_type(event_code)) {
897 case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
898 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
899 /* We really dont care if the hardware is going to suspend
900 * the device since it's being resumed anyway */
901 dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
902 "%s: SCIC Remote Node Context 0x%p was "
903 "suspeneded by hardware while being resumed.\n",
904 __func__, sci_rnc);
905 break;
906 default:
907 goto out;
908 }
909 }
910 break;
911 case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE:
912 switch (scu_get_event_type(event_code)) {
913 case SCU_EVENT_TL_RNC_SUSPEND_TX:
914 sci_base_state_machine_change_state(&sci_rnc->state_machine,
915 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE);
916 sci_rnc->suspension_code = scu_get_event_specifier(event_code);
917 break;
918 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
919 sci_base_state_machine_change_state(&sci_rnc->state_machine,
920 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE);
921 sci_rnc->suspension_code = scu_get_event_specifier(event_code);
922 break;
923 default:
924 goto out;
925 }
926 break;
927 case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE:
928 switch (scu_get_event_type(event_code)) {
929 case SCU_EVENT_TL_RNC_SUSPEND_TX:
930 sci_base_state_machine_change_state(&sci_rnc->state_machine,
931 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE);
932 sci_rnc->suspension_code = scu_get_event_specifier(event_code);
933 break;
934 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
935 sci_base_state_machine_change_state(&sci_rnc->state_machine,
936 SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE);
937 sci_rnc->suspension_code = scu_get_event_specifier(event_code);
938 break;
939 default:
940 goto out;
941 }
942 break;
943 default:
944 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
945 "%s: invalid state %d\n", __func__, state);
946 return SCI_FAILURE_INVALID_STATE;
947 }
948 return SCI_SUCCESS;
949
950 out:
951 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
952 "%s: code: %#x state: %d\n", __func__, event_code, state);
953 return SCI_FAILURE;
954
955}
Dan Williamsc845ae92011-05-12 08:26:56 -0700956
957enum sci_status scic_sds_remote_node_context_destruct(struct scic_sds_remote_node_context *sci_rnc,
958 scics_sds_remote_node_context_callback cb_fn,
959 void *cb_p)
960{
961 enum scis_sds_remote_node_context_states state;
962
963 state = sci_rnc->state_machine.current_state_id;
964 switch (state) {
965 case SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE:
966 scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p);
967 return SCI_SUCCESS;
968 case SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE:
969 case SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE:
970 case SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE:
971 case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE:
972 case SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE:
973 case SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE:
974 scic_sds_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p);
975 sci_base_state_machine_change_state(&sci_rnc->state_machine,
976 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE);
977 return SCI_SUCCESS;
978 case SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE:
979 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
980 "%s: invalid state %d\n", __func__, state);
981 /* We have decided that the destruct request on the remote node context
982 * can not fail since it is either in the initial/destroyed state or is
983 * can be destroyed.
984 */
985 return SCI_SUCCESS;
986 default:
987 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
988 "%s: invalid state %d\n", __func__, state);
989 return SCI_FAILURE_INVALID_STATE;
990 }
991}