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