Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.4-rc4 624 lines 21 kB view raw
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) 65const 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 */ 81bool 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 93static 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 102static 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 */ 165static 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 177static 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 */ 193static 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 204static 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 211static 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 234static 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 248static 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 261static 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 268static 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 275static 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 298static 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 308static 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 315static 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 322static 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 347void 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 358enum 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 458enum 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 493enum 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 520enum 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 579enum 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 604enum 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}