/* * 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.h> #include <linux/bitops.h> #include "isci.h" #include "port.h" #include "remote_device.h" #include "request.h" #include "remote_node_context.h" #include "scu_event_codes.h" #include "task.h" #undef C #define C … const char *dev_state_name(enum sci_remote_device_states state) { … } #undef C enum sci_status sci_remote_device_suspend(struct isci_remote_device *idev, enum sci_remote_node_suspension_reasons reason) { … } /** * isci_remote_device_ready() - This function is called by the ihost when the * remote device is ready. We mark the isci device as ready and signal the * waiting proccess. * @ihost: our valid isci_host * @idev: remote device * */ static void isci_remote_device_ready(struct isci_host *ihost, struct isci_remote_device *idev) { … } static enum sci_status sci_remote_device_terminate_req( struct isci_host *ihost, struct isci_remote_device *idev, int check_abort, struct isci_request *ireq) { … } static enum sci_status sci_remote_device_terminate_reqs_checkabort( struct isci_remote_device *idev, int chk) { … } static bool isci_compare_suspendcount( struct isci_remote_device *idev, u32 localcount) { … } static bool isci_check_reqterm( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq, u32 localcount) { … } static bool isci_check_devempty( struct isci_host *ihost, struct isci_remote_device *idev, u32 localcount) { … } enum sci_status isci_remote_device_terminate_requests( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { … } /** * isci_remote_device_not_ready() - This function is called by the ihost when * the remote device is not ready. We mark the isci device as ready (not * "ready_for_io") and signal the waiting proccess. * @ihost: This parameter specifies the isci host object. * @idev: This parameter specifies the remote device * @reason: Reason to switch on * * sci_lock is held on entrance to this function. */ static void isci_remote_device_not_ready(struct isci_host *ihost, struct isci_remote_device *idev, u32 reason) { … } /* called once the remote node context is ready to be freed. * The remote device can now report that its stop operation is complete. none */ static void rnc_destruct_done(void *_dev) { … } enum sci_status sci_remote_device_terminate_requests( struct isci_remote_device *idev) { … } enum sci_status sci_remote_device_stop(struct isci_remote_device *idev, u32 timeout) { … } enum sci_status sci_remote_device_reset(struct isci_remote_device *idev) { … } enum sci_status sci_remote_device_reset_complete(struct isci_remote_device *idev) { … } enum sci_status sci_remote_device_frame_handler(struct isci_remote_device *idev, u32 frame_index) { … } static bool is_remote_device_ready(struct isci_remote_device *idev) { … } /* * called once the remote node context has transisitioned to a ready * state (after suspending RX and/or TX due to early D2H fis) */ static void atapi_remote_device_resume_done(void *_dev) { … } enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, u32 event_code) { … } static void sci_remote_device_start_request(struct isci_remote_device *idev, struct isci_request *ireq, enum sci_status status) { … } enum sci_status sci_remote_device_start_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { … } static enum sci_status common_complete_io(struct isci_port *iport, struct isci_remote_device *idev, struct isci_request *ireq) { … } enum sci_status sci_remote_device_complete_io(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { … } static void sci_remote_device_continue_request(void *dev) { … } enum sci_status sci_remote_device_start_task(struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { … } void sci_remote_device_post_request(struct isci_remote_device *idev, u32 request) { … } /* called once the remote node context has transisitioned to a * ready state. This is the indication that the remote device object can also * transition to ready. */ static void remote_device_resume_done(void *_dev) { … } static void sci_stp_remote_device_ready_idle_substate_resume_complete_handler(void *_dev) { … } static void sci_remote_device_initial_state_enter(struct sci_base_state_machine *sm) { … } /** * sci_remote_device_destruct() - free remote node context and destruct * @idev: This parameter specifies the remote device to be destructed. * * Remote device objects are a limited resource. As such, they must be * protected. Thus calls to construct and destruct are mutually exclusive and * non-reentrant. The return value shall indicate if the device was * successfully destructed or if some failure occurred. enum sci_status This value * is returned if the device is successfully destructed. * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied * device isn't valid (e.g. it's already been destoryed, the handle isn't * valid, etc.). */ static enum sci_status sci_remote_device_destruct(struct isci_remote_device *idev) { … } /** * isci_remote_device_deconstruct() - This function frees an isci_remote_device. * @ihost: This parameter specifies the isci host object. * @idev: This parameter specifies the remote device to be freed. * */ static void isci_remote_device_deconstruct(struct isci_host *ihost, struct isci_remote_device *idev) { … } static void sci_remote_device_stopped_state_enter(struct sci_base_state_machine *sm) { … } static void sci_remote_device_starting_state_enter(struct sci_base_state_machine *sm) { … } static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *sm) { … } static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm) { … } static void sci_remote_device_resetting_state_enter(struct sci_base_state_machine *sm) { … } static void sci_remote_device_resetting_state_exit(struct sci_base_state_machine *sm) { … } static void sci_stp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { … } static void sci_stp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { … } static void sci_stp_remote_device_ready_ncq_error_substate_enter(struct sci_base_state_machine *sm) { … } static void sci_smp_remote_device_ready_idle_substate_enter(struct sci_base_state_machine *sm) { … } static void sci_smp_remote_device_ready_cmd_substate_enter(struct sci_base_state_machine *sm) { … } static void sci_smp_remote_device_ready_cmd_substate_exit(struct sci_base_state_machine *sm) { … } static const struct sci_base_state sci_remote_device_state_table[] = …; /** * sci_remote_device_construct() - common construction * @iport: SAS/SATA port through which this device is accessed. * @idev: remote device to construct * * This routine just performs benign initialization and does not * allocate the remote_node_context which is left to * sci_remote_device_[de]a_construct(). sci_remote_device_destruct() * frees the remote_node_context(s) for the device. */ static void sci_remote_device_construct(struct isci_port *iport, struct isci_remote_device *idev) { … } /* * sci_remote_device_da_construct() - construct direct attached device. * * The information (e.g. IAF, Signature FIS, etc.) necessary to build * the device is known to the SCI Core since it is contained in the * sci_phy object. Remote node context(s) is/are a global resource * allocated by this routine, freed by sci_remote_device_destruct(). * * Returns: * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed. * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to * sata-only controller instance. * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport, struct isci_remote_device *idev) { … } /* * sci_remote_device_ea_construct() - construct expander attached device * * Remote node context(s) is/are a global resource allocated by this * routine, freed by sci_remote_device_destruct(). * * Returns: * SCI_FAILURE_DEVICE_EXISTS - device has already been constructed. * SCI_FAILURE_UNSUPPORTED_PROTOCOL - e.g. sas device attached to * sata-only controller instance. * SCI_FAILURE_INSUFFICIENT_RESOURCES - remote node contexts exhausted. */ static enum sci_status sci_remote_device_ea_construct(struct isci_port *iport, struct isci_remote_device *idev) { … } enum sci_status sci_remote_device_resume( struct isci_remote_device *idev, scics_sds_remote_node_context_callback cb_fn, void *cb_p) { … } static void isci_remote_device_resume_from_abort_complete(void *cbparam) { … } static bool isci_remote_device_test_resume_done( struct isci_host *ihost, struct isci_remote_device *idev) { … } static void isci_remote_device_wait_for_resume_from_abort( struct isci_host *ihost, struct isci_remote_device *idev) { … } enum sci_status isci_remote_device_resume_from_abort( struct isci_host *ihost, struct isci_remote_device *idev) { … } /** * sci_remote_device_start() - This method will start the supplied remote * device. This method enables normal IO requests to flow through to the * remote device. * @idev: This parameter specifies the device to be started. * @timeout: This parameter specifies the number of milliseconds in which the * start operation should complete. * * An indication of whether the device was successfully started. SCI_SUCCESS * This value is returned if the device was successfully started. * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start * the device when there have been no phys added to it. */ static enum sci_status sci_remote_device_start(struct isci_remote_device *idev, u32 timeout) { … } static enum sci_status isci_remote_device_construct(struct isci_port *iport, struct isci_remote_device *idev) { … } /** * isci_remote_device_alloc() * This function builds the isci_remote_device when a libsas dev_found message * is received. * @ihost: This parameter specifies the isci host object. * @iport: This parameter specifies the isci_port connected to this device. * * pointer to new isci_remote_device. */ static struct isci_remote_device * isci_remote_device_alloc(struct isci_host *ihost, struct isci_port *iport) { … } void isci_remote_device_release(struct kref *kref) { … } /** * isci_remote_device_stop() - This function is called internally to stop the * remote device. * @ihost: This parameter specifies the isci host object. * @idev: This parameter specifies the remote device. * * The status of the ihost request to stop. */ enum sci_status isci_remote_device_stop(struct isci_host *ihost, struct isci_remote_device *idev) { … } /** * isci_remote_device_gone() - This function is called by libsas when a domain * device is removed. * @dev: This parameter specifies the libsas domain device. */ void isci_remote_device_gone(struct domain_device *dev) { … } /** * isci_remote_device_found() - This function is called by libsas when a remote * device is discovered. A remote device object is created and started. the * function then sleeps until the sci core device started message is * received. * @dev: This parameter specifies the libsas domain device. * * status, zero indicates success. */ int isci_remote_device_found(struct domain_device *dev) { … } enum sci_status isci_remote_device_suspend_terminate( struct isci_host *ihost, struct isci_remote_device *idev, struct isci_request *ireq) { … } int isci_remote_device_is_safe_to_abort( struct isci_remote_device *idev) { … } enum sci_status sci_remote_device_abort_requests_pending_abort( struct isci_remote_device *idev) { … } enum sci_status isci_remote_device_reset_complete( struct isci_host *ihost, struct isci_remote_device *idev) { … } void isci_dev_set_hang_detection_timeout( struct isci_remote_device *idev, u32 timeout) { … }