2005-04-16 15:20:36 -07:00
/*
2005-10-27 11:10:08 -07:00
* QLogic Fibre Channel HBA Driver
2014-04-11 16:54:24 -04:00
* Copyright ( c ) 2003 - 2014 QLogic Corporation
2005-04-16 15:20:36 -07:00
*
2005-10-27 11:10:08 -07:00
* See LICENSE . qla2xxx for copyright and licensing details .
2005-04-16 15:20:36 -07:00
*/
2014-04-11 16:54:43 -04:00
# include "qla_target.h"
2013-03-28 08:21:23 -04:00
/**
* qla24xx_calc_iocbs ( ) - Determine number of Command Type 3 and
* Continuation Type 1 IOCBs to allocate .
*
* @ dsds : number of data segment decriptors needed
*
* Returns the number of IOCB entries needed to store @ dsds .
*/
static inline uint16_t
qla24xx_calc_iocbs ( scsi_qla_host_t * vha , uint16_t dsds )
{
uint16_t iocbs ;
iocbs = 1 ;
if ( dsds > 1 ) {
iocbs + = ( dsds - 1 ) / 5 ;
if ( ( dsds - 1 ) % 5 )
iocbs + + ;
}
return iocbs ;
}
2005-04-16 15:20:36 -07:00
/*
* qla2x00_debounce_register
* Debounce register .
*
* Input :
* port = register address .
*
* Returns :
* register value .
*/
static __inline__ uint16_t
2005-07-06 10:32:07 -07:00
qla2x00_debounce_register ( volatile uint16_t __iomem * addr )
2005-04-16 15:20:36 -07:00
{
volatile uint16_t first ;
volatile uint16_t second ;
do {
first = RD_REG_WORD ( addr ) ;
barrier ( ) ;
cpu_relax ( ) ;
second = RD_REG_WORD ( addr ) ;
} while ( first ! = second ) ;
return ( first ) ;
}
2005-07-06 10:32:07 -07:00
static inline void
2008-11-06 10:40:51 -08:00
qla2x00_poll ( struct rsp_que * rsp )
2005-04-16 15:20:36 -07:00
{
2008-05-12 22:21:14 -07:00
unsigned long flags ;
2008-11-06 10:40:51 -08:00
struct qla_hw_data * ha = rsp - > hw ;
2008-05-12 22:21:14 -07:00
local_irq_save ( flags ) ;
2013-08-27 01:37:28 -04:00
if ( IS_P3P_TYPE ( ha ) )
2010-04-12 17:59:55 -07:00
qla82xx_poll ( 0 , rsp ) ;
else
ha - > isp_ops - > intr_handler ( 0 , rsp ) ;
2008-05-12 22:21:14 -07:00
local_irq_restore ( flags ) ;
2005-04-16 15:20:36 -07:00
}
2005-07-06 10:31:17 -07:00
static inline uint8_t *
host_to_fcp_swap ( uint8_t * fcp , uint32_t bsize )
{
uint32_t * ifcp = ( uint32_t * ) fcp ;
uint32_t * ofcp = ( uint32_t * ) fcp ;
uint32_t iter = bsize > > 2 ;
for ( ; iter ; iter - - )
* ofcp + + = swab32 ( * ifcp + + ) ;
return fcp ;
}
2005-07-06 10:30:26 -07:00
2013-03-28 08:21:23 -04:00
static inline void
host_to_adap ( uint8_t * src , uint8_t * dst , uint32_t bsize )
{
uint32_t * isrc = ( uint32_t * ) src ;
2013-06-25 11:27:21 -04:00
__le32 * odest = ( __le32 * ) dst ;
2013-03-28 08:21:23 -04:00
uint32_t iter = bsize > > 2 ;
2016-01-27 12:03:34 -05:00
for ( ; iter - - ; isrc + + )
* odest + + = cpu_to_le32 ( * isrc ) ;
2013-03-28 08:21:23 -04:00
}
2012-08-22 14:21:00 -04:00
static inline void
qla2x00_set_reserved_loop_ids ( struct qla_hw_data * ha )
{
int i ;
if ( IS_FWI2_CAPABLE ( ha ) )
return ;
for ( i = 0 ; i < SNS_FIRST_LOOP_ID ; i + + )
set_bit ( i , ha - > loop_id_map ) ;
set_bit ( MANAGEMENT_SERVER , ha - > loop_id_map ) ;
set_bit ( BROADCAST , ha - > loop_id_map ) ;
}
2005-07-06 10:30:26 -07:00
static inline int
2008-11-06 10:40:51 -08:00
qla2x00_is_reserved_id ( scsi_qla_host_t * vha , uint16_t loop_id )
2005-07-06 10:30:26 -07:00
{
2008-11-06 10:40:51 -08:00
struct qla_hw_data * ha = vha - > hw ;
2007-07-19 15:05:56 -07:00
if ( IS_FWI2_CAPABLE ( ha ) )
2005-07-06 10:30:26 -07:00
return ( loop_id > NPH_LAST_HANDLE ) ;
2008-11-06 10:40:51 -08:00
return ( ( loop_id > ha - > max_loop_id & & loop_id < SNS_FIRST_LOOP_ID ) | |
2005-07-06 10:30:26 -07:00
loop_id = = MANAGEMENT_SERVER | | loop_id = = BROADCAST ) ;
2008-12-18 10:06:15 -08:00
}
2010-05-04 15:01:30 -07:00
2012-08-22 14:21:00 -04:00
static inline void
qla2x00_clear_loop_id ( fc_port_t * fcport ) {
struct qla_hw_data * ha = fcport - > vha - > hw ;
if ( fcport - > loop_id = = FC_NO_LOOP_ID | |
qla2x00_is_reserved_id ( fcport - > vha , fcport - > loop_id ) )
return ;
clear_bit ( fcport - > loop_id , ha - > loop_id_map ) ;
fcport - > loop_id = FC_NO_LOOP_ID ;
}
2010-05-04 15:01:30 -07:00
static inline void
2014-04-11 16:54:43 -04:00
qla2x00_clean_dsd_pool ( struct qla_hw_data * ha , srb_t * sp ,
struct qla_tgt_cmd * tc )
2010-05-04 15:01:30 -07:00
{
struct dsd_dma * dsd_ptr , * tdsd_ptr ;
2012-02-09 11:15:36 -08:00
struct crc_context * ctx ;
2014-04-11 16:54:43 -04:00
if ( sp )
ctx = ( struct crc_context * ) GET_CMD_CTX_SP ( sp ) ;
else if ( tc )
ctx = ( struct crc_context * ) tc - > ctx ;
else {
BUG ( ) ;
return ;
}
2010-05-04 15:01:30 -07:00
/* clean up allocated prev pool */
list_for_each_entry_safe ( dsd_ptr , tdsd_ptr ,
2012-02-09 11:15:36 -08:00
& ctx - > dsd_list , list ) {
2010-05-04 15:01:30 -07:00
dma_pool_free ( ha - > dl_dma_pool , dsd_ptr - > dsd_addr ,
dsd_ptr - > dsd_list_dma ) ;
list_del ( & dsd_ptr - > list ) ;
kfree ( dsd_ptr ) ;
}
2012-02-09 11:15:36 -08:00
INIT_LIST_HEAD ( & ctx - > dsd_list ) ;
2010-05-04 15:01:30 -07:00
}
2011-03-30 11:46:32 -07:00
static inline void
qla2x00_set_fcport_state ( fc_port_t * fcport , int state )
{
int old_state ;
old_state = atomic_read ( & fcport - > state ) ;
atomic_set ( & fcport - > state , state ) ;
/* Don't print state transitions during initial allocation of fcport */
if ( old_state & & old_state ! = state ) {
2011-07-14 12:00:13 -07:00
ql_dbg ( ql_dbg_disc , fcport - > vha , 0x207d ,
" FCPort state transitioned from %s to %s - "
" portid=%02x%02x%02x. \n " ,
2011-03-30 11:46:32 -07:00
port_state_str [ old_state ] , port_state_str [ state ] ,
fcport - > d_id . b . domain , fcport - > d_id . b . area ,
2011-07-14 12:00:13 -07:00
fcport - > d_id . b . al_pa ) ;
2011-03-30 11:46:32 -07:00
}
}
2011-08-16 11:29:22 -07:00
static inline int
2011-08-16 11:29:23 -07:00
qla2x00_hba_err_chk_enabled ( srb_t * sp )
2011-08-16 11:29:22 -07:00
{
2011-08-16 11:29:23 -07:00
/*
* Uncomment when corresponding SCSI changes are done .
*
if ( ! sp - > cmd - > prot_chk )
return 0 ;
*
*/
2012-02-09 11:15:36 -08:00
switch ( scsi_get_prot_op ( GET_CMD_SP ( sp ) ) ) {
2011-08-16 11:29:22 -07:00
case SCSI_PROT_READ_STRIP :
case SCSI_PROT_WRITE_INSERT :
if ( ql2xenablehba_err_chk > = 1 )
return 1 ;
break ;
case SCSI_PROT_READ_PASS :
case SCSI_PROT_WRITE_PASS :
if ( ql2xenablehba_err_chk > = 2 )
return 1 ;
break ;
case SCSI_PROT_READ_INSERT :
case SCSI_PROT_WRITE_STRIP :
return 1 ;
}
return 0 ;
}
2012-02-09 11:14:05 -08:00
static inline int
qla2x00_reset_active ( scsi_qla_host_t * vha )
{
scsi_qla_host_t * base_vha = pci_get_drvdata ( vha - > hw - > pdev ) ;
/* Test appropriate base-vha and vha flags. */
return test_bit ( ISP_ABORT_NEEDED , & base_vha - > dpc_flags ) | |
test_bit ( ABORT_ISP_ACTIVE , & base_vha - > dpc_flags ) | |
test_bit ( ISP_ABORT_RETRY , & base_vha - > dpc_flags ) | |
test_bit ( ISP_ABORT_NEEDED , & vha - > dpc_flags ) | |
test_bit ( ABORT_ISP_ACTIVE , & vha - > dpc_flags ) ;
}
2012-02-09 11:15:36 -08:00
static inline srb_t *
qla2x00_get_sp ( scsi_qla_host_t * vha , fc_port_t * fcport , gfp_t flag )
{
srb_t * sp = NULL ;
struct qla_hw_data * ha = vha - > hw ;
uint8_t bail ;
QLA_VHA_MARK_BUSY ( vha , bail ) ;
if ( unlikely ( bail ) )
return NULL ;
sp = mempool_alloc ( ha - > srb_mempool , flag ) ;
if ( ! sp )
goto done ;
memset ( sp , 0 , sizeof ( * sp ) ) ;
sp - > fcport = fcport ;
sp - > iocbs = 1 ;
done :
if ( ! sp )
QLA_VHA_MARK_NOT_BUSY ( vha ) ;
return sp ;
}
2013-02-08 01:57:50 -05:00
static inline void
qla2x00_rel_sp ( scsi_qla_host_t * vha , srb_t * sp )
{
mempool_free ( sp , vha - > hw - > srb_mempool ) ;
QLA_VHA_MARK_NOT_BUSY ( vha ) ;
}
2012-02-09 11:15:36 -08:00
static inline void
qla2x00_init_timer ( srb_t * sp , unsigned long tmo )
{
init_timer ( & sp - > u . iocb_cmd . timer ) ;
sp - > u . iocb_cmd . timer . expires = jiffies + tmo * HZ ;
sp - > u . iocb_cmd . timer . data = ( unsigned long ) sp ;
sp - > u . iocb_cmd . timer . function = qla2x00_sp_timeout ;
add_timer ( & sp - > u . iocb_cmd . timer ) ;
sp - > free = qla2x00_sp_free ;
2013-03-28 08:21:23 -04:00
if ( ( IS_QLAFX00 ( sp - > fcport - > vha - > hw ) ) & &
( sp - > type = = SRB_FXIOCB_DCMD ) )
init_completion ( & sp - > u . iocb_cmd . u . fxiocb . fxiocb_comp ) ;
2015-12-17 14:57:00 -05:00
if ( sp - > type = = SRB_ELS_DCMD )
init_completion ( & sp - > u . iocb_cmd . u . els_logo . comp ) ;
2012-02-09 11:15:36 -08:00
}
2012-02-09 11:15:57 -08:00
static inline int
qla2x00_gid_list_size ( struct qla_hw_data * ha )
{
2013-03-28 08:21:23 -04:00
if ( IS_QLAFX00 ( ha ) )
return sizeof ( uint32_t ) * 32 ;
else
return sizeof ( struct gid_list_info ) * ha - > max_fibre_devices ;
2012-02-09 11:15:57 -08:00
}
2013-01-30 03:34:38 -05:00
2013-04-23 10:13:17 -07:00
static inline void
qla2x00_handle_mbx_completion ( struct qla_hw_data * ha , int status )
{
if ( test_bit ( MBX_INTR_WAIT , & ha - > mbx_cmd_flags ) & &
( status & MBX_INTERRUPT ) & & ha - > flags . mbox_int ) {
set_bit ( MBX_INTERRUPT , & ha - > mbx_cmd_flags ) ;
clear_bit ( MBX_INTR_WAIT , & ha - > mbx_cmd_flags ) ;
complete ( & ha - > mbx_intr_comp ) ;
}
}
2014-09-25 05:16:59 -04:00
static inline void
qla2x00_set_retry_delay_timestamp ( fc_port_t * fcport , uint16_t retry_delay )
{
if ( retry_delay )
fcport - > retry_delay_timestamp = jiffies +
( retry_delay * HZ / 10 ) ;
}