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 "host.h" 57 #include "isci.h" 58 #include "remote_device.h" 59 #include "remote_node_context.h" 60 #include "scu_event_codes.h" 61 #include "scu_task_context.h" 62 63 #undef C 64 #define C(a) (#a) 65 const char *rnc_state_name(enum scis_sds_remote_node_context_states state) 66 { 67 static const char * const strings[] = RNC_STATES; 68 69 return strings[state]; 70 } 71 #undef C 72 73 /** 74 * 75 * @sci_rnc: The state of the remote node context object to check. 76 * 77 * This method will return true if the remote node context is in a READY state 78 * otherwise it will return false bool true if the remote node context is in 79 * the ready state. false if the remote node context is not in the ready state. 80 */ 81 bool sci_remote_node_context_is_ready( 82 struct sci_remote_node_context *sci_rnc) 83 { 84 u32 current_state = sci_rnc->sm.current_state_id; 85 86 if (current_state == SCI_RNC_READY) { 87 return true; 88 } 89 90 return false; 91 } 92 93 static union scu_remote_node_context *sci_rnc_by_id(struct isci_host *ihost, u16 id) 94 { 95 if (id < ihost->remote_node_entries && 96 ihost->device_table[id]) 97 return &ihost->remote_node_context_table[id]; 98 99 return NULL; 100 } 101 102 static void sci_remote_node_context_construct_buffer(struct sci_remote_node_context *sci_rnc) 103 { 104 struct isci_remote_device *idev = rnc_to_dev(sci_rnc); 105 struct domain_device *dev = idev->domain_dev; 106 int rni = sci_rnc->remote_node_index; 107 union scu_remote_node_context *rnc; 108 struct isci_host *ihost; 109 __le64 sas_addr; 110 111 ihost = idev->owning_port->owning_controller; 112 rnc = sci_rnc_by_id(ihost, rni); 113 114 memset(rnc, 0, sizeof(union scu_remote_node_context) 115 * sci_remote_device_node_count(idev)); 116 117 rnc->ssp.remote_node_index = rni; 118 rnc->ssp.remote_node_port_width = idev->device_port_width; 119 rnc->ssp.logical_port_index = idev->owning_port->physical_port_index; 120 121 /* sas address is __be64, context ram format is __le64 */ 122 sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr)); 123 rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr); 124 rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr); 125 126 rnc->ssp.nexus_loss_timer_enable = true; 127 rnc->ssp.check_bit = false; 128 rnc->ssp.is_valid = false; 129 rnc->ssp.is_remote_node_context = true; 130 rnc->ssp.function_number = 0; 131 132 rnc->ssp.arbitration_wait_time = 0; 133 134 if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { 135 rnc->ssp.connection_occupancy_timeout = 136 ihost->user_parameters.stp_max_occupancy_timeout; 137 rnc->ssp.connection_inactivity_timeout = 138 ihost->user_parameters.stp_inactivity_timeout; 139 } else { 140 rnc->ssp.connection_occupancy_timeout = 141 ihost->user_parameters.ssp_max_occupancy_timeout; 142 rnc->ssp.connection_inactivity_timeout = 143 ihost->user_parameters.ssp_inactivity_timeout; 144 } 145 146 rnc->ssp.initial_arbitration_wait_time = 0; 147 148 /* Open Address Frame Parameters */ 149 rnc->ssp.oaf_connection_rate = idev->connection_rate; 150 rnc->ssp.oaf_features = 0; 151 rnc->ssp.oaf_source_zone_group = 0; 152 rnc->ssp.oaf_more_compatibility_features = 0; 153 } 154 155 /** 156 * 157 * @sci_rnc: 158 * @callback: 159 * @callback_parameter: 160 * 161 * This method will setup the remote node context object so it will transition 162 * to its ready state. If the remote node context is already setup to 163 * transition to its final state then this function does nothing. none 164 */ 165 static void sci_remote_node_context_setup_to_resume( 166 struct sci_remote_node_context *sci_rnc, 167 scics_sds_remote_node_context_callback callback, 168 void *callback_parameter) 169 { 170 if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { 171 sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; 172 sci_rnc->user_callback = callback; 173 sci_rnc->user_cookie = callback_parameter; 174 } 175 } 176 177 static void sci_remote_node_context_setup_to_destory( 178 struct sci_remote_node_context *sci_rnc, 179 scics_sds_remote_node_context_callback callback, 180 void *callback_parameter) 181 { 182 sci_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; 183 sci_rnc->user_callback = callback; 184 sci_rnc->user_cookie = callback_parameter; 185 } 186 187 /** 188 * 189 * 190 * This method just calls the user callback function and then resets the 191 * callback. 192 */ 193 static void sci_remote_node_context_notify_user( 194 struct sci_remote_node_context *rnc) 195 { 196 if (rnc->user_callback != NULL) { 197 (*rnc->user_callback)(rnc->user_cookie); 198 199 rnc->user_callback = NULL; 200 rnc->user_cookie = NULL; 201 } 202 } 203 204 static void sci_remote_node_context_continue_state_transitions(struct sci_remote_node_context *rnc) 205 { 206 if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) 207 sci_remote_node_context_resume(rnc, rnc->user_callback, 208 rnc->user_cookie); 209 } 210 211 static void sci_remote_node_context_validate_context_buffer(struct sci_remote_node_context *sci_rnc) 212 { 213 union scu_remote_node_context *rnc_buffer; 214 struct isci_remote_device *idev = rnc_to_dev(sci_rnc); 215 struct domain_device *dev = idev->domain_dev; 216 struct isci_host *ihost = idev->owning_port->owning_controller; 217 218 rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index); 219 220 rnc_buffer->ssp.is_valid = true; 221 222 if (!idev->is_direct_attached && 223 (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP))) { 224 sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_96); 225 } else { 226 sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32); 227 228 if (idev->is_direct_attached) 229 sci_port_setup_transports(idev->owning_port, 230 sci_rnc->remote_node_index); 231 } 232 } 233 234 static void sci_remote_node_context_invalidate_context_buffer(struct sci_remote_node_context *sci_rnc) 235 { 236 union scu_remote_node_context *rnc_buffer; 237 struct isci_remote_device *idev = rnc_to_dev(sci_rnc); 238 struct isci_host *ihost = idev->owning_port->owning_controller; 239 240 rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index); 241 242 rnc_buffer->ssp.is_valid = false; 243 244 sci_remote_device_post_request(rnc_to_dev(sci_rnc), 245 SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE); 246 } 247 248 static void sci_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm) 249 { 250 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); 251 252 /* Check to see if we have gotten back to the initial state because 253 * someone requested to destroy the remote node context object. 254 */ 255 if (sm->previous_state_id == SCI_RNC_INVALIDATING) { 256 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; 257 sci_remote_node_context_notify_user(rnc); 258 } 259 } 260 261 static void sci_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm) 262 { 263 struct sci_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), sm); 264 265 sci_remote_node_context_validate_context_buffer(sci_rnc); 266 } 267 268 static void sci_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm) 269 { 270 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); 271 272 sci_remote_node_context_invalidate_context_buffer(rnc); 273 } 274 275 static void sci_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm) 276 { 277 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); 278 struct isci_remote_device *idev; 279 struct domain_device *dev; 280 281 idev = rnc_to_dev(rnc); 282 dev = idev->domain_dev; 283 284 /* 285 * For direct attached SATA devices we need to clear the TLCR 286 * NCQ to TCi tag mapping on the phy and in cases where we 287 * resume because of a target reset we also need to update 288 * the STPTLDARNI register with the RNi of the device 289 */ 290 if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) && 291 idev->is_direct_attached) 292 sci_port_setup_transports(idev->owning_port, 293 rnc->remote_node_index); 294 295 sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME); 296 } 297 298 static void sci_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm) 299 { 300 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); 301 302 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; 303 304 if (rnc->user_callback) 305 sci_remote_node_context_notify_user(rnc); 306 } 307 308 static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm) 309 { 310 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); 311 312 sci_remote_node_context_continue_state_transitions(rnc); 313 } 314 315 static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm) 316 { 317 struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm); 318 319 sci_remote_node_context_continue_state_transitions(rnc); 320 } 321 322 static const struct sci_base_state sci_remote_node_context_state_table[] = { 323 [SCI_RNC_INITIAL] = { 324 .enter_state = sci_remote_node_context_initial_state_enter, 325 }, 326 [SCI_RNC_POSTING] = { 327 .enter_state = sci_remote_node_context_posting_state_enter, 328 }, 329 [SCI_RNC_INVALIDATING] = { 330 .enter_state = sci_remote_node_context_invalidating_state_enter, 331 }, 332 [SCI_RNC_RESUMING] = { 333 .enter_state = sci_remote_node_context_resuming_state_enter, 334 }, 335 [SCI_RNC_READY] = { 336 .enter_state = sci_remote_node_context_ready_state_enter, 337 }, 338 [SCI_RNC_TX_SUSPENDED] = { 339 .enter_state = sci_remote_node_context_tx_suspended_state_enter, 340 }, 341 [SCI_RNC_TX_RX_SUSPENDED] = { 342 .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter, 343 }, 344 [SCI_RNC_AWAIT_SUSPENSION] = { }, 345 }; 346 347 void sci_remote_node_context_construct(struct sci_remote_node_context *rnc, 348 u16 remote_node_index) 349 { 350 memset(rnc, 0, sizeof(struct sci_remote_node_context)); 351 352 rnc->remote_node_index = remote_node_index; 353 rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; 354 355 sci_init_sm(&rnc->sm, sci_remote_node_context_state_table, SCI_RNC_INITIAL); 356 } 357 358 enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc, 359 u32 event_code) 360 { 361 enum scis_sds_remote_node_context_states state; 362 363 state = sci_rnc->sm.current_state_id; 364 switch (state) { 365 case SCI_RNC_POSTING: 366 switch (scu_get_event_code(event_code)) { 367 case SCU_EVENT_POST_RNC_COMPLETE: 368 sci_change_state(&sci_rnc->sm, SCI_RNC_READY); 369 break; 370 default: 371 goto out; 372 } 373 break; 374 case SCI_RNC_INVALIDATING: 375 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { 376 if (sci_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) 377 state = SCI_RNC_INITIAL; 378 else 379 state = SCI_RNC_POSTING; 380 sci_change_state(&sci_rnc->sm, state); 381 } else { 382 switch (scu_get_event_type(event_code)) { 383 case SCU_EVENT_TYPE_RNC_SUSPEND_TX: 384 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: 385 /* We really dont care if the hardware is going to suspend 386 * the device since it's being invalidated anyway */ 387 dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), 388 "%s: SCIC Remote Node Context 0x%p was " 389 "suspeneded by hardware while being " 390 "invalidated.\n", __func__, sci_rnc); 391 break; 392 default: 393 goto out; 394 } 395 } 396 break; 397 case SCI_RNC_RESUMING: 398 if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { 399 sci_change_state(&sci_rnc->sm, SCI_RNC_READY); 400 } else { 401 switch (scu_get_event_type(event_code)) { 402 case SCU_EVENT_TYPE_RNC_SUSPEND_TX: 403 case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: 404 /* We really dont care if the hardware is going to suspend 405 * the device since it's being resumed anyway */ 406 dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), 407 "%s: SCIC Remote Node Context 0x%p was " 408 "suspeneded by hardware while being resumed.\n", 409 __func__, sci_rnc); 410 break; 411 default: 412 goto out; 413 } 414 } 415 break; 416 case SCI_RNC_READY: 417 switch (scu_get_event_type(event_code)) { 418 case SCU_EVENT_TL_RNC_SUSPEND_TX: 419 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED); 420 sci_rnc->suspension_code = scu_get_event_specifier(event_code); 421 break; 422 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 423 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED); 424 sci_rnc->suspension_code = scu_get_event_specifier(event_code); 425 break; 426 default: 427 goto out; 428 } 429 break; 430 case SCI_RNC_AWAIT_SUSPENSION: 431 switch (scu_get_event_type(event_code)) { 432 case SCU_EVENT_TL_RNC_SUSPEND_TX: 433 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED); 434 sci_rnc->suspension_code = scu_get_event_specifier(event_code); 435 break; 436 case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: 437 sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED); 438 sci_rnc->suspension_code = scu_get_event_specifier(event_code); 439 break; 440 default: 441 goto out; 442 } 443 break; 444 default: 445 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 446 "%s: invalid state %d\n", __func__, state); 447 return SCI_FAILURE_INVALID_STATE; 448 } 449 return SCI_SUCCESS; 450 451 out: 452 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 453 "%s: code: %#x state: %d\n", __func__, event_code, state); 454 return SCI_FAILURE; 455 456 } 457 458 enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc, 459 scics_sds_remote_node_context_callback cb_fn, 460 void *cb_p) 461 { 462 enum scis_sds_remote_node_context_states state; 463 464 state = sci_rnc->sm.current_state_id; 465 switch (state) { 466 case SCI_RNC_INVALIDATING: 467 sci_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); 468 return SCI_SUCCESS; 469 case SCI_RNC_POSTING: 470 case SCI_RNC_RESUMING: 471 case SCI_RNC_READY: 472 case SCI_RNC_TX_SUSPENDED: 473 case SCI_RNC_TX_RX_SUSPENDED: 474 case SCI_RNC_AWAIT_SUSPENSION: 475 sci_remote_node_context_setup_to_destory(sci_rnc, cb_fn, cb_p); 476 sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING); 477 return SCI_SUCCESS; 478 case SCI_RNC_INITIAL: 479 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 480 "%s: invalid state %d\n", __func__, state); 481 /* We have decided that the destruct request on the remote node context 482 * can not fail since it is either in the initial/destroyed state or is 483 * can be destroyed. 484 */ 485 return SCI_SUCCESS; 486 default: 487 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 488 "%s: invalid state %d\n", __func__, state); 489 return SCI_FAILURE_INVALID_STATE; 490 } 491 } 492 493 enum sci_status sci_remote_node_context_suspend(struct sci_remote_node_context *sci_rnc, 494 u32 suspend_type, 495 scics_sds_remote_node_context_callback cb_fn, 496 void *cb_p) 497 { 498 enum scis_sds_remote_node_context_states state; 499 500 state = sci_rnc->sm.current_state_id; 501 if (state != SCI_RNC_READY) { 502 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 503 "%s: invalid state %d\n", __func__, state); 504 return SCI_FAILURE_INVALID_STATE; 505 } 506 507 sci_rnc->user_callback = cb_fn; 508 sci_rnc->user_cookie = cb_p; 509 sci_rnc->suspension_code = suspend_type; 510 511 if (suspend_type == SCI_SOFTWARE_SUSPENSION) { 512 sci_remote_device_post_request(rnc_to_dev(sci_rnc), 513 SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX); 514 } 515 516 sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION); 517 return SCI_SUCCESS; 518 } 519 520 enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc, 521 scics_sds_remote_node_context_callback cb_fn, 522 void *cb_p) 523 { 524 enum scis_sds_remote_node_context_states state; 525 526 state = sci_rnc->sm.current_state_id; 527 switch (state) { 528 case SCI_RNC_INITIAL: 529 if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) 530 return SCI_FAILURE_INVALID_STATE; 531 532 sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); 533 sci_remote_node_context_construct_buffer(sci_rnc); 534 sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING); 535 return SCI_SUCCESS; 536 case SCI_RNC_POSTING: 537 case SCI_RNC_INVALIDATING: 538 case SCI_RNC_RESUMING: 539 if (sci_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) 540 return SCI_FAILURE_INVALID_STATE; 541 542 sci_rnc->user_callback = cb_fn; 543 sci_rnc->user_cookie = cb_p; 544 return SCI_SUCCESS; 545 case SCI_RNC_TX_SUSPENDED: { 546 struct isci_remote_device *idev = rnc_to_dev(sci_rnc); 547 struct domain_device *dev = idev->domain_dev; 548 549 sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); 550 551 /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ 552 if (dev->dev_type == SAS_END_DEV || dev_is_expander(dev)) 553 sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); 554 else if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { 555 if (idev->is_direct_attached) { 556 /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ 557 sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); 558 } else { 559 sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING); 560 } 561 } else 562 return SCI_FAILURE; 563 return SCI_SUCCESS; 564 } 565 case SCI_RNC_TX_RX_SUSPENDED: 566 sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); 567 sci_change_state(&sci_rnc->sm, SCI_RNC_RESUMING); 568 return SCI_FAILURE_INVALID_STATE; 569 case SCI_RNC_AWAIT_SUSPENSION: 570 sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p); 571 return SCI_SUCCESS; 572 default: 573 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 574 "%s: invalid state %d\n", __func__, state); 575 return SCI_FAILURE_INVALID_STATE; 576 } 577 } 578 579 enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc, 580 struct isci_request *ireq) 581 { 582 enum scis_sds_remote_node_context_states state; 583 584 state = sci_rnc->sm.current_state_id; 585 586 switch (state) { 587 case SCI_RNC_READY: 588 return SCI_SUCCESS; 589 case SCI_RNC_TX_SUSPENDED: 590 case SCI_RNC_TX_RX_SUSPENDED: 591 case SCI_RNC_AWAIT_SUSPENSION: 592 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 593 "%s: invalid state %d\n", __func__, state); 594 return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; 595 default: 596 break; 597 } 598 dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)), 599 "%s: requested to start IO while still resuming, %d\n", 600 __func__, state); 601 return SCI_FAILURE_INVALID_STATE; 602 } 603 604 enum sci_status sci_remote_node_context_start_task(struct sci_remote_node_context *sci_rnc, 605 struct isci_request *ireq) 606 { 607 enum scis_sds_remote_node_context_states state; 608 609 state = sci_rnc->sm.current_state_id; 610 switch (state) { 611 case SCI_RNC_RESUMING: 612 case SCI_RNC_READY: 613 case SCI_RNC_AWAIT_SUSPENSION: 614 return SCI_SUCCESS; 615 case SCI_RNC_TX_SUSPENDED: 616 case SCI_RNC_TX_RX_SUSPENDED: 617 sci_remote_node_context_resume(sci_rnc, NULL, NULL); 618 return SCI_SUCCESS; 619 default: 620 dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), 621 "%s: invalid state %d\n", __func__, state); 622 return SCI_FAILURE_INVALID_STATE; 623 } 624 } 625