/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * BSD LICENSE * * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ #include <scsi/sas_ata.h> #include"host.h" #include"isci.h" #include"remote_device.h" #include"remote_node_context.h" #include"scu_event_codes.h" #include"scu_task_context.h"
if (state >= ARRAY_SIZE(strings)) return"UNKNOWN";
return strings[state];
} #undef C
/** * sci_remote_node_context_is_ready() * @sci_rnc: The state of the remote node context object to check. * * This method will return true if the remote node context is in a READY state * otherwise it will return false bool true if the remote node context is in * the ready state. false if the remote node context is not in the ready state.
*/ bool sci_remote_node_context_is_ready( struct sci_remote_node_context *sci_rnc)
{
u32 current_state = sci_rnc->sm.current_state_id;
if (current_state == SCI_RNC_READY) { returntrue;
}
/* sas address is __be64, context ram format is __le64 */
sas_addr = cpu_to_le64(SAS_ADDR(dev->sas_addr));
rnc->ssp.remote_sas_address_hi = upper_32_bits(sas_addr);
rnc->ssp.remote_sas_address_lo = lower_32_bits(sas_addr);
/* Open Address Frame Parameters */
rnc->ssp.oaf_connection_rate = idev->connection_rate;
rnc->ssp.oaf_features = 0;
rnc->ssp.oaf_source_zone_group = 0;
rnc->ssp.oaf_more_compatibility_features = 0;
} /* * This method will setup the remote node context object so it will transition * to its ready state. If the remote node context is already setup to * transition to its final state then this function does nothing. none
*/ staticvoid sci_remote_node_context_setup_to_resume( struct sci_remote_node_context *sci_rnc,
scics_sds_remote_node_context_callback callback, void *callback_parameter, enum sci_remote_node_context_destination_state dest_param)
{ if (sci_rnc->destination_state != RNC_DEST_FINAL) {
sci_rnc->destination_state = dest_param; if (callback != NULL) {
sci_rnc->user_callback = callback;
sci_rnc->user_cookie = callback_parameter;
}
}
}
/* * This method just calls the user callback function and then resets the * callback.
*/ staticvoid sci_remote_node_context_notify_user( struct sci_remote_node_context *rnc)
{ if (rnc->user_callback != NULL) {
(*rnc->user_callback)(rnc->user_cookie);
/* Check to see if we have gotten back to the initial state because * someone requested to destroy the remote node context object.
*/ if (sm->previous_state_id == SCI_RNC_INVALIDATING) {
rnc->destination_state = RNC_DEST_UNSPECIFIED;
sci_remote_node_context_notify_user(rnc);
/* * For direct attached SATA devices we need to clear the TLCR * NCQ to TCi tag mapping on the phy and in cases where we * resume because of a target reset we also need to update * the STPTLDARNI register with the RNi of the device
*/ if (dev_is_sata(dev) && !dev->parent)
sci_port_setup_transports(idev->owning_port, rnc->remote_node_index);
state = sci_rnc->sm.current_state_id; switch (state) { case SCI_RNC_POSTING: switch (scu_get_event_code(event_code)) { case SCU_EVENT_POST_RNC_COMPLETE:
sci_change_state(&sci_rnc->sm, SCI_RNC_READY); break; default: goto out;
} break; case SCI_RNC_INVALIDATING: if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { if (sci_rnc->destination_state == RNC_DEST_FINAL)
next_state = SCI_RNC_INITIAL; else
next_state = SCI_RNC_POSTING;
sci_change_state(&sci_rnc->sm, next_state);
} else { switch (scu_get_event_type(event_code)) { case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: /* We really dont care if the hardware is going to suspend
* the device since it's being invalidated anyway */
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p was " "suspended by hardware while being " "invalidated.\n", __func__, sci_rnc); break; default: goto out;
}
} break; case SCI_RNC_RESUMING: if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) {
sci_change_state(&sci_rnc->sm, SCI_RNC_READY);
} else { switch (scu_get_event_type(event_code)) { case SCU_EVENT_TYPE_RNC_SUSPEND_TX: case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: /* We really dont care if the hardware is going to suspend
* the device since it's being resumed anyway */
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: SCIC Remote Node Context 0x%p was " "suspended by hardware while being resumed.\n",
__func__, sci_rnc); break; default: goto out;
}
} break; case SCI_RNC_READY: switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_SUSPENDED);
sci_rnc->suspend_type = scu_get_event_type(event_code); break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
sci_change_state(&sci_rnc->sm, SCI_RNC_TX_RX_SUSPENDED);
sci_rnc->suspend_type = scu_get_event_type(event_code); break; default: goto out;
} break; case SCI_RNC_AWAIT_SUSPENSION: switch (scu_get_event_type(event_code)) { case SCU_EVENT_TL_RNC_SUSPEND_TX:
next_state = SCI_RNC_TX_SUSPENDED; break; case SCU_EVENT_TL_RNC_SUSPEND_TX_RX:
next_state = SCI_RNC_TX_RX_SUSPENDED; break; default: goto out;
} if (sci_rnc->suspend_type == scu_get_event_type(event_code))
sci_change_state(&sci_rnc->sm, next_state); break; default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state: %s\n", __func__,
rnc_state_name(state)); return SCI_FAILURE_INVALID_STATE;
} return SCI_SUCCESS;
state = sci_rnc->sm.current_state_id; switch (state) { case SCI_RNC_INVALIDATING:
sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p); return SCI_SUCCESS; case SCI_RNC_POSTING: case SCI_RNC_RESUMING: case SCI_RNC_READY: case SCI_RNC_TX_SUSPENDED: case SCI_RNC_TX_RX_SUSPENDED:
sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p);
sci_change_state(&sci_rnc->sm, SCI_RNC_INVALIDATING); return SCI_SUCCESS; case SCI_RNC_AWAIT_SUSPENSION:
sci_remote_node_context_setup_to_destroy(sci_rnc, cb_fn, cb_p); return SCI_SUCCESS; case SCI_RNC_INITIAL:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state: %s\n", __func__,
rnc_state_name(state)); /* We have decided that the destruct request on the remote node context * can not fail since it is either in the initial/destroyed state or is * can be destroyed.
*/ return SCI_SUCCESS; default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %s\n", __func__,
rnc_state_name(state)); return SCI_FAILURE_INVALID_STATE;
}
}
dev_dbg(scirdev_to_dev(idev), "%s: current state %s, current suspend_type %x dest state %d," " arg suspend_reason %d, arg suspend_type %x",
__func__, rnc_state_name(state), sci_rnc->suspend_type,
sci_rnc->destination_state, suspend_reason,
suspend_type);
/* Disable automatic state continuations if explicitly suspending. */ if ((suspend_reason == SCI_HW_SUSPEND) ||
(sci_rnc->destination_state == RNC_DEST_FINAL))
dest_param = sci_rnc->destination_state;
switch (state) { case SCI_RNC_READY: break; case SCI_RNC_INVALIDATING: if (sci_rnc->destination_state == RNC_DEST_FINAL) {
dev_warn(scirdev_to_dev(idev), "%s: already destroying %p\n",
__func__, sci_rnc); return SCI_FAILURE_INVALID_STATE;
}
fallthrough; /* and handle like SCI_RNC_POSTING */ case SCI_RNC_RESUMING:
fallthrough; /* and handle like SCI_RNC_POSTING */ case SCI_RNC_POSTING: /* Set the destination state to AWAIT - this signals the * entry into the SCI_RNC_READY state that a suspension * needs to be done immediately.
*/ if (sci_rnc->destination_state != RNC_DEST_FINAL)
sci_rnc->destination_state = RNC_DEST_SUSPENDED;
sci_rnc->suspend_type = suspend_type;
sci_rnc->suspend_reason = suspend_reason; return SCI_SUCCESS;
case SCI_RNC_TX_SUSPENDED: if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX)
status = SCI_SUCCESS; break; case SCI_RNC_TX_RX_SUSPENDED: if (suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
status = SCI_SUCCESS; break; case SCI_RNC_AWAIT_SUSPENSION: if ((sci_rnc->suspend_type == SCU_EVENT_TL_RNC_SUSPEND_TX_RX)
|| (suspend_type == sci_rnc->suspend_type)) return SCI_SUCCESS; break; default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %s\n", __func__,
rnc_state_name(state)); return SCI_FAILURE_INVALID_STATE;
}
sci_rnc->destination_state = dest_param;
sci_rnc->suspend_type = suspend_type;
sci_rnc->suspend_reason = suspend_reason;
if (status == SCI_SUCCESS) { /* Already in the destination state? */ struct isci_host *ihost = idev->owning_port->owning_controller;
wake_up_all(&ihost->eventq); /* Let observers look. */ return SCI_SUCCESS;
} if ((suspend_reason == SCI_SW_SUSPEND_NORMAL) ||
(suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)) {
if (suspend_reason == SCI_SW_SUSPEND_LINKHANG_DETECT)
isci_dev_set_hang_detection_timeout(idev, 0x00000001);
sci_remote_device_post_request(
idev, SCI_SOFTWARE_SUSPEND_CMD);
} if (state != SCI_RNC_AWAIT_SUSPENSION)
sci_change_state(&sci_rnc->sm, SCI_RNC_AWAIT_SUSPENSION);
case SCI_RNC_POSTING: case SCI_RNC_INVALIDATING: case SCI_RNC_RESUMING: /* We are still waiting to post when a resume was * requested.
*/ switch (sci_rnc->destination_state) { case RNC_DEST_SUSPENDED: case RNC_DEST_SUSPENDED_RESUME: /* Previously waiting to suspend after posting. * Now continue onto resumption.
*/
sci_remote_node_context_setup_to_resume(
sci_rnc, cb_fn, cb_p,
RNC_DEST_SUSPENDED_RESUME); break; default:
sci_remote_node_context_setup_to_resume(
sci_rnc, cb_fn, cb_p,
RNC_DEST_READY); break;
} return SCI_SUCCESS;
case SCI_RNC_TX_SUSPENDED: case SCI_RNC_TX_RX_SUSPENDED:
{ struct domain_device *dev = idev->domain_dev; /* If this is an expander attached SATA device we must * invalidate and repost the RNC since this is the only * way to clear the TCi to NCQ tag mapping table for * the RNi. All other device types we can just resume.
*/
sci_remote_node_context_setup_to_resume(
sci_rnc, cb_fn, cb_p, RNC_DEST_READY);
int sci_remote_node_context_is_safe_to_abort( struct sci_remote_node_context *sci_rnc)
{ enum scis_sds_remote_node_context_states state;
state = sci_rnc->sm.current_state_id; switch (state) { case SCI_RNC_INVALIDATING: case SCI_RNC_TX_RX_SUSPENDED: return 1; case SCI_RNC_POSTING: case SCI_RNC_RESUMING: case SCI_RNC_READY: case SCI_RNC_TX_SUSPENDED: case SCI_RNC_AWAIT_SUSPENSION: case SCI_RNC_INITIAL: return 0; default:
dev_warn(scirdev_to_dev(rnc_to_dev(sci_rnc)), "%s: invalid state %d\n", __func__, state); return 0;
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.