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