2020-05-27 16:21:28 +01:00
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2014 - 2020 Intel Corporation */
2014-06-05 13:42:58 -07:00
# include <linux/mutex.h>
# include <linux/slab.h>
# include <linux/seq_file.h>
# include "adf_accel_devices.h"
# include "adf_transport_internal.h"
# include "adf_transport_access_macros.h"
static DEFINE_MUTEX ( ring_read_lock ) ;
static DEFINE_MUTEX ( bank_read_lock ) ;
static void * adf_ring_start ( struct seq_file * sfile , loff_t * pos )
{
struct adf_etr_ring_data * ring = sfile - > private ;
2014-06-24 15:19:34 -07:00
2014-06-05 13:42:58 -07:00
mutex_lock ( & ring_read_lock ) ;
if ( * pos = = 0 )
return SEQ_START_TOKEN ;
if ( * pos > = ( ADF_SIZE_TO_RING_SIZE_IN_BYTES ( ring - > ring_size ) /
ADF_MSG_SIZE_TO_BYTES ( ring - > msg_size ) ) )
return NULL ;
return ring - > base_addr +
( ADF_MSG_SIZE_TO_BYTES ( ring - > msg_size ) * ( * pos ) + + ) ;
}
static void * adf_ring_next ( struct seq_file * sfile , void * v , loff_t * pos )
{
struct adf_etr_ring_data * ring = sfile - > private ;
if ( * pos > = ( ADF_SIZE_TO_RING_SIZE_IN_BYTES ( ring - > ring_size ) /
ADF_MSG_SIZE_TO_BYTES ( ring - > msg_size ) ) )
return NULL ;
return ring - > base_addr +
( ADF_MSG_SIZE_TO_BYTES ( ring - > msg_size ) * ( * pos ) + + ) ;
}
static int adf_ring_show ( struct seq_file * sfile , void * v )
{
struct adf_etr_ring_data * ring = sfile - > private ;
struct adf_etr_bank_data * bank = ring - > bank ;
void __iomem * csr = ring - > bank - > csr_addr ;
if ( v = = SEQ_START_TOKEN ) {
int head , tail , empty ;
head = READ_CSR_RING_HEAD ( csr , bank - > bank_number ,
ring - > ring_number ) ;
tail = READ_CSR_RING_TAIL ( csr , bank - > bank_number ,
ring - > ring_number ) ;
empty = READ_CSR_E_STAT ( csr , bank - > bank_number ) ;
seq_puts ( sfile , " ------- Ring configuration ------- \n " ) ;
2015-04-03 08:40:58 -07:00
seq_printf ( sfile , " ring name: %s \n " ,
ring - > ring_debug - > ring_name ) ;
2014-06-05 13:42:58 -07:00
seq_printf ( sfile , " ring num %d, bank num %d \n " ,
ring - > ring_number , ring - > bank - > bank_number ) ;
seq_printf ( sfile , " head %x, tail %x, empty: %d \n " ,
head , tail , ( empty & 1 < < ring - > ring_number )
> > ring - > ring_number ) ;
seq_printf ( sfile , " ring size %d, msg size %d \n " ,
ADF_SIZE_TO_RING_SIZE_IN_BYTES ( ring - > ring_size ) ,
ADF_MSG_SIZE_TO_BYTES ( ring - > msg_size ) ) ;
seq_puts ( sfile , " ----------- Ring data ------------ \n " ) ;
return 0 ;
}
2015-09-09 15:38:36 -07:00
seq_hex_dump ( sfile , " " , DUMP_PREFIX_ADDRESS , 32 , 4 ,
v , ADF_MSG_SIZE_TO_BYTES ( ring - > msg_size ) , false ) ;
2014-06-05 13:42:58 -07:00
return 0 ;
}
static void adf_ring_stop ( struct seq_file * sfile , void * v )
{
mutex_unlock ( & ring_read_lock ) ;
}
2020-09-16 10:50:17 +08:00
static const struct seq_operations adf_ring_debug_sops = {
2014-06-05 13:42:58 -07:00
. start = adf_ring_start ,
. next = adf_ring_next ,
. stop = adf_ring_stop ,
. show = adf_ring_show
} ;
2020-09-16 10:50:17 +08:00
DEFINE_SEQ_ATTRIBUTE ( adf_ring_debug ) ;
2014-06-05 13:42:58 -07:00
int adf_ring_debugfs_add ( struct adf_etr_ring_data * ring , const char * name )
{
struct adf_etr_ring_debug_entry * ring_debug ;
char entry_name [ 8 ] ;
ring_debug = kzalloc ( sizeof ( * ring_debug ) , GFP_KERNEL ) ;
if ( ! ring_debug )
return - ENOMEM ;
strlcpy ( ring_debug - > ring_name , name , sizeof ( ring_debug - > ring_name ) ) ;
snprintf ( entry_name , sizeof ( entry_name ) , " ring_%02d " ,
ring - > ring_number ) ;
ring_debug - > debug = debugfs_create_file ( entry_name , S_IRUSR ,
ring - > bank - > bank_debug_dir ,
ring , & adf_ring_debug_fops ) ;
ring - > ring_debug = ring_debug ;
return 0 ;
}
void adf_ring_debugfs_rm ( struct adf_etr_ring_data * ring )
{
if ( ring - > ring_debug ) {
debugfs_remove ( ring - > ring_debug - > debug ) ;
kfree ( ring - > ring_debug ) ;
ring - > ring_debug = NULL ;
}
}
static void * adf_bank_start ( struct seq_file * sfile , loff_t * pos )
{
mutex_lock ( & bank_read_lock ) ;
if ( * pos = = 0 )
return SEQ_START_TOKEN ;
if ( * pos > = ADF_ETR_MAX_RINGS_PER_BANK )
return NULL ;
return pos ;
}
static void * adf_bank_next ( struct seq_file * sfile , void * v , loff_t * pos )
{
if ( + + ( * pos ) > = ADF_ETR_MAX_RINGS_PER_BANK )
return NULL ;
return pos ;
}
static int adf_bank_show ( struct seq_file * sfile , void * v )
{
struct adf_etr_bank_data * bank = sfile - > private ;
if ( v = = SEQ_START_TOKEN ) {
seq_printf ( sfile , " ------- Bank %d configuration ------- \n " ,
bank - > bank_number ) ;
} else {
int ring_id = * ( ( int * ) v ) - 1 ;
struct adf_etr_ring_data * ring = & bank - > rings [ ring_id ] ;
void __iomem * csr = bank - > csr_addr ;
int head , tail , empty ;
if ( ! ( bank - > ring_mask & 1 < < ring_id ) )
return 0 ;
head = READ_CSR_RING_HEAD ( csr , bank - > bank_number ,
ring - > ring_number ) ;
tail = READ_CSR_RING_TAIL ( csr , bank - > bank_number ,
ring - > ring_number ) ;
empty = READ_CSR_E_STAT ( csr , bank - > bank_number ) ;
seq_printf ( sfile ,
" ring num %02d, head %04x, tail %04x, empty: %d \n " ,
ring - > ring_number , head , tail ,
( empty & 1 < < ring - > ring_number ) > >
ring - > ring_number ) ;
}
return 0 ;
}
static void adf_bank_stop ( struct seq_file * sfile , void * v )
{
mutex_unlock ( & bank_read_lock ) ;
}
2020-09-16 10:50:17 +08:00
static const struct seq_operations adf_bank_debug_sops = {
2014-06-05 13:42:58 -07:00
. start = adf_bank_start ,
. next = adf_bank_next ,
. stop = adf_bank_stop ,
. show = adf_bank_show
} ;
2020-09-16 10:50:17 +08:00
DEFINE_SEQ_ATTRIBUTE ( adf_bank_debug ) ;
2014-06-05 13:42:58 -07:00
int adf_bank_debugfs_add ( struct adf_etr_bank_data * bank )
{
struct adf_accel_dev * accel_dev = bank - > accel_dev ;
struct dentry * parent = accel_dev - > transport - > debug ;
char name [ 8 ] ;
snprintf ( name , sizeof ( name ) , " bank_%02d " , bank - > bank_number ) ;
bank - > bank_debug_dir = debugfs_create_dir ( name , parent ) ;
bank - > bank_debug_cfg = debugfs_create_file ( " config " , S_IRUSR ,
bank - > bank_debug_dir , bank ,
& adf_bank_debug_fops ) ;
return 0 ;
}
void adf_bank_debugfs_rm ( struct adf_etr_bank_data * bank )
{
debugfs_remove ( bank - > bank_debug_cfg ) ;
debugfs_remove ( bank - > bank_debug_dir ) ;
}