linux/drivers/scsi/isci/remote_node_context.c
<<
>>
Prefs
   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#include <scsi/sas_ata.h>
  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
  93bool sci_remote_node_context_is_suspended(struct sci_remote_node_context *sci_rnc)
  94{
  95        u32 current_state = sci_rnc->sm.current_state_id;
  96
  97        if (current_state == SCI_RNC_TX_RX_SUSPENDED)
  98                return true;
  99        return false;
 100}
 101
 102static union scu_remote_node_context *sci_rnc_by_id(struct isci_host *ihost, u16 id)
 103{
 104        if (id < ihost->remote_node_entries &&
 105            ihost->device_table[id])
 106                return &ihost->remote_node_context_table[id];
 107
 108        return NULL;
 109}
 110
 111static void sci_remote_node_context_construct_buffer(struct sci_remote_node_context *sci_rnc)
 112{
 113        struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
 114        struct domain_device *dev = idev->domain_dev;
 115        int rni = sci_rnc->remote_node_index;
 116        union scu_remote_node_context *rnc;
 117        struct isci_host *ihost;
 118        __le64 sas_addr;
 119
 120        ihost = idev->owning_port->owning_controller;
 121        rnc = sci_rnc_by_id(ihost, rni);
 122
 123        memset(rnc, 0, sizeof(union scu_remote_node_context)
 124                * sci_remote_device_node_count(idev));
 125
 126        rnc->ssp.remote_node_index = rni;
 127        rnc->ssp.remote_node_port_width = idev->device_port_width;
 128        rnc->ssp.logical_port_index = idev->owning_port->physical_port_index;
 129
 130        /* sas address is __be64, context ram format is __le64 */
 131        sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr));
 132        rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr);
 133        rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr);
 134
 135        rnc->ssp.nexus_loss_timer_enable = true;
 136        rnc->ssp.check_bit               = false;
 137        rnc->ssp.is_valid                = false;
 138        rnc->ssp.is_remote_node_context  = true;
 139        rnc->ssp.function_number         = 0;
 140
 141        rnc->ssp.arbitration_wait_time = 0;
 142
 143        if (dev_is_sata(dev)) {
 144                rnc->ssp.connection_occupancy_timeout =
 145                        ihost->user_parameters.stp_max_occupancy_timeout;
 146                rnc->ssp.connection_inactivity_timeout =
 147                        ihost->user_parameters.stp_inactivity_timeout;
 148        } else {
 149                rnc->ssp.connection_occupancy_timeout  =
 150                        ihost->user_parameters.ssp_max_occupancy_timeout;
 151                rnc->ssp.connection_inactivity_timeout =
 152                        ihost->user_parameters.ssp_inactivity_timeout;
 153        }
 154
 155        rnc->ssp.initial_arbitration_wait_time = 0;
 156
 157        /* Open Address Frame Parameters */
 158        rnc->ssp.oaf_connection_rate = idev->connection_rate;
 159        rnc->ssp.oaf_features = 0;
 160        rnc->ssp.oaf_source_zone_group = 0;
 161        rnc->ssp.oaf_more_compatibility_features = 0;
 162}
 163/**
 164 *
 165 * @sci_rnc:
 166 * @callback:
 167 * @callback_parameter:
 168 *
 169 * This method will setup the remote node context object so it will transition
 170 * to its ready state.  If the remote node context is already setup to
 171 * transition to its final state then this function does nothing. none
 172 */
 173static void sci_remote_node_context_setup_to_resume(
 174        struct sci_remote_node_context *sci_rnc,
 175        scics_sds_remote_node_context_callback callback,
 176        void *callback_parameter,
 177        enum sci_remote_node_context_destination_state dest_param)
 178{
 179        if (sci_rnc->destination_state != RNC_DEST_FINAL) {
 180                sci_rnc->destination_state = dest_param;
 181                if (callback != NULL) {
 182                        sci_rnc->user_callback = callback;
 183                        sci_rnc->user_cookie   = callback_parameter;
 184                }
 185        }
 186}
 187
 188static void sci_remote_node_context_setup_to_destroy(
 189        struct sci_remote_node_context *sci_rnc,
 190        scics_sds_remote_node_context_callback callback,
 191        void *callback_parameter)
 192{
 193        struct isci_host *ihost = idev_to_ihost(rnc_to_dev(sci_rnc));
 194
 195        sci_rnc->destination_state = RNC_DEST_FINAL;
 196        sci_rnc->user_callback     = callback;
 197        sci_rnc->user_cookie       = callback_parameter;
 198
 199        wake_up(&ihost->eventq);
 200}
 201
 202/**
 203 *
 204 *
 205 * This method just calls the user callback function and then resets the
 206 * callback.
 207 */
 208static void sci_remote_node_context_notify_user(
 209        struct sci_remote_node_context *rnc)
 210{
 211        if (rnc->user_callback != NULL) {
 212                (*rnc->user_callback)(rnc->user_cookie);
 213
 214                rnc->user_callback = NULL;
 215                rnc->user_cookie = NULL;
 216        }
 217}
 218
 219static void sci_remote_node_context_continue_state_transitions(struct sci_remote_node_context *rnc)
 220{
 221        switch (rnc->destination_state) {
 222        case RNC_DEST_READY:
 223        case RNC_DEST_SUSPENDED_RESUME:
 224                rnc->destination_state = RNC_DEST_READY;
 225                /* Fall through... */
 226        case RNC_DEST_FINAL:
 227                sci_remote_node_context_resume(rnc, rnc->user_callback,
 228                                               rnc->user_cookie);
 229                break;
 230        default:
 231                rnc->destination_state = RNC_DEST_UNSPECIFIED;
 232                break;
 233        }
 234}
 235
 236static void sci_remote_node_context_validate_context_buffer(struct sci_remote_node_context *sci_rnc)
 237{
 238        union scu_remote_node_context *rnc_buffer;
 239        struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
 240        struct domain_device *dev = idev->domain_dev;
 241        struct isci_host *ihost = idev->owning_port->owning_controller;
 242
 243        rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index);
 244
 245        rnc_buffer->ssp.is_valid = true;
 246
 247        if (dev_is_sata(dev) && dev->parent) {
 248                sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_96);
 249        } else {
 250                sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_32);
 251
 252                if (!dev->parent)
 253                        sci_port_setup_transports(idev->owning_port,
 254                                                  sci_rnc->remote_node_index);
 255        }
 256}
 257
 258static void sci_remote_node_context_invalidate_context_buffer(struct sci_remote_node_context *sci_rnc)
 259{
 260        union scu_remote_node_context *rnc_buffer;
 261        struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
 262        struct isci_host *ihost = idev->owning_port->owning_controller;
 263
 264        rnc_buffer = sci_rnc_by_id(ihost, sci_rnc->remote_node_index);
 265
 266        rnc_buffer->ssp.is_valid = false;
 267
 268        sci_remote_device_post_request(rnc_to_dev(sci_rnc),
 269                                       SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE);
 270}
 271
 272static void sci_remote_node_context_initial_state_enter(struct sci_base_state_machine *sm)
 273{
 274        struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
 275        struct isci_remote_device *idev = rnc_to_dev(rnc);
 276        struct isci_host *ihost = idev->owning_port->owning_controller;
 277
 278        /* Check to see if we have gotten back to the initial state because
 279         * someone requested to destroy the remote node context object.
 280         */
 281        if (sm->previous_state_id == SCI_RNC_INVALIDATING) {
 282                rnc->destination_state = RNC_DEST_UNSPECIFIED;
 283                sci_remote_node_context_notify_user(rnc);
 284
 285                smp_wmb();
 286                wake_up(&ihost->eventq);
 287        }
 288}
 289
 290static void sci_remote_node_context_posting_state_enter(struct sci_base_state_machine *sm)
 291{
 292        struct sci_remote_node_context *sci_rnc = container_of(sm, typeof(*sci_rnc), sm);
 293
 294        sci_remote_node_context_validate_context_buffer(sci_rnc);
 295}
 296
 297static void sci_remote_node_context_invalidating_state_enter(struct sci_base_state_machine *sm)
 298{
 299        struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
 300
 301        /* Terminate all outstanding requests. */
 302        sci_remote_device_terminate_requests(rnc_to_dev(rnc));
 303        sci_remote_node_context_invalidate_context_buffer(rnc);
 304}
 305
 306static void sci_remote_node_context_resuming_state_enter(struct sci_base_state_machine *sm)
 307{
 308        struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
 309        struct isci_remote_device *idev;
 310        struct domain_device *dev;
 311
 312        idev = rnc_to_dev(rnc);
 313        dev = idev->domain_dev;
 314
 315        /*
 316         * For direct attached SATA devices we need to clear the TLCR
 317         * NCQ to TCi tag mapping on the phy and in cases where we
 318         * resume because of a target reset we also need to update
 319         * the STPTLDARNI register with the RNi of the device
 320         */
 321        if (dev_is_sata(dev) && !dev->parent)
 322                sci_port_setup_transports(idev->owning_port, rnc->remote_node_index);
 323
 324        sci_remote_device_post_request(idev, SCU_CONTEXT_COMMAND_POST_RNC_RESUME);
 325}
 326
 327static void sci_remote_node_context_ready_state_enter(struct sci_base_state_machine *sm)
 328{
 329        struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
 330        enum sci_remote_node_context_destination_state dest_select;
 331        int tell_user = 1;
 332
 333        dest_select = rnc->destination_state;
 334        rnc->destination_state = RNC_DEST_UNSPECIFIED;
 335
 336        if ((dest_select == RNC_DEST_SUSPENDED) ||
 337            (dest_select == RNC_DEST_SUSPENDED_RESUME)) {
 338                sci_remote_node_context_suspend(
 339                        rnc, rnc->suspend_reason,
 340                        SCI_SOFTWARE_SUSPEND_EXPECTED_EVENT);
 341
 342                if (dest_select == RNC_DEST_SUSPENDED_RESUME)
 343                        tell_user = 0;  /* Wait until ready again. */
 344        }
 345        if (tell_user)
 346                sci_remote_node_context_notify_user(rnc);
 347}
 348
 349static void sci_remote_node_context_tx_suspended_state_enter(struct sci_base_state_machine *sm)
 350{
 351        struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
 352
 353        sci_remote_node_context_continue_state_transitions(rnc);
 354}
 355
 356static void sci_remote_node_context_tx_rx_suspended_state_enter(struct sci_base_state_machine *sm)
 357{
 358        struct sci_remote_node_context *rnc = container_of(sm, typeof(*rnc), sm);
 359        struct isci_remote_device *idev = rnc_to_dev(rnc);
 360        struct isci_host *ihost = idev->owning_port->owning_controller;
 361        u32 new_count = rnc->suspend_count + 1;
 362
 363        if (new_count == 0)
 364                rnc->suspend_count = 1;
 365        else
 366                rnc->suspend_count = new_count;
 367        smp_wmb();
 368
 369        /* Terminate outstanding requests pending abort. */
 370        sci_remote_device_abort_requests_pending_abort(idev);
 371
 372        wake_up(&ihost->eventq);
 373        sci_remote_node_context_continue_state_transitions(rnc);
 374}
 375
 376static void sci_remote_node_context_await_suspend_state_exit(
 377        struct sci_base_state_machine *sm)
 378{
 379        struct sci_remote_node_context *rnc
 380                = container_of(sm, typeof(*rnc), sm);
 381        struct isci_remote_device *idev = rnc_to_dev(rnc);
 382
 383        if (dev_is_sata(idev->domain_dev))
 384                isci_dev_set_hang_detection_timeout(idev, 0);
 385}
 386
 387static const struct sci_base_state sci_remote_node_context_state_table[] = {
 388        [SCI_RNC_INITIAL] = {
 389                .enter_state = sci_remote_node_context_initial_state_enter,
 390        },
 391        [SCI_RNC_POSTING] = {
 392                .enter_state = sci_remote_node_context_posting_state_enter,
 393        },
 394        [SCI_RNC_INVALIDATING] = {
 395                .enter_state = sci_remote_node_context_invalidating_state_enter,
 396        },
 397        [SCI_RNC_RESUMING] = {
 398                .enter_state = sci_remote_node_context_resuming_state_enter,
 399        },
 400        [SCI_RNC_READY] = {
 401                .enter_state = sci_remote_node_context_ready_state_enter,
 402        },
 403        [SCI_RNC_TX_SUSPENDED] = {
 404                .enter_state = sci_remote_node_context_tx_suspended_state_enter,
 405        },
 406        [SCI_RNC_TX_RX_SUSPENDED] = {
 407                .enter_state = sci_remote_node_context_tx_rx_suspended_state_enter,
 408        },
 409        [SCI_RNC_AWAIT_SUSPENSION] = {
 410                .exit_state = sci_remote_node_context_await_suspend_state_exit,
 411        },
 412};
 413
 414void sci_remote_node_context_construct(struct sci_remote_node_context *rnc,
 415                                            u16 remote_node_index)
 416{
 417        memset(rnc, 0, sizeof(struct sci_remote_node_context));
 418
 419        rnc->remote_node_index = remote_node_index;
 420        rnc->destination_state = RNC_DEST_UNSPECIFIED;
 421
 422        sci_init_sm(&rnc->sm, sci_remote_node_context_state_table, SCI_RNC_INITIAL);
 423}
 424
 425enum sci_status sci_remote_node_context_event_handler(struct sci_remote_node_context *sci_rnc,
 426                                                           u32 event_code)
 427{
 428        enum scis_sds_remote_node_context_states state;
 429        u32 next_state;
 430
 431        state = sci_rnc->sm.current_state_id;
 432        switch (state) {
 433        case SCI_RNC_POSTING:
 434                switch (scu_get_event_code(event_code)) {
 435                case SCU_EVENT_POST_RNC_COMPLETE:
 436                        sci_change_state(&sci_rnc->sm, SCI_RNC_READY);
 437                        break;
 438                default:
 439                        goto out;
 440                }
 441                break;
 442        case SCI_RNC_INVALIDATING:
 443                if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) {
 444                        if (sci_rnc->destination_state == RNC_DEST_FINAL)
 445                                next_state = SCI_RNC_INITIAL;
 446                        else
 447                                next_state = SCI_RNC_POSTING;
 448                        sci_change_state(&sci_rnc->sm, next_state);
 449                } else {
 450                        switch (scu_get_event_type(event_code)) {
 451                        case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
 452                        case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
 453                                /* We really dont care if the hardware is going to suspend
 454                                 * the device since it's being invalidated anyway */
 455                                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 456                                        "%s: SCIC Remote Node Context 0x%p was "
 457                                        "suspeneded by hardware while being "
 458                                        "invalidated.\n", __func__, sci_rnc);
 459                                break;
 460                        default:
 461                                goto out;
 462                        }
 463                }
 464                break;
 465        case SCI_RNC_RESUMING:
 466                if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
 467                        sci_change_state(&sci_rnc->sm, SCI_RNC_READY);
 468                } else {
 469                        switch (scu_get_event_type(event_code)) {
 470                        case SCU_EVENT_TYPE_RNC_SUSPEND_TX:
 471                        case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX:
 472                                /* We really dont care if the hardware is going to suspend
 473                                 * the device since it's being resumed anyway */
 474                                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 475                                        "%s: SCIC Remote Node Context 0x%p was "
 476                                        "suspeneded by hardware while being resumed.\n",
 477                                        __func__, sci_rnc);
 478                                break;
 479                        default:
 480                                goto out;
 481                        }
 482                }
 483                break;
 484        case SCI_RNC_READY:
 485                switch (scu_get_event_type(event_code)) {
 486                case SCU_EVENT_TL_RNC_SUSPEND_TX:
 487                        sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
 488                        sci_rnc->suspend_type = scu_get_event_type(event_code);
 489                        break;
 490                case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
 491                        sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
 492                        sci_rnc->suspend_type = scu_get_event_type(event_code);
 493                        break;
 494                default:
 495                        goto out;
 496                }
 497                break;
 498        case SCI_RNC_AWAIT_SUSPENSION:
 499                switch (scu_get_event_type(event_code)) {
 500                case SCU_EVENT_TL_RNC_SUSPEND_TX:
 501                        next_state = SCI_RNC_TX_SUSPENDED;
 502                        break;
 503                case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
 504                        next_state = SCI_RNC_TX_RX_SUSPENDED;
 505                        break;
 506                default:
 507                        goto out;
 508                }
 509                if (sci_rnc->suspend_type == scu_get_event_type(event_code))
 510                        sci_change_state(&sci_rnc->sm, next_state);
 511                break;
 512        default:
 513                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 514                         "%s: invalid state: %s\n", __func__,
 515                         rnc_state_name(state));
 516                return SCI_FAILURE_INVALID_STATE;
 517        }
 518        return SCI_SUCCESS;
 519
 520 out:
 521        dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 522                 "%s: code: %#x state: %s\n", __func__, event_code,
 523                 rnc_state_name(state));
 524        return SCI_FAILURE;
 525
 526}
 527
 528enum sci_status sci_remote_node_context_destruct(struct sci_remote_node_context *sci_rnc,
 529                                                      scics_sds_remote_node_context_callback cb_fn,
 530                                                      void *cb_p)
 531{
 532        enum scis_sds_remote_node_context_states state;
 533
 534        state = sci_rnc->sm.current_state_id;
 535        switch (state) {
 536        case SCI_RNC_INVALIDATING:
 537                sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
 538                return SCI_SUCCESS;
 539        case SCI_RNC_POSTING:
 540        case SCI_RNC_RESUMING:
 541        case SCI_RNC_READY:
 542        case SCI_RNC_TX_SUSPENDED:
 543        case SCI_RNC_TX_RX_SUSPENDED:
 544                sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
 545                sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING);
 546                return SCI_SUCCESS;
 547        case SCI_RNC_AWAIT_SUSPENSION:
 548                sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
 549                return SCI_SUCCESS;
 550        case SCI_RNC_INITIAL:
 551                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 552                         "%s: invalid state: %s\n", __func__,
 553                         rnc_state_name(state));
 554                /* We have decided that the destruct request on the remote node context
 555                 * can not fail since it is either in the initial/destroyed state or is
 556                 * can be destroyed.
 557                 */
 558                return SCI_SUCCESS;
 559        default:
 560                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 561                         "%s: invalid state %s\n", __func__,
 562                         rnc_state_name(state));
 563                return SCI_FAILURE_INVALID_STATE;
 564        }
 565}
 566
 567enum sci_status sci_remote_node_context_suspend(
 568                        struct sci_remote_node_context *sci_rnc,
 569                        enum sci_remote_node_suspension_reasons suspend_reason,
 570                        u32 suspend_type)
 571{
 572        enum scis_sds_remote_node_context_states state
 573                = sci_rnc->sm.current_state_id;
 574        struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
 575        enum sci_status status = SCI_FAILURE_INVALID_STATE;
 576        enum sci_remote_node_context_destination_state dest_param =
 577                RNC_DEST_UNSPECIFIED;
 578
 579        dev_dbg(scirdev_to_dev(idev),
 580                "%s: current state %s, current suspend_type %x dest state %d,"
 581                        " arg suspend_reason %d, arg suspend_type %x",
 582                __func__, rnc_state_name(state), sci_rnc->suspend_type,
 583                sci_rnc->destination_state, suspend_reason,
 584                suspend_type);
 585
 586        /* Disable automatic state continuations if explicitly suspending. */
 587        if ((suspend_reason == SCI_HW_SUSPEND) ||
 588            (sci_rnc->destination_state == RNC_DEST_FINAL))
 589                dest_param = sci_rnc->destination_state;
 590
 591        switch (state) {
 592        case SCI_RNC_READY:
 593                break;
 594        case SCI_RNC_INVALIDATING:
 595                if (sci_rnc->destination_state == RNC_DEST_FINAL) {
 596                        dev_warn(scirdev_to_dev(idev),
 597                                 "%s: already destroying %p\n",
 598                                 __func__, sci_rnc);
 599                        return SCI_FAILURE_INVALID_STATE;
 600                }
 601                /* Fall through and handle like SCI_RNC_POSTING */
 602        case SCI_RNC_RESUMING:
 603                /* Fall through and handle like SCI_RNC_POSTING */
 604        case SCI_RNC_POSTING:
 605                /* Set the destination state to AWAIT - this signals the
 606                 * entry into the SCI_RNC_READY state that a suspension
 607                 * needs to be done immediately.
 608                 */
 609                if (sci_rnc->destination_state != RNC_DEST_FINAL)
 610                        sci_rnc->destination_state = RNC_DEST_SUSPENDED;
 611                sci_rnc->suspend_type = suspend_type;
 612                sci_rnc->suspend_reason = suspend_reason;
 613                return SCI_SUCCESS;
 614
 615        case SCI_RNC_TX_SUSPENDED:
 616                if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX)
 617                        status = SCI_SUCCESS;
 618                break;
 619        case SCI_RNC_TX_RX_SUSPENDED:
 620                if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
 621                        status = SCI_SUCCESS;
 622                break;
 623        case SCI_RNC_AWAIT_SUSPENSION:
 624                if ((sci_rnc->suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
 625                    || (suspend_type == sci_rnc->suspend_type))
 626                        return SCI_SUCCESS;
 627                break;
 628        default:
 629                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 630                         "%s: invalid state %s\n", __func__,
 631                         rnc_state_name(state));
 632                return SCI_FAILURE_INVALID_STATE;
 633        }
 634        sci_rnc->destination_state = dest_param;
 635        sci_rnc->suspend_type = suspend_type;
 636        sci_rnc->suspend_reason = suspend_reason;
 637
 638        if (status == SCI_SUCCESS) { /* Already in the destination state? */
 639                struct isci_host *ihost = idev->owning_port->owning_controller;
 640
 641                wake_up_all(&ihost->eventq); /* Let observers look. */
 642                return SCI_SUCCESS;
 643        }
 644        if ((suspend_reason == SCI_SW_SUSPEND_NORMAL) ||
 645            (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)) {
 646
 647                if (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)
 648                        isci_dev_set_hang_detection_timeout(idev, 0x00000001);
 649
 650                sci_remote_device_post_request(
 651                        idev, SCI_SOFTWARE_SUSPEND_CMD);
 652        }
 653        if (state != SCI_RNC_AWAIT_SUSPENSION)
 654                sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
 655
 656        return SCI_SUCCESS;
 657}
 658
 659enum sci_status sci_remote_node_context_resume(struct sci_remote_node_context *sci_rnc,
 660                                                    scics_sds_remote_node_context_callback cb_fn,
 661                                                    void *cb_p)
 662{
 663        enum scis_sds_remote_node_context_states state;
 664        struct isci_remote_device *idev = rnc_to_dev(sci_rnc);
 665
 666        state = sci_rnc->sm.current_state_id;
 667        dev_dbg(scirdev_to_dev(idev),
 668                "%s: state %s, cb_fn = %p, cb_p = %p; dest_state = %d; "
 669                        "dev resume path %s\n",
 670                __func__, rnc_state_name(state), cb_fn, cb_p,
 671                sci_rnc->destination_state,
 672                test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)
 673                        ? "<abort active>" : "<normal>");
 674
 675        switch (state) {
 676        case SCI_RNC_INITIAL:
 677                if (sci_rnc->remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX)
 678                        return SCI_FAILURE_INVALID_STATE;
 679
 680                sci_remote_node_context_setup_to_resume(sci_rnc, cb_fn, cb_p,
 681                                                        RNC_DEST_READY);
 682                if (!test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)) {
 683                        sci_remote_node_context_construct_buffer(sci_rnc);
 684                        sci_change_state(&sci_rnc->sm, SCI_RNC_POSTING);
 685                }
 686                return SCI_SUCCESS;
 687
 688        case SCI_RNC_POSTING:
 689        case SCI_RNC_INVALIDATING:
 690        case SCI_RNC_RESUMING:
 691                /* We are still waiting to post when a resume was
 692                 * requested.
 693                 */
 694                switch (sci_rnc->destination_state) {
 695                case RNC_DEST_SUSPENDED:
 696                case RNC_DEST_SUSPENDED_RESUME:
 697                        /* Previously waiting to suspend after posting.
 698                         * Now continue onto resumption.
 699                         */
 700                        sci_remote_node_context_setup_to_resume(
 701                                sci_rnc, cb_fn, cb_p,
 702                                RNC_DEST_SUSPENDED_RESUME);
 703                        break;
 704                default:
 705                        sci_remote_node_context_setup_to_resume(
 706                                sci_rnc, cb_fn, cb_p,
 707                                RNC_DEST_READY);
 708                        break;
 709                }
 710                return SCI_SUCCESS;
 711
 712        case SCI_RNC_TX_SUSPENDED:
 713        case SCI_RNC_TX_RX_SUSPENDED:
 714                {
 715                        struct domain_device *dev = idev->domain_dev;
 716                        /* If this is an expander attached SATA device we must
 717                         * invalidate and repost the RNC since this is the only
 718                         * way to clear the TCi to NCQ tag mapping table for
 719                         * the RNi. All other device types we can just resume.
 720                         */
 721                        sci_remote_node_context_setup_to_resume(
 722                                sci_rnc, cb_fn, cb_p, RNC_DEST_READY);
 723
 724                        if (!test_bit(IDEV_ABORT_PATH_ACTIVE, &idev->flags)) {
 725                                if ((dev_is_sata(dev) && dev->parent) ||
 726                                    (sci_rnc->destination_state == RNC_DEST_FINAL))
 727                                        sci_change_state(&sci_rnc->sm,
 728                                                         SCI_RNC_INVALIDATING);
 729                                else
 730                                        sci_change_state(&sci_rnc->sm,
 731                                                         SCI_RNC_RESUMING);
 732                        }
 733                }
 734                return SCI_SUCCESS;
 735
 736        case SCI_RNC_AWAIT_SUSPENSION:
 737                sci_remote_node_context_setup_to_resume(
 738                        sci_rnc, cb_fn, cb_p, RNC_DEST_SUSPENDED_RESUME);
 739                return SCI_SUCCESS;
 740        default:
 741                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 742                         "%s: invalid state %s\n", __func__,
 743                         rnc_state_name(state));
 744                return SCI_FAILURE_INVALID_STATE;
 745        }
 746}
 747
 748enum sci_status sci_remote_node_context_start_io(struct sci_remote_node_context *sci_rnc,
 749                                                             struct isci_request *ireq)
 750{
 751        enum scis_sds_remote_node_context_states state;
 752
 753        state = sci_rnc->sm.current_state_id;
 754
 755        switch (state) {
 756        case SCI_RNC_READY:
 757                return SCI_SUCCESS;
 758        case SCI_RNC_TX_SUSPENDED:
 759        case SCI_RNC_TX_RX_SUSPENDED:
 760        case SCI_RNC_AWAIT_SUSPENSION:
 761                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 762                         "%s: invalid state %s\n", __func__,
 763                         rnc_state_name(state));
 764                return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
 765        default:
 766                dev_dbg(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 767                        "%s: invalid state %s\n", __func__,
 768                        rnc_state_name(state));
 769                return SCI_FAILURE_INVALID_STATE;
 770        }
 771}
 772
 773enum sci_status sci_remote_node_context_start_task(
 774        struct sci_remote_node_context *sci_rnc,
 775        struct isci_request *ireq,
 776        scics_sds_remote_node_context_callback cb_fn,
 777        void *cb_p)
 778{
 779        enum sci_status status = sci_remote_node_context_resume(sci_rnc,
 780                                                                cb_fn, cb_p);
 781        if (status != SCI_SUCCESS)
 782                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 783                        "%s: resume failed: %d\n", __func__, status);
 784        return status;
 785}
 786
 787int sci_remote_node_context_is_safe_to_abort(
 788        struct sci_remote_node_context *sci_rnc)
 789{
 790        enum scis_sds_remote_node_context_states state;
 791
 792        state = sci_rnc->sm.current_state_id;
 793        switch (state) {
 794        case SCI_RNC_INVALIDATING:
 795        case SCI_RNC_TX_RX_SUSPENDED:
 796                return 1;
 797        case SCI_RNC_POSTING:
 798        case SCI_RNC_RESUMING:
 799        case SCI_RNC_READY:
 800        case SCI_RNC_TX_SUSPENDED:
 801        case SCI_RNC_AWAIT_SUSPENSION:
 802        case SCI_RNC_INITIAL:
 803                return 0;
 804        default:
 805                dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)),
 806                         "%s: invalid state %d\n", __func__, state);
 807                return 0;
 808        }
 809}
 810