/*-
* SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
*
* 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.
*
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/**
* @file
*
* @brief This file contains all of the state handler routines for each
* of the controller states defined by the SCI_BASE_CONTROLLER state
* machine.
*/
#include <dev/isci/scil/sci_util.h>
#include <dev/isci/scil/scic_controller.h>
#include <dev/isci/scil/scic_port.h>
#include <dev/isci/scil/scic_remote_device.h>
#include <dev/isci/scil/scic_io_request.h>
#include <dev/isci/scil/scif_sas_controller.h>
#include <dev/isci/scil/scif_sas_remote_device.h>
#include <dev/isci/scil/scif_sas_logger.h>
#include <dev/isci/scil/scif_sas_smp_remote_device.h>
//******************************************************************************
//* P R I V A T E M E T H O D S
//******************************************************************************
/**
* @brief This method simply executes the reset operation by entering
* the reset state and allowing the state to perform it's work.
*
* @param[in] fw_controller This parameter specifies the SAS framework
* controller for execute the reset.
*
* @return Indicate the status of the reset operation. Was it successful?
* @retval SCI_SUCCESS This value is returned if it was successfully reset.
*/
static
SCI_STATUS scif_sas_controller_execute_reset(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
SCI_STATUS status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET,
"scif_sas_controller_execute_reset(0x%x) enter\n",
fw_controller
));
//clean the timer to avoid timer leak.
scif_sas_controller_release_resource(fw_controller);
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_RESETTING
);
// Retrieve the status for the operations performed during the entrance
// to the resetting state were executing successfully.
status = fw_controller->operation_status;
fw_controller->operation_status = SCI_SUCCESS;
return status;
}
/**
* @brief This method checks that the memory descriptor list is valid
* and hasn't been corrupted in some way by the user.
*
* @param[in] fw_controller This parameter specifies the framework
* controller object for which to validation the MDL.
*
* @return This method returns a value indicating if the operation succeeded.
* @retval SCI_SUCCESS This value indicates that MDL is valid.
* @retval SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD This value indicates
* that some portion of the memory descriptor list is invalid.
*/
static
SCI_STATUS scif_sas_controller_validate_mdl(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
BOOL is_mde_list_valid;
// Currently there is only a single MDE in the list.
is_mde_list_valid = sci_base_mde_is_valid(
&fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO],
4,
fw_controller->internal_request_entries *
scif_sas_internal_request_get_object_size(),
SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
);
if (is_mde_list_valid == FALSE)
return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD;
return SCI_SUCCESS;
}
/**
* @brief This method stops all the domains associated to this
* controller.
*
* @param[in] fw_controller This parameter specifies the framework
* controller object for whose remote devices are to be stopped.
*
* @return This method returns a value indicating if the operation succeeded.
* @retval SCI_SUCCESS This value indicates that all the devices are stopped.
* @retval SCI_FAILURE This value indicates certain failure during the process
* of stopping remote devices.
*/
static
SCI_STATUS scif_sas_controller_stop_domains(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
U8 index;
SCI_STATUS status = SCI_SUCCESS;
SCIF_SAS_DOMAIN_T * fw_domain;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"scif_sas_controller_stop_domains(0x%x) enter\n",
fw_controller
));
for (index = 0; index < SCI_MAX_DOMAINS && status == SCI_SUCCESS; index++)
{
fw_domain = &fw_controller->domains[index];
//Change this domain to STOPPING state. All the remote devices will be
//stopped subsquentially.
if (fw_domain->parent.state_machine.current_state_id ==
SCI_BASE_DOMAIN_STATE_READY
|| fw_domain->parent.state_machine.current_state_id ==
SCI_BASE_DOMAIN_STATE_DISCOVERING)
{
sci_base_state_machine_change_state(
&fw_domain->parent.state_machine, SCI_BASE_DOMAIN_STATE_STOPPING
);
}
}
return status;
}
/**
* @brief This method continue to stop the controller after clear affiliation
* is done.
*
* @param[in] fw_controller This parameter specifies the framework
* controller object to be stopped.
*
* @return This method returns a value indicating if the operation succeeded.
* @retval SCI_SUCCESS This value indicates the controller_stop succeeds.
* @retval SCI_FAILURE This value indicates certain failure during the process
* of stopping controller.
*/
SCI_STATUS scif_sas_controller_continue_to_stop(
SCIF_SAS_CONTROLLER_T * fw_controller
)
{
SCI_STATUS status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"scif_sas_controller_continue_to_stop (0x%x).\n",
fw_controller
));
//stop all the domains and their remote devices.
status = scif_sas_controller_stop_domains(fw_controller);
if (status == SCI_SUCCESS)
{
// Attempt to stop the core controller.
status = scic_controller_stop(fw_controller->core_object, 0);
if (status != SCI_SUCCESS)
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"Controller:0x%x Status:0x%x unable to stop controller.\n",
fw_controller, status
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_FAILED
);
}
}
else
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
"Controller:0x%x Status:0x%x unable to stop domains.\n",
fw_controller, status
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_FAILED
);
}
return status;
}
//******************************************************************************
//* R E S E T H A N D L E R S
//******************************************************************************
/**
* @brief This method provides RESET state specific handling for
* when a user attempts to initialize a controller. This is a legal
* state in which to attempt an initialize call.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform an initialize
* operation.
*
* @return This method returns an indication of whether the initialize
* operation succeeded.
* @retval SCI_SUCCESS This value when the initialization completes
* successfully.
*/
static
SCI_STATUS scif_sas_controller_reset_initialize_handler(
SCI_BASE_CONTROLLER_T * controller
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
SCI_STATUS status;
U32 index;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scif_sas_controller_reset_initialize_handler(0x%x) enter\n",
controller
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_INITIALIZING
);
scif_sas_controller_build_mdl(fw_controller);
// Perform any domain object initialization that is necessary.
for (index = 0; index < SCI_MAX_DOMAINS; index++)
scif_sas_domain_initialize(&fw_controller->domains[index]);
scif_cb_lock_associate(fw_controller, &fw_controller->hprq.lock);
// Attempt to initialize the core controller.
status = scic_controller_initialize(fw_controller->core_object);
if (status == SCI_SUCCESS)
{
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_INITIALIZED
);
}
if (status != SCI_SUCCESS)
{
// Initialization failed, Release resources and do not change state
scif_sas_controller_release_resource(fw_controller);
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"Controller:0x%x Status:0x%x unable to successfully initialize.\n",
fw_controller, status
));
}
return status;
}
//******************************************************************************
//* I N I T I A L I Z E D H A N D L E R S
//******************************************************************************
/**
* @brief This method provides INITIALIZED state specific handling for
* when a user attempts to start a controller.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start
* operation.
* @param[in] timeout This parameter specifies the timeout value (in
* milliseconds) to be utilized for this operation.
*
* @return This method returns an indication of whether the start operation
* succeeded.
* @retval SCI_SUCCESS This value is returned when the start operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_initialized_start_handler(
SCI_BASE_CONTROLLER_T * controller,
U32 timeout
)
{
SCI_STATUS status = SCI_SUCCESS;
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
U16 index = 0;
SCI_PHYSICAL_MEMORY_DESCRIPTOR_T internal_reqeust_mde =
fw_controller->mdes[SCIF_SAS_MDE_INTERNAL_IO];
void * internal_request_virtual_address = internal_reqeust_mde.virtual_address;
POINTER_UINT address = (POINTER_UINT)internal_request_virtual_address;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scif_sas_controller_initialized_start_handler(0x%x, 0x%x) enter\n",
controller, timeout
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_STARTING
);
status = scif_sas_controller_validate_mdl(fw_controller);
// initialization work for internal request path. It must be done before
// starting domain.
if (status == SCI_SUCCESS)
{
// fill in the sci_pool for internal requests.
sci_pool_initialize(fw_controller->internal_request_memory_pool);
for (index = 0; index < fw_controller->internal_request_entries; index++)
{
sci_pool_put(fw_controller->internal_request_memory_pool, address);
address += scif_sas_internal_request_get_object_size();
}
// Using DPC for starting internal IOs, if yes, we need to intialize
// DPC here.
scif_cb_start_internal_io_task_create(fw_controller);
}
if (status == SCI_SUCCESS)
{
// Kick-start the domain state machines and, by association, the
// core port's.
// This will ensure we get valid port objects supplied with link up
// messages.
for (index = 0;
(index < SCI_MAX_DOMAINS) && (status == SCI_SUCCESS);
index++)
{
sci_base_state_machine_change_state(
&fw_controller->domains[index].parent.state_machine,
SCI_BASE_DOMAIN_STATE_STARTING
);
status = fw_controller->domains[index].operation.status;
}
}
// Validate that all the domain state machines began successfully.
if (status != SCI_SUCCESS)
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"Controller:0x%x Domain:0x%x Status:0x%x unable to start\n",
fw_controller, index, status
));
return status;
}
// Attempt to start the core controller.
status = scic_controller_start(fw_controller->core_object, timeout);
if (status != SCI_SUCCESS)
{
SCIF_LOG_ERROR((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"Controller:0x%x Status:0x%x unable to start controller.\n",
fw_controller, status
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_FAILED
);
}
return status;
}
//******************************************************************************
//* R E A D Y H A N D L E R S
//******************************************************************************
/**
* @brief This method provides READY state specific handling for
* when a user attempts to stop a controller.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a stop
* operation.
* @param[in] timeout This parameter specifies the timeout value (in
* milliseconds) to be utilized for this operation.
*
* @return This method returns an indication of whether the stop operation
* succeeded.
* @retval SCI_SUCCESS This value is returned when the stop operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_stop_handler(
SCI_BASE_CONTROLLER_T * controller,
U32 timeout
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)controller;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
"scif_sas_controller_ready_stop_handler(0x%x, 0x%x) enter\n",
controller, timeout
));
sci_base_state_machine_change_state(
&fw_controller->parent.state_machine,
SCI_BASE_CONTROLLER_STATE_STOPPING
);
if (fw_controller->user_parameters.sas.clear_affiliation_during_controller_stop)
{
fw_controller->current_domain_to_clear_affiliation = 0;
//clear affiliation first. After the last domain finishes clearing
//affiliation, it will call back to controller to continue to stop.
scif_sas_controller_clear_affiliation(fw_controller);
}
else
scif_sas_controller_continue_to_stop(fw_controller);
//Must return SUCCESS at this point.
return SCI_SUCCESS;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to reset a controller.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a reset
* operation.
*
* @return This method returns an indication of whether the reset operation
* succeeded.
* @retval SCI_SUCCESS This value is returned when the reset operation
* completes successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_reset_handler(
SCI_BASE_CONTROLLER_T * controller
)
{
return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to start an IO request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_io() for
* more information.
*
* @return This method returns an indication of whether the start IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the start IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_start_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request,
U16 io_tag
)
{
SCI_STATUS status;
SCIF_SAS_IO_REQUEST_T *fw_io = (SCIF_SAS_IO_REQUEST_T*)io_request;
SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
SCIF_SAS_REMOTE_DEVICE_T *fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
remote_device;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_ready_start_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request, io_tag
));
status = fw_device->domain->state_handlers->start_io_handler(
&fw_device->domain->parent, remote_device, io_request
);
// Check to see that the other objects in the framework allowed
// this IO to be started.
if (status == SCI_SUCCESS)
{
// Ask the core to start processing for this IO request.
status = (SCI_STATUS)scic_controller_start_io(
fw_controller->core_object,
fw_device->core_object,
fw_io->parent.core_object,
io_tag
);
if (status == SCI_SUCCESS)
{
// We were able to start the core request. As a result,
// commit to starting the request for the framework by changing
// the state of the IO request.
sci_base_state_machine_change_state(
&io_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
);
}
else
{
// We were unable to start the core IO request. As a result,
// back out the start operation for the framework. It's easier to
// back out the framework start operation then to backout the core
// start IO operation.
fw_device->domain->state_handlers->complete_io_handler(
&fw_device->domain->parent, remote_device, io_request
);
// Invoke the IO completion handler. For most IOs, this does nothing
// since we are still in the constructed state. For NCQ, this will
// the return of the NCQ tag back to the remote device free pool.
fw_io->parent.state_handlers->complete_handler(io_request);
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x IORequest:0x%x Status:0x%x core IO start failed\n",
fw_controller, fw_io, status
));
}
}
else
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x IORequest:0x%x Status:0x%x IO start failed\n",
fw_controller, fw_io, status
));
}
return status;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to complete an IO request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a complete IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
*
* @return This method returns an indication of whether the complete IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the complete IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_complete_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*)
controller;
SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
remote_device;
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
io_request;
SCI_STATUS status;
SCI_STATUS core_status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_ready_complete_io_handler(0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request
));
fw_io->parent.state_handlers->destruct_handler(&fw_io->parent.parent);
status = fw_device->domain->state_handlers->complete_io_handler(
&fw_device->domain->parent, remote_device, io_request
);
// Ask the core to finish processing for this IO request.
core_status = scic_controller_complete_io(
fw_controller->core_object,
fw_device->core_object,
fw_io->parent.core_object
);
if (status == SCI_SUCCESS)
status = core_status;
if (status != SCI_SUCCESS)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x IORequest:0x%x Status:0x%x CoreStatus:0x%x "
"failure to complete IO\n",
fw_controller, fw_io, status, core_status
));
}
return status;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to complete a high priority IO request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a complete IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
*
* @return This method returns an indication of whether the complete IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the complete IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_complete_high_priority_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*)
controller;
SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
remote_device;
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T*)
io_request;
SCI_IO_STATUS core_completion_status =
scic_request_get_sci_status(fw_io->parent.core_object);
U8 response_data[SCIF_SAS_RESPONSE_DATA_LENGTH];
SCI_STATUS status;
SCI_STATUS core_status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_ready_complete_high_priority_io_handler(0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request
));
// In high priority path, we ask the core to finish IO request before framework.
// retrieve and save io response from core now.
memcpy(response_data,
scic_io_request_get_response_iu_address(fw_io->parent.core_object),
SCIF_SAS_RESPONSE_DATA_LENGTH
);
core_status = scic_controller_complete_io(
fw_controller->core_object,
fw_device->core_object,
fw_io->parent.core_object
);
fw_io->parent.state_handlers->destruct_handler(&fw_io->parent.parent);
status = fw_device->domain->state_handlers->complete_high_priority_io_handler(
&fw_device->domain->parent,
remote_device,
io_request,
(void *)response_data,
core_completion_status
);
if (status == SCI_SUCCESS)
status = core_status;
if (status == SCI_SUCCESS)
{
//issue DPC to start next internal io in high prioriy queue.
if( !sci_pool_empty(fw_controller->hprq.pool) )
scif_cb_start_internal_io_task_schedule(
fw_controller,
scif_sas_controller_start_high_priority_io,
fw_controller
);
}
else
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x IORequest:0x%x Status:0x%x CoreStatus:0x%x "
"failure to complete IO\n",
fw_controller, fw_io, status, core_status
));
}
return status;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to continue an IO request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a continue IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
*
* @return This method returns an indication of whether the continue IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the continue IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_continue_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_ready_continue_io_handler(0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request
));
/// @todo Function unimplemented. fix return code handling.
return SCI_FAILURE;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to start a task request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start task
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start
* task operation.
* @param[in] task_request This parameter specifies the task management
* request to be started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_task() for
* more information.
*
* @return This method returns an indication of whether the start task
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the start task operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_start_task_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * task_request,
U16 io_tag
)
{
SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*)
controller;
SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
remote_device;
SCIF_SAS_TASK_REQUEST_T * fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
SCI_STATUS status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
"scif_sas_controller_ready_start_task_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, task_request, io_tag
));
status = fw_device->domain->state_handlers->start_task_handler(
&fw_device->domain->parent, remote_device, task_request
);
if (status == SCI_SUCCESS)
{
if (scif_sas_task_request_get_function(fw_task)
== SCI_SAS_HARD_RESET)
{
// Go off to special target reset path. Don't start task to core.
scif_sas_remote_device_target_reset(
fw_device,
(SCIF_SAS_REQUEST_T *)fw_task
);
return SCI_SUCCESS;
}
// Ask the core to start processing for this task request.
status = (SCI_STATUS)scic_controller_start_task(
fw_controller->core_object,
fw_device->core_object,
fw_task->parent.core_object,
io_tag
);
if (status == SCI_SUCCESS)
{
// We were able to start the core request. As a result,
// commit to starting the request for the framework by changing
// the state of the task request.
fw_task->parent.state_handlers->start_handler(&fw_task->parent.parent);
}
else
{
// We were unable to start the core task request. As a result,
// back out the start operation for the framework. It's easier to
// back out the framework start operation then to backout the core
// start task operation.
fw_device->domain->state_handlers->complete_task_handler(
&fw_device->domain->parent, remote_device, task_request
);
if (status == SCI_SUCCESS)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x TaskRequest:0x%x Status:0x%x core start failed\n",
fw_controller, fw_task, status
));
}
}
}
else
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x TaskRequest:0x%x Status:0x%x Task start failed\n",
fw_controller, fw_task, status
));
}
return status;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to complete a task request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a complete task
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start
* task operation.
* @param[in] task_request This parameter specifies the task management
* request to be started.
*
* @return This method returns an indication of whether the complete task
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the complete task operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_complete_task_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * task_request
)
{
SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
SCIF_SAS_REMOTE_DEVICE_T *fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)remote_device;
SCIF_SAS_TASK_REQUEST_T *fw_task = (SCIF_SAS_TASK_REQUEST_T*)task_request;
SCI_STATUS status;
SCI_STATUS core_status;
SCIF_LOG_TRACE((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT,
"scif_sas_controller_ready_complete_task_handler(0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, task_request
));
status = fw_device->domain->state_handlers->complete_task_handler(
&fw_device->domain->parent, remote_device, task_request
);
if (scif_sas_task_request_get_function(fw_task)
== SCI_SAS_HARD_RESET)
{
//No more things to do in the core, since this task is for Target Reset.
return status;
}
fw_task->parent.state_handlers->destruct_handler(&fw_task->parent.parent);
// Ask the core to finish processing for this task request.
core_status = scic_controller_complete_task(
fw_controller->core_object,
fw_device->core_object,
fw_task->parent.core_object
);
if (status == SCI_SUCCESS)
status = core_status;
if (status != SCI_SUCCESS)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x TaskRequest:0x%x Status:0x%x CoreStatus:0x%x "
"failed to complete\n",
fw_controller, fw_task, status, core_status
));
}
return status;
}
/**
* @brief This method provides common handling for several states
* when a user attempts to start an internal request.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_io() for
* more information.
*
* @return This method returns an indication of whether the start IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the start IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_common_start_high_priority_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request,
U16 io_tag
)
{
SCI_STATUS status;
SCIF_SAS_IO_REQUEST_T *fw_io = (SCIF_SAS_IO_REQUEST_T*)io_request;
SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)controller;
SCIF_SAS_REMOTE_DEVICE_T *fw_device = (SCIF_SAS_REMOTE_DEVICE_T*)
remote_device;
status = fw_device->domain->state_handlers->start_high_priority_io_handler(
&fw_device->domain->parent, remote_device, io_request
);
// Check to see that the other objects in the framework allowed
// this IO to be started.
if (status == SCI_SUCCESS)
{
// Ask the core to start processing for this IO request.
status = (SCI_STATUS)scic_controller_start_io(
fw_controller->core_object,
fw_device->core_object,
fw_io->parent.core_object,
io_tag
);
if (status == SCI_SUCCESS)
{
// We were able to start the core request. As a result,
// commit to starting the request for the framework by changing
// the state of the IO request.
sci_base_state_machine_change_state(
&io_request->state_machine, SCI_BASE_REQUEST_STATE_STARTED
);
}
else
{
// We were unable to start the core IO request. As a result,
// back out the start operation for the framework. It's easier to
// back out the framework start operation then to backout the core
// start IO operation.
fw_device->domain->state_handlers->complete_io_handler(
&fw_device->domain->parent, remote_device, io_request
);
// Invoke the IO completion handler. For most IOs, this does nothing
// since we are still in the constructed state. For NCQ, this will
// the return of the NCQ tag back to the remote device free pool.
fw_io->parent.state_handlers->complete_handler(io_request);
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x IORequest:0x%x Status:0x%x core IO start failed\n",
fw_controller, fw_io, status
));
}
}
else
{
SCIF_LOG_WARNING((
sci_base_object_get_logger(fw_controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x IORequest:0x%x Status:0x%x IO start failed\n",
fw_controller, fw_io, status
));
// Invoke the IO completion handler. For most IOs, this does nothing
// since we are still in the constructed state. For NCQ, this will
// the return of the NCQ tag back to the remote device free pool.
fw_io->parent.state_handlers->complete_handler(io_request);
}
if (fw_io->parent.is_internal && status != SCI_SUCCESS )
{
SCIC_TRANSPORT_PROTOCOL protocol =
scic_io_request_get_protocol(fw_io->parent.core_object);
U8 retry_count = fw_io->retry_count;
scif_sas_internal_io_request_destruct(
fw_device->domain->controller,
(SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io
);
if ( protocol == SCIC_SMP_PROTOCOL )
{
if (fw_device->protocol_device.smp_device.smp_activity_timer != NULL)
{
//destroy the smp_activity_timer
scif_cb_timer_destroy (
fw_controller,
fw_device->protocol_device.smp_device.smp_activity_timer
);
fw_device->protocol_device.smp_device.smp_activity_timer = NULL;
}
//we should retry for finite times
if ( retry_count < SCIF_SAS_IO_RETRY_LIMIT)
{
//An internal smp request failed being started, most likely due to remote device
//is not in ready state, for example, UPDATING_PORT_WIDTH state. In this case,
//we should retry the IO.
scif_sas_smp_remote_device_retry_internal_io(
(SCIF_SAS_REMOTE_DEVICE_T *)remote_device,
retry_count,
SMP_REQUEST_RETRY_WAIT_DURATION
);
}
}
}
return status;
}
/**
* @brief This method provides READY state specific handling for
* when a user attempts to start an internal request. If the high
* priority IO is also internal, this method will schedule its timer.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_io() for
* more information.
*
* @return This method returns an indication of whether the start IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the start IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_ready_start_high_priority_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request,
U16 io_tag
)
{
SCI_STATUS status;
SCIF_SAS_IO_REQUEST_T * fw_io = (SCIF_SAS_IO_REQUEST_T *)io_request;
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_ready_start_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request, io_tag
));
status = scif_sas_controller_common_start_high_priority_io_handler(
controller, remote_device, io_request, io_tag);
if (status == SCI_SUCCESS)
{
//External io could also be put in high priority queue. i.e. the
//smp request for EA Target Reset.
if (fw_io->parent.is_internal)
{
SCIF_SAS_INTERNAL_IO_REQUEST_T * fw_internal_io =
(SCIF_SAS_INTERNAL_IO_REQUEST_T *)fw_io;
//start the timer for internal io
scif_cb_timer_start(
(SCI_CONTROLLER_HANDLE_T)controller,
fw_internal_io->internal_io_timer,
SCIF_SAS_INTERNAL_REQUEST_TIMEOUT
);
}
}
else
{
//If failed to start, most likely the device or domain is not in
//correct state, and the IO has been cleaned up in controller's start
//high priority IO handler. We should just continue to start the next
//IO in the HP queue.
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_controller_start_high_priority_io(0x%x, 0x%x), starting io failed\n",
controller, fw_io
));
}
return status;
}
//******************************************************************************
//* S T O P P I N G H A N D L E R S
//******************************************************************************
/**
* @brief This method provides STOPPING state specific handling for
* when a user attempts to start an internal request. Note that we don't
* start the timer for internal IO during controller stopping state.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_io() for
* more information.
*
* @return This method returns an indication of whether the start IO
* operation succeeded.
* @retval SCI_SUCCESS This value is returned when the start IO operation
* begins successfully.
*/
static
SCI_STATUS scif_sas_controller_stopping_start_high_priority_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request,
U16 io_tag
)
{
SCIF_LOG_TRACE((
sci_base_object_get_logger(controller),
SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
"scif_sas_controller_stopping_start_high_priority_io_handler(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
controller, remote_device, io_request, io_tag
));
return scif_sas_controller_common_start_high_priority_io_handler(
controller, remote_device, io_request, io_tag);
}
//******************************************************************************
//* S T O P P E D H A N D L E R S
//******************************************************************************
/**
* @brief This method provides STOPPED state specific handling for
* when a user attempts to reset a controller.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a reset
* operation.
*
* @return This method returns an indication of whether the reset operation
* succeeded.
* @retval SCI_SUCCESS This value is returned when the reset operation
* completes successfully.
*/
static
SCI_STATUS scif_sas_controller_stopped_reset_handler(
SCI_BASE_CONTROLLER_T * controller
)
{
return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
}
//******************************************************************************
//* F A I L E D H A N D L E R S
//******************************************************************************
/**
* @brief This method provides FAILED state specific handling for
* when a user attempts to reset a controller.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a reset
* operation.
*
* @return This method returns an indication of whether the reset operation
* succeeded.
* @retval SCI_SUCCESS This value is returned when the reset operation
* completes successfully.
*/
static
SCI_STATUS scif_sas_controller_failed_reset_handler(
SCI_BASE_CONTROLLER_T * controller
)
{
return scif_sas_controller_execute_reset((SCIF_SAS_CONTROLLER_T*)controller);
}
//******************************************************************************
//* D E F A U L T H A N D L E R S
//******************************************************************************
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to start a controller and a start operation
* is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start operation.
* @param[in] timeout This parameter specifies the timeout value (in
* milliseconds) to be utilized for this operation.
*
* @return This method returns an indication that start operations are not
* allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_start_handler(
SCI_BASE_CONTROLLER_T * controller,
U32 timeout
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to start controller.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to stop a controller and a stop operation
* is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a stop operation.
* @param[in] timeout This parameter specifies the timeout value (in
* milliseconds) to be utilized for this operation.
*
* @return This method returns an indication that stop operations are not
* allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_stop_handler(
SCI_BASE_CONTROLLER_T * controller,
U32 timeout
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to stop controller.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to reset a controller and a reset operation
* is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a reset operation.
*
* @return This method returns an indication that reset operations are not
* allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_reset_handler(
SCI_BASE_CONTROLLER_T * controller
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to reset controller.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to initialize a controller and an initialize
* operation is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform an initialize
* operation.
*
* @return This method returns an indication that initialize operations
* are not allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_initialize_handler(
SCI_BASE_CONTROLLER_T * controller
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to initialize controller.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to start an IO on a controller and a start
* IO operation is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_io() for
* more information.
*
* @return This method returns an indication that start IO operations
* are not allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_start_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request,
U16 io_tag
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to start IO.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to complete an IO on a controller and a
* complete IO operation is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a complete IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
*
* @return This method returns an indication that complete IO operations
* are not allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_complete_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to complete IO.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to continue an IO on a controller and a
* continue IO operation is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a continue IO
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start IO
* operation.
* @param[in] io_request This parameter specifies the IO request to be
* started.
*
* @return This method returns an indication that continue IO operations
* are not allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_continue_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to continue IO.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to start a task on a controller and a start
* task operation is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a start task
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start
* task operation.
* @param[in] task_request This parameter specifies the task management
* request to be started.
* @param[in] io_tag This parameter specifies the optional allocated
* IO tag. Please reference scif_controller_start_task() for
* more information.
*
* @return This method returns an indication that start task operations
* are not allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_start_task_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * task_request,
U16 io_tag
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to start task mgmt.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
/**
* @brief This method provides default handling (i.e. returns an error)
* when a user attempts to complete a task on a controller and a
* complete task operation is not allowed.
*
* @param[in] controller This parameter specifies the controller object
* on which the user is attempting to perform a complete task
* operation.
* @param[in] remote_device This parameter specifies the remote deivce
* object on which the user is attempting to perform a start
* task operation.
* @param[in] task_request This parameter specifies the task management
* request to be started.
*
* @return This method returns an indication that complete task operations
* are not allowed.
* @retval SCI_FAILURE_INVALID_STATE This value is always returned.
*/
static
SCI_STATUS scif_sas_controller_default_complete_task_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * task_request
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to complete task mgmt.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE_INVALID_STATE;
}
static
SCI_STATUS scif_sas_controller_failed_state_start_io_handler(
SCI_BASE_CONTROLLER_T * controller,
SCI_BASE_REMOTE_DEVICE_T * remote_device,
SCI_BASE_REQUEST_T * io_request,
U16 io_tag
)
{
SCIF_LOG_WARNING((
sci_base_object_get_logger((SCIF_SAS_CONTROLLER_T *)controller),
SCIF_LOG_OBJECT_CONTROLLER,
"Controller:0x%x State:0x%x invalid state to start IO.\n",
controller,
sci_base_state_machine_get_state(
&((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine)
));
return SCI_FAILURE;
}
#define scif_sas_controller_stopping_complete_io_handler \
scif_sas_controller_ready_complete_io_handler
#define scif_sas_controller_stopping_complete_task_handler \
scif_sas_controller_ready_complete_task_handler
#define scif_sas_controller_default_start_high_priority_io_handler \
scif_sas_controller_default_start_io_handler
#define scif_sas_controller_default_complete_high_priority_io_handler \
scif_sas_controller_default_complete_io_handler
#define scif_sas_controller_stopping_complete_high_priority_io_handler \
scif_sas_controller_ready_complete_high_priority_io_handler
SCI_BASE_CONTROLLER_STATE_HANDLER_T
scif_sas_controller_state_handler_table[SCI_BASE_CONTROLLER_MAX_STATES] =
{
// SCI_BASE_CONTROLLER_STATE_INITIAL
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_RESET
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_reset_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_INITIALIZING
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_INITIALIZED
{
scif_sas_controller_initialized_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_STARTING
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_READY
{
scif_sas_controller_default_start_handler,
scif_sas_controller_ready_stop_handler,
scif_sas_controller_ready_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_ready_start_io_handler,
scif_sas_controller_ready_start_high_priority_io_handler,
scif_sas_controller_ready_complete_io_handler,
scif_sas_controller_ready_complete_high_priority_io_handler,
scif_sas_controller_ready_continue_io_handler,
scif_sas_controller_ready_start_task_handler,
scif_sas_controller_ready_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_RESETTING
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_STOPPING
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_default_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_stopping_start_high_priority_io_handler,
scif_sas_controller_stopping_complete_io_handler,
scif_sas_controller_stopping_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler, /**@todo Allow in core?*/
scif_sas_controller_stopping_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_STOPPED
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_stopped_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_default_start_io_handler,
scif_sas_controller_default_start_high_priority_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
},
// SCI_BASE_CONTROLLER_STATE_FAILED
{
scif_sas_controller_default_start_handler,
scif_sas_controller_default_stop_handler,
scif_sas_controller_failed_reset_handler,
scif_sas_controller_default_initialize_handler,
scif_sas_controller_failed_state_start_io_handler,
scif_sas_controller_failed_state_start_io_handler,
scif_sas_controller_default_complete_io_handler,
scif_sas_controller_default_complete_high_priority_io_handler,
scif_sas_controller_default_continue_io_handler,
scif_sas_controller_default_start_task_handler,
scif_sas_controller_default_complete_task_handler
}
};