2017-11-24 15:00:36 +01:00
// SPDX-License-Identifier: GPL-2.0
2012-12-11 14:53:35 +01:00
/*
2015-06-29 18:47:28 +02:00
* Copyright IBM Corp . 2012 , 2015
2012-12-11 14:53:35 +01:00
*
* Author ( s ) :
* Jan Glauber < jang @ linux . vnet . ibm . com >
*/
2014-07-16 17:21:01 +02:00
# define KMSG_COMPONENT "zpci"
# define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
2012-12-11 14:53:35 +01:00
# include <linux/kernel.h>
# include <linux/seq_file.h>
# include <linux/debugfs.h>
2013-04-16 14:11:14 +02:00
# include <linux/export.h>
2012-12-11 14:53:35 +01:00
# include <linux/pci.h>
# include <asm/debug.h>
# include <asm/pci_dma.h>
static struct dentry * debugfs_root ;
2013-04-16 14:11:14 +02:00
debug_info_t * pci_debug_msg_id ;
EXPORT_SYMBOL_GPL ( pci_debug_msg_id ) ;
debug_info_t * pci_debug_err_id ;
EXPORT_SYMBOL_GPL ( pci_debug_err_id ) ;
2012-12-11 14:53:35 +01:00
2015-06-29 18:47:28 +02:00
static char * pci_common_names [ ] = {
2012-12-11 14:53:35 +01:00
" Load operations " ,
" Store operations " ,
" Store block operations " ,
" Refresh operations " ,
2015-06-29 18:47:28 +02:00
} ;
static char * pci_fmt0_names [ ] = {
2012-12-11 14:53:35 +01:00
" DMA read bytes " ,
" DMA write bytes " ,
2015-04-10 14:33:08 +02:00
} ;
2015-06-29 18:47:28 +02:00
static char * pci_fmt1_names [ ] = {
" Received bytes " ,
" Received packets " ,
" Transmitted bytes " ,
" Transmitted packets " ,
} ;
static char * pci_fmt2_names [ ] = {
" Consumed work units " ,
" Maximum work units " ,
} ;
2016-04-08 17:55:19 +02:00
static char * pci_fmt3_names [ ] = {
" Transmitted bytes " ,
} ;
2015-04-10 14:33:08 +02:00
static char * pci_sw_names [ ] = {
2012-12-11 14:53:35 +01:00
" Allocated pages " ,
" Mapped pages " ,
" Unmapped pages " ,
} ;
2015-06-29 18:47:28 +02:00
static void pci_fmb_show ( struct seq_file * m , char * name [ ] , int length ,
u64 * data )
{
int i ;
for ( i = 0 ; i < length ; i + + , data + + )
seq_printf ( m , " %26s: \t %llu \n " , name [ i ] , * data ) ;
}
2015-04-10 14:33:08 +02:00
static void pci_sw_counter_show ( struct seq_file * m )
{
struct zpci_dev * zdev = m - > private ;
atomic64_t * counter = & zdev - > allocated_pages ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( pci_sw_names ) ; i + + , counter + + )
2019-05-22 14:22:34 +01:00
seq_printf ( m , " %26s: \t %llu \n " , pci_sw_names [ i ] ,
2019-05-22 14:22:50 +01:00
atomic64_read ( counter ) ) ;
2015-04-10 14:33:08 +02:00
}
2012-12-11 14:53:35 +01:00
static int pci_perf_show ( struct seq_file * m , void * v )
{
struct zpci_dev * zdev = m - > private ;
if ( ! zdev )
return 0 ;
2015-04-10 14:34:33 +02:00
mutex_lock ( & zdev - > lock ) ;
2015-04-15 16:18:14 -07:00
if ( ! zdev - > fmb ) {
2015-04-10 14:34:33 +02:00
mutex_unlock ( & zdev - > lock ) ;
2015-04-15 16:18:14 -07:00
seq_puts ( m , " FMB statistics disabled \n " ) ;
return 0 ;
}
2012-12-11 14:53:35 +01:00
/* header */
seq_printf ( m , " Update interval: %u ms \n " , zdev - > fmb_update ) ;
seq_printf ( m , " Samples: %u \n " , zdev - > fmb - > samples ) ;
seq_printf ( m , " Last update TOD: %Lx \n " , zdev - > fmb - > last_update ) ;
2015-06-29 18:47:28 +02:00
pci_fmb_show ( m , pci_common_names , ARRAY_SIZE ( pci_common_names ) ,
& zdev - > fmb - > ld_ops ) ;
switch ( zdev - > fmb - > format ) {
case 0 :
if ( ! ( zdev - > fmb - > fmt_ind & ZPCI_FMB_DMA_COUNTER_VALID ) )
break ;
pci_fmb_show ( m , pci_fmt0_names , ARRAY_SIZE ( pci_fmt0_names ) ,
& zdev - > fmb - > fmt0 . dma_rbytes ) ;
break ;
case 1 :
pci_fmb_show ( m , pci_fmt1_names , ARRAY_SIZE ( pci_fmt1_names ) ,
& zdev - > fmb - > fmt1 . rx_bytes ) ;
break ;
case 2 :
pci_fmb_show ( m , pci_fmt2_names , ARRAY_SIZE ( pci_fmt2_names ) ,
& zdev - > fmb - > fmt2 . consumed_work_units ) ;
break ;
2016-04-08 17:55:19 +02:00
case 3 :
pci_fmb_show ( m , pci_fmt3_names , ARRAY_SIZE ( pci_fmt3_names ) ,
& zdev - > fmb - > fmt3 . tx_bytes ) ;
break ;
2015-06-29 18:47:28 +02:00
default :
seq_puts ( m , " Unknown format \n " ) ;
}
2012-12-11 14:53:35 +01:00
2015-04-10 14:33:08 +02:00
pci_sw_counter_show ( m ) ;
2015-04-10 14:34:33 +02:00
mutex_unlock ( & zdev - > lock ) ;
2012-12-11 14:53:35 +01:00
return 0 ;
}
static ssize_t pci_perf_seq_write ( struct file * file , const char __user * ubuf ,
size_t count , loff_t * off )
{
struct zpci_dev * zdev = ( ( struct seq_file * ) file - > private_data ) - > private ;
unsigned long val ;
int rc ;
if ( ! zdev )
return 0 ;
rc = kstrtoul_from_user ( ubuf , count , 10 , & val ) ;
if ( rc )
return rc ;
2015-04-10 14:34:33 +02:00
mutex_lock ( & zdev - > lock ) ;
2012-12-11 14:53:35 +01:00
switch ( val ) {
case 0 :
rc = zpci_fmb_disable_device ( zdev ) ;
break ;
case 1 :
rc = zpci_fmb_enable_device ( zdev ) ;
break ;
}
2015-04-10 14:34:33 +02:00
mutex_unlock ( & zdev - > lock ) ;
return rc ? rc : count ;
2012-12-11 14:53:35 +01:00
}
static int pci_perf_seq_open ( struct inode * inode , struct file * filp )
{
return single_open ( filp , pci_perf_show ,
2013-01-23 17:07:38 -05:00
file_inode ( filp ) - > i_private ) ;
2012-12-11 14:53:35 +01:00
}
static const struct file_operations debugfs_pci_perf_fops = {
. open = pci_perf_seq_open ,
. read = seq_read ,
. write = pci_perf_seq_write ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2016-01-29 15:13:30 +01:00
void zpci_debug_init_device ( struct zpci_dev * zdev , const char * name )
2012-12-11 14:53:35 +01:00
{
2016-01-29 15:13:30 +01:00
zdev - > debugfs_dev = debugfs_create_dir ( name , debugfs_root ) ;
2019-01-22 16:21:01 +01:00
debugfs_create_file ( " statistics " , S_IFREG | S_IRUGO | S_IWUSR ,
zdev - > debugfs_dev , zdev , & debugfs_pci_perf_fops ) ;
2012-12-11 14:53:35 +01:00
}
void zpci_debug_exit_device ( struct zpci_dev * zdev )
{
2019-01-22 16:21:01 +01:00
debugfs_remove_recursive ( zdev - > debugfs_dev ) ;
2012-12-11 14:53:35 +01:00
}
int __init zpci_debug_init ( void )
{
/* event trace buffer */
2014-02-17 11:16:10 +01:00
pci_debug_msg_id = debug_register ( " pci_msg " , 8 , 1 , 8 * sizeof ( long ) ) ;
2012-12-11 14:53:35 +01:00
if ( ! pci_debug_msg_id )
return - EINVAL ;
debug_register_view ( pci_debug_msg_id , & debug_sprintf_view ) ;
debug_set_level ( pci_debug_msg_id , 3 ) ;
/* error log */
pci_debug_err_id = debug_register ( " pci_error " , 2 , 1 , 16 ) ;
if ( ! pci_debug_err_id )
return - EINVAL ;
debug_register_view ( pci_debug_err_id , & debug_hex_ascii_view ) ;
debug_set_level ( pci_debug_err_id , 6 ) ;
debugfs_root = debugfs_create_dir ( " pci " , NULL ) ;
return 0 ;
}
void zpci_debug_exit ( void )
{
2014-11-22 15:00:55 +01:00
debug_unregister ( pci_debug_msg_id ) ;
debug_unregister ( pci_debug_err_id ) ;
2012-12-11 14:53:35 +01:00
debugfs_remove ( debugfs_root ) ;
}