isci: Intel(R) C600 Series Chipset Storage Control Unit Driver
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / scsi / isci / core / scic_sds_smp_request.c
1 /*
2  * This file is provided under a dual BSD/GPLv2 license.  When using or
3  * redistributing this file, you may do so under either license.
4  *
5  * GPL LICENSE SUMMARY
6  *
7  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of version 2 of the GNU General Public License as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
24  * BSD LICENSE
25  *
26  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27  * All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  *
33  *   * Redistributions of source code must retain the above copyright
34  *     notice, this list of conditions and the following disclaimer.
35  *   * Redistributions in binary form must reproduce the above copyright
36  *     notice, this list of conditions and the following disclaimer in
37  *     the documentation and/or other materials provided with the
38  *     distribution.
39  *   * Neither the name of Intel Corporation nor the names of its
40  *     contributors may be used to endorse or promote products derived
41  *     from this software without specific prior written permission.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  */
55
56 #include "intel_sas.h"
57 #include "sci_base_state_machine.h"
58 #include "scic_controller.h"
59 #include "scic_remote_device.h"
60 #include "scic_sds_controller.h"
61 #include "scic_sds_remote_device.h"
62 #include "scic_sds_request.h"
63 #include "scic_sds_smp_request.h"
64 #include "sci_environment.h"
65 #include "sci_util.h"
66 #include "scu_completion_codes.h"
67 #include "scu_task_context.h"
68
69 static void scu_smp_request_construct_task_context(
70         struct scic_sds_request *this_request,
71         struct smp_request *smp_request);
72
73 /**
74  *
75  *
76  * This method return the memory space required for STP PIO requests. u32
77  */
78 u32 scic_sds_smp_request_get_object_size(void)
79 {
80         return sizeof(struct scic_sds_request)
81                + sizeof(struct smp_request)
82                + sizeof(struct smp_response)
83                + sizeof(struct scu_task_context);
84 }
85
86 /**
87  * scic_sds_smp_request_get_command_buffer() -
88  *
89  * This macro returns the address of the smp command buffer in the smp request
90  * memory. No need to cast to SMP request type.
91  */
92 #define scic_sds_smp_request_get_command_buffer(memory) \
93         (((char *)(memory)) + sizeof(struct scic_sds_request))
94
95 /**
96  * scic_sds_smp_request_get_response_buffer() -
97  *
98  * This macro returns the address of the smp response buffer in the smp request
99  * memory.
100  */
101 #define scic_sds_smp_request_get_response_buffer(memory) \
102         (((char *)(scic_sds_smp_request_get_command_buffer(memory))) \
103          + sizeof(struct smp_request))
104
105 /**
106  * scic_sds_smp_request_get_task_context_buffer() -
107  *
108  * This macro returs the task context buffer for the SMP request.
109  */
110 #define scic_sds_smp_request_get_task_context_buffer(memory) \
111         ((struct scu_task_context *)(\
112                  ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \
113                  + sizeof(struct smp_response) \
114                  ))
115
116
117
118 /**
119  * This method build the remainder of the IO request object.
120  * @this_request: This parameter specifies the request object being constructed.
121  *
122  * The scic_sds_general_request_construct() must be called before this call is
123  * valid. none
124  */
125
126 void scic_sds_smp_request_assign_buffers(
127         struct scic_sds_request *this_request)
128 {
129         /* Assign all of the buffer pointers */
130         this_request->command_buffer =
131                 scic_sds_smp_request_get_command_buffer(this_request);
132         this_request->response_buffer =
133                 scic_sds_smp_request_get_response_buffer(this_request);
134         this_request->sgl_element_pair_buffer = NULL;
135
136         if (this_request->was_tag_assigned_by_user == false) {
137                 this_request->task_context_buffer =
138                         scic_sds_smp_request_get_task_context_buffer(this_request);
139                 this_request->task_context_buffer =
140                         scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
141         }
142
143 }
144 /**
145  * This method is called by the SCI user to build an SMP IO request.
146  *
147  * - The user must have previously called scic_io_request_construct() on the
148  * supplied IO request. Indicate if the controller successfully built the IO
149  * request. SCI_SUCCESS This value is returned if the IO request was
150  * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
151  * if the remote_device does not support the SMP protocol.
152  * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
153  * properly set the association between the SCIC IO request and the user's IO
154  * request.  Please refer to the sci_object_set_association() routine for more
155  * information.
156  */
157 enum sci_status scic_io_request_construct_smp(
158         struct scic_sds_request *sci_req)
159 {
160         struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL);
161
162         if (!smp_req)
163                 return SCI_FAILURE_INSUFFICIENT_RESOURCES;
164
165         sci_req->protocol                     = SCIC_SMP_PROTOCOL;
166         sci_req->has_started_substate_machine = true;
167
168         /* Construct the started sub-state machine. */
169         sci_base_state_machine_construct(
170                 &sci_req->started_substate_machine,
171                 &sci_req->parent.parent,
172                 scic_sds_smp_request_started_substate_table,
173                 SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
174                 );
175
176         /* Construct the SMP SCU Task Context */
177         memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req));
178
179         /*
180          * Look at the SMP requests' header fields; for certain SAS 1.x SMP
181          * functions under SAS 2.0, a zero request length really indicates
182          * a non-zero default length. */
183         if (smp_req->header.request_length == 0) {
184                 switch (smp_req->header.function) {
185                 case SMP_FUNCTION_DISCOVER:
186                 case SMP_FUNCTION_REPORT_PHY_ERROR_LOG:
187                 case SMP_FUNCTION_REPORT_PHY_SATA:
188                 case SMP_FUNCTION_REPORT_ROUTE_INFORMATION:
189                         smp_req->header.request_length = 2;
190                         break;
191                 case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
192                 case SMP_FUNCTION_PHY_CONTROL:
193                 case SMP_FUNCTION_PHY_TEST:
194                         smp_req->header.request_length = 9;
195                         break;
196                         /* Default - zero is a valid default for 2.0. */
197                 }
198         }
199
200         scu_smp_request_construct_task_context(sci_req, smp_req);
201
202         sci_base_state_machine_change_state(
203                 &sci_req->parent.state_machine,
204                 SCI_BASE_REQUEST_STATE_CONSTRUCTED
205                 );
206
207         kfree(smp_req);
208
209         return SCI_SUCCESS;
210 }
211
212 /**
213  * This method is called by the SCI user to build an SMP pass-through IO
214  *    request.
215  * @scic_smp_request: This parameter specifies the handle to the io request
216  *    object to be built.
217  * @passthru_cb: This parameter specifies the pointer to the callback structure
218  *    that contains the function pointers
219  *
220  * - The user must have previously called scic_io_request_construct() on the
221  * supplied IO request. Indicate if the controller successfully built the IO
222  * request.
223  */
224
225 /**
226  * This method will fill in the SCU Task Context for a SMP request. The
227  *    following important settings are utilized: -# task_type ==
228  *    SCU_TASK_TYPE_SMP.  This simply indicates that a normal request type
229  *    (i.e. non-raw frame) is being utilized to perform task management. -#
230  *    control_frame == 1.  This ensures that the proper endianess is set so
231  *    that the bytes are transmitted in the right order for a smp request frame.
232  * @this_request: This parameter specifies the smp request object being
233  *    constructed.
234  *
235  */
236 static void scu_smp_request_construct_task_context(
237         struct scic_sds_request *this_request,
238         struct smp_request *smp_request)
239 {
240         dma_addr_t physical_address;
241         struct scic_sds_controller *owning_controller;
242         struct scic_sds_remote_device *target_device;
243         struct scic_sds_port *target_port;
244         struct scu_task_context *task_context;
245
246         /* byte swap the smp request. */
247         scic_word_copy_with_swap(
248                 this_request->command_buffer,
249                 (u32 *)smp_request,
250                 sizeof(struct smp_request) / sizeof(u32)
251                 );
252
253         task_context = scic_sds_request_get_task_context(this_request);
254
255         owning_controller = scic_sds_request_get_controller(this_request);
256         target_device = scic_sds_request_get_device(this_request);
257         target_port = scic_sds_request_get_port(this_request);
258
259         /*
260          * Fill in the TC with the its required data
261          * 00h */
262         task_context->priority = 0;
263         task_context->initiator_request = 1;
264         task_context->connection_rate =
265                 scic_remote_device_get_connection_rate(target_device);
266         task_context->protocol_engine_index =
267                 scic_sds_controller_get_protocol_engine_group(owning_controller);
268         task_context->logical_port_index =
269                 scic_sds_port_get_index(target_port);
270         task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
271         task_context->abort = 0;
272         task_context->valid = SCU_TASK_CONTEXT_VALID;
273         task_context->context_type = SCU_TASK_CONTEXT_TYPE;
274
275         /* 04h */
276         task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
277         task_context->command_code = 0;
278         task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
279
280         /* 08h */
281         task_context->link_layer_control = 0;
282         task_context->do_not_dma_ssp_good_response = 1;
283         task_context->strict_ordering = 0;
284         task_context->control_frame = 1;
285         task_context->timeout_enable = 0;
286         task_context->block_guard_enable = 0;
287
288         /* 0ch */
289         task_context->address_modifier = 0;
290
291         /* 10h */
292         task_context->ssp_command_iu_length = smp_request->header.request_length;
293
294         /* 14h */
295         task_context->transfer_length_bytes = 0;
296
297         /*
298          * 18h ~ 30h, protocol specific
299          * since commandIU has been build by framework at this point, we just
300          * copy the frist DWord from command IU to this location. */
301         memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32));
302
303         /*
304          * 40h
305          * "For SMP you could program it to zero. We would prefer that way so that
306          * done code will be consistent." - Venki */
307         task_context->task_phase = 0;
308
309         if (this_request->was_tag_assigned_by_user) {
310                 /* Build the task context now since we have already read the data */
311                 this_request->post_context = (
312                         SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
313                         | (
314                                 scic_sds_controller_get_protocol_engine_group(owning_controller)
315                                 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
316                                 )
317                         | (
318                                 scic_sds_port_get_index(target_port)
319                                 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
320                                 )
321                         | scic_sds_io_tag_get_index(this_request->io_tag)
322                         );
323         } else {
324                 /* Build the task context now since we have already read the data */
325                 this_request->post_context = (
326                         SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
327                         | (
328                                 scic_sds_controller_get_protocol_engine_group(owning_controller)
329                                 << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
330                                 )
331                         | (
332                                 scic_sds_port_get_index(target_port)
333                                 << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
334                                 )
335                         /* This is not assigned because we have to wait until we get a TCi */
336                         );
337         }
338
339         /*
340          * Copy the physical address for the command buffer to the SCU Task Context
341          * command buffer should not contain command header. */
342         scic_cb_io_request_get_physical_address(
343                 scic_sds_request_get_controller(this_request),
344                 this_request,
345                 ((char *)(this_request->command_buffer) + sizeof(u32)),
346                 &physical_address
347                 );
348
349         task_context->command_iu_upper =
350                 upper_32_bits(physical_address);
351         task_context->command_iu_lower =
352                 lower_32_bits(physical_address);
353
354
355         /* SMP response comes as UF, so no need to set response IU address. */
356         task_context->response_iu_upper = 0;
357         task_context->response_iu_lower = 0;
358 }
359
360 /**
361  * This method processes an unsolicited frame while the SMP request is waiting
362  *    for a response frame.  It will copy the response data, release the
363  *    unsolicited frame, and transition the request to the
364  *    SCI_BASE_REQUEST_STATE_COMPLETED state.
365  * @this_request: This parameter specifies the request for which the
366  *    unsolicited frame was received.
367  * @frame_index: This parameter indicates the unsolicited frame index that
368  *    should contain the response.
369  *
370  * This method returns an indication of whether the response frame was handled
371  * successfully or not. SCI_SUCCESS Currently this value is always returned and
372  * indicates successful processing of the TC response.
373  */
374 static enum sci_status scic_sds_smp_request_await_response_frame_handler(
375         struct scic_sds_request *this_request,
376         u32 frame_index)
377 {
378         enum sci_status status;
379         void *frame_header;
380         struct smp_response_header *this_frame_header;
381         u8 *user_smp_buffer = this_request->response_buffer;
382
383         status = scic_sds_unsolicited_frame_control_get_header(
384                 &(scic_sds_request_get_controller(this_request)->uf_control),
385                 frame_index,
386                 &frame_header
387                 );
388
389         /* byte swap the header. */
390         scic_word_copy_with_swap(
391                 (u32 *)user_smp_buffer,
392                 frame_header,
393                 sizeof(struct smp_response_header) / sizeof(u32)
394                 );
395         this_frame_header = (struct smp_response_header *)user_smp_buffer;
396
397         if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) {
398                 void *smp_response_buffer;
399
400                 status = scic_sds_unsolicited_frame_control_get_buffer(
401                         &(scic_sds_request_get_controller(this_request)->uf_control),
402                         frame_index,
403                         &smp_response_buffer
404                         );
405
406                 scic_word_copy_with_swap(
407                         (u32 *)(user_smp_buffer + sizeof(struct smp_response_header)),
408                         smp_response_buffer,
409                         sizeof(union smp_response_body) / sizeof(u32)
410                         );
411                 if (this_frame_header->function == SMP_FUNCTION_DISCOVER) {
412                         struct smp_response *this_smp_response;
413
414                         this_smp_response = (struct smp_response *)user_smp_buffer;
415
416                         /*
417                          * Some expanders only report an attached SATA device, and
418                          * not an STP target.  Since the core depends on the STP
419                          * target attribute to correctly build I/O, set the bit now
420                          * if necessary. */
421                         if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
422                             && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) {
423                                 this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;
424
425                                 dev_dbg(scic_to_dev(this_request->owning_controller),
426                                         "%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n",
427                                         __func__, this_request);
428                         }
429                 }
430
431                 /*
432                  * Don't need to copy to user space. User instead will refer to
433                  * core request's response buffer. */
434
435                 /*
436                  * copy the smp response to framework smp request's response buffer.
437                  * scic_sds_smp_request_copy_response(this_request); */
438
439                 scic_sds_request_set_status(
440                         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
441                         );
442
443                 sci_base_state_machine_change_state(
444                         &this_request->started_substate_machine,
445                         SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
446                         );
447         } else {
448                 /* This was not a response frame why did it get forwarded? */
449                 dev_err(scic_to_dev(this_request->owning_controller),
450                         "%s: SCIC SMP Request 0x%p received unexpected frame "
451                         "%d type 0x%02x\n",
452                         __func__,
453                         this_request,
454                         frame_index,
455                         this_frame_header->smp_frame_type);
456
457                 scic_sds_request_set_status(
458                         this_request,
459                         SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
460                         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
461                         );
462
463                 sci_base_state_machine_change_state(
464                         &this_request->parent.state_machine,
465                         SCI_BASE_REQUEST_STATE_COMPLETED
466                         );
467         }
468
469         scic_sds_controller_release_frame(
470                 this_request->owning_controller, frame_index
471                 );
472
473         return SCI_SUCCESS;
474 }
475
476
477 /**
478  * This method processes an abnormal TC completion while the SMP request is
479  *    waiting for a response frame.  It decides what happened to the IO based
480  *    on TC completion status.
481  * @this_request: This parameter specifies the request for which the TC
482  *    completion was received.
483  * @completion_code: This parameter indicates the completion status information
484  *    for the TC.
485  *
486  * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
487  * this method always returns success.
488  */
489 static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler(
490         struct scic_sds_request *this_request,
491         u32 completion_code)
492 {
493         switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
494         case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
495                 /*
496                  * In the AWAIT RESPONSE state, any TC completion is unexpected.
497                  * but if the TC has success status, we complete the IO anyway. */
498                 scic_sds_request_set_status(
499                         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
500                         );
501
502                 sci_base_state_machine_change_state(
503                         &this_request->parent.state_machine,
504                         SCI_BASE_REQUEST_STATE_COMPLETED
505                         );
506                 break;
507
508         case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
509         case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
510         case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
511         case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
512                 /*
513                  * These status has been seen in a specific LSI expander, which sometimes
514                  * is not able to send smp response within 2 ms. This causes our hardware
515                  * break the connection and set TC completion with one of these SMP_XXX_XX_ERR
516                  * status. For these type of error, we ask scic user to retry the request. */
517                 scic_sds_request_set_status(
518                         this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
519                         );
520
521                 sci_base_state_machine_change_state(
522                         &this_request->parent.state_machine,
523                         SCI_BASE_REQUEST_STATE_COMPLETED
524                         );
525                 break;
526
527         default:
528                 /*
529                  * All other completion status cause the IO to be complete.  If a NAK
530                  * was received, then it is up to the user to retry the request. */
531                 scic_sds_request_set_status(
532                         this_request,
533                         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
534                         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
535                         );
536
537                 sci_base_state_machine_change_state(
538                         &this_request->parent.state_machine,
539                         SCI_BASE_REQUEST_STATE_COMPLETED
540                         );
541                 break;
542         }
543
544         return SCI_SUCCESS;
545 }
546
547
548 /**
549  * This method processes the completions transport layer (TL) status to
550  *    determine if the SMP request was sent successfully. If the SMP request
551  *    was sent successfully, then the state for the SMP request transits to
552  *    waiting for a response frame.
553  * @this_request: This parameter specifies the request for which the TC
554  *    completion was received.
555  * @completion_code: This parameter indicates the completion status information
556  *    for the TC.
557  *
558  * Indicate if the tc completion handler was successful. SCI_SUCCESS currently
559  * this method always returns success.
560  */
561 static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler(
562         struct scic_sds_request *this_request,
563         u32 completion_code)
564 {
565         switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
566         case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
567                 scic_sds_request_set_status(
568                         this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
569                         );
570
571                 sci_base_state_machine_change_state(
572                         &this_request->parent.state_machine,
573                         SCI_BASE_REQUEST_STATE_COMPLETED
574                         );
575                 break;
576
577         default:
578                 /*
579                  * All other completion status cause the IO to be complete.  If a NAK
580                  * was received, then it is up to the user to retry the request. */
581                 scic_sds_request_set_status(
582                         this_request,
583                         SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
584                         SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
585                         );
586
587                 sci_base_state_machine_change_state(
588                         &this_request->parent.state_machine,
589                         SCI_BASE_REQUEST_STATE_COMPLETED
590                         );
591                 break;
592         }
593
594         return SCI_SUCCESS;
595 }
596
597
598 const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = {
599         [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
600                 .parent.start_handler    = scic_sds_request_default_start_handler,
601                 .parent.abort_handler    = scic_sds_request_started_state_abort_handler,
602                 .parent.complete_handler = scic_sds_request_default_complete_handler,
603                 .parent.destruct_handler = scic_sds_request_default_destruct_handler,
604                 .tc_completion_handler   = scic_sds_smp_request_await_response_tc_completion_handler,
605                 .event_handler           = scic_sds_request_default_event_handler,
606                 .frame_handler           = scic_sds_smp_request_await_response_frame_handler,
607         },
608         [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
609                 .parent.start_handler    = scic_sds_request_default_start_handler,
610                 .parent.abort_handler    = scic_sds_request_started_state_abort_handler,
611                 .parent.complete_handler = scic_sds_request_default_complete_handler,
612                 .parent.destruct_handler = scic_sds_request_default_destruct_handler,
613                 .tc_completion_handler   =  scic_sds_smp_request_await_tc_completion_tc_completion_handler,
614                 .event_handler           =  scic_sds_request_default_event_handler,
615                 .frame_handler           =  scic_sds_request_default_frame_handler,
616         }
617 };
618
619 /**
620  * This method performs the actions required when entering the
621  *    SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
622  *    includes setting the IO request state handlers for this sub-state.
623  * @object: This parameter specifies the request object for which the sub-state
624  *    change is occuring.
625  *
626  * none.
627  */
628 static void scic_sds_smp_request_started_await_response_substate_enter(
629         struct sci_base_object *object)
630 {
631         struct scic_sds_request *this_request = (struct scic_sds_request *)object;
632
633         SET_STATE_HANDLER(
634                 this_request,
635                 scic_sds_smp_request_started_substate_handler_table,
636                 SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
637                 );
638 }
639
640 /**
641  * This method performs the actions required when entering the
642  *    SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state.
643  *    This includes setting the SMP request state handlers for this sub-state.
644  * @object: This parameter specifies the request object for which the sub-state
645  *    change is occuring.
646  *
647  * none.
648  */
649 static void scic_sds_smp_request_started_await_tc_completion_substate_enter(
650         struct sci_base_object *object)
651 {
652         struct scic_sds_request *this_request = (struct scic_sds_request *)object;
653
654         SET_STATE_HANDLER(
655                 this_request,
656                 scic_sds_smp_request_started_substate_handler_table,
657                 SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
658                 );
659 }
660
661 const struct sci_base_state scic_sds_smp_request_started_substate_table[] = {
662         [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
663                 .enter_state = scic_sds_smp_request_started_await_response_substate_enter,
664         },
665         [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
666                 .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter,
667         },
668 };
669