xref: /freebsd/sys/dev/isci/scil/scic_sds_smp_remote_device.c (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
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  *
40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51  */
52 
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
55 
56 /**
57  * @file
58  *
59  * @brief This file contains This file contains the SMP remote device
60  *        object methods and it's state machines.
61  */
62 
63 #include <dev/isci/scil/scic_user_callback.h>
64 #include <dev/isci/scil/scic_sds_logger.h>
65 #include <dev/isci/scil/scic_sds_remote_device.h>
66 #include <dev/isci/scil/scic_sds_controller.h>
67 #include <dev/isci/scil/scic_sds_port.h>
68 #include <dev/isci/scil/scic_sds_request.h>
69 #include <dev/isci/scil/scu_event_codes.h>
70 #include <dev/isci/scil/scu_task_context.h>
71 #include <dev/isci/scil/scic_remote_device.h>
72 
73 //*****************************************************************************
74 //*  SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
75 //*****************************************************************************
76 
77 /**
78  * This method will handle the start io operation for a SMP device that is in
79  * the idle state.
80  *
81  * @param [in] device The device the io is sent to.
82  * @param [in] request The io to start.
83  *
84  * @return SCI_STATUS
85  */
86 static
87 SCI_STATUS scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
88    SCI_BASE_REMOTE_DEVICE_T * device,
89    SCI_BASE_REQUEST_T       * request
90 )
91 {
92    SCI_STATUS status;
93    SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
94    SCIC_SDS_REQUEST_T       * io_request  = (SCIC_SDS_REQUEST_T       *)request;
95 
96    // Will the port allow the io request to start?
97    status = this_device->owning_port->state_handlers->start_io_handler(
98       this_device->owning_port,
99       this_device,
100       io_request
101    );
102 
103    if (status == SCI_SUCCESS)
104    {
105       status =
106          scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
107 
108       if (status == SCI_SUCCESS)
109       {
110          status = scic_sds_request_start(io_request);
111       }
112 
113       if (status == SCI_SUCCESS)
114       {
115          this_device->working_request = io_request;
116 
117          sci_base_state_machine_change_state(
118                &this_device->ready_substate_machine,
119                SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
120          );
121       }
122 
123       scic_sds_remote_device_start_request(this_device, io_request, status);
124    }
125 
126    return status;
127 }
128 
129 
130 //******************************************************************************
131 //* SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS
132 //******************************************************************************
133 /**
134  * This device is already handling a command it can not accept new commands
135  * until this one is complete.
136  *
137  * @param[in] device This is the device object that is receiving the IO.
138  *
139  * @param[in] request The io to start.
140  *
141  * @return SCI_STATUS
142  */
143 static
144 SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
145    SCI_BASE_REMOTE_DEVICE_T * device,
146    SCI_BASE_REQUEST_T       * request
147 )
148 {
149    return SCI_FAILURE_INVALID_STATE;
150 }
151 
152 
153 /**
154  * @brief this is the complete_io_handler for smp device at ready cmd substate.
155  *
156  * @param[in] device This is the device object that is receiving the IO.
157  * @param[in] request The io to start.
158  *
159  * @return SCI_STATUS
160  */
161 static
162 SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
163    SCI_BASE_REMOTE_DEVICE_T * device,
164    SCI_BASE_REQUEST_T       * request
165 )
166 {
167    SCI_STATUS                 status;
168    SCIC_SDS_REMOTE_DEVICE_T * this_device;
169    SCIC_SDS_REQUEST_T       * the_request;
170 
171    this_device = (SCIC_SDS_REMOTE_DEVICE_T *)device;
172    the_request = (SCIC_SDS_REQUEST_T       *)request;
173 
174    status = scic_sds_io_request_complete(the_request);
175 
176    if (status == SCI_SUCCESS)
177    {
178       status = scic_sds_port_complete_io(
179          this_device->owning_port, this_device, the_request);
180 
181       if (status == SCI_SUCCESS)
182       {
183        scic_sds_remote_device_decrement_request_count(this_device);
184          sci_base_state_machine_change_state(
185             &this_device->ready_substate_machine,
186             SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
187          );
188       }
189       else
190       {
191          SCIC_LOG_ERROR((
192             sci_base_object_get_logger(this_device),
193             SCIC_LOG_OBJECT_SMP_REMOTE_TARGET,
194             "SCIC SDS Remote Device 0x%x io request 0x%x could not be completd on the port 0x%x failed with status %d.\n",
195             this_device, the_request, this_device->owning_port, status
196          ));
197       }
198    }
199 
200    return status;
201 }
202 
203 /**
204  * @brief This is frame handler for smp device ready cmd substate.
205  *
206  * @param[in] this_device This is the device object that is receiving the frame.
207  * @param[in] frame_index The index for the frame received.
208  *
209  * @return SCI_STATUS
210  */
211 static
212 SCI_STATUS scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
213    SCIC_SDS_REMOTE_DEVICE_T * this_device,
214    U32                        frame_index
215 )
216 {
217    SCI_STATUS status;
218 
219    /// The device does not process any UF received from the hardware while
220    /// in this state.  All unsolicited frames are forwarded to the io request
221    /// object.
222    status = scic_sds_io_request_frame_handler(
223       this_device->working_request,
224       frame_index
225    );
226 
227    return status;
228 }
229 
230 // ---------------------------------------------------------------------------
231 
232 SCIC_SDS_REMOTE_DEVICE_STATE_HANDLER_T
233    scic_sds_smp_remote_device_ready_substate_handler_table[
234                               SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
235 {
236    // SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
237    {
238       {
239          scic_sds_remote_device_default_start_handler,
240          scic_sds_remote_device_ready_state_stop_handler,
241          scic_sds_remote_device_default_fail_handler,
242          scic_sds_remote_device_default_destruct_handler,
243          scic_sds_remote_device_default_reset_handler,
244          scic_sds_remote_device_default_reset_complete_handler,
245          scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
246          scic_sds_remote_device_default_complete_request_handler,
247          scic_sds_remote_device_default_continue_request_handler,
248          scic_sds_remote_device_default_start_request_handler,
249          scic_sds_remote_device_default_complete_request_handler
250       },
251       scic_sds_remote_device_default_suspend_handler,
252       scic_sds_remote_device_default_resume_handler,
253       scic_sds_remote_device_general_event_handler,
254       scic_sds_remote_device_default_frame_handler
255    },
256    // SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
257    {
258       {
259          scic_sds_remote_device_default_start_handler,
260          scic_sds_remote_device_ready_state_stop_handler,
261          scic_sds_remote_device_default_fail_handler,
262          scic_sds_remote_device_default_destruct_handler,
263          scic_sds_remote_device_default_reset_handler,
264          scic_sds_remote_device_default_reset_complete_handler,
265          scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
266          scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
267          scic_sds_remote_device_default_continue_request_handler,
268          scic_sds_remote_device_default_start_request_handler,
269          scic_sds_remote_device_default_complete_request_handler
270       },
271       scic_sds_remote_device_default_suspend_handler,
272       scic_sds_remote_device_default_resume_handler,
273       scic_sds_remote_device_general_event_handler,
274       scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
275    }
276 };
277 
278 /**
279  * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. This
280  * method sets the ready cmd substate handlers and reports the device as ready.
281  *
282  * @param[in] object This is the SCI_BASE_OBJECT which is cast into a
283  *       SCIC_SDS_REMOTE_DEVICE.
284  *
285  * @return none
286  */
287 static
288 void scic_sds_smp_remote_device_ready_idle_substate_enter(
289    SCI_BASE_OBJECT_T *object
290 )
291 {
292    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
293 
294    SET_STATE_HANDLER(
295       this_device,
296       scic_sds_smp_remote_device_ready_substate_handler_table,
297       SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
298    );
299 
300    scic_cb_remote_device_ready(
301       scic_sds_remote_device_get_controller(this_device), this_device);
302 }
303 
304 /**
305  * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This
306  * method sets the remote device objects ready cmd substate handlers, and notify
307  * core user that the device is not ready.
308  *
309  * @param[in] object This is the SCI_BASE_OBJECT which is cast into a
310  *       SCIC_SDS_REMOTE_DEVICE.
311  *
312  * @return none
313  */
314 static
315 void scic_sds_smp_remote_device_ready_cmd_substate_enter(
316    SCI_BASE_OBJECT_T *object
317 )
318 {
319    SCIC_SDS_REMOTE_DEVICE_T *this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
320 
321    ASSERT(this_device->working_request != NULL);
322 
323    SET_STATE_HANDLER(
324       this_device,
325       scic_sds_smp_remote_device_ready_substate_handler_table,
326       SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
327    );
328 
329    scic_cb_remote_device_not_ready(
330       scic_sds_remote_device_get_controller(this_device),
331       this_device,
332       SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED
333    );
334 }
335 
336 /**
337  * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method.
338  *
339  * @param[in] object This is the SCI_BASE_OBJECT which is cast into a
340  *       SCIC_SDS_REMOTE_DEVICE.
341  *
342  * @return none
343  */
344 static
345 void scic_sds_smp_remote_device_ready_cmd_substate_exit(
346    SCI_BASE_OBJECT_T *object
347 )
348 {
349    SCIC_SDS_REMOTE_DEVICE_T * this_device = (SCIC_SDS_REMOTE_DEVICE_T *)object;
350 
351    this_device->working_request = NULL;
352 }
353 
354 // ---------------------------------------------------------------------------
355 
356 SCI_BASE_STATE_T
357    scic_sds_smp_remote_device_ready_substate_table[
358                      SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
359 {
360    {
361       SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
362       scic_sds_smp_remote_device_ready_idle_substate_enter,
363       NULL
364    },
365    {
366       SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
367       scic_sds_smp_remote_device_ready_cmd_substate_enter,
368       scic_sds_smp_remote_device_ready_cmd_substate_exit
369    }
370 };
371 
372