2020-09-08 15:34:48 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2008-01-17 20:02:17 +03:00
/*
* QLogic Fibre Channel HBA Driver
2014-04-12 00:54:24 +04:00
* Copyright ( c ) 2003 - 2014 QLogic Corporation
2008-01-17 20:02:17 +03:00
*/
# include "qla_def.h"
# include <linux/debugfs.h>
# include <linux/seq_file.h>
static struct dentry * qla2x00_dfs_root ;
static atomic_t qla2x00_dfs_root_count ;
2020-09-04 07:51:18 +03:00
# define QLA_DFS_RPORT_DEVLOSS_TMO 1
static int
qla_dfs_rport_get ( struct fc_port * fp , int attr_id , u64 * val )
{
switch ( attr_id ) {
case QLA_DFS_RPORT_DEVLOSS_TMO :
/* Only supported for FC-NVMe devices that are registered. */
if ( ! ( fp - > nvme_flag & NVME_FLAG_REGISTERED ) )
return - EIO ;
* val = fp - > nvme_remote_port - > dev_loss_tmo ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
static int
qla_dfs_rport_set ( struct fc_port * fp , int attr_id , u64 val )
{
switch ( attr_id ) {
case QLA_DFS_RPORT_DEVLOSS_TMO :
/* Only supported for FC-NVMe devices that are registered. */
if ( ! ( fp - > nvme_flag & NVME_FLAG_REGISTERED ) )
return - EIO ;
# if (IS_ENABLED(CONFIG_NVME_FC))
return nvme_fc_set_remoteport_devloss ( fp - > nvme_remote_port ,
val ) ;
# else /* CONFIG_NVME_FC */
return - EINVAL ;
# endif /* CONFIG_NVME_FC */
default :
return - EINVAL ;
}
return 0 ;
}
# define DEFINE_QLA_DFS_RPORT_RW_ATTR(_attr_id, _attr) \
static int qla_dfs_rport_ # # _attr # # _get ( void * data , u64 * val ) \
{ \
struct fc_port * fp = data ; \
return qla_dfs_rport_get ( fp , _attr_id , val ) ; \
} \
static int qla_dfs_rport_ # # _attr # # _set ( void * data , u64 val ) \
{ \
struct fc_port * fp = data ; \
return qla_dfs_rport_set ( fp , _attr_id , val ) ; \
} \
DEFINE_DEBUGFS_ATTRIBUTE ( qla_dfs_rport_ # # _attr # # _fops , \
qla_dfs_rport_ # # _attr # # _get , \
qla_dfs_rport_ # # _attr # # _set , " %llu \n " )
2020-09-04 07:51:25 +03:00
/*
* Wrapper for getting fc_port fields .
*
* _attr : Attribute name .
* _get_val : Accessor macro to retrieve the value .
*/
# define DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val) \
static int qla_dfs_rport_field_ # # _attr # # _get ( void * data , u64 * val ) \
{ \
struct fc_port * fp = data ; \
* val = _get_val ; \
return 0 ; \
} \
DEFINE_DEBUGFS_ATTRIBUTE ( qla_dfs_rport_field_ # # _attr # # _fops , \
qla_dfs_rport_field_ # # _attr # # _get , \
NULL , " %llu \n " )
# define DEFINE_QLA_DFS_RPORT_ACCESS(_attr, _get_val) \
DEFINE_QLA_DFS_RPORT_FIELD_GET ( _attr , _get_val )
# define DEFINE_QLA_DFS_RPORT_FIELD(_attr) \
DEFINE_QLA_DFS_RPORT_FIELD_GET ( _attr , fp - > _attr )
2020-09-04 07:51:18 +03:00
DEFINE_QLA_DFS_RPORT_RW_ATTR ( QLA_DFS_RPORT_DEVLOSS_TMO , dev_loss_tmo ) ;
2020-09-04 07:51:25 +03:00
DEFINE_QLA_DFS_RPORT_FIELD ( disc_state ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( scan_state ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( fw_login_state ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( login_pause ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( flags ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( nvme_flag ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( last_rscn_gen ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( rscn_gen ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( login_gen ) ;
DEFINE_QLA_DFS_RPORT_FIELD ( loop_id ) ;
DEFINE_QLA_DFS_RPORT_FIELD_GET ( port_id , fp - > d_id . b24 ) ;
DEFINE_QLA_DFS_RPORT_FIELD_GET ( sess_kref , kref_read ( & fp - > sess_kref ) ) ;
2020-09-04 07:51:17 +03:00
void
qla2x00_dfs_create_rport ( scsi_qla_host_t * vha , struct fc_port * fp )
{
char wwn [ 32 ] ;
2020-09-04 07:51:25 +03:00
# define QLA_CREATE_RPORT_FIELD_ATTR(_attr) \
debugfs_create_file ( # _attr , 0400 , fp - > dfs_rport_dir , \
fp , & qla_dfs_rport_field_ # # _attr # # _fops )
2020-09-04 07:51:17 +03:00
if ( ! vha - > dfs_rport_root | | fp - > dfs_rport_dir )
return ;
sprintf ( wwn , " pn-%016llx " , wwn_to_u64 ( fp - > port_name ) ) ;
fp - > dfs_rport_dir = debugfs_create_dir ( wwn , vha - > dfs_rport_root ) ;
if ( ! fp - > dfs_rport_dir )
return ;
2020-09-04 07:51:18 +03:00
if ( NVME_TARGET ( vha - > hw , fp ) )
debugfs_create_file ( " dev_loss_tmo " , 0600 , fp - > dfs_rport_dir ,
fp , & qla_dfs_rport_dev_loss_tmo_fops ) ;
2020-09-04 07:51:25 +03:00
QLA_CREATE_RPORT_FIELD_ATTR ( disc_state ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( scan_state ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( fw_login_state ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( login_pause ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( flags ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( nvme_flag ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( last_rscn_gen ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( rscn_gen ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( login_gen ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( loop_id ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( port_id ) ;
QLA_CREATE_RPORT_FIELD_ATTR ( sess_kref ) ;
2020-09-04 07:51:17 +03:00
}
void
qla2x00_dfs_remove_rport ( scsi_qla_host_t * vha , struct fc_port * fp )
{
if ( ! vha - > dfs_rport_root | | ! fp - > dfs_rport_dir )
return ;
debugfs_remove_recursive ( fp - > dfs_rport_dir ) ;
fp - > dfs_rport_dir = NULL ;
}
2016-02-04 19:45:18 +03:00
static int
qla2x00_dfs_tgt_sess_show ( struct seq_file * s , void * unused )
{
scsi_qla_host_t * vha = s - > private ;
struct qla_hw_data * ha = vha - > hw ;
unsigned long flags ;
2017-01-20 09:27:59 +03:00
struct fc_port * sess = NULL ;
2017-03-15 19:48:53 +03:00
struct qla_tgt * tgt = vha - > vha_tgt . qla_tgt ;
2016-02-04 19:45:18 +03:00
2017-03-15 19:48:53 +03:00
seq_printf ( s , " %s \n " , vha - > host_str ) ;
2016-02-04 19:45:18 +03:00
if ( tgt ) {
2017-03-15 19:48:53 +03:00
seq_puts ( s , " Port ID Port Name Handle \n " ) ;
2016-02-04 19:45:18 +03:00
spin_lock_irqsave ( & ha - > tgt . sess_lock , flags ) ;
2017-01-20 09:27:59 +03:00
list_for_each_entry ( sess , & vha - > vp_fcports , list )
2016-02-04 19:45:18 +03:00
seq_printf ( s , " %02x:%02x:%02x %8phC %d \n " ,
2017-01-20 09:27:58 +03:00
sess - > d_id . b . domain , sess - > d_id . b . area ,
sess - > d_id . b . al_pa , sess - > port_name ,
sess - > loop_id ) ;
2016-02-04 19:45:18 +03:00
spin_unlock_irqrestore ( & ha - > tgt . sess_lock , flags ) ;
}
return 0 ;
}
2020-09-19 05:52:02 +03:00
DEFINE_SHOW_ATTRIBUTE ( qla2x00_dfs_tgt_sess ) ;
2016-02-04 19:45:18 +03:00
2017-03-15 19:48:53 +03:00
static int
qla2x00_dfs_tgt_port_database_show ( struct seq_file * s , void * unused )
{
scsi_qla_host_t * vha = s - > private ;
struct qla_hw_data * ha = vha - > hw ;
2020-09-04 07:51:24 +03:00
struct gid_list_info * gid_list ;
2017-03-15 19:48:53 +03:00
dma_addr_t gid_list_dma ;
fc_port_t fc_port ;
2020-09-04 07:51:24 +03:00
char * id_iter ;
2017-03-15 19:48:53 +03:00
int rc , i ;
uint16_t entries , loop_id ;
seq_printf ( s , " %s \n " , vha - > host_str ) ;
2020-09-04 07:51:24 +03:00
gid_list = dma_alloc_coherent ( & ha - > pdev - > dev ,
qla2x00_gid_list_size ( ha ) ,
& gid_list_dma , GFP_KERNEL ) ;
if ( ! gid_list ) {
ql_dbg ( ql_dbg_user , vha , 0x7018 ,
" DMA allocation failed for %u \n " ,
qla2x00_gid_list_size ( ha ) ) ;
return 0 ;
2017-03-15 19:48:53 +03:00
}
2020-09-04 07:51:24 +03:00
rc = qla24xx_gidlist_wait ( vha , gid_list , gid_list_dma ,
& entries ) ;
if ( rc ! = QLA_SUCCESS )
goto out_free_id_list ;
id_iter = ( char * ) gid_list ;
seq_puts ( s , " Port Name Port ID Loop ID \n " ) ;
for ( i = 0 ; i < entries ; i + + ) {
struct gid_list_info * gid =
( struct gid_list_info * ) id_iter ;
loop_id = le16_to_cpu ( gid - > loop_id ) ;
memset ( & fc_port , 0 , sizeof ( fc_port_t ) ) ;
fc_port . loop_id = loop_id ;
rc = qla24xx_gpdb_wait ( vha , & fc_port , 0 ) ;
seq_printf ( s , " %8phC %02x%02x%02x %d \n " ,
fc_port . port_name , fc_port . d_id . b . domain ,
fc_port . d_id . b . area , fc_port . d_id . b . al_pa ,
fc_port . loop_id ) ;
id_iter + = ha - > gid_list_info_size ;
}
out_free_id_list :
dma_free_coherent ( & ha - > pdev - > dev , qla2x00_gid_list_size ( ha ) ,
gid_list , gid_list_dma ) ;
2017-03-15 19:48:53 +03:00
return 0 ;
}
2020-09-19 05:52:02 +03:00
DEFINE_SHOW_ATTRIBUTE ( qla2x00_dfs_tgt_port_database ) ;
2017-03-15 19:48:53 +03:00
2015-12-17 22:56:59 +03:00
static int
qla_dfs_fw_resource_cnt_show ( struct seq_file * s , void * unused )
{
struct scsi_qla_host * vha = s - > private ;
2017-12-28 23:33:23 +03:00
uint16_t mb [ MAX_IOCB_MB_REG ] ;
int rc ;
2020-09-04 07:51:26 +03:00
struct qla_hw_data * ha = vha - > hw ;
u16 iocbs_used , i ;
2017-12-28 23:33:23 +03:00
rc = qla24xx_res_count_wait ( vha , mb , SIZEOF_IOCB_MB_REG ) ;
if ( rc ! = QLA_SUCCESS ) {
seq_printf ( s , " Mailbox Command failed %d, mb %#x " , rc , mb [ 0 ] ) ;
} else {
seq_puts ( s , " FW Resource count \n \n " ) ;
seq_printf ( s , " Original TGT exchg count[%d] \n " , mb [ 1 ] ) ;
2020-02-27 01:40:12 +03:00
seq_printf ( s , " Current TGT exchg count[%d] \n " , mb [ 2 ] ) ;
seq_printf ( s , " Current Initiator Exchange count[%d] \n " , mb [ 3 ] ) ;
seq_printf ( s , " Original Initiator Exchange count[%d] \n " , mb [ 6 ] ) ;
seq_printf ( s , " Current IOCB count[%d] \n " , mb [ 7 ] ) ;
seq_printf ( s , " Original IOCB count[%d] \n " , mb [ 10 ] ) ;
2017-12-28 23:33:23 +03:00
seq_printf ( s , " MAX VP count[%d] \n " , mb [ 11 ] ) ;
seq_printf ( s , " MAX FCF count[%d] \n " , mb [ 12 ] ) ;
2018-01-16 07:46:52 +03:00
seq_printf ( s , " Current free pageable XCB buffer cnt[%d] \n " ,
mb [ 20 ] ) ;
seq_printf ( s , " Original Initiator fast XCB buffer cnt[%d] \n " ,
mb [ 21 ] ) ;
seq_printf ( s , " Current free Initiator fast XCB buffer cnt[%d] \n " ,
mb [ 22 ] ) ;
seq_printf ( s , " Original Target fast XCB buffer cnt[%d] \n " ,
mb [ 23 ] ) ;
2017-12-28 23:33:23 +03:00
}
2015-12-17 22:56:59 +03:00
2020-09-04 07:51:26 +03:00
if ( ql2xenforce_iocb_limit ) {
/* lock is not require. It's an estimate. */
iocbs_used = ha - > base_qpair - > fwres . iocbs_used ;
for ( i = 0 ; i < ha - > max_qpairs ; i + + ) {
if ( ha - > queue_pair_map [ i ] )
iocbs_used + = ha - > queue_pair_map [ i ] - > fwres . iocbs_used ;
}
seq_printf ( s , " Driver: estimate iocb used [%d] high water limit [%d] \n " ,
iocbs_used , ha - > base_qpair - > fwres . iocbs_limit ) ;
}
2015-12-17 22:56:59 +03:00
return 0 ;
}
2020-09-19 05:52:02 +03:00
DEFINE_SHOW_ATTRIBUTE ( qla_dfs_fw_resource_cnt ) ;
2015-12-17 22:56:59 +03:00
2015-12-17 22:56:58 +03:00
static int
qla_dfs_tgt_counters_show ( struct seq_file * s , void * unused )
{
struct scsi_qla_host * vha = s - > private ;
2017-06-14 06:47:28 +03:00
struct qla_qpair * qpair = vha - > hw - > base_qpair ;
uint64_t qla_core_sbt_cmd , core_qla_que_buf , qla_core_ret_ctio ,
core_qla_snd_status , qla_core_ret_sta_ctio , core_qla_free_cmd ,
num_q_full_sent , num_alloc_iocb_failed , num_term_xchg_sent ;
u16 i ;
2021-01-11 12:31:29 +03:00
fc_port_t * fcport = NULL ;
if ( qla2x00_chip_is_down ( vha ) )
return 0 ;
2017-06-14 06:47:28 +03:00
qla_core_sbt_cmd = qpair - > tgt_counters . qla_core_sbt_cmd ;
core_qla_que_buf = qpair - > tgt_counters . core_qla_que_buf ;
qla_core_ret_ctio = qpair - > tgt_counters . qla_core_ret_ctio ;
core_qla_snd_status = qpair - > tgt_counters . core_qla_snd_status ;
qla_core_ret_sta_ctio = qpair - > tgt_counters . qla_core_ret_sta_ctio ;
core_qla_free_cmd = qpair - > tgt_counters . core_qla_free_cmd ;
num_q_full_sent = qpair - > tgt_counters . num_q_full_sent ;
num_alloc_iocb_failed = qpair - > tgt_counters . num_alloc_iocb_failed ;
num_term_xchg_sent = qpair - > tgt_counters . num_term_xchg_sent ;
for ( i = 0 ; i < vha - > hw - > max_qpairs ; i + + ) {
qpair = vha - > hw - > queue_pair_map [ i ] ;
2019-03-04 16:25:46 +03:00
if ( ! qpair )
continue ;
2017-06-14 06:47:28 +03:00
qla_core_sbt_cmd + = qpair - > tgt_counters . qla_core_sbt_cmd ;
core_qla_que_buf + = qpair - > tgt_counters . core_qla_que_buf ;
qla_core_ret_ctio + = qpair - > tgt_counters . qla_core_ret_ctio ;
core_qla_snd_status + = qpair - > tgt_counters . core_qla_snd_status ;
qla_core_ret_sta_ctio + =
qpair - > tgt_counters . qla_core_ret_sta_ctio ;
core_qla_free_cmd + = qpair - > tgt_counters . core_qla_free_cmd ;
num_q_full_sent + = qpair - > tgt_counters . num_q_full_sent ;
num_alloc_iocb_failed + =
qpair - > tgt_counters . num_alloc_iocb_failed ;
num_term_xchg_sent + = qpair - > tgt_counters . num_term_xchg_sent ;
}
2015-12-17 22:56:58 +03:00
seq_puts ( s , " Target Counters \n " ) ;
seq_printf ( s , " qla_core_sbt_cmd = %lld \n " ,
2017-06-14 06:47:28 +03:00
qla_core_sbt_cmd ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " qla_core_ret_sta_ctio = %lld \n " ,
2017-06-14 06:47:28 +03:00
qla_core_ret_sta_ctio ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " qla_core_ret_ctio = %lld \n " ,
2017-06-14 06:47:28 +03:00
qla_core_ret_ctio ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " core_qla_que_buf = %lld \n " ,
2017-06-14 06:47:28 +03:00
core_qla_que_buf ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " core_qla_snd_status = %lld \n " ,
2017-06-14 06:47:28 +03:00
core_qla_snd_status ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " core_qla_free_cmd = %lld \n " ,
2017-06-14 06:47:28 +03:00
core_qla_free_cmd ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " num alloc iocb failed = %lld \n " ,
2017-06-14 06:47:28 +03:00
num_alloc_iocb_failed ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " num term exchange sent = %lld \n " ,
2017-06-14 06:47:28 +03:00
num_term_xchg_sent ) ;
2015-12-17 22:56:58 +03:00
seq_printf ( s , " num Q full sent = %lld \n " ,
2017-06-14 06:47:28 +03:00
num_q_full_sent ) ;
2015-12-17 22:56:58 +03:00
2017-03-15 19:48:50 +03:00
/* DIF stats */
seq_printf ( s , " DIF Inp Bytes = %lld \n " ,
vha - > qla_stats . qla_dif_stats . dif_input_bytes ) ;
seq_printf ( s , " DIF Outp Bytes = %lld \n " ,
vha - > qla_stats . qla_dif_stats . dif_output_bytes ) ;
seq_printf ( s , " DIF Inp Req = %lld \n " ,
vha - > qla_stats . qla_dif_stats . dif_input_requests ) ;
seq_printf ( s , " DIF Outp Req = %lld \n " ,
vha - > qla_stats . qla_dif_stats . dif_output_requests ) ;
seq_printf ( s , " DIF Guard err = %d \n " ,
vha - > qla_stats . qla_dif_stats . dif_guard_err ) ;
seq_printf ( s , " DIF Ref tag err = %d \n " ,
vha - > qla_stats . qla_dif_stats . dif_ref_tag_err ) ;
seq_printf ( s , " DIF App tag err = %d \n " ,
vha - > qla_stats . qla_dif_stats . dif_app_tag_err ) ;
2021-01-11 12:31:29 +03:00
seq_puts ( s , " \n " ) ;
seq_puts ( s , " Initiator Error Counters \n " ) ;
seq_printf ( s , " HW Error Count = %14lld \n " ,
vha - > hw_err_cnt ) ;
seq_printf ( s , " Link Down Count = %14lld \n " ,
vha - > short_link_down_cnt ) ;
seq_printf ( s , " Interface Err Count = %14lld \n " ,
vha - > interface_err_cnt ) ;
seq_printf ( s , " Cmd Timeout Count = %14lld \n " ,
vha - > cmd_timeout_cnt ) ;
seq_printf ( s , " Reset Count = %14lld \n " ,
vha - > reset_cmd_err_cnt ) ;
seq_puts ( s , " \n " ) ;
list_for_each_entry ( fcport , & vha - > vp_fcports , list ) {
2021-01-21 09:08:41 +03:00
if ( ! fcport - > rport )
2021-01-11 12:31:29 +03:00
continue ;
seq_printf ( s , " Target Num = %7d Link Down Count = %14lld \n " ,
fcport - > rport - > number , fcport - > tgt_short_link_down_cnt ) ;
}
seq_puts ( s , " \n " ) ;
2015-12-17 22:56:58 +03:00
return 0 ;
}
2020-09-19 05:52:02 +03:00
DEFINE_SHOW_ATTRIBUTE ( qla_dfs_tgt_counters ) ;
2015-12-17 22:56:58 +03:00
2008-01-17 20:02:17 +03:00
static int
qla2x00_dfs_fce_show ( struct seq_file * s , void * unused )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = s - > private ;
2008-01-17 20:02:17 +03:00
uint32_t cnt ;
uint32_t * fce ;
uint64_t fce_start ;
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2008-01-17 20:02:17 +03:00
mutex_lock ( & ha - > fce_mutex ) ;
2014-12-03 02:10:52 +03:00
seq_puts ( s , " FCE Trace Buffer \n " ) ;
2008-02-16 09:24:41 +03:00
seq_printf ( s , " In Pointer = %llx \n \n " , ( unsigned long long ) ha - > fce_wr ) ;
2008-01-17 20:02:17 +03:00
seq_printf ( s , " Base = %llx \n \n " , ( unsigned long long ) ha - > fce_dma ) ;
2014-12-03 02:10:52 +03:00
seq_puts ( s , " FCE Enable Registers \n " ) ;
2008-01-17 20:02:17 +03:00
seq_printf ( s , " %08x %08x %08x %08x %08x %08x \n " ,
ha - > fce_mb [ 0 ] , ha - > fce_mb [ 2 ] , ha - > fce_mb [ 3 ] , ha - > fce_mb [ 4 ] ,
ha - > fce_mb [ 5 ] , ha - > fce_mb [ 6 ] ) ;
fce = ( uint32_t * ) ha - > fce ;
fce_start = ( unsigned long long ) ha - > fce_dma ;
for ( cnt = 0 ; cnt < fce_calc_size ( ha - > fce_bufs ) / 4 ; cnt + + ) {
if ( cnt % 8 = = 0 )
seq_printf ( s , " \n %llx: " ,
( unsigned long long ) ( ( cnt * 4 ) + fce_start ) ) ;
else
2014-12-03 02:10:54 +03:00
seq_putc ( s , ' ' ) ;
2008-01-17 20:02:17 +03:00
seq_printf ( s , " %08x " , * fce + + ) ;
}
2014-12-03 02:10:52 +03:00
seq_puts ( s , " \n End \n " ) ;
2008-01-17 20:02:17 +03:00
mutex_unlock ( & ha - > fce_mutex ) ;
return 0 ;
}
static int
qla2x00_dfs_fce_open ( struct inode * inode , struct file * file )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = inode - > i_private ;
struct qla_hw_data * ha = vha - > hw ;
2008-01-17 20:02:17 +03:00
int rval ;
if ( ! ha - > flags . fce_enabled )
goto out ;
mutex_lock ( & ha - > fce_mutex ) ;
/* Pause tracing to flush FCE buffers. */
2008-11-06 21:40:19 +03:00
rval = qla2x00_disable_fce_trace ( vha , & ha - > fce_wr , & ha - > fce_rd ) ;
2008-01-17 20:02:17 +03:00
if ( rval )
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_user , vha , 0x705c ,
2008-01-17 20:02:17 +03:00
" DebugFS: Unable to disable FCE (%d). \n " , rval ) ;
ha - > flags . fce_enabled = 0 ;
mutex_unlock ( & ha - > fce_mutex ) ;
out :
2009-03-24 19:07:57 +03:00
return single_open ( file , qla2x00_dfs_fce_show , vha ) ;
2008-01-17 20:02:17 +03:00
}
static int
qla2x00_dfs_fce_release ( struct inode * inode , struct file * file )
{
2008-11-06 21:40:19 +03:00
scsi_qla_host_t * vha = inode - > i_private ;
struct qla_hw_data * ha = vha - > hw ;
2008-01-17 20:02:17 +03:00
int rval ;
if ( ha - > flags . fce_enabled )
goto out ;
mutex_lock ( & ha - > fce_mutex ) ;
/* Re-enable FCE tracing. */
ha - > flags . fce_enabled = 1 ;
memset ( ha - > fce , 0 , fce_calc_size ( ha - > fce_bufs ) ) ;
2008-11-06 21:40:19 +03:00
rval = qla2x00_enable_fce_trace ( vha , ha - > fce_dma , ha - > fce_bufs ,
2008-01-17 20:02:17 +03:00
ha - > fce_mb , & ha - > fce_bufs ) ;
if ( rval ) {
2011-07-14 23:00:13 +04:00
ql_dbg ( ql_dbg_user , vha , 0x700d ,
2008-01-17 20:02:17 +03:00
" DebugFS: Unable to reinitialize FCE (%d). \n " , rval ) ;
ha - > flags . fce_enabled = 0 ;
}
mutex_unlock ( & ha - > fce_mutex ) ;
out :
return single_release ( inode , file ) ;
}
static const struct file_operations dfs_fce_ops = {
. open = qla2x00_dfs_fce_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = qla2x00_dfs_fce_release ,
} ;
2017-06-14 06:47:20 +03:00
static int
qla_dfs_naqp_show ( struct seq_file * s , void * unused )
{
struct scsi_qla_host * vha = s - > private ;
struct qla_hw_data * ha = vha - > hw ;
seq_printf ( s , " %d \n " , ha - > tgt . num_act_qpairs ) ;
return 0 ;
}
static int
qla_dfs_naqp_open ( struct inode * inode , struct file * file )
{
struct scsi_qla_host * vha = inode - > i_private ;
return single_open ( file , qla_dfs_naqp_show , vha ) ;
}
static ssize_t
qla_dfs_naqp_write ( struct file * file , const char __user * buffer ,
size_t count , loff_t * pos )
{
struct seq_file * s = file - > private_data ;
struct scsi_qla_host * vha = s - > private ;
struct qla_hw_data * ha = vha - > hw ;
char * buf ;
int rc = 0 ;
unsigned long num_act_qp ;
2019-03-12 21:08:13 +03:00
if ( ! ( IS_QLA27XX ( ha ) | | IS_QLA83XX ( ha ) | | IS_QLA28XX ( ha ) ) ) {
2017-06-14 06:47:20 +03:00
pr_err ( " host%ld: this adapter does not support Multi Q. " ,
vha - > host_no ) ;
return - EINVAL ;
}
if ( ! vha - > flags . qpairs_available ) {
pr_err ( " host%ld: Driver is not setup with Multi Q. " ,
vha - > host_no ) ;
return - EINVAL ;
}
buf = memdup_user_nul ( buffer , count ) ;
if ( IS_ERR ( buf ) ) {
pr_err ( " host%ld: fail to copy user buffer. " ,
vha - > host_no ) ;
return PTR_ERR ( buf ) ;
}
num_act_qp = simple_strtoul ( buf , NULL , 0 ) ;
if ( num_act_qp > = vha - > hw - > max_qpairs ) {
pr_err ( " User set invalid number of qpairs %lu. Max = %d " ,
num_act_qp , vha - > hw - > max_qpairs ) ;
rc = - EINVAL ;
goto out_free ;
}
if ( num_act_qp ! = ha - > tgt . num_act_qpairs ) {
ha - > tgt . num_act_qpairs = num_act_qp ;
qlt_clr_qp_table ( vha ) ;
}
rc = count ;
out_free :
kfree ( buf ) ;
return rc ;
}
static const struct file_operations dfs_naqp_ops = {
. open = qla_dfs_naqp_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
. write = qla_dfs_naqp_write ,
} ;
2008-01-17 20:02:17 +03:00
int
2008-11-06 21:40:19 +03:00
qla2x00_dfs_setup ( scsi_qla_host_t * vha )
2008-01-17 20:02:17 +03:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2009-01-05 22:18:11 +03:00
2014-02-26 13:15:06 +04:00
if ( ! IS_QLA25XX ( ha ) & & ! IS_QLA81XX ( ha ) & & ! IS_QLA83XX ( ha ) & &
2019-03-12 21:08:13 +03:00
! IS_QLA27XX ( ha ) & & ! IS_QLA28XX ( ha ) )
2008-01-17 20:02:17 +03:00
goto out ;
if ( ! ha - > fce )
goto out ;
if ( qla2x00_dfs_root )
goto create_dir ;
atomic_set ( & qla2x00_dfs_root_count , 0 ) ;
qla2x00_dfs_root = debugfs_create_dir ( QLA2XXX_DRIVER_NAME , NULL ) ;
create_dir :
if ( ha - > dfs_dir )
goto create_nodes ;
mutex_init ( & ha - > fce_mutex ) ;
2008-11-06 21:40:19 +03:00
ha - > dfs_dir = debugfs_create_dir ( vha - > host_str , qla2x00_dfs_root ) ;
2008-01-17 20:02:17 +03:00
atomic_inc ( & qla2x00_dfs_root_count ) ;
create_nodes :
2015-12-17 22:56:59 +03:00
ha - > dfs_fw_resource_cnt = debugfs_create_file ( " fw_resource_count " ,
2020-09-19 05:52:02 +03:00
S_IRUSR , ha - > dfs_dir , vha , & qla_dfs_fw_resource_cnt_fops ) ;
2015-12-17 22:56:59 +03:00
2015-12-17 22:56:58 +03:00
ha - > dfs_tgt_counters = debugfs_create_file ( " tgt_counters " , S_IRUSR ,
2020-09-19 05:52:02 +03:00
ha - > dfs_dir , vha , & qla_dfs_tgt_counters_fops ) ;
2015-12-17 22:56:58 +03:00
2017-03-15 19:48:53 +03:00
ha - > tgt . dfs_tgt_port_database = debugfs_create_file ( " tgt_port_database " ,
2020-09-19 05:52:02 +03:00
S_IRUSR , ha - > dfs_dir , vha , & qla2x00_dfs_tgt_port_database_fops ) ;
2017-03-15 19:48:53 +03:00
2009-03-24 19:07:57 +03:00
ha - > dfs_fce = debugfs_create_file ( " fce " , S_IRUSR , ha - > dfs_dir , vha ,
2008-01-17 20:02:17 +03:00
& dfs_fce_ops ) ;
2016-02-04 19:45:18 +03:00
ha - > tgt . dfs_tgt_sess = debugfs_create_file ( " tgt_sess " ,
2020-09-19 05:52:02 +03:00
S_IRUSR , ha - > dfs_dir , vha , & qla2x00_dfs_tgt_sess_fops ) ;
2016-02-04 19:45:18 +03:00
2020-09-04 07:51:17 +03:00
if ( IS_QLA27XX ( ha ) | | IS_QLA83XX ( ha ) | | IS_QLA28XX ( ha ) ) {
2017-06-14 06:47:20 +03:00
ha - > tgt . dfs_naqp = debugfs_create_file ( " naqp " ,
0400 , ha - > dfs_dir , vha , & dfs_naqp_ops ) ;
2020-09-04 07:51:17 +03:00
if ( ! ha - > tgt . dfs_naqp ) {
ql_log ( ql_log_warn , vha , 0xd011 ,
" Unable to create debugFS naqp node. \n " ) ;
goto out ;
}
}
vha - > dfs_rport_root = debugfs_create_dir ( " rports " , ha - > dfs_dir ) ;
if ( ! vha - > dfs_rport_root ) {
ql_log ( ql_log_warn , vha , 0xd012 ,
" Unable to create debugFS rports node. \n " ) ;
goto out ;
}
2008-01-17 20:02:17 +03:00
out :
return 0 ;
}
int
2008-11-06 21:40:19 +03:00
qla2x00_dfs_remove ( scsi_qla_host_t * vha )
2008-01-17 20:02:17 +03:00
{
2008-11-06 21:40:19 +03:00
struct qla_hw_data * ha = vha - > hw ;
2015-12-17 22:56:58 +03:00
2017-06-14 06:47:20 +03:00
if ( ha - > tgt . dfs_naqp ) {
debugfs_remove ( ha - > tgt . dfs_naqp ) ;
ha - > tgt . dfs_naqp = NULL ;
}
2016-02-04 19:45:18 +03:00
if ( ha - > tgt . dfs_tgt_sess ) {
debugfs_remove ( ha - > tgt . dfs_tgt_sess ) ;
ha - > tgt . dfs_tgt_sess = NULL ;
}
2017-03-15 19:48:53 +03:00
if ( ha - > tgt . dfs_tgt_port_database ) {
debugfs_remove ( ha - > tgt . dfs_tgt_port_database ) ;
ha - > tgt . dfs_tgt_port_database = NULL ;
}
2015-12-17 22:56:59 +03:00
if ( ha - > dfs_fw_resource_cnt ) {
debugfs_remove ( ha - > dfs_fw_resource_cnt ) ;
ha - > dfs_fw_resource_cnt = NULL ;
}
2015-12-17 22:56:58 +03:00
if ( ha - > dfs_tgt_counters ) {
debugfs_remove ( ha - > dfs_tgt_counters ) ;
ha - > dfs_tgt_counters = NULL ;
}
2008-01-17 20:02:17 +03:00
if ( ha - > dfs_fce ) {
debugfs_remove ( ha - > dfs_fce ) ;
ha - > dfs_fce = NULL ;
}
2020-09-04 07:51:17 +03:00
if ( vha - > dfs_rport_root ) {
debugfs_remove_recursive ( vha - > dfs_rport_root ) ;
vha - > dfs_rport_root = NULL ;
}
2008-01-17 20:02:17 +03:00
if ( ha - > dfs_dir ) {
debugfs_remove ( ha - > dfs_dir ) ;
ha - > dfs_dir = NULL ;
atomic_dec ( & qla2x00_dfs_root_count ) ;
}
if ( atomic_read ( & qla2x00_dfs_root_count ) = = 0 & &
qla2x00_dfs_root ) {
debugfs_remove ( qla2x00_dfs_root ) ;
qla2x00_dfs_root = NULL ;
}
return 0 ;
}