1/*-
2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3 *
4 * This file is provided under a dual BSD/GPLv2 license.  When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * The full GNU General Public License is included in this distribution
24 * in the file called LICENSE.GPL.
25 *
26 * BSD LICENSE
27 *
28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
35 *   * Redistributions of source code must retain the above copyright
36 *     notice, this list of conditions and the following disclaimer.
37 *   * Redistributions in binary form must reproduce the above copyright
38 *     notice, this list of conditions and the following disclaimer in
39 *     the documentation and/or other materials provided with the
40 *     distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 */
54
55#include <sys/cdefs.h>
56__FBSDID("$FreeBSD$");
57
58/**
59 * @file
60 *
61 * @brief This file contains the entrance and exit methods for the ready
62 *        sub-state machine states (OPERATIONAL, TASK_MGMT).
63 */
64
65#include <dev/isci/scil/scif_sas_remote_device.h>
66#include <dev/isci/scil/scif_sas_domain.h>
67#include <dev/isci/scil/scif_sas_logger.h>
68#include <dev/isci/scil/scif_sas_internal_io_request.h>
69#include <dev/isci/scil/scif_sas_controller.h>
70#include <dev/isci/scil/sci_controller.h>
71
72//******************************************************************************
73//* P R O T E C T E D   M E T H O D S
74//******************************************************************************
75
76/**
77 * @brief This method implements the actions taken when entering the
78 *        READY OPERATIONAL substate.  This includes setting the state
79 *        handler methods and issuing a scif_cb_remote_device_ready()
80 *        notification to the user.
81 *
82 * @param[in]  object This parameter specifies the base object for which
83 *             the state transition is occurring.  This is cast into a
84 *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
85 *
86 * @return none
87 */
88static
89void scif_sas_remote_device_ready_operational_substate_enter(
90   SCI_BASE_OBJECT_T *object
91)
92{
93   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
94
95   SET_STATE_HANDLER(
96      fw_device,
97      scif_sas_remote_device_ready_substate_handler_table,
98      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL
99   );
100
101   SCIF_LOG_INFO((
102      sci_base_object_get_logger(fw_device),
103      SCIF_LOG_OBJECT_REMOTE_DEVICE | SCIF_LOG_OBJECT_REMOTE_DEVICE_CONFIG,
104      "Domain:0x%x Device:0x%x device ready\n",
105      fw_device->domain, fw_device
106   ));
107
108   // Notify the user that the device has become ready.
109   scif_cb_remote_device_ready(
110      fw_device->domain->controller, fw_device->domain, fw_device
111   );
112}
113
114/**
115 * @brief This method implements the actions taken when exiting the
116 *        READY OPERATIONAL substate.  This method issues a
117 *        scif_cb_remote_device_not_ready() notification to the framework
118 *        user.
119 *
120 * @param[in]  object This parameter specifies the base object for which
121 *             the state transition is occurring.  This is cast into a
122 *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
123 *
124 * @return none
125 */
126static
127void scif_sas_remote_device_ready_operational_substate_exit(
128   SCI_BASE_OBJECT_T *object
129)
130{
131   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
132
133   // Notify the user that the device has become ready.
134   scif_cb_remote_device_not_ready(
135      fw_device->domain->controller, fw_device->domain, fw_device
136   );
137}
138
139/**
140 * @brief This method implements the actions taken when entering the
141 *        READY SUSPENDED substate.  This includes setting the state
142 *        handler methods.
143 *
144 * @param[in]  object This parameter specifies the base object for which
145 *             the state transition is occurring.  This is cast into a
146 *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
147 *
148 * @return none
149 */
150static
151void scif_sas_remote_device_ready_suspended_substate_enter(
152   SCI_BASE_OBJECT_T *object
153)
154{
155   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
156
157   SET_STATE_HANDLER(
158      fw_device,
159      scif_sas_remote_device_ready_substate_handler_table,
160      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED
161   );
162}
163
164/**
165 * @brief This method implements the actions taken when entering the
166 *        READY TASK MGMT substate.  This includes setting the state
167 *        handler methods.
168 *
169 * @param[in]  object This parameter specifies the base object for which
170 *             the state transition is occurring.  This is cast into a
171 *             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
172 *
173 * @return none
174 */
175static
176void scif_sas_remote_device_ready_taskmgmt_substate_enter(
177   SCI_BASE_OBJECT_T *object
178)
179{
180   SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
181
182   SET_STATE_HANDLER(
183      fw_device,
184      scif_sas_remote_device_ready_substate_handler_table,
185      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT
186   );
187}
188
189/**
190* @brief This method implements the actions taken when entering the
191*        READY NCQ ERROR substate.  This includes setting the state
192*        handler methods.
193*
194* @param[in]  object This parameter specifies the base object for which
195*             the state transition is occurring.  This is cast into a
196*             SCIF_SAS_REMOTE_DEVICE object in the method implementation.
197*
198* @return none
199*/
200static
201void scif_sas_remote_device_ready_ncq_error_substate_enter(
202   SCI_BASE_OBJECT_T *object
203)
204{
205   SCIF_SAS_REMOTE_DEVICE_T         * fw_device = (SCIF_SAS_REMOTE_DEVICE_T *)object;
206   SCI_STATUS                         status = SCI_SUCCESS;
207   SCI_TASK_REQUEST_HANDLE_T          handle;
208   SCIF_SAS_CONTROLLER_T            * fw_controller = fw_device->domain->controller;
209   SCIF_SAS_TASK_REQUEST_T          * fw_task_request;
210   SCIF_SAS_REQUEST_T               * fw_request;
211   void                             * internal_task_memory;
212   SCIF_SAS_DOMAIN_T                * fw_domain = fw_device->domain;
213   SCI_FAST_LIST_ELEMENT_T          * pending_request_element;
214   SCIF_SAS_REQUEST_T               * pending_request = NULL;
215
216   SET_STATE_HANDLER(
217      fw_device,
218      scif_sas_remote_device_ready_substate_handler_table,
219      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
220   );
221
222   internal_task_memory = scif_sas_controller_allocate_internal_request(fw_controller);
223   ASSERT(internal_task_memory != NULL);
224
225   fw_task_request = (SCIF_SAS_TASK_REQUEST_T*)internal_task_memory;
226
227   fw_request = &fw_task_request->parent;
228
229   //construct the scif io request
230   status = scif_sas_internal_task_request_construct(
231      fw_controller,
232      fw_device,
233      SCI_CONTROLLER_INVALID_IO_TAG,
234      (void *)fw_task_request,
235      &handle,
236      SCI_SAS_ABORT_TASK_SET
237   );
238
239   pending_request_element = fw_domain->request_list.list_head;
240
241   // Cycle through the fast list of IO requests.  Mark each request
242   //  pending to this remote device so that they are not completed
243   //  to the operating system when the request is terminated, but
244   //  rather when the abort task set completes.
245   while (pending_request_element != NULL)
246   {
247      pending_request =
248         (SCIF_SAS_REQUEST_T*) sci_fast_list_get_object(pending_request_element);
249
250      // The current element may be deleted from the list because of
251      // IO completion so advance to the next element early
252      pending_request_element = sci_fast_list_get_next(pending_request_element);
253
254      if (pending_request->device == fw_device)
255      {
256         pending_request->is_waiting_for_abort_task_set = TRUE;
257      }
258   }
259
260   scif_controller_start_task(
261      fw_controller,
262      fw_device,
263      fw_request,
264      SCI_CONTROLLER_INVALID_IO_TAG
265   );
266}
267
268SCI_BASE_STATE_T scif_sas_remote_device_ready_substate_table
269[SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_MAX_STATES] =
270{
271   {
272      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
273      scif_sas_remote_device_ready_operational_substate_enter,
274      scif_sas_remote_device_ready_operational_substate_exit
275   },
276   {
277      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
278      scif_sas_remote_device_ready_suspended_substate_enter,
279      NULL
280   },
281   {
282      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_TASK_MGMT,
283      scif_sas_remote_device_ready_taskmgmt_substate_enter,
284      NULL
285   },
286   {
287      SCIF_SAS_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
288      scif_sas_remote_device_ready_ncq_error_substate_enter,
289      NULL
290   }
291};
292
293