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 .
*
2018-01-23 16:33:51 -08:00
* @ vha : HA context
2013-03-28 08:21:23 -04:00
* @ 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-11-06 10:40:51 -08:00
struct qla_hw_data * ha = rsp - > hw ;
2018-06-11 16:40:53 +02:00
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 ) ;
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
}
2010-05-04 15:01:30 -07:00
static inline void
2017-05-24 18:06:24 -07:00
qla2x00_clean_dsd_pool ( struct qla_hw_data * ha , struct crc_context * ctx )
2010-05-04 15:01:30 -07:00
{
2017-05-24 18:06:24 -07:00
struct dsd_dma * dsd , * tdsd ;
2010-05-04 15:01:30 -07:00
/* clean up allocated prev pool */
2017-05-24 18:06:24 -07:00
list_for_each_entry_safe ( dsd , tdsd , & ctx - > dsd_list , list ) {
dma_pool_free ( ha - > dl_dma_pool , dsd - > dsd_addr ,
dsd - > dsd_list_dma ) ;
list_del ( & dsd - > list ) ;
kfree ( dsd ) ;
2010-05-04 15:01:30 -07:00
}
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
2019-12-17 14:06:06 -08:00
static inline void
qla2x00_set_fcport_disc_state ( fc_port_t * fcport , int state )
{
int old_val ;
uint8_t shiftbits , mask ;
/* This will have to change when the max no. of states > 16 */
shiftbits = 4 ;
mask = ( 1 < < shiftbits ) - 1 ;
fcport - > disc_state = state ;
while ( 1 ) {
old_val = atomic_read ( & fcport - > shadow_disc_state ) ;
if ( old_val = = atomic_cmpxchg ( & fcport - > shadow_disc_state ,
old_val , ( old_val < < shiftbits ) | state ) ) {
ql_dbg ( ql_dbg_disc , fcport - > vha , 0x2134 ,
" FCPort %8phC disc_state transition: %s to %s - portid=%06x. \n " ,
fcport - > port_name , port_dstate_str [ old_val & mask ] ,
port_dstate_str [ state ] , fcport - > d_id . b24 ) ;
return ;
}
}
}
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
2018-08-02 13:16:47 -07:00
static inline int
qla2x00_chip_is_down ( scsi_qla_host_t * vha )
{
return ( qla2x00_reset_active ( vha ) | | ! vha - > hw - > flags . fw_started ) ;
}
2019-08-08 20:02:05 -07:00
static void qla2xxx_init_sp ( srb_t * sp , scsi_qla_host_t * vha ,
struct qla_qpair * qpair , fc_port_t * fcport )
{
memset ( sp , 0 , sizeof ( * sp ) ) ;
sp - > fcport = fcport ;
sp - > iocbs = 1 ;
sp - > vha = vha ;
sp - > qpair = qpair ;
sp - > cmd_type = TYPE_SRB ;
INIT_LIST_HEAD ( & sp - > elem ) ;
}
2016-12-12 14:40:07 -08:00
static inline srb_t *
2018-09-04 14:19:15 -07:00
qla2xxx_get_qpair_sp ( scsi_qla_host_t * vha , struct qla_qpair * qpair ,
fc_port_t * fcport , gfp_t flag )
2016-12-12 14:40:07 -08:00
{
srb_t * sp = NULL ;
uint8_t bail ;
QLA_QPAIR_MARK_BUSY ( qpair , bail ) ;
if ( unlikely ( bail ) )
return NULL ;
sp = mempool_alloc ( qpair - > srb_mempool , flag ) ;
2019-08-08 20:02:05 -07:00
if ( sp )
qla2xxx_init_sp ( sp , vha , qpair , fcport ) ;
else
2016-12-12 14:40:07 -08:00
QLA_QPAIR_MARK_NOT_BUSY ( qpair ) ;
return sp ;
}
static inline void
qla2xxx_rel_qpair_sp ( struct qla_qpair * qpair , srb_t * sp )
{
2019-04-02 14:24:21 -07:00
sp - > qpair = NULL ;
2016-12-12 14:40:07 -08:00
mempool_free ( sp , qpair - > srb_mempool ) ;
QLA_QPAIR_MARK_NOT_BUSY ( qpair ) ;
}
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 ;
uint8_t bail ;
2018-09-04 14:19:15 -07:00
struct qla_qpair * qpair ;
2012-02-09 11:15:36 -08:00
QLA_VHA_MARK_BUSY ( vha , bail ) ;
if ( unlikely ( bail ) )
return NULL ;
2018-09-04 14:19:15 -07:00
qpair = vha - > hw - > base_qpair ;
sp = qla2xxx_get_qpair_sp ( vha , qpair , fcport , flag ) ;
2012-02-09 11:15:36 -08:00
if ( ! sp )
goto done ;
2017-01-19 22:28:00 -08:00
sp - > vha = vha ;
2012-02-09 11:15:36 -08:00
done :
if ( ! sp )
QLA_VHA_MARK_NOT_BUSY ( vha ) ;
return sp ;
}
2013-02-08 01:57:50 -05:00
static inline void
2017-01-19 22:28:04 -08:00
qla2x00_rel_sp ( srb_t * sp )
2013-02-08 01:57:50 -05:00
{
2017-01-19 22:28:04 -08:00
QLA_VHA_MARK_NOT_BUSY ( sp - > vha ) ;
2018-09-04 14:19:15 -07:00
qla2xxx_rel_qpair_sp ( sp - > qpair , sp ) ;
2013-02-08 01:57:50 -05: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 ) ;
}
2017-06-02 09:12:03 -07:00
static inline bool
qla_is_exch_offld_enabled ( struct scsi_qla_host * vha )
{
if ( qla_ini_mode_enabled ( vha ) & &
2018-09-11 10:18:18 -07:00
( vha - > ql2xiniexchg > FW_DEF_EXCHANGES_CNT ) )
2017-06-02 09:12:03 -07:00
return true ;
else if ( qla_tgt_mode_enabled ( vha ) & &
2018-09-11 10:18:18 -07:00
( vha - > ql2xexchoffld > FW_DEF_EXCHANGES_CNT ) )
2017-06-02 09:12:03 -07:00
return true ;
else if ( qla_dual_mode_enabled ( vha ) & &
2018-09-11 10:18:18 -07:00
( ( vha - > ql2xiniexchg + vha - > ql2xexchoffld ) > FW_DEF_EXCHANGES_CNT ) )
2017-06-02 09:12:03 -07:00
return true ;
else
return false ;
}
2017-06-13 20:47:18 -07:00
static inline void
qla_cpu_update ( struct qla_qpair * qpair , uint16_t cpuid )
{
qpair - > cpuid = cpuid ;
if ( ! list_empty ( & qpair - > hints_list ) ) {
struct qla_qpair_hint * h ;
list_for_each_entry ( h , & qpair - > hints_list , hint_elem )
h - > cpuid = qpair - > cpuid ;
}
}
static inline struct qla_qpair_hint *
qla_qpair_to_hint ( struct qla_tgt * tgt , struct qla_qpair * qpair )
{
struct qla_qpair_hint * h ;
u16 i ;
for ( i = 0 ; i < tgt - > ha - > max_qpairs + 1 ; i + + ) {
h = & tgt - > qphints [ i ] ;
if ( h - > qpair = = qpair )
return h ;
}
return NULL ;
}
2017-06-13 20:47:24 -07:00
static inline void
qla_83xx_start_iocbs ( struct qla_qpair * qpair )
{
struct req_que * req = qpair - > req ;
req - > ring_index + + ;
if ( req - > ring_index = = req - > length ) {
req - > ring_index = 0 ;
req - > ring_ptr = req - > ring ;
} else
req - > ring_ptr + + ;
WRT_REG_DWORD ( req - > req_q_in , req - > ring_index ) ;
}
2019-09-12 11:09:12 -07:00
static inline int
qla2xxx_get_fc4_priority ( struct scsi_qla_host * vha )
{
uint32_t data ;
data =
( ( uint8_t * ) vha - > hw - > nvram ) [ NVRAM_DUAL_FCP_NVME_FLAG_OFFSET ] ;
2019-11-07 22:48:57 +00:00
return ( data > > 6 ) & BIT_0 ? FC4_PRIORITY_FCP : FC4_PRIORITY_NVME ;
2019-09-12 11:09:12 -07:00
}