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