blob: 298086afa5aac0fac5daa48df3358fc0d46d7297 [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
Dave Jiange76d6182011-05-04 15:02:03 -070056#include <scsi/sas.h>
57#include "sas.h"
Dan Williams3bff9d52011-05-08 22:15:10 -070058#include "state_machine.h"
Dan Williams88f3b622011-04-22 19:18:03 -070059#include "remote_device.h"
Dan Williamsf1f52e72011-05-10 02:28:45 -070060#include "stp_request.h"
Dan Williams63a3a152011-05-08 21:36:46 -070061#include "unsolicited_frame_control.h"
Dan Williams6f231dd2011-07-02 22:56:22 -070062#include "scu_completion_codes.h"
63#include "scu_event_codes.h"
64#include "scu_task_context.h"
Dan Williamsce2b3262011-05-08 15:49:15 -070065#include "request.h"
Dan Williams6f231dd2011-07-02 22:56:22 -070066
Dan Williamsfe9a6432011-03-03 14:58:11 -080067void scic_sds_stp_request_assign_buffers(struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -070068{
Dan Williams26298262011-05-07 19:07:14 -070069 if (sci_req->was_tag_assigned_by_user == false)
70 sci_req->task_context_buffer = &sci_req->tc;
Dan Williams6f231dd2011-07-02 22:56:22 -070071}
72
73/**
74 * This method is will fill in the SCU Task Context for any type of SATA
75 * request. This is called from the various SATA constructors.
Dave Jiange2023b82011-04-21 05:34:49 +000076 * @sci_req: The general IO request object which is to be used in
Dan Williams6f231dd2011-07-02 22:56:22 -070077 * constructing the SCU task context.
78 * @task_context: The buffer pointer for the SCU task context which is being
79 * constructed.
80 *
81 * The general io request construction is complete. The buffer assignment for
82 * the command buffer is complete. none Revisit task context construction to
83 * determine what is common for SSP/SMP/STP task context structures.
84 */
85static void scu_sata_reqeust_construct_task_context(
Dan Williamsb7645812011-05-08 02:35:32 -070086 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -070087 struct scu_task_context *task_context)
88{
Dave Jiang6389a772011-02-23 15:57:27 -080089 dma_addr_t dma_addr;
90 struct scic_sds_controller *controller;
Dan Williams6f231dd2011-07-02 22:56:22 -070091 struct scic_sds_remote_device *target_device;
92 struct scic_sds_port *target_port;
93
Dan Williamsb7645812011-05-08 02:35:32 -070094 controller = scic_sds_request_get_controller(sci_req);
95 target_device = scic_sds_request_get_device(sci_req);
96 target_port = scic_sds_request_get_port(sci_req);
Dan Williams6f231dd2011-07-02 22:56:22 -070097
98 /* Fill in the TC with the its required data */
99 task_context->abort = 0;
100 task_context->priority = SCU_TASK_PRIORITY_NORMAL;
101 task_context->initiator_request = 1;
Dan Williams8f304c32011-04-29 13:20:30 -0700102 task_context->connection_rate = target_device->connection_rate;
Dan Williams6f231dd2011-07-02 22:56:22 -0700103 task_context->protocol_engine_index =
Dave Jiang6389a772011-02-23 15:57:27 -0800104 scic_sds_controller_get_protocol_engine_group(controller);
Dan Williams6f231dd2011-07-02 22:56:22 -0700105 task_context->logical_port_index =
106 scic_sds_port_get_index(target_port);
107 task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP;
108 task_context->valid = SCU_TASK_CONTEXT_VALID;
109 task_context->context_type = SCU_TASK_CONTEXT_TYPE;
110
111 task_context->remote_node_index =
Dan Williamsb7645812011-05-08 02:35:32 -0700112 scic_sds_remote_device_get_index(sci_req->target_device);
Dan Williams6f231dd2011-07-02 22:56:22 -0700113 task_context->command_code = 0;
114
115 task_context->link_layer_control = 0;
116 task_context->do_not_dma_ssp_good_response = 1;
117 task_context->strict_ordering = 0;
118 task_context->control_frame = 0;
119 task_context->timeout_enable = 0;
120 task_context->block_guard_enable = 0;
121
122 task_context->address_modifier = 0;
123 task_context->task_phase = 0x01;
124
125 task_context->ssp_command_iu_length =
Dave Jiangf2f30082011-05-04 15:02:02 -0700126 (sizeof(struct host_to_dev_fis) - sizeof(u32)) / sizeof(u32);
Dan Williams6f231dd2011-07-02 22:56:22 -0700127
128 /* Set the first word of the H2D REG FIS */
Dan Williamsb7645812011-05-08 02:35:32 -0700129 task_context->type.words[0] = *(u32 *)&sci_req->stp.cmd;
Dan Williams6f231dd2011-07-02 22:56:22 -0700130
Dan Williamsb7645812011-05-08 02:35:32 -0700131 if (sci_req->was_tag_assigned_by_user) {
Dave Jiang6389a772011-02-23 15:57:27 -0800132 /*
133 * Build the task context now since we have already read
134 * the data
135 */
Dan Williamsb7645812011-05-08 02:35:32 -0700136 sci_req->post_context =
Dave Jiang6389a772011-02-23 15:57:27 -0800137 (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
138 (scic_sds_controller_get_protocol_engine_group(
139 controller) <<
140 SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
141 (scic_sds_port_get_index(target_port) <<
142 SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) |
Dan Williamsb7645812011-05-08 02:35:32 -0700143 scic_sds_io_tag_get_index(sci_req->io_tag));
Dan Williams6f231dd2011-07-02 22:56:22 -0700144 } else {
Dave Jiang6389a772011-02-23 15:57:27 -0800145 /*
146 * Build the task context now since we have already read
147 * the data.
148 * I/O tag index is not assigned because we have to wait
149 * until we get a TCi.
150 */
Dan Williamsb7645812011-05-08 02:35:32 -0700151 sci_req->post_context =
Dave Jiang6389a772011-02-23 15:57:27 -0800152 (SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
153 (scic_sds_controller_get_protocol_engine_group(
154 controller) <<
155 SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) |
156 (scic_sds_port_get_index(target_port) <<
157 SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT));
Dan Williams6f231dd2011-07-02 22:56:22 -0700158 }
159
160 /*
Dave Jiang6389a772011-02-23 15:57:27 -0800161 * Copy the physical address for the command buffer to the SCU Task
162 * Context. We must offset the command buffer by 4 bytes because the
163 * first 4 bytes are transfered in the body of the TC.
164 */
Dan Williamsb7645812011-05-08 02:35:32 -0700165 dma_addr = scic_io_request_get_dma_addr(sci_req,
166 ((char *) &sci_req->stp.cmd) +
167 sizeof(u32));
Dan Williams6f231dd2011-07-02 22:56:22 -0700168
Dave Jiang6389a772011-02-23 15:57:27 -0800169 task_context->command_iu_upper = upper_32_bits(dma_addr);
170 task_context->command_iu_lower = lower_32_bits(dma_addr);
Dan Williams6f231dd2011-07-02 22:56:22 -0700171
172 /* SATA Requests do not have a response buffer */
173 task_context->response_iu_upper = 0;
174 task_context->response_iu_lower = 0;
175}
176
177/**
178 *
Dave Jiange2023b82011-04-21 05:34:49 +0000179 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -0700180 *
181 * This method will perform any general sata request construction. What part of
182 * SATA IO request construction is general? none
183 */
Dan Williams35173d52011-03-26 16:43:01 -0700184static void scic_sds_stp_non_ncq_request_construct(
Dave Jiange2023b82011-04-21 05:34:49 +0000185 struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700186{
Dave Jiange2023b82011-04-21 05:34:49 +0000187 sci_req->has_started_substate_machine = true;
Dan Williams6f231dd2011-07-02 22:56:22 -0700188}
189
190/**
191 *
Dan Williams82d29922011-02-08 17:53:10 -0800192 * @sci_req: This parameter specifies the request to be constructed as an
Dan Williams6f231dd2011-07-02 22:56:22 -0700193 * optimized request.
194 * @optimized_task_type: This parameter specifies whether the request is to be
195 * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A
196 * value of 1 indicates NCQ.
197 *
198 * This method will perform request construction common to all types of STP
199 * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method
200 * returns an indication as to whether the construction was successful.
201 */
Dan Williams82d29922011-02-08 17:53:10 -0800202static void scic_sds_stp_optimized_request_construct(struct scic_sds_request *sci_req,
203 u8 optimized_task_type,
204 u32 len,
205 enum dma_data_direction dir)
Dan Williams6f231dd2011-07-02 22:56:22 -0700206{
Dan Williams82d29922011-02-08 17:53:10 -0800207 struct scu_task_context *task_context = sci_req->task_context_buffer;
Dan Williams6f231dd2011-07-02 22:56:22 -0700208
209 /* Build the STP task context structure */
Dan Williams82d29922011-02-08 17:53:10 -0800210 scu_sata_reqeust_construct_task_context(sci_req, task_context);
Dan Williams6f231dd2011-07-02 22:56:22 -0700211
212 /* Copy over the SGL elements */
Dan Williams82d29922011-02-08 17:53:10 -0800213 scic_sds_request_build_sgl(sci_req);
Dan Williams6f231dd2011-07-02 22:56:22 -0700214
215 /* Copy over the number of bytes to be transfered */
Dan Williams82d29922011-02-08 17:53:10 -0800216 task_context->transfer_length_bytes = len;
Dan Williams6f231dd2011-07-02 22:56:22 -0700217
Dan Williams82d29922011-02-08 17:53:10 -0800218 if (dir == DMA_TO_DEVICE) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700219 /*
220 * The difference between the DMA IN and DMA OUT request task type
221 * values are consistent with the difference between FPDMA READ
222 * and FPDMA WRITE values. Add the supplied task type parameter
223 * to this difference to set the task type properly for this
224 * DATA OUT (WRITE) case. */
225 task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT
226 - SCU_TASK_TYPE_DMA_IN);
227 } else {
228 /*
229 * For the DATA IN (READ) case, simply save the supplied
230 * optimized task type. */
231 task_context->task_type = optimized_task_type;
232 }
233}
234
235/**
236 *
Dan Williams82d29922011-02-08 17:53:10 -0800237 * @sci_req: This parameter specifies the request to be constructed.
Dan Williams6f231dd2011-07-02 22:56:22 -0700238 *
239 * This method will construct the STP UDMA request and its associated TC data.
240 * This method returns an indication as to whether the construction was
241 * successful. SCI_SUCCESS Currently this method always returns this value.
242 */
Dan Williams82d29922011-02-08 17:53:10 -0800243enum sci_status scic_sds_stp_ncq_request_construct(struct scic_sds_request *sci_req,
244 u32 len,
245 enum dma_data_direction dir)
Dan Williams6f231dd2011-07-02 22:56:22 -0700246{
Dan Williams82d29922011-02-08 17:53:10 -0800247 scic_sds_stp_optimized_request_construct(sci_req,
248 SCU_TASK_TYPE_FPDMAQ_READ,
249 len, dir);
Dan Williams6f231dd2011-07-02 22:56:22 -0700250 return SCI_SUCCESS;
251}
252
253/**
Dan Williams35173d52011-03-26 16:43:01 -0700254 * scu_stp_raw_request_construct_task_context -
Dave Jiange2023b82011-04-21 05:34:49 +0000255 * @sci_req: This parameter specifies the STP request object for which to
Dan Williams6f231dd2011-07-02 22:56:22 -0700256 * construct a RAW command frame task context.
257 * @task_context: This parameter specifies the SCU specific task context buffer
258 * to construct.
259 *
260 * This method performs the operations common to all SATA/STP requests
261 * utilizing the raw frame method. none
262 */
Dan Williams35173d52011-03-26 16:43:01 -0700263static void scu_stp_raw_request_construct_task_context(
Dan Williams827a84d2011-05-07 15:59:09 -0700264 struct scic_sds_stp_request *stp_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700265 struct scu_task_context *task_context)
266{
Dan Williams827a84d2011-05-07 15:59:09 -0700267 struct scic_sds_request *sci_req = to_sci_req(stp_req);
268
269 scu_sata_reqeust_construct_task_context(sci_req, task_context);
Dan Williams6f231dd2011-07-02 22:56:22 -0700270
271 task_context->control_frame = 0;
272 task_context->priority = SCU_TASK_PRIORITY_NORMAL;
273 task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME;
Dave Jiange76d6182011-05-04 15:02:03 -0700274 task_context->type.stp.fis_type = FIS_REGH2D;
Dan Williams827a84d2011-05-07 15:59:09 -0700275 task_context->transfer_length_bytes = sizeof(struct host_to_dev_fis) - sizeof(u32);
Dan Williams6f231dd2011-07-02 22:56:22 -0700276}
277
Dan Williams6f231dd2011-07-02 22:56:22 -0700278void scic_stp_io_request_set_ncq_tag(
279 struct scic_sds_request *req,
280 u16 ncq_tag)
281{
282 /**
283 * @note This could be made to return an error to the user if the user
284 * attempts to set the NCQ tag in the wrong state.
285 */
286 req->task_context_buffer->type.stp.ncq_tag = ncq_tag;
287}
288
Dan Williams6f231dd2011-07-02 22:56:22 -0700289/**
290 *
Dave Jiange2023b82011-04-21 05:34:49 +0000291 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -0700292 *
293 * Get the next SGL element from the request. - Check on which SGL element pair
294 * we are working - if working on SLG pair element A - advance to element B -
295 * else - check to see if there are more SGL element pairs for this IO request
296 * - if there are more SGL element pairs - advance to the next pair and return
297 * element A struct scu_sgl_element*
298 */
Dan Williams35173d52011-03-26 16:43:01 -0700299static struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(struct scic_sds_stp_request *stp_req)
Dave Jiang103a00c2011-02-23 15:57:24 -0800300{
Dan Williams6f231dd2011-07-02 22:56:22 -0700301 struct scu_sgl_element *current_sgl;
Dan Williams827a84d2011-05-07 15:59:09 -0700302 struct scic_sds_request *sci_req = to_sci_req(stp_req);
Dave Jiang103a00c2011-02-23 15:57:24 -0800303 struct scic_sds_request_pio_sgl *pio_sgl = &stp_req->type.pio.request_current;
Dan Williams6f231dd2011-07-02 22:56:22 -0700304
Dave Jiang103a00c2011-02-23 15:57:24 -0800305 if (pio_sgl->sgl_set == SCU_SGL_ELEMENT_PAIR_A) {
306 if (pio_sgl->sgl_pair->B.address_lower == 0 &&
307 pio_sgl->sgl_pair->B.address_upper == 0) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700308 current_sgl = NULL;
309 } else {
Dave Jiang103a00c2011-02-23 15:57:24 -0800310 pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_B;
311 current_sgl = &pio_sgl->sgl_pair->B;
Dan Williams6f231dd2011-07-02 22:56:22 -0700312 }
313 } else {
Dave Jiang103a00c2011-02-23 15:57:24 -0800314 if (pio_sgl->sgl_pair->next_pair_lower == 0 &&
315 pio_sgl->sgl_pair->next_pair_upper == 0) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700316 current_sgl = NULL;
317 } else {
Dave Jiang103a00c2011-02-23 15:57:24 -0800318 u64 phys_addr;
Dan Williams6f231dd2011-07-02 22:56:22 -0700319
Dave Jiang103a00c2011-02-23 15:57:24 -0800320 phys_addr = pio_sgl->sgl_pair->next_pair_upper;
321 phys_addr <<= 32;
322 phys_addr |= pio_sgl->sgl_pair->next_pair_lower;
Dan Williams6f231dd2011-07-02 22:56:22 -0700323
Dave Jiang103a00c2011-02-23 15:57:24 -0800324 pio_sgl->sgl_pair = scic_request_get_virt_addr(sci_req, phys_addr);
325 pio_sgl->sgl_set = SCU_SGL_ELEMENT_PAIR_A;
326 current_sgl = &pio_sgl->sgl_pair->A;
Dan Williams6f231dd2011-07-02 22:56:22 -0700327 }
328 }
329
330 return current_sgl;
331}
332
333/**
334 *
Dave Jiange2023b82011-04-21 05:34:49 +0000335 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -0700336 * @completion_code:
337 *
338 * This method processes a TC completion. The expected TC completion is for
339 * the transmission of the H2D register FIS containing the SATA/STP non-data
340 * request. This method always successfully processes the TC completion.
341 * SCI_SUCCESS This value is always returned.
342 */
343static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000344 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700345 u32 completion_code)
346{
347 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
348 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
349 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +0000350 sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS
Dan Williams6f231dd2011-07-02 22:56:22 -0700351 );
352
353 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000354 &sci_req->started_substate_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700355 SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
356 );
357 break;
358
359 default:
360 /*
361 * All other completion status cause the IO to be complete. If a NAK
362 * was received, then it is up to the user to retry the request. */
363 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +0000364 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700365 SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
366 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
367 );
368
369 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000370 &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED);
Dan Williams6f231dd2011-07-02 22:56:22 -0700371 break;
372 }
373
374 return SCI_SUCCESS;
375}
376
377/**
378 *
379 * @request: This parameter specifies the request for which a frame has been
380 * received.
381 * @frame_index: This parameter specifies the index of the frame that has been
382 * received.
383 *
384 * This method processes frames received from the target while waiting for a
385 * device to host register FIS. If a non-register FIS is received during this
386 * time, it is treated as a protocol violation from an IO perspective. Indicate
387 * if the received frame was processed successfully.
388 */
389static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler(
Dave Jiange76d6182011-05-04 15:02:03 -0700390 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700391 u32 frame_index)
392{
393 enum sci_status status;
Dave Jiange76d6182011-05-04 15:02:03 -0700394 struct dev_to_host_fis *frame_header;
Dan Williams6f231dd2011-07-02 22:56:22 -0700395 u32 *frame_buffer;
Dan Williams827a84d2011-05-07 15:59:09 -0700396 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
397 struct scic_sds_controller *scic = sci_req->owning_controller;
Dan Williams6f231dd2011-07-02 22:56:22 -0700398
Dan Williams827a84d2011-05-07 15:59:09 -0700399 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
400 frame_index,
401 (void **)&frame_header);
Dan Williams6f231dd2011-07-02 22:56:22 -0700402
Dan Williams827a84d2011-05-07 15:59:09 -0700403 if (status != SCI_SUCCESS) {
Dave Jiange76d6182011-05-04 15:02:03 -0700404 dev_err(scic_to_dev(sci_req->owning_controller),
Dan Williams6f231dd2011-07-02 22:56:22 -0700405 "%s: SCIC IO Request 0x%p could not get frame header "
406 "for frame index %d, status %x\n",
Dave Jiange76d6182011-05-04 15:02:03 -0700407 __func__, stp_req, frame_index, status);
Dan Williams6f231dd2011-07-02 22:56:22 -0700408
Dan Williams827a84d2011-05-07 15:59:09 -0700409 return status;
410 }
411
412 switch (frame_header->fis_type) {
413 case FIS_REGD2H:
414 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
415 frame_index,
416 (void **)&frame_buffer);
417
Dan Williamsb7645812011-05-08 02:35:32 -0700418 scic_sds_controller_copy_sata_response(&sci_req->stp.rsp,
Dan Williams827a84d2011-05-07 15:59:09 -0700419 frame_header,
420 frame_buffer);
421
422 /* The command has completed with error */
423 scic_sds_request_set_status(sci_req, SCU_TASK_DONE_CHECK_RESPONSE,
424 SCI_FAILURE_IO_RESPONSE_VALID);
425 break;
426
427 default:
428 dev_warn(scic_to_dev(scic),
429 "%s: IO Request:0x%p Frame Id:%d protocol "
430 "violation occurred\n", __func__, stp_req,
431 frame_index);
432
433 scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS,
434 SCI_FAILURE_PROTOCOL_VIOLATION);
435 break;
436 }
437
438 sci_base_state_machine_change_state(&sci_req->state_machine,
439 SCI_BASE_REQUEST_STATE_COMPLETED);
440
441 /* Frame has been decoded return it to the controller */
442 scic_sds_controller_release_frame(scic, frame_index);
443
Dan Williams6f231dd2011-07-02 22:56:22 -0700444 return status;
445}
446
447/* --------------------------------------------------------------------------- */
448
Dan Williams35173d52011-03-26 16:43:01 -0700449static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -0700450 [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -0400451 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -0400452 .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700453 },
454 [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -0400455 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -0400456 .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -0700457 }
458};
459
460static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000461 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700462{
Maciej Patelczyk890cae92011-04-28 22:06:31 +0000463 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700464
465 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +0000466 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700467 scic_sds_stp_request_started_non_data_substate_handler_table,
468 SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE
469 );
470
471 scic_sds_remote_device_set_working_request(
Dave Jiange2023b82011-04-21 05:34:49 +0000472 sci_req->target_device, sci_req
Dan Williams6f231dd2011-07-02 22:56:22 -0700473 );
474}
475
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +0000476static void scic_sds_stp_request_started_non_data_await_d2h_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -0700477{
Maciej Patelczyk890cae92011-04-28 22:06:31 +0000478 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -0700479
480 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +0000481 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700482 scic_sds_stp_request_started_non_data_substate_handler_table,
483 SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE
484 );
485}
486
487/* --------------------------------------------------------------------------- */
488
Dan Williams35173d52011-03-26 16:43:01 -0700489static const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -0700490 [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = {
491 .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter,
492 },
493 [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = {
494 .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter,
495 },
496};
497
Dan Williams35173d52011-03-26 16:43:01 -0700498enum sci_status scic_sds_stp_non_data_request_construct(struct scic_sds_request *sci_req)
499{
Dan Williams827a84d2011-05-07 15:59:09 -0700500 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
Dan Williams35173d52011-03-26 16:43:01 -0700501
502 scic_sds_stp_non_ncq_request_construct(sci_req);
503
504 /* Build the STP task context structure */
505 scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer);
506
507 sci_base_state_machine_construct(&sci_req->started_substate_machine,
Maciej Patelczyk890cae92011-04-28 22:06:31 +0000508 sci_req,
Dan Williams35173d52011-03-26 16:43:01 -0700509 scic_sds_stp_request_started_non_data_substate_table,
510 SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE);
511
512 return SCI_SUCCESS;
513}
514
Dan Williams6f231dd2011-07-02 22:56:22 -0700515#define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */
516
Dan Williams827a84d2011-05-07 15:59:09 -0700517/* transmit DATA_FIS from (current sgl + offset) for input
Dan Williams6f231dd2011-07-02 22:56:22 -0700518 * parameter length. current sgl and offset is alreay stored in the IO request
Dan Williams6f231dd2011-07-02 22:56:22 -0700519 */
Dan Williams6f231dd2011-07-02 22:56:22 -0700520static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame(
Dave Jiange2023b82011-04-21 05:34:49 +0000521 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700522 u32 length)
523{
Dan Williams827a84d2011-05-07 15:59:09 -0700524 struct scic_sds_controller *scic = sci_req->owning_controller;
525 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
526 struct scu_task_context *task_context;
Dan Williams6f231dd2011-07-02 22:56:22 -0700527 struct scu_sgl_element *current_sgl;
Dan Williams6f231dd2011-07-02 22:56:22 -0700528
Dan Williams827a84d2011-05-07 15:59:09 -0700529 /* Recycle the TC and reconstruct it for sending out DATA FIS containing
530 * for the data from current_sgl+offset for the input length
531 */
532 task_context = scic_sds_controller_get_task_context_buffer(scic,
533 sci_req->io_tag);
Dan Williams6f231dd2011-07-02 22:56:22 -0700534
Dave Jiange2023b82011-04-21 05:34:49 +0000535 if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A)
Dan Williams827a84d2011-05-07 15:59:09 -0700536 current_sgl = &stp_req->type.pio.request_current.sgl_pair->A;
Dan Williams6f231dd2011-07-02 22:56:22 -0700537 else
Dan Williams827a84d2011-05-07 15:59:09 -0700538 current_sgl = &stp_req->type.pio.request_current.sgl_pair->B;
Dan Williams6f231dd2011-07-02 22:56:22 -0700539
540 /* update the TC */
541 task_context->command_iu_upper = current_sgl->address_upper;
542 task_context->command_iu_lower = current_sgl->address_lower;
543 task_context->transfer_length_bytes = length;
Dave Jiange76d6182011-05-04 15:02:03 -0700544 task_context->type.stp.fis_type = FIS_DATA;
Dan Williams6f231dd2011-07-02 22:56:22 -0700545
546 /* send the new TC out. */
Dave Jiange2023b82011-04-21 05:34:49 +0000547 return scic_controller_continue_io(sci_req);
Dan Williams6f231dd2011-07-02 22:56:22 -0700548}
549
Dan Williams827a84d2011-05-07 15:59:09 -0700550static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data(struct scic_sds_request *sci_req)
Dan Williams6f231dd2011-07-02 22:56:22 -0700551{
552
553 struct scu_sgl_element *current_sgl;
554 u32 sgl_offset;
555 u32 remaining_bytes_in_current_sgl = 0;
556 enum sci_status status = SCI_SUCCESS;
Dan Williams827a84d2011-05-07 15:59:09 -0700557 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
Dan Williams6f231dd2011-07-02 22:56:22 -0700558
Dave Jiange2023b82011-04-21 05:34:49 +0000559 sgl_offset = stp_req->type.pio.request_current.sgl_offset;
Dan Williams6f231dd2011-07-02 22:56:22 -0700560
Dave Jiange2023b82011-04-21 05:34:49 +0000561 if (stp_req->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) {
562 current_sgl = &(stp_req->type.pio.request_current.sgl_pair->A);
563 remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->A.length - sgl_offset;
Dan Williams6f231dd2011-07-02 22:56:22 -0700564 } else {
Dave Jiange2023b82011-04-21 05:34:49 +0000565 current_sgl = &(stp_req->type.pio.request_current.sgl_pair->B);
566 remaining_bytes_in_current_sgl = stp_req->type.pio.request_current.sgl_pair->B.length - sgl_offset;
Dan Williams6f231dd2011-07-02 22:56:22 -0700567 }
568
569
Dave Jiange2023b82011-04-21 05:34:49 +0000570 if (stp_req->type.pio.pio_transfer_bytes > 0) {
571 if (stp_req->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700572 /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */
Dave Jiange2023b82011-04-21 05:34:49 +0000573 status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, remaining_bytes_in_current_sgl);
Dan Williams6f231dd2011-07-02 22:56:22 -0700574 if (status == SCI_SUCCESS) {
Dave Jiange2023b82011-04-21 05:34:49 +0000575 stp_req->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl;
Dan Williams6f231dd2011-07-02 22:56:22 -0700576
577 /* update the current sgl, sgl_offset and save for future */
Dave Jiange2023b82011-04-21 05:34:49 +0000578 current_sgl = scic_sds_stp_request_pio_get_next_sgl(stp_req);
Dan Williams6f231dd2011-07-02 22:56:22 -0700579 sgl_offset = 0;
580 }
Dave Jiange2023b82011-04-21 05:34:49 +0000581 } else if (stp_req->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700582 /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */
Dave Jiange2023b82011-04-21 05:34:49 +0000583 scic_sds_stp_request_pio_data_out_trasmit_data_frame(sci_req, stp_req->type.pio.pio_transfer_bytes);
Dan Williams6f231dd2011-07-02 22:56:22 -0700584
585 if (status == SCI_SUCCESS) {
586 /* Sgl offset will be adjusted and saved for future */
Dave Jiange2023b82011-04-21 05:34:49 +0000587 sgl_offset += stp_req->type.pio.pio_transfer_bytes;
588 current_sgl->address_lower += stp_req->type.pio.pio_transfer_bytes;
589 stp_req->type.pio.pio_transfer_bytes = 0;
Dan Williams6f231dd2011-07-02 22:56:22 -0700590 }
591 }
592 }
593
594 if (status == SCI_SUCCESS) {
Dave Jiange2023b82011-04-21 05:34:49 +0000595 stp_req->type.pio.request_current.sgl_offset = sgl_offset;
Dan Williams6f231dd2011-07-02 22:56:22 -0700596 }
597
598 return status;
599}
600
601/**
602 *
Dave Jiang103a00c2011-02-23 15:57:24 -0800603 * @stp_request: The request that is used for the SGL processing.
Dan Williams6f231dd2011-07-02 22:56:22 -0700604 * @data_buffer: The buffer of data to be copied.
605 * @length: The length of the data transfer.
606 *
607 * Copy the data from the buffer for the length specified to the IO reqeust SGL
608 * specified data region. enum sci_status
609 */
Dave Jiang103a00c2011-02-23 15:57:24 -0800610static enum sci_status
611scic_sds_stp_request_pio_data_in_copy_data_buffer(struct scic_sds_stp_request *stp_req,
612 u8 *data_buf, u32 len)
Dan Williams6f231dd2011-07-02 22:56:22 -0700613{
Dave Jiang103a00c2011-02-23 15:57:24 -0800614 struct scic_sds_request *sci_req;
615 struct isci_request *ireq;
616 u8 *src_addr;
617 int copy_len;
618 struct sas_task *task;
619 struct scatterlist *sg;
620 void *kaddr;
621 int total_len = len;
Dan Williams6f231dd2011-07-02 22:56:22 -0700622
Dan Williams827a84d2011-05-07 15:59:09 -0700623 sci_req = to_sci_req(stp_req);
Dan Williams67ea8382011-05-08 11:47:15 -0700624 ireq = sci_req_to_ireq(sci_req);
Dave Jiang103a00c2011-02-23 15:57:24 -0800625 task = isci_request_access_task(ireq);
626 src_addr = data_buf;
Dan Williams6f231dd2011-07-02 22:56:22 -0700627
Dave Jiang103a00c2011-02-23 15:57:24 -0800628 if (task->num_scatter > 0) {
629 sg = task->scatter;
Dan Williams6f231dd2011-07-02 22:56:22 -0700630
Dave Jiang103a00c2011-02-23 15:57:24 -0800631 while (total_len > 0) {
632 struct page *page = sg_page(sg);
Dan Williams6f231dd2011-07-02 22:56:22 -0700633
Dave Jiang103a00c2011-02-23 15:57:24 -0800634 copy_len = min_t(int, total_len, sg_dma_len(sg));
635 kaddr = kmap_atomic(page, KM_IRQ0);
636 memcpy(kaddr + sg->offset, src_addr, copy_len);
637 kunmap_atomic(kaddr, KM_IRQ0);
638 total_len -= copy_len;
639 src_addr += copy_len;
640 sg = sg_next(sg);
Dan Williams6f231dd2011-07-02 22:56:22 -0700641 }
Dave Jiang103a00c2011-02-23 15:57:24 -0800642 } else {
643 BUG_ON(task->total_xfer_len < total_len);
644 memcpy(task->scatter, src_addr, total_len);
Dan Williams6f231dd2011-07-02 22:56:22 -0700645 }
646
Dave Jiang103a00c2011-02-23 15:57:24 -0800647 return SCI_SUCCESS;
Dan Williams6f231dd2011-07-02 22:56:22 -0700648}
649
650/**
651 *
Dave Jiange2023b82011-04-21 05:34:49 +0000652 * @sci_req: The PIO DATA IN request that is to receive the data.
Dan Williams6f231dd2011-07-02 22:56:22 -0700653 * @data_buffer: The buffer to copy from.
654 *
655 * Copy the data buffer to the io request data region. enum sci_status
656 */
657static enum sci_status scic_sds_stp_request_pio_data_in_copy_data(
Dave Jiange2023b82011-04-21 05:34:49 +0000658 struct scic_sds_stp_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700659 u8 *data_buffer)
660{
661 enum sci_status status;
662
663 /*
664 * If there is less than 1K remaining in the transfer request
665 * copy just the data for the transfer */
Dave Jiange2023b82011-04-21 05:34:49 +0000666 if (sci_req->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700667 status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
Dave Jiange2023b82011-04-21 05:34:49 +0000668 sci_req, data_buffer, sci_req->type.pio.pio_transfer_bytes);
Dan Williams6f231dd2011-07-02 22:56:22 -0700669
670 if (status == SCI_SUCCESS)
Dave Jiange2023b82011-04-21 05:34:49 +0000671 sci_req->type.pio.pio_transfer_bytes = 0;
Dan Williams6f231dd2011-07-02 22:56:22 -0700672 } else {
673 /* We are transfering the whole frame so copy */
674 status = scic_sds_stp_request_pio_data_in_copy_data_buffer(
Dave Jiange2023b82011-04-21 05:34:49 +0000675 sci_req, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE);
Dan Williams6f231dd2011-07-02 22:56:22 -0700676
677 if (status == SCI_SUCCESS)
Dave Jiange2023b82011-04-21 05:34:49 +0000678 sci_req->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE;
Dan Williams6f231dd2011-07-02 22:56:22 -0700679 }
680
681 return status;
682}
683
684/**
685 *
Dave Jiange2023b82011-04-21 05:34:49 +0000686 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -0700687 * @completion_code:
688 *
689 * enum sci_status
690 */
691static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler(
Dave Jiange2023b82011-04-21 05:34:49 +0000692 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700693 u32 completion_code)
694{
695 enum sci_status status = SCI_SUCCESS;
696
697 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
698 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
699 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +0000700 sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS
Dan Williams6f231dd2011-07-02 22:56:22 -0700701 );
702
703 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000704 &sci_req->started_substate_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700705 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
706 );
707 break;
708
709 default:
710 /*
711 * All other completion status cause the IO to be complete. If a NAK
712 * was received, then it is up to the user to retry the request. */
713 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +0000714 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700715 SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
716 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
717 );
718
719 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000720 &sci_req->state_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700721 SCI_BASE_REQUEST_STATE_COMPLETED
722 );
723 break;
724 }
725
726 return status;
727}
728
Dan Williams827a84d2011-05-07 15:59:09 -0700729static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler(struct scic_sds_request *sci_req,
730 u32 frame_index)
Dan Williams6f231dd2011-07-02 22:56:22 -0700731{
Dan Williams827a84d2011-05-07 15:59:09 -0700732 struct scic_sds_controller *scic = sci_req->owning_controller;
733 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
Dan Williams67ea8382011-05-08 11:47:15 -0700734 struct isci_request *ireq = sci_req_to_ireq(sci_req);
Dave Jiange76d6182011-05-04 15:02:03 -0700735 struct sas_task *task = isci_request_access_task(ireq);
Dan Williams827a84d2011-05-07 15:59:09 -0700736 struct dev_to_host_fis *frame_header;
737 enum sci_status status;
738 u32 *frame_buffer;
Dan Williams6f231dd2011-07-02 22:56:22 -0700739
Dan Williams827a84d2011-05-07 15:59:09 -0700740 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
741 frame_index,
742 (void **)&frame_header);
Dan Williams6f231dd2011-07-02 22:56:22 -0700743
Dan Williams827a84d2011-05-07 15:59:09 -0700744 if (status != SCI_SUCCESS) {
745 dev_err(scic_to_dev(scic),
Dan Williams6f231dd2011-07-02 22:56:22 -0700746 "%s: SCIC IO Request 0x%p could not get frame header "
747 "for frame index %d, status %x\n",
Dave Jiange76d6182011-05-04 15:02:03 -0700748 __func__, stp_req, frame_index, status);
Dan Williams827a84d2011-05-07 15:59:09 -0700749 return status;
750 }
751
752 switch (frame_header->fis_type) {
753 case FIS_PIO_SETUP:
754 /* Get from the frame buffer the PIO Setup Data */
755 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
756 frame_index,
757 (void **)&frame_buffer);
758
759 /* Get the data from the PIO Setup The SCU Hardware returns
760 * first word in the frame_header and the rest of the data is in
761 * the frame buffer so we need to back up one dword
762 */
763
764 /* transfer_count: first 16bits in the 4th dword */
765 stp_req->type.pio.pio_transfer_bytes = frame_buffer[3] & 0xffff;
766
767 /* ending_status: 4th byte in the 3rd dword */
768 stp_req->type.pio.ending_status = (frame_buffer[2] >> 24) & 0xff;
769
Dan Williamsb7645812011-05-08 02:35:32 -0700770 scic_sds_controller_copy_sata_response(&sci_req->stp.rsp,
Dan Williams827a84d2011-05-07 15:59:09 -0700771 frame_header,
772 frame_buffer);
773
Dan Williamsb7645812011-05-08 02:35:32 -0700774 sci_req->stp.rsp.status = stp_req->type.pio.ending_status;
Dan Williams827a84d2011-05-07 15:59:09 -0700775
776 /* The next state is dependent on whether the
777 * request was PIO Data-in or Data out
778 */
779 if (task->data_dir == DMA_FROM_DEVICE) {
780 sci_base_state_machine_change_state(&sci_req->started_substate_machine,
781 SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE);
782 } else if (task->data_dir == DMA_TO_DEVICE) {
783 /* Transmit data */
784 status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req);
785 if (status != SCI_SUCCESS)
786 break;
787 sci_base_state_machine_change_state(&sci_req->started_substate_machine,
788 SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE);
789 }
790 break;
791 case FIS_SETDEVBITS:
792 sci_base_state_machine_change_state(&sci_req->started_substate_machine,
793 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE);
794 break;
795 case FIS_REGD2H:
796 if (frame_header->status & ATA_BUSY) {
797 /* Now why is the drive sending a D2H Register FIS when
798 * it is still busy? Do nothing since we are still in
799 * the right state.
800 */
801 dev_dbg(scic_to_dev(scic),
802 "%s: SCIC PIO Request 0x%p received "
803 "D2H Register FIS with BSY status "
804 "0x%x\n", __func__, stp_req,
805 frame_header->status);
806 break;
807 }
808
809 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
810 frame_index,
811 (void **)&frame_buffer);
812
Dan Williamsb7645812011-05-08 02:35:32 -0700813 scic_sds_controller_copy_sata_response(&sci_req->stp.req,
Dan Williams827a84d2011-05-07 15:59:09 -0700814 frame_header,
815 frame_buffer);
816
817 scic_sds_request_set_status(sci_req,
818 SCU_TASK_DONE_CHECK_RESPONSE,
819 SCI_FAILURE_IO_RESPONSE_VALID);
820
821 sci_base_state_machine_change_state(&sci_req->state_machine,
822 SCI_BASE_REQUEST_STATE_COMPLETED);
823 break;
824 default:
825 /* FIXME: what do we do here? */
826 break;
827 }
828
829 /* Frame is decoded return it to the controller */
830 scic_sds_controller_release_frame(scic, frame_index);
Dan Williams6f231dd2011-07-02 22:56:22 -0700831
832 return status;
833}
834
Dan Williams827a84d2011-05-07 15:59:09 -0700835static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler(struct scic_sds_request *sci_req,
836 u32 frame_index)
Dan Williams6f231dd2011-07-02 22:56:22 -0700837{
838 enum sci_status status;
Dave Jiange76d6182011-05-04 15:02:03 -0700839 struct dev_to_host_fis *frame_header;
Dan Williams6f231dd2011-07-02 22:56:22 -0700840 struct sata_fis_data *frame_buffer;
Dan Williams827a84d2011-05-07 15:59:09 -0700841 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
842 struct scic_sds_controller *scic = sci_req->owning_controller;
Dan Williams6f231dd2011-07-02 22:56:22 -0700843
Dan Williams827a84d2011-05-07 15:59:09 -0700844 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
845 frame_index,
846 (void **)&frame_header);
Dan Williams6f231dd2011-07-02 22:56:22 -0700847
Dan Williams827a84d2011-05-07 15:59:09 -0700848 if (status != SCI_SUCCESS) {
849 dev_err(scic_to_dev(scic),
Dan Williams6f231dd2011-07-02 22:56:22 -0700850 "%s: SCIC IO Request 0x%p could not get frame header "
851 "for frame index %d, status %x\n",
Dave Jiange76d6182011-05-04 15:02:03 -0700852 __func__, stp_req, frame_index, status);
Dan Williams827a84d2011-05-07 15:59:09 -0700853 return status;
854 }
855
856 if (frame_header->fis_type == FIS_DATA) {
857 if (stp_req->type.pio.request_current.sgl_pair == NULL) {
858 sci_req->saved_rx_frame_index = frame_index;
859 stp_req->type.pio.pio_transfer_bytes = 0;
860 } else {
861 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
862 frame_index,
863 (void **)&frame_buffer);
864
865 status = scic_sds_stp_request_pio_data_in_copy_data(stp_req,
866 (u8 *)frame_buffer);
867
868 /* Frame is decoded return it to the controller */
869 scic_sds_controller_release_frame(scic, frame_index);
870 }
871
872 /* Check for the end of the transfer, are there more
873 * bytes remaining for this data transfer
874 */
875 if (status != SCI_SUCCESS ||
876 stp_req->type.pio.pio_transfer_bytes != 0)
877 return status;
878
879 if ((stp_req->type.pio.ending_status & ATA_BUSY) == 0) {
880 scic_sds_request_set_status(sci_req,
881 SCU_TASK_DONE_CHECK_RESPONSE,
882 SCI_FAILURE_IO_RESPONSE_VALID);
883
884 sci_base_state_machine_change_state(&sci_req->state_machine,
885 SCI_BASE_REQUEST_STATE_COMPLETED);
886 } else {
887 sci_base_state_machine_change_state(&sci_req->started_substate_machine,
888 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE);
889 }
890 } else {
891 dev_err(scic_to_dev(scic),
892 "%s: SCIC PIO Request 0x%p received frame %d "
893 "with fis type 0x%02x when expecting a data "
894 "fis.\n", __func__, stp_req, frame_index,
895 frame_header->fis_type);
896
897 scic_sds_request_set_status(sci_req,
898 SCU_TASK_DONE_GOOD,
899 SCI_FAILURE_IO_REQUIRES_SCSI_ABORT);
900
901 sci_base_state_machine_change_state(&sci_req->state_machine,
902 SCI_BASE_REQUEST_STATE_COMPLETED);
903
904 /* Frame is decoded return it to the controller */
905 scic_sds_controller_release_frame(scic, frame_index);
906 }
Dan Williams6f231dd2011-07-02 22:56:22 -0700907
908 return status;
909}
910
911
912/**
913 *
Dave Jiange2023b82011-04-21 05:34:49 +0000914 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -0700915 * @completion_code:
916 *
917 * enum sci_status
918 */
919static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler(
920
Dave Jiange2023b82011-04-21 05:34:49 +0000921 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700922 u32 completion_code)
923{
Dave Jiange76d6182011-05-04 15:02:03 -0700924 enum sci_status status = SCI_SUCCESS;
925 bool all_frames_transferred = false;
Dan Williams827a84d2011-05-07 15:59:09 -0700926 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
Dan Williams6f231dd2011-07-02 22:56:22 -0700927
928 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
929 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
930 /* Transmit data */
Dave Jiange2023b82011-04-21 05:34:49 +0000931 if (stp_req->type.pio.pio_transfer_bytes != 0) {
932 status = scic_sds_stp_request_pio_data_out_transmit_data(sci_req);
Dan Williams6f231dd2011-07-02 22:56:22 -0700933 if (status == SCI_SUCCESS) {
Dave Jiange2023b82011-04-21 05:34:49 +0000934 if (stp_req->type.pio.pio_transfer_bytes == 0)
Dan Williams6f231dd2011-07-02 22:56:22 -0700935 all_frames_transferred = true;
936 }
Dave Jiange2023b82011-04-21 05:34:49 +0000937 } else if (stp_req->type.pio.pio_transfer_bytes == 0) {
Dan Williams6f231dd2011-07-02 22:56:22 -0700938 /*
939 * this will happen if the all data is written at the
940 * first time after the pio setup fis is received
941 */
942 all_frames_transferred = true;
943 }
944
945 /* all data transferred. */
946 if (all_frames_transferred) {
947 /*
948 * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE
949 * and wait for PIO_SETUP fis / or D2H REg fis. */
950 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000951 &sci_req->started_substate_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700952 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
953 );
954 }
955 break;
956
957 default:
958 /*
959 * All other completion status cause the IO to be complete. If a NAK
960 * was received, then it is up to the user to retry the request. */
961 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +0000962 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -0700963 SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
964 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
965 );
966
967 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +0000968 &sci_req->state_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -0700969 SCI_BASE_REQUEST_STATE_COMPLETED
970 );
971 break;
972 }
973
974 return status;
975}
976
977/**
978 *
979 * @request: This is the request which is receiving the event.
980 * @event_code: This is the event code that the request on which the request is
981 * expected to take action.
982 *
983 * This method will handle any link layer events while waiting for the data
984 * frame. enum sci_status SCI_SUCCESS SCI_FAILURE
985 */
986static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler(
987 struct scic_sds_request *request,
988 u32 event_code)
989{
990 enum sci_status status;
991
992 switch (scu_get_event_specifier(event_code)) {
993 case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT:
994 /*
995 * We are waiting for data and the SCU has R_ERR the data frame.
996 * Go back to waiting for the D2H Register FIS */
997 sci_base_state_machine_change_state(
998 &request->started_substate_machine,
999 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1000 );
1001
1002 status = SCI_SUCCESS;
1003 break;
1004
1005 default:
1006 dev_err(scic_to_dev(request->owning_controller),
1007 "%s: SCIC PIO Request 0x%p received unexpected "
1008 "event 0x%08x\n",
1009 __func__, request, event_code);
1010
1011 /* / @todo Should we fail the PIO request when we get an unexpected event? */
1012 status = SCI_FAILURE;
1013 break;
1014 }
1015
1016 return status;
1017}
1018
1019/* --------------------------------------------------------------------------- */
1020
Dan Williams35173d52011-03-26 16:43:01 -07001021static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -07001022 [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001023 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001024 .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001025 },
1026 [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001027 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001028 .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler
Dan Williams6f231dd2011-07-02 22:56:22 -07001029 },
1030 [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001031 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001032 .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler,
1033 .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler
Dan Williams6f231dd2011-07-02 22:56:22 -07001034 },
1035 [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001036 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001037 .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001038 }
1039};
1040
1041static void scic_sds_stp_request_started_pio_await_h2d_completion_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001042 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001043{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001044 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001045
1046 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001047 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001048 scic_sds_stp_request_started_pio_substate_handler_table,
1049 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE
1050 );
1051
1052 scic_sds_remote_device_set_working_request(
Dave Jiange2023b82011-04-21 05:34:49 +00001053 sci_req->target_device, sci_req);
Dan Williams6f231dd2011-07-02 22:56:22 -07001054}
1055
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001056static void scic_sds_stp_request_started_pio_await_frame_enter(void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001057{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001058 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001059
1060 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001061 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001062 scic_sds_stp_request_started_pio_substate_handler_table,
1063 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE
1064 );
1065}
1066
1067static void scic_sds_stp_request_started_pio_data_in_await_data_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001068 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001069{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001070 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001071
1072 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001073 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001074 scic_sds_stp_request_started_pio_substate_handler_table,
1075 SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE
1076 );
1077}
1078
1079static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001080 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001081{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001082 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001083
1084 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001085 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001086 scic_sds_stp_request_started_pio_substate_handler_table,
1087 SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE
1088 );
1089}
1090
1091/* --------------------------------------------------------------------------- */
1092
Dan Williams35173d52011-03-26 16:43:01 -07001093static const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -07001094 [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = {
1095 .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter,
1096 },
1097 [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = {
1098 .enter_state = scic_sds_stp_request_started_pio_await_frame_enter,
1099 },
1100 [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = {
1101 .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter,
1102 },
1103 [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = {
1104 .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter,
1105 }
1106};
1107
Dave Jiange76d6182011-05-04 15:02:03 -07001108enum sci_status
1109scic_sds_stp_pio_request_construct(struct scic_sds_request *sci_req,
1110 bool copy_rx_frame)
Dan Williams35173d52011-03-26 16:43:01 -07001111{
Dan Williams827a84d2011-05-07 15:59:09 -07001112 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
Dan Williams35173d52011-03-26 16:43:01 -07001113 struct scic_sds_stp_pio_request *pio = &stp_req->type.pio;
1114
1115 scic_sds_stp_non_ncq_request_construct(sci_req);
1116
1117 scu_stp_raw_request_construct_task_context(stp_req,
1118 sci_req->task_context_buffer);
1119
1120 pio->current_transfer_bytes = 0;
1121 pio->ending_error = 0;
1122 pio->ending_status = 0;
1123
1124 pio->request_current.sgl_offset = 0;
1125 pio->request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A;
Dan Williams35173d52011-03-26 16:43:01 -07001126
1127 if (copy_rx_frame) {
1128 scic_sds_request_build_sgl(sci_req);
1129 /* Since the IO request copy of the TC contains the same data as
1130 * the actual TC this pointer is vaild for either.
1131 */
1132 pio->request_current.sgl_pair = &sci_req->task_context_buffer->sgl_pair_ab;
1133 } else {
1134 /* The user does not want the data copied to the SGL buffer location */
1135 pio->request_current.sgl_pair = NULL;
1136 }
1137
1138 sci_base_state_machine_construct(&sci_req->started_substate_machine,
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001139 sci_req,
Dan Williams35173d52011-03-26 16:43:01 -07001140 scic_sds_stp_request_started_pio_substate_table,
1141 SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE);
1142
1143 return SCI_SUCCESS;
1144}
1145
Dan Williams6f231dd2011-07-02 22:56:22 -07001146static void scic_sds_stp_request_udma_complete_request(
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001147 struct scic_sds_request *request,
Dan Williams6f231dd2011-07-02 22:56:22 -07001148 u32 scu_status,
1149 enum sci_status sci_status)
1150{
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001151 scic_sds_request_set_status(request, scu_status, sci_status);
1152 sci_base_state_machine_change_state(&request->state_machine,
1153 SCI_BASE_REQUEST_STATE_COMPLETED);
Dan Williams6f231dd2011-07-02 22:56:22 -07001154}
1155
Dan Williams827a84d2011-05-07 15:59:09 -07001156static enum sci_status scic_sds_stp_request_udma_general_frame_handler(struct scic_sds_request *sci_req,
1157 u32 frame_index)
Dan Williams6f231dd2011-07-02 22:56:22 -07001158{
Dan Williams827a84d2011-05-07 15:59:09 -07001159 struct scic_sds_controller *scic = sci_req->owning_controller;
Dave Jiange76d6182011-05-04 15:02:03 -07001160 struct dev_to_host_fis *frame_header;
Dan Williams827a84d2011-05-07 15:59:09 -07001161 enum sci_status status;
Dan Williams6f231dd2011-07-02 22:56:22 -07001162 u32 *frame_buffer;
1163
Dan Williams827a84d2011-05-07 15:59:09 -07001164 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
1165 frame_index,
1166 (void **)&frame_header);
Dan Williams6f231dd2011-07-02 22:56:22 -07001167
Dave Jiange76d6182011-05-04 15:02:03 -07001168 if ((status == SCI_SUCCESS) &&
1169 (frame_header->fis_type == FIS_REGD2H)) {
Dan Williams827a84d2011-05-07 15:59:09 -07001170 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
1171 frame_index,
1172 (void **)&frame_buffer);
Dan Williams6f231dd2011-07-02 22:56:22 -07001173
Dan Williamsb7645812011-05-08 02:35:32 -07001174 scic_sds_controller_copy_sata_response(&sci_req->stp.rsp,
Dan Williams827a84d2011-05-07 15:59:09 -07001175 frame_header,
1176 frame_buffer);
Dan Williams6f231dd2011-07-02 22:56:22 -07001177 }
1178
Dan Williams827a84d2011-05-07 15:59:09 -07001179 scic_sds_controller_release_frame(scic, frame_index);
Dan Williams6f231dd2011-07-02 22:56:22 -07001180
1181 return status;
1182}
1183
Dan Williams6f231dd2011-07-02 22:56:22 -07001184static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler(
Dan Williams827a84d2011-05-07 15:59:09 -07001185 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001186 u32 completion_code)
1187{
1188 enum sci_status status = SCI_SUCCESS;
Dan Williams6f231dd2011-07-02 22:56:22 -07001189
1190 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
1191 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
Dan Williams827a84d2011-05-07 15:59:09 -07001192 scic_sds_stp_request_udma_complete_request(sci_req,
1193 SCU_TASK_DONE_GOOD,
1194 SCI_SUCCESS);
Dan Williams6f231dd2011-07-02 22:56:22 -07001195 break;
Dan Williams6f231dd2011-07-02 22:56:22 -07001196 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS):
1197 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR):
1198 /*
1199 * We must check ther response buffer to see if the D2H Register FIS was
1200 * received before we got the TC completion. */
Dan Williamsb7645812011-05-08 02:35:32 -07001201 if (sci_req->stp.rsp.fis_type == FIS_REGD2H) {
Dan Williams827a84d2011-05-07 15:59:09 -07001202 scic_sds_remote_device_suspend(sci_req->target_device,
1203 SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
Dan Williams6f231dd2011-07-02 22:56:22 -07001204
Dan Williams827a84d2011-05-07 15:59:09 -07001205 scic_sds_stp_request_udma_complete_request(sci_req,
1206 SCU_TASK_DONE_CHECK_RESPONSE,
1207 SCI_FAILURE_IO_RESPONSE_VALID);
Dan Williams6f231dd2011-07-02 22:56:22 -07001208 } else {
1209 /*
1210 * If we have an error completion status for the TC then we can expect a
1211 * D2H register FIS from the device so we must change state to wait for it */
Dan Williams827a84d2011-05-07 15:59:09 -07001212 sci_base_state_machine_change_state(&sci_req->started_substate_machine,
1213 SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE);
Dan Williams6f231dd2011-07-02 22:56:22 -07001214 }
1215 break;
1216
1217 /*
1218 * / @todo Check to see if any of these completion status need to wait for
1219 * / the device to host register fis. */
Tomasz Chudy52b957c2011-02-23 00:09:04 -08001220 /* / @todo We can retry the command for SCU_TASK_DONE_CMD_LL_R_ERR - this comes only for B0 */
Dan Williams6f231dd2011-07-02 22:56:22 -07001221 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN):
1222 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR):
1223 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR):
Tomasz Chudy52b957c2011-02-23 00:09:04 -08001224 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CMD_LL_R_ERR):
Dan Williams6f231dd2011-07-02 22:56:22 -07001225 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR):
Dan Williams827a84d2011-05-07 15:59:09 -07001226 scic_sds_remote_device_suspend(sci_req->target_device,
1227 SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)));
Dan Williams6f231dd2011-07-02 22:56:22 -07001228 /* Fall through to the default case */
1229 default:
1230 /* All other completion status cause the IO to be complete. */
Dan Williams827a84d2011-05-07 15:59:09 -07001231 scic_sds_stp_request_udma_complete_request(sci_req,
1232 SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1233 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR);
Dan Williams6f231dd2011-07-02 22:56:22 -07001234 break;
1235 }
1236
1237 return status;
1238}
1239
1240static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler(
Dave Jiange2023b82011-04-21 05:34:49 +00001241 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001242 u32 frame_index)
1243{
1244 enum sci_status status;
1245
1246 /* Use the general frame handler to copy the resposne data */
Dave Jiange2023b82011-04-21 05:34:49 +00001247 status = scic_sds_stp_request_udma_general_frame_handler(sci_req, frame_index);
Dan Williams6f231dd2011-07-02 22:56:22 -07001248
Dan Williams827a84d2011-05-07 15:59:09 -07001249 if (status != SCI_SUCCESS)
1250 return status;
1251
1252 scic_sds_stp_request_udma_complete_request(sci_req,
1253 SCU_TASK_DONE_CHECK_RESPONSE,
1254 SCI_FAILURE_IO_RESPONSE_VALID);
Dan Williams6f231dd2011-07-02 22:56:22 -07001255
1256 return status;
1257}
1258
1259/* --------------------------------------------------------------------------- */
1260
Dan Williams35173d52011-03-26 16:43:01 -07001261static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -07001262 [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001263 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001264 .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001265 .frame_handler = scic_sds_stp_request_udma_general_frame_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001266 },
1267 [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001268 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001269 .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001270 },
1271};
1272
1273static void scic_sds_stp_request_started_udma_await_tc_completion_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001274 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001275{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001276 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001277
1278 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001279 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001280 scic_sds_stp_request_started_udma_substate_handler_table,
1281 SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
1282 );
1283}
1284
1285/**
1286 *
1287 *
1288 * This state is entered when there is an TC completion failure. The hardware
1289 * received an unexpected condition while processing the IO request and now
1290 * will UF the D2H register FIS to complete the IO.
1291 */
1292static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001293 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001294{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001295 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001296
1297 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001298 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001299 scic_sds_stp_request_started_udma_substate_handler_table,
1300 SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE
1301 );
1302}
1303
1304/* --------------------------------------------------------------------------- */
1305
Dan Williams35173d52011-03-26 16:43:01 -07001306static const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -07001307 [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = {
1308 .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter,
1309 },
1310 [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = {
1311 .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter,
1312 },
1313};
1314
Dan Williams35173d52011-03-26 16:43:01 -07001315enum sci_status scic_sds_stp_udma_request_construct(struct scic_sds_request *sci_req,
1316 u32 len,
1317 enum dma_data_direction dir)
1318{
1319 scic_sds_stp_non_ncq_request_construct(sci_req);
1320
1321 scic_sds_stp_optimized_request_construct(sci_req, SCU_TASK_TYPE_DMA_IN,
1322 len, dir);
1323
1324 sci_base_state_machine_construct(
1325 &sci_req->started_substate_machine,
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001326 sci_req,
Dan Williams35173d52011-03-26 16:43:01 -07001327 scic_sds_stp_request_started_udma_substate_table,
1328 SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE
1329 );
1330
1331 return SCI_SUCCESS;
1332}
1333
Dan Williams6f231dd2011-07-02 22:56:22 -07001334/**
1335 *
Dave Jiange2023b82011-04-21 05:34:49 +00001336 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -07001337 * @completion_code:
1338 *
1339 * This method processes a TC completion. The expected TC completion is for
1340 * the transmission of the H2D register FIS containing the SATA/STP non-data
1341 * request. This method always successfully processes the TC completion.
1342 * SCI_SUCCESS This value is always returned.
1343 */
1344static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler(
Dave Jiange2023b82011-04-21 05:34:49 +00001345 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001346 u32 completion_code)
1347{
1348 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
1349 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1350 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +00001351 sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS
Dan Williams6f231dd2011-07-02 22:56:22 -07001352 );
1353
1354 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +00001355 &sci_req->started_substate_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -07001356 SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
1357 );
1358 break;
1359
1360 default:
1361 /*
1362 * All other completion status cause the IO to be complete. If a NAK
1363 * was received, then it is up to the user to retry the request. */
1364 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +00001365 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001366 SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1367 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
1368 );
1369
1370 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +00001371 &sci_req->state_machine, SCI_BASE_REQUEST_STATE_COMPLETED);
Dan Williams6f231dd2011-07-02 22:56:22 -07001372 break;
1373 }
1374
1375 return SCI_SUCCESS;
1376}
1377
1378/**
1379 *
Dave Jiange2023b82011-04-21 05:34:49 +00001380 * @sci_req:
Dan Williams6f231dd2011-07-02 22:56:22 -07001381 * @completion_code:
1382 *
1383 * This method processes a TC completion. The expected TC completion is for
1384 * the transmission of the H2D register FIS containing the SATA/STP non-data
1385 * request. This method always successfully processes the TC completion.
1386 * SCI_SUCCESS This value is always returned.
1387 */
1388static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler(
Dave Jiange2023b82011-04-21 05:34:49 +00001389 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001390 u32 completion_code)
1391{
1392 switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
1393 case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
1394 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +00001395 sci_req, SCU_TASK_DONE_GOOD, SCI_SUCCESS
Dan Williams6f231dd2011-07-02 22:56:22 -07001396 );
1397
1398 sci_base_state_machine_change_state(
Dave Jiange2023b82011-04-21 05:34:49 +00001399 &sci_req->started_substate_machine,
Dan Williams6f231dd2011-07-02 22:56:22 -07001400 SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
1401 );
1402 break;
1403
1404 default:
1405 /*
1406 * All other completion status cause the IO to be complete. If a NAK
1407 * was received, then it is up to the user to retry the request. */
1408 scic_sds_request_set_status(
Dave Jiange2023b82011-04-21 05:34:49 +00001409 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001410 SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
1411 SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
1412 );
1413
Dave Jiange2023b82011-04-21 05:34:49 +00001414 sci_base_state_machine_change_state(&sci_req->state_machine,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001415 SCI_BASE_REQUEST_STATE_COMPLETED);
Dan Williams6f231dd2011-07-02 22:56:22 -07001416 break;
1417 }
1418
1419 return SCI_SUCCESS;
1420}
1421
1422/**
1423 *
1424 * @request: This parameter specifies the request for which a frame has been
1425 * received.
1426 * @frame_index: This parameter specifies the index of the frame that has been
1427 * received.
1428 *
1429 * This method processes frames received from the target while waiting for a
1430 * device to host register FIS. If a non-register FIS is received during this
1431 * time, it is treated as a protocol violation from an IO perspective. Indicate
1432 * if the received frame was processed successfully.
1433 */
1434static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler(
Dan Williams827a84d2011-05-07 15:59:09 -07001435 struct scic_sds_request *sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001436 u32 frame_index)
1437{
1438 enum sci_status status;
Dave Jiange76d6182011-05-04 15:02:03 -07001439 struct dev_to_host_fis *frame_header;
Dan Williams6f231dd2011-07-02 22:56:22 -07001440 u32 *frame_buffer;
Dan Williams827a84d2011-05-07 15:59:09 -07001441 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
1442 struct scic_sds_controller *scic = sci_req->owning_controller;
Dan Williams6f231dd2011-07-02 22:56:22 -07001443
Dan Williams827a84d2011-05-07 15:59:09 -07001444 status = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
1445 frame_index,
1446 (void **)&frame_header);
1447 if (status != SCI_SUCCESS) {
1448 dev_err(scic_to_dev(scic),
Dan Williams6f231dd2011-07-02 22:56:22 -07001449 "%s: SCIC IO Request 0x%p could not get frame header "
1450 "for frame index %d, status %x\n",
Dave Jiange76d6182011-05-04 15:02:03 -07001451 __func__, stp_req, frame_index, status);
Dan Williams827a84d2011-05-07 15:59:09 -07001452 return status;
1453 }
1454
1455 switch (frame_header->fis_type) {
1456 case FIS_REGD2H:
1457 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
1458 frame_index,
1459 (void **)&frame_buffer);
1460
Dan Williamsb7645812011-05-08 02:35:32 -07001461 scic_sds_controller_copy_sata_response(&sci_req->stp.rsp,
Dan Williams827a84d2011-05-07 15:59:09 -07001462 frame_header,
1463 frame_buffer);
1464
1465 /* The command has completed with error */
1466 scic_sds_request_set_status(sci_req,
1467 SCU_TASK_DONE_CHECK_RESPONSE,
1468 SCI_FAILURE_IO_RESPONSE_VALID);
1469 break;
1470
1471 default:
1472 dev_warn(scic_to_dev(scic),
1473 "%s: IO Request:0x%p Frame Id:%d protocol "
1474 "violation occurred\n", __func__, stp_req,
1475 frame_index);
1476
1477 scic_sds_request_set_status(sci_req, SCU_TASK_DONE_UNEXP_FIS,
1478 SCI_FAILURE_PROTOCOL_VIOLATION);
1479 break;
1480 }
1481
1482 sci_base_state_machine_change_state(&sci_req->state_machine,
1483 SCI_BASE_REQUEST_STATE_COMPLETED);
1484
1485 /* Frame has been decoded return it to the controller */
1486 scic_sds_controller_release_frame(scic, frame_index);
Dan Williams6f231dd2011-07-02 22:56:22 -07001487
1488 return status;
1489}
1490
1491/* --------------------------------------------------------------------------- */
1492
Dan Williams35173d52011-03-26 16:43:01 -07001493static const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -07001494 [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001495 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001496 .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001497 },
1498 [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001499 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001500 .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001501 },
1502 [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = {
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001503 .abort_handler = scic_sds_request_started_state_abort_handler,
Christoph Hellwig38aa74e2011-03-28 09:21:14 -04001504 .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler,
Dan Williams6f231dd2011-07-02 22:56:22 -07001505 },
1506};
1507
1508static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001509 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001510{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001511 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001512
1513 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001514 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001515 scic_sds_stp_request_started_soft_reset_substate_handler_table,
1516 SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE
1517 );
1518
1519 scic_sds_remote_device_set_working_request(
Dave Jiange2023b82011-04-21 05:34:49 +00001520 sci_req->target_device, sci_req
Dan Williams6f231dd2011-07-02 22:56:22 -07001521 );
1522}
1523
1524static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001525 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001526{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001527 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001528 struct scu_task_context *task_context;
Dave Jiangf2f30082011-05-04 15:02:02 -07001529 struct host_to_dev_fis *h2d_fis;
Dan Williams6f231dd2011-07-02 22:56:22 -07001530 enum sci_status status;
Dan Williams6f231dd2011-07-02 22:56:22 -07001531
1532 /* Clear the SRST bit */
Dan Williamsb7645812011-05-08 02:35:32 -07001533 h2d_fis = &sci_req->stp.cmd;
Dan Williams6f231dd2011-07-02 22:56:22 -07001534 h2d_fis->control = 0;
1535
1536 /* Clear the TC control bit */
1537 task_context = scic_sds_controller_get_task_context_buffer(
Dave Jiange2023b82011-04-21 05:34:49 +00001538 sci_req->owning_controller, sci_req->io_tag);
Dan Williams6f231dd2011-07-02 22:56:22 -07001539 task_context->control_frame = 0;
1540
Dave Jiange2023b82011-04-21 05:34:49 +00001541 status = scic_controller_continue_io(sci_req);
Dan Williams6f231dd2011-07-02 22:56:22 -07001542 if (status == SCI_SUCCESS) {
1543 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001544 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001545 scic_sds_stp_request_started_soft_reset_substate_handler_table,
1546 SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE
1547 );
1548 }
1549}
1550
1551static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter(
Maciej Patelczyk9a0fff72011-04-28 22:06:01 +00001552 void *object)
Dan Williams6f231dd2011-07-02 22:56:22 -07001553{
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001554 struct scic_sds_request *sci_req = object;
Dan Williams6f231dd2011-07-02 22:56:22 -07001555
1556 SET_STATE_HANDLER(
Dave Jiange2023b82011-04-21 05:34:49 +00001557 sci_req,
Dan Williams6f231dd2011-07-02 22:56:22 -07001558 scic_sds_stp_request_started_soft_reset_substate_handler_table,
1559 SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE
1560 );
1561}
1562
Dan Williams35173d52011-03-26 16:43:01 -07001563static const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = {
Dan Williams6f231dd2011-07-02 22:56:22 -07001564 [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = {
1565 .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter,
1566 },
1567 [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = {
1568 .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter,
1569 },
1570 [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = {
1571 .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter,
1572 },
1573};
1574
Dan Williams35173d52011-03-26 16:43:01 -07001575enum sci_status scic_sds_stp_soft_reset_request_construct(struct scic_sds_request *sci_req)
1576{
Dan Williams827a84d2011-05-07 15:59:09 -07001577 struct scic_sds_stp_request *stp_req = &sci_req->stp.req;
Dan Williams35173d52011-03-26 16:43:01 -07001578
1579 scic_sds_stp_non_ncq_request_construct(sci_req);
1580
1581 /* Build the STP task context structure */
1582 scu_stp_raw_request_construct_task_context(stp_req, sci_req->task_context_buffer);
1583
1584 sci_base_state_machine_construct(&sci_req->started_substate_machine,
Maciej Patelczyk890cae92011-04-28 22:06:31 +00001585 sci_req,
Dan Williams35173d52011-03-26 16:43:01 -07001586 scic_sds_stp_request_started_soft_reset_substate_table,
1587 SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE);
1588
1589 return SCI_SUCCESS;
1590}