2011-07-03 09:56:22 +04:00
/*
* 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 .
*/
2011-05-08 12:56:57 +04:00
# ifndef _ISCI_REQUEST_H_
2011-07-03 09:56:22 +04:00
# define _ISCI_REQUEST_H_
# include "isci.h"
2011-05-09 02:49:15 +04:00
# include "host.h"
2011-05-10 13:28:45 +04:00
# include "scu_task_context.h"
2011-07-03 09:56:22 +04:00
/**
* struct isci_request_status - This enum defines the possible states of an I / O
* request .
*
*
*/
enum isci_request_status {
unallocated = 0x00 ,
allocated = 0x01 ,
started = 0x02 ,
completed = 0x03 ,
aborting = 0x04 ,
aborted = 0x05 ,
2011-03-05 01:06:52 +03:00
terminating = 0x06 ,
dead = 0x07
2011-07-03 09:56:22 +04:00
} ;
enum task_type {
io_task = 0 ,
tmf_task = 1
} ;
2011-05-10 13:28:45 +04:00
enum sci_request_protocol {
SCIC_NO_PROTOCOL ,
SCIC_SMP_PROTOCOL ,
SCIC_SSP_PROTOCOL ,
SCIC_STP_PROTOCOL
2011-05-10 13:28:48 +04:00
} ; /* XXX remove me, use sas_task.{dev|task_proto} instead */ ;
2011-05-10 13:28:45 +04:00
2011-06-27 22:56:41 +04:00
/**
* isci_stp_request - extra request infrastructure to handle pio / atapi protocol
* @ pio_len - number of bytes requested at PIO setup
* @ status - pio setup ending status value to tell us if we need
2011-06-28 01:57:03 +04:00
* to wait for another fis or if the transfer is complete . Upon
2011-06-27 22:56:41 +04:00
* receipt of a d2h fis this will be the status field of that fis .
* @ sgl - track pio transfer progress as we iterate through the sgl
* @ device_cdb_len - atapi device advertises it ' s transfer constraints at setup
*/
struct isci_stp_request {
u32 pio_len ;
u8 status ;
struct isci_stp_pio_sgl {
int index ;
u8 set ;
u32 offset ;
} sgl ;
u32 device_cdb_len ;
2011-05-10 13:28:49 +04:00
} ;
2011-06-28 01:57:03 +04:00
struct isci_request {
enum isci_request_status status ;
# define IREQ_COMPLETE_IN_TARGET 0
# define IREQ_TERMINATED 1
# define IREQ_TMF 2
# define IREQ_ACTIVE 3
unsigned long flags ;
/* XXX kill ttype and ttype_ptr, allocate full sas_task */
enum task_type ttype ;
union ttype_ptr_union {
struct sas_task * io_task_ptr ; /* When ttype==io_task */
struct isci_tmf * tmf_task_ptr ; /* When ttype==tmf_task */
} ttype_ptr ;
struct isci_host * isci_host ;
/* For use in the requests_to_{complete|abort} lists: */
struct list_head completed_node ;
/* For use in the reqs_in_process list: */
struct list_head dev_node ;
spinlock_t state_lock ;
dma_addr_t request_daddr ;
dma_addr_t zero_scatter_daddr ;
unsigned int num_sg_entries ;
/* Note: "io_request_completion" is completed in two different ways
* depending on whether this is a TMF or regular request .
* - TMF requests are completed in the thread that started them ;
* - regular requests are completed in the request completion callback
* function .
* This difference in operation allows the aborter of a TMF request
* to be sure that once the TMF request completes , the I / O that the
* TMF was aborting is guaranteed to have completed .
*
* XXX kill io_request_completion
2011-05-10 13:28:45 +04:00
*/
2011-06-28 01:57:03 +04:00
struct completion * io_request_completion ;
2011-06-02 04:10:43 +04:00
struct sci_base_state_machine sm ;
2011-05-10 13:28:45 +04:00
struct scic_sds_controller * owning_controller ;
struct scic_sds_remote_device * target_device ;
u16 io_tag ;
enum sci_request_protocol protocol ;
2011-06-28 01:57:03 +04:00
u32 scu_status ; /* hardware result */
u32 sci_status ; /* upper layer disposition */
2011-05-10 13:28:45 +04:00
u32 post_context ;
2011-06-29 00:47:09 +04:00
struct scu_task_context * tc ;
2011-05-10 13:28:45 +04:00
/* could be larger with sg chaining */
2011-06-02 03:00:01 +04:00
# define SCU_SGL_SIZE ((SCI_MAX_SCATTER_GATHER_ELEMENTS + 1) / 2)
2011-05-10 13:28:45 +04:00
struct scu_sgl_element_pair sg_table [ SCU_SGL_SIZE ] __attribute__ ( ( aligned ( 32 ) ) ) ;
2011-06-28 01:57:03 +04:00
/* This field is a pointer to the stored rx frame data. It is used in
2011-06-02 04:10:43 +04:00
* STP internal requests and SMP response frames . If this field is
* non - NULL the saved frame must be released on IO request completion .
2011-05-10 13:28:45 +04:00
*/
u32 saved_rx_frame_index ;
union {
struct {
union {
struct ssp_cmd_iu cmd ;
struct ssp_task_iu tmf ;
} ;
union {
struct ssp_response_iu rsp ;
u8 rsp_buf [ SSP_RESP_IU_MAX_SIZE ] ;
} ;
} ssp ;
struct {
struct smp_resp rsp ;
} smp ;
struct {
2011-06-27 22:56:41 +04:00
struct isci_stp_request req ;
2011-05-10 13:28:45 +04:00
struct host_to_dev_fis cmd ;
struct dev_to_host_fis rsp ;
} stp ;
} ;
} ;
2011-06-28 01:57:03 +04:00
static inline struct isci_request * to_ireq ( struct isci_stp_request * stp_req )
2011-05-08 22:47:15 +04:00
{
2011-06-28 01:57:03 +04:00
struct isci_request * ireq ;
2011-05-08 22:47:15 +04:00
2011-06-28 01:57:03 +04:00
ireq = container_of ( stp_req , typeof ( * ireq ) , stp . req ) ;
2011-05-08 22:47:15 +04:00
return ireq ;
}
2011-05-10 13:28:45 +04:00
/**
* enum sci_base_request_states - This enumeration depicts all the states for
* the common request state machine .
*
*
*/
enum sci_base_request_states {
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:45 +04:00
* Simply the initial state for the base request state machine .
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_INIT ,
2011-05-10 13:28:45 +04:00
2011-06-02 04:10:43 +04:00
/*
* This state indicates that the request has been constructed .
* This state is entered from the INITIAL state .
2011-05-10 13:28:45 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_CONSTRUCTED ,
2011-05-10 13:28:45 +04:00
2011-06-02 04:10:43 +04:00
/*
* This state indicates that the request has been started . This state
* is entered from the CONSTRUCTED state .
2011-05-10 13:28:45 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_STARTED ,
2011-05-10 13:28:45 +04:00
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_UDMA_WAIT_TC_COMP ,
SCI_REQ_STP_UDMA_WAIT_D2H ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_NON_DATA_WAIT_H2D ,
SCI_REQ_STP_NON_DATA_WAIT_D2H ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_SOFT_RESET_WAIT_H2D_ASSERTED ,
SCI_REQ_STP_SOFT_RESET_WAIT_H2D_DIAG ,
SCI_REQ_STP_SOFT_RESET_WAIT_D2H ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
/*
* While in this state the IO request object is waiting for the TC
* completion notification for the H2D Register FIS
2011-05-10 13:28:49 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_PIO_WAIT_H2D ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
/*
* While in this state the IO request object is waiting for either a
* PIO Setup FIS or a D2H register FIS . The type of frame received is
* based on the result of the prior frame and line conditions .
2011-05-10 13:28:49 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_PIO_WAIT_FRAME ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
/*
* While in this state the IO request object is waiting for a DATA
* frame from the device .
2011-05-10 13:28:49 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_PIO_DATA_IN ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
/*
* While in this state the IO request object is waiting to transmit
* the next data frame to the device .
2011-05-10 13:28:49 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_STP_PIO_DATA_OUT ,
2011-05-10 13:28:49 +04:00
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:47 +04:00
* The AWAIT_TC_COMPLETION sub - state indicates that the started raw
* task management request is waiting for the transmission of the
* initial frame ( i . e . command , task , etc . ) .
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_TASK_WAIT_TC_COMP ,
2011-05-10 13:28:47 +04:00
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:47 +04:00
* This sub - state indicates that the started task management request
* is waiting for the reception of an unsolicited frame
* ( i . e . response IU ) .
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_TASK_WAIT_TC_RESP ,
2011-05-10 13:28:47 +04:00
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:48 +04:00
* This sub - state indicates that the started task management request
* is waiting for the reception of an unsolicited frame
* ( i . e . response IU ) .
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_SMP_WAIT_RESP ,
2011-05-10 13:28:48 +04:00
2011-06-02 04:10:43 +04:00
/*
* The AWAIT_TC_COMPLETION sub - state indicates that the started SMP
* request is waiting for the transmission of the initial frame
* ( i . e . command , task , etc . ) .
2011-05-10 13:28:48 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_SMP_WAIT_TC_COMP ,
2011-05-10 13:28:48 +04:00
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:45 +04:00
* This state indicates that the request has completed .
2011-06-02 04:10:43 +04:00
* This state is entered from the STARTED state . This state is entered
* from the ABORTING state .
2011-05-10 13:28:45 +04:00
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_COMPLETED ,
2011-05-10 13:28:45 +04:00
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:45 +04:00
* This state indicates that the request is in the process of being
* terminated / aborted .
* This state is entered from the CONSTRUCTED state .
* This state is entered from the STARTED state .
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_ABORTING ,
2011-05-10 13:28:45 +04:00
2011-06-02 04:10:43 +04:00
/*
2011-05-10 13:28:45 +04:00
* Simply the final state for the base request state machine .
*/
2011-06-02 04:10:43 +04:00
SCI_REQ_FINAL ,
2011-05-10 13:28:45 +04:00
} ;
/**
* scic_sds_request_get_controller ( ) -
*
* This macro will return the controller for this io request object
*/
2011-06-28 01:57:03 +04:00
# define scic_sds_request_get_controller(ireq) \
( ( ireq ) - > owning_controller )
2011-05-10 13:28:45 +04:00
/**
* scic_sds_request_get_device ( ) -
*
* This macro will return the device for this io request object
*/
2011-06-28 01:57:03 +04:00
# define scic_sds_request_get_device(ireq) \
( ( ireq ) - > target_device )
2011-05-10 13:28:45 +04:00
/**
* scic_sds_request_get_port ( ) -
*
* This macro will return the port for this io request object
*/
2011-06-28 01:57:03 +04:00
# define scic_sds_request_get_port(ireq) \
scic_sds_remote_device_get_port ( scic_sds_request_get_device ( ireq ) )
2011-05-10 13:28:45 +04:00
/**
* scic_sds_request_get_post_context ( ) -
*
* This macro returns the constructed post context result for the io request .
*/
2011-06-28 01:57:03 +04:00
# define scic_sds_request_get_post_context(ireq) \
( ( ireq ) - > post_context )
2011-05-10 13:28:45 +04:00
/**
* scic_sds_request_get_task_context ( ) -
*
* This is a helper macro to return the os handle for this request object .
*/
# define scic_sds_request_get_task_context(request) \
( ( request ) - > task_context_buffer )
/**
* scic_sds_request_set_status ( ) -
*
* This macro will set the scu hardware status and sci request completion
* status for an io request .
*/
# define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \
{ \
( request ) - > scu_status = ( scu_status_code ) ; \
( request ) - > sci_status = ( sci_status_code ) ; \
}
2011-06-28 01:57:03 +04:00
enum sci_status scic_sds_request_start ( struct isci_request * ireq ) ;
enum sci_status scic_sds_io_request_terminate ( struct isci_request * ireq ) ;
2011-06-02 04:10:43 +04:00
enum sci_status
2011-06-28 01:57:03 +04:00
scic_sds_io_request_event_handler ( struct isci_request * ireq ,
2011-06-02 04:10:43 +04:00
u32 event_code ) ;
enum sci_status
2011-06-28 01:57:03 +04:00
scic_sds_io_request_frame_handler ( struct isci_request * ireq ,
2011-06-02 04:10:43 +04:00
u32 frame_index ) ;
enum sci_status
2011-06-28 01:57:03 +04:00
scic_sds_task_request_terminate ( struct isci_request * ireq ) ;
2011-06-02 04:10:43 +04:00
extern enum sci_status
2011-06-28 01:57:03 +04:00
scic_sds_request_complete ( struct isci_request * ireq ) ;
2011-06-02 04:10:43 +04:00
extern enum sci_status
2011-06-28 01:57:03 +04:00
scic_sds_io_request_tc_completion ( struct isci_request * ireq , u32 code ) ;
2011-05-10 13:28:45 +04:00
/* XXX open code in caller */
2011-06-02 04:10:43 +04:00
static inline dma_addr_t
2011-06-28 01:57:03 +04:00
scic_io_request_get_dma_addr ( struct isci_request * ireq , void * virt_addr )
2011-05-10 13:28:45 +04:00
{
char * requested_addr = ( char * ) virt_addr ;
char * base_addr = ( char * ) ireq ;
BUG_ON ( requested_addr < base_addr ) ;
BUG_ON ( ( requested_addr - base_addr ) > = sizeof ( * ireq ) ) ;
return ireq - > request_daddr + ( requested_addr - base_addr ) ;
}
2011-07-03 09:56:22 +04:00
/**
* This function gets the status of the request object .
* @ request : This parameter points to the isci_request object
*
* status of the object as a isci_request_status enum .
*/
2011-06-02 04:10:43 +04:00
static inline enum isci_request_status
isci_request_get_state ( struct isci_request * isci_request )
2011-07-03 09:56:22 +04:00
{
BUG_ON ( isci_request = = NULL ) ;
/*probably a bad sign... */
if ( isci_request - > status = = unallocated )
dev_warn ( & isci_request - > isci_host - > pdev - > dev ,
" %s: isci_request->status == unallocated \n " ,
__func__ ) ;
return isci_request - > status ;
}
/**
* isci_request_change_state ( ) - This function sets the status of the request
* object .
* @ request : This parameter points to the isci_request object
* @ status : This Parameter is the new status of the object
*
*/
2011-06-02 04:10:43 +04:00
static inline enum isci_request_status
isci_request_change_state ( struct isci_request * isci_request ,
enum isci_request_status status )
2011-07-03 09:56:22 +04:00
{
enum isci_request_status old_state ;
unsigned long flags ;
dev_dbg ( & isci_request - > isci_host - > pdev - > dev ,
" %s: isci_request = %p, state = 0x%x \n " ,
__func__ ,
isci_request ,
status ) ;
BUG_ON ( isci_request = = NULL ) ;
spin_lock_irqsave ( & isci_request - > state_lock , flags ) ;
old_state = isci_request - > status ;
isci_request - > status = status ;
spin_unlock_irqrestore ( & isci_request - > state_lock , flags ) ;
return old_state ;
}
/**
* isci_request_change_started_to_newstate ( ) - This function sets the status of
* the request object .
* @ request : This parameter points to the isci_request object
* @ status : This Parameter is the new status of the object
*
* state previous to any change .
*/
2011-06-02 04:10:43 +04:00
static inline enum isci_request_status
isci_request_change_started_to_newstate ( struct isci_request * isci_request ,
struct completion * completion_ptr ,
enum isci_request_status newstate )
2011-07-03 09:56:22 +04:00
{
enum isci_request_status old_state ;
unsigned long flags ;
spin_lock_irqsave ( & isci_request - > state_lock , flags ) ;
old_state = isci_request - > status ;
2011-04-01 00:10:34 +04:00
if ( old_state = = started | | old_state = = aborting ) {
2011-07-03 09:56:22 +04:00
BUG_ON ( isci_request - > io_request_completion ! = NULL ) ;
isci_request - > io_request_completion = completion_ptr ;
isci_request - > status = newstate ;
}
2011-06-02 04:10:43 +04:00
2011-07-03 09:56:22 +04:00
spin_unlock_irqrestore ( & isci_request - > state_lock , flags ) ;
dev_dbg ( & isci_request - > isci_host - > pdev - > dev ,
" %s: isci_request = %p, old_state = 0x%x \n " ,
__func__ ,
isci_request ,
old_state ) ;
return old_state ;
}
/**
* isci_request_change_started_to_aborted ( ) - This function sets the status of
* the request object .
* @ request : This parameter points to the isci_request object
* @ completion_ptr : This parameter is saved as the kernel completion structure
* signalled when the old request completes .
*
* state previous to any change .
*/
2011-06-02 04:10:43 +04:00
static inline enum isci_request_status
isci_request_change_started_to_aborted ( struct isci_request * isci_request ,
struct completion * completion_ptr )
2011-07-03 09:56:22 +04:00
{
2011-06-02 04:10:43 +04:00
return isci_request_change_started_to_newstate ( isci_request ,
completion_ptr ,
aborted ) ;
2011-07-03 09:56:22 +04:00
}
2011-06-02 04:10:43 +04:00
# define isci_request_access_task(req) ((req)->ttype_ptr.io_task_ptr)
2011-07-03 09:56:22 +04:00
2011-06-02 04:10:43 +04:00
# define isci_request_access_tmf(req) ((req)->ttype_ptr.tmf_task_ptr)
2011-07-03 09:56:22 +04:00
2011-06-18 01:18:39 +04:00
struct isci_request * isci_tmf_request_from_tag ( struct isci_host * ihost ,
struct isci_tmf * isci_tmf ,
u16 tag ) ;
2011-06-14 04:39:44 +04:00
int isci_request_execute ( struct isci_host * ihost , struct isci_remote_device * idev ,
2011-06-18 01:18:39 +04:00
struct sas_task * task , u16 tag ) ;
2011-06-17 21:40:43 +04:00
void isci_terminate_pending_requests ( struct isci_host * ihost ,
struct isci_remote_device * idev ) ;
2011-06-02 04:10:43 +04:00
enum sci_status
scic_task_request_construct ( struct scic_sds_controller * scic ,
struct scic_sds_remote_device * sci_dev ,
u16 io_tag ,
2011-06-28 01:57:03 +04:00
struct isci_request * ireq ) ;
2011-06-02 04:10:43 +04:00
enum sci_status
2011-06-28 01:57:03 +04:00
scic_task_request_construct_ssp ( struct isci_request * ireq ) ;
2011-06-02 04:10:43 +04:00
enum sci_status
2011-06-28 01:57:03 +04:00
scic_task_request_construct_sata ( struct isci_request * ireq ) ;
2011-06-02 04:10:43 +04:00
void
2011-06-28 01:57:03 +04:00
scic_stp_io_request_set_ncq_tag ( struct isci_request * ireq , u16 ncq_tag ) ;
void scic_sds_smp_request_copy_response ( struct isci_request * ireq ) ;
2011-06-24 04:09:02 +04:00
static inline int isci_task_is_ncq_recovery ( struct sas_task * task )
{
return ( sas_protocol_ata ( task - > task_proto ) & &
task - > ata_task . fis . command = = ATA_CMD_READ_LOG_EXT & &
task - > ata_task . fis . lbal = = ATA_LOG_SATA_NCQ ) ;
}
2011-07-03 09:56:22 +04:00
# endif /* !defined(_ISCI_REQUEST_H_) */