2018-05-09 21:06:04 +03:00
// SPDX-License-Identifier: GPL-2.0
2016-02-18 03:51:49 +03:00
/*
* Copyright ( C ) 2015 Linaro Limited . All rights reserved .
* Author : Mathieu Poirier < mathieu . poirier @ linaro . org >
*/
2018-07-11 22:40:11 +03:00
# include <linux/pid_namespace.h>
2016-02-18 03:51:49 +03:00
# include <linux/pm_runtime.h>
# include <linux/sysfs.h>
# include "coresight-etm.h"
2016-08-26 00:19:11 +03:00
# include "coresight-priv.h"
2016-02-18 03:51:49 +03:00
static ssize_t nr_addr_cmp_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
val = drvdata - > nr_addr_cmp ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static DEVICE_ATTR_RO ( nr_addr_cmp ) ;
static ssize_t nr_cntr_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{ unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
val = drvdata - > nr_cntr ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static DEVICE_ATTR_RO ( nr_cntr ) ;
static ssize_t nr_ctxid_cmp_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
val = drvdata - > nr_ctxid_cmp ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static DEVICE_ATTR_RO ( nr_ctxid_cmp ) ;
static ssize_t etmsr_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long flags , val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2019-06-19 20:29:16 +03:00
pm_runtime_get_sync ( dev - > parent ) ;
2016-02-18 03:51:49 +03:00
spin_lock_irqsave ( & drvdata - > spinlock , flags ) ;
CS_UNLOCK ( drvdata - > base ) ;
val = etm_readl ( drvdata , ETMSR ) ;
CS_LOCK ( drvdata - > base ) ;
spin_unlock_irqrestore ( & drvdata - > spinlock , flags ) ;
2019-06-19 20:29:16 +03:00
pm_runtime_put ( dev - > parent ) ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static DEVICE_ATTR_RO ( etmsr ) ;
static ssize_t reset_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int i , ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
if ( val ) {
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
memset ( config , 0 , sizeof ( struct etm_config ) ) ;
config - > mode = ETM_MODE_EXCLUDE ;
config - > trigger_event = ETM_DEFAULT_EVENT_VAL ;
2016-02-18 03:51:49 +03:00
for ( i = 0 ; i < drvdata - > nr_addr_cmp ; i + + ) {
2016-02-18 03:51:51 +03:00
config - > addr_type [ i ] = ETM_ADDR_TYPE_NONE ;
2016-02-18 03:51:49 +03:00
}
2016-02-18 03:51:51 +03:00
etm_set_default ( config ) ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
}
return size ;
}
static DEVICE_ATTR_WO ( reset ) ;
static ssize_t mode_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > mode ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t mode_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > mode = val & ETM_MODE_ALL ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
if ( config - > mode & ETM_MODE_EXCLUDE )
config - > enable_ctrl1 | = ETMTECR1_INC_EXC ;
2016-02-18 03:51:49 +03:00
else
2016-02-18 03:51:51 +03:00
config - > enable_ctrl1 & = ~ ETMTECR1_INC_EXC ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
if ( config - > mode & ETM_MODE_CYCACC )
config - > ctrl | = ETMCR_CYC_ACC ;
2016-02-18 03:51:49 +03:00
else
2016-02-18 03:51:51 +03:00
config - > ctrl & = ~ ETMCR_CYC_ACC ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
if ( config - > mode & ETM_MODE_STALL ) {
2016-02-18 03:51:49 +03:00
if ( ! ( drvdata - > etmccr & ETMCCR_FIFOFULL ) ) {
2019-06-19 20:29:16 +03:00
dev_warn ( dev , " stall mode not supported \n " ) ;
2016-02-18 03:51:49 +03:00
ret = - EINVAL ;
goto err_unlock ;
}
2016-02-18 03:51:51 +03:00
config - > ctrl | = ETMCR_STALL_MODE ;
2016-11-29 19:47:12 +03:00
} else
2016-02-18 03:51:51 +03:00
config - > ctrl & = ~ ETMCR_STALL_MODE ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
if ( config - > mode & ETM_MODE_TIMESTAMP ) {
2016-02-18 03:51:49 +03:00
if ( ! ( drvdata - > etmccer & ETMCCER_TIMESTAMP ) ) {
2019-06-19 20:29:16 +03:00
dev_warn ( dev , " timestamp not supported \n " ) ;
2016-02-18 03:51:49 +03:00
ret = - EINVAL ;
goto err_unlock ;
}
2016-02-18 03:51:51 +03:00
config - > ctrl | = ETMCR_TIMESTAMP_EN ;
2016-02-18 03:51:49 +03:00
} else
2016-02-18 03:51:51 +03:00
config - > ctrl & = ~ ETMCR_TIMESTAMP_EN ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
if ( config - > mode & ETM_MODE_CTXID )
config - > ctrl | = ETMCR_CTXID_SIZE ;
2016-02-18 03:51:49 +03:00
else
2016-02-18 03:51:51 +03:00
config - > ctrl & = ~ ETMCR_CTXID_SIZE ;
2016-02-18 03:51:56 +03:00
2016-11-29 19:47:13 +03:00
if ( config - > mode & ETM_MODE_BBROAD )
config - > ctrl | = ETMCR_BRANCH_BROADCAST ;
else
config - > ctrl & = ~ ETMCR_BRANCH_BROADCAST ;
if ( config - > mode & ETM_MODE_RET_STACK )
config - > ctrl | = ETMCR_RETURN_STACK ;
else
config - > ctrl & = ~ ETMCR_RETURN_STACK ;
2016-02-18 03:51:56 +03:00
if ( config - > mode & ( ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER ) )
etm_config_trace_mode ( config ) ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
err_unlock :
spin_unlock ( & drvdata - > spinlock ) ;
return ret ;
}
static DEVICE_ATTR_RW ( mode ) ;
static ssize_t trigger_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > trigger_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t trigger_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > trigger_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( trigger_event ) ;
static ssize_t enable_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > enable_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t enable_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > enable_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( enable_event ) ;
static ssize_t fifofull_level_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > fifofull_level ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t fifofull_level_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > fifofull_level = val ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( fifofull_level ) ;
static ssize_t addr_idx_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > addr_idx ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t addr_idx_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
if ( val > = drvdata - > nr_addr_cmp )
return - EINVAL ;
/*
* Use spinlock to ensure index doesn ' t change while it gets
* dereferenced multiple times within a spinlock block elsewhere .
*/
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > addr_idx = val ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( addr_idx ) ;
static ssize_t addr_single_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
u8 idx ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
if ( ! ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE | |
config - > addr_type [ idx ] = = ETM_ADDR_TYPE_SINGLE ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EINVAL ;
}
2016-02-18 03:51:51 +03:00
val = config - > addr_val [ idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t addr_single_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
u8 idx ;
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
if ( ! ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE | |
config - > addr_type [ idx ] = = ETM_ADDR_TYPE_SINGLE ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EINVAL ;
}
2016-02-18 03:51:51 +03:00
config - > addr_val [ idx ] = val ;
config - > addr_type [ idx ] = ETM_ADDR_TYPE_SINGLE ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( addr_single ) ;
static ssize_t addr_range_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
u8 idx ;
unsigned long val1 , val2 ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
2016-02-18 03:51:49 +03:00
if ( idx % 2 ! = 0 ) {
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
if ( ! ( ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE & &
config - > addr_type [ idx + 1 ] = = ETM_ADDR_TYPE_NONE ) | |
( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_RANGE & &
config - > addr_type [ idx + 1 ] = = ETM_ADDR_TYPE_RANGE ) ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
val1 = config - > addr_val [ idx ] ;
val2 = config - > addr_val [ idx + 1 ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx %#lx \n " , val1 , val2 ) ;
}
static ssize_t addr_range_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
u8 idx ;
unsigned long val1 , val2 ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
if ( sscanf ( buf , " %lx %lx " , & val1 , & val2 ) ! = 2 )
return - EINVAL ;
/* Lower address comparator cannot have a higher address value */
if ( val1 > val2 )
return - EINVAL ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
2016-02-18 03:51:49 +03:00
if ( idx % 2 ! = 0 ) {
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
if ( ! ( ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE & &
config - > addr_type [ idx + 1 ] = = ETM_ADDR_TYPE_NONE ) | |
( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_RANGE & &
config - > addr_type [ idx + 1 ] = = ETM_ADDR_TYPE_RANGE ) ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
config - > addr_val [ idx ] = val1 ;
config - > addr_type [ idx ] = ETM_ADDR_TYPE_RANGE ;
config - > addr_val [ idx + 1 ] = val2 ;
config - > addr_type [ idx + 1 ] = ETM_ADDR_TYPE_RANGE ;
config - > enable_ctrl1 | = ( 1 < < ( idx / 2 ) ) ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( addr_range ) ;
static ssize_t addr_start_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
u8 idx ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
if ( ! ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE | |
config - > addr_type [ idx ] = = ETM_ADDR_TYPE_START ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
val = config - > addr_val [ idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t addr_start_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
u8 idx ;
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
if ( ! ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE | |
config - > addr_type [ idx ] = = ETM_ADDR_TYPE_START ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
config - > addr_val [ idx ] = val ;
config - > addr_type [ idx ] = ETM_ADDR_TYPE_START ;
config - > startstop_ctrl | = ( 1 < < idx ) ;
config - > enable_ctrl1 | = BIT ( 25 ) ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( addr_start ) ;
static ssize_t addr_stop_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
u8 idx ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
if ( ! ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE | |
config - > addr_type [ idx ] = = ETM_ADDR_TYPE_STOP ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
val = config - > addr_val [ idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t addr_stop_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
u8 idx ;
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
idx = config - > addr_idx ;
if ( ! ( config - > addr_type [ idx ] = = ETM_ADDR_TYPE_NONE | |
config - > addr_type [ idx ] = = ETM_ADDR_TYPE_STOP ) ) {
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return - EPERM ;
}
2016-02-18 03:51:51 +03:00
config - > addr_val [ idx ] = val ;
config - > addr_type [ idx ] = ETM_ADDR_TYPE_STOP ;
config - > startstop_ctrl | = ( 1 < < ( idx + 16 ) ) ;
config - > enable_ctrl1 | = ETMTECR1_START_STOP ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( addr_stop ) ;
static ssize_t addr_acctype_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
val = config - > addr_acctype [ config - > addr_idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t addr_acctype_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > addr_acctype [ config - > addr_idx ] = val ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( addr_acctype ) ;
static ssize_t cntr_idx_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > cntr_idx ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t cntr_idx_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
if ( val > = drvdata - > nr_cntr )
return - EINVAL ;
/*
* Use spinlock to ensure index doesn ' t change while it gets
* dereferenced multiple times within a spinlock block elsewhere .
*/
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > cntr_idx = val ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( cntr_idx ) ;
static ssize_t cntr_rld_val_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
val = config - > cntr_rld_val [ config - > cntr_idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t cntr_rld_val_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > cntr_rld_val [ config - > cntr_idx ] = val ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( cntr_rld_val ) ;
static ssize_t cntr_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
val = config - > cntr_event [ config - > cntr_idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t cntr_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > cntr_event [ config - > cntr_idx ] = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( cntr_event ) ;
static ssize_t cntr_rld_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
val = config - > cntr_rld_event [ config - > cntr_idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t cntr_rld_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > cntr_rld_event [ config - > cntr_idx ] = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( cntr_rld_event ) ;
static ssize_t cntr_val_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
int i , ret = 0 ;
u32 val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:52 +03:00
if ( ! local_read ( & drvdata - > mode ) ) {
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
for ( i = 0 ; i < drvdata - > nr_cntr ; i + + )
ret + = sprintf ( buf , " counter %d: %x \n " ,
2016-02-18 03:51:51 +03:00
i , config - > cntr_val [ i ] ) ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return ret ;
}
for ( i = 0 ; i < drvdata - > nr_cntr ; i + + ) {
val = etm_readl ( drvdata , ETMCNTVRn ( i ) ) ;
ret + = sprintf ( buf , " counter %d: %x \n " , i , val ) ;
}
return ret ;
}
static ssize_t cntr_val_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > cntr_val [ config - > cntr_idx ] = val ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( cntr_val ) ;
static ssize_t seq_12_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > seq_12_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_12_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > seq_12_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_12_event ) ;
static ssize_t seq_21_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > seq_21_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_21_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > seq_21_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_21_event ) ;
static ssize_t seq_23_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > seq_23_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_23_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > seq_23_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_23_event ) ;
static ssize_t seq_31_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > seq_31_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_31_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > seq_31_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_31_event ) ;
static ssize_t seq_32_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > seq_32_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_32_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > seq_32_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_32_event ) ;
static ssize_t seq_13_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > seq_13_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_13_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > seq_13_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_13_event ) ;
static ssize_t seq_curr_state_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val , flags ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:52 +03:00
if ( ! local_read ( & drvdata - > mode ) ) {
2016-02-18 03:51:51 +03:00
val = config - > seq_curr_state ;
2016-02-18 03:51:49 +03:00
goto out ;
}
2019-06-19 20:29:16 +03:00
pm_runtime_get_sync ( dev - > parent ) ;
2016-02-18 03:51:49 +03:00
spin_lock_irqsave ( & drvdata - > spinlock , flags ) ;
CS_UNLOCK ( drvdata - > base ) ;
val = ( etm_readl ( drvdata , ETMSQR ) & ETM_SQR_MASK ) ;
CS_LOCK ( drvdata - > base ) ;
spin_unlock_irqrestore ( & drvdata - > spinlock , flags ) ;
2019-06-19 20:29:16 +03:00
pm_runtime_put ( dev - > parent ) ;
2016-02-18 03:51:49 +03:00
out :
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t seq_curr_state_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
if ( val > ETM_SEQ_STATE_MAX_VAL )
return - EINVAL ;
2016-02-18 03:51:51 +03:00
config - > seq_curr_state = val ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( seq_curr_state ) ;
static ssize_t ctxid_idx_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > ctxid_idx ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t ctxid_idx_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
if ( val > = drvdata - > nr_ctxid_cmp )
return - EINVAL ;
/*
* Use spinlock to ensure index doesn ' t change while it gets
* dereferenced multiple times within a spinlock block elsewhere .
*/
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > ctxid_idx = val ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( ctxid_idx ) ;
static ssize_t ctxid_pid_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2018-07-11 22:40:11 +03:00
/*
* Don ' t use contextID tracing if coming from a PID namespace . See
* comment in ctxid_pid_store ( ) .
*/
if ( task_active_pid_ns ( current ) ! = & init_pid_ns )
return - EINVAL ;
2016-02-18 03:51:49 +03:00
spin_lock ( & drvdata - > spinlock ) ;
2018-07-11 22:40:11 +03:00
val = config - > ctxid_pid [ config - > ctxid_idx ] ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t ctxid_pid_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
2018-07-11 22:40:11 +03:00
unsigned long pid ;
2016-02-18 03:51:49 +03:00
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2018-07-11 22:40:11 +03:00
/*
* When contextID tracing is enabled the tracers will insert the
* value found in the contextID register in the trace stream . But if
* a process is in a namespace the PID of that process as seen from the
* namespace won ' t be what the kernel sees , something that makes the
* feature confusing and can potentially leak kernel only information .
* As such refuse to use the feature if @ current is not in the initial
* PID namespace .
*/
if ( task_active_pid_ns ( current ) ! = & init_pid_ns )
return - EINVAL ;
ret = kstrtoul ( buf , 16 , & pid ) ;
2016-02-18 03:51:49 +03:00
if ( ret )
return ret ;
spin_lock ( & drvdata - > spinlock ) ;
2016-02-18 03:51:51 +03:00
config - > ctxid_pid [ config - > ctxid_idx ] = pid ;
2016-02-18 03:51:49 +03:00
spin_unlock ( & drvdata - > spinlock ) ;
return size ;
}
static DEVICE_ATTR_RW ( ctxid_pid ) ;
static ssize_t ctxid_mask_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2018-07-11 22:40:11 +03:00
/*
* Don ' t use contextID tracing if coming from a PID namespace . See
* comment in ctxid_pid_store ( ) .
*/
if ( task_active_pid_ns ( current ) ! = & init_pid_ns )
return - EINVAL ;
2016-02-18 03:51:51 +03:00
val = config - > ctxid_mask ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t ctxid_mask_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2018-07-11 22:40:11 +03:00
/*
* Don ' t use contextID tracing if coming from a PID namespace . See
* comment in ctxid_pid_store ( ) .
*/
if ( task_active_pid_ns ( current ) ! = & init_pid_ns )
return - EINVAL ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > ctxid_mask = val ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( ctxid_mask ) ;
static ssize_t sync_freq_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > sync_freq ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t sync_freq_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > sync_freq = val & ETM_SYNC_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( sync_freq ) ;
static ssize_t timestamp_event_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
2016-02-18 03:51:51 +03:00
val = config - > timestamp_event ;
2016-02-18 03:51:49 +03:00
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t timestamp_event_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
2016-02-18 03:51:51 +03:00
struct etm_config * config = & drvdata - > config ;
2016-02-18 03:51:49 +03:00
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
2016-02-18 03:51:51 +03:00
config - > timestamp_event = val & ETM_EVENT_MASK ;
2016-02-18 03:51:49 +03:00
return size ;
}
static DEVICE_ATTR_RW ( timestamp_event ) ;
static ssize_t cpu_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
int val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
val = drvdata - > cpu ;
return scnprintf ( buf , PAGE_SIZE , " %d \n " , val ) ;
}
static DEVICE_ATTR_RO ( cpu ) ;
static ssize_t traceid_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
val = etm_get_trace_id ( drvdata ) ;
return sprintf ( buf , " %#lx \n " , val ) ;
}
static ssize_t traceid_store ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t size )
{
int ret ;
unsigned long val ;
struct etm_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
ret = kstrtoul ( buf , 16 , & val ) ;
if ( ret )
return ret ;
drvdata - > traceid = val & ETM_TRACEID_MASK ;
return size ;
}
static DEVICE_ATTR_RW ( traceid ) ;
static struct attribute * coresight_etm_attrs [ ] = {
& dev_attr_nr_addr_cmp . attr ,
& dev_attr_nr_cntr . attr ,
& dev_attr_nr_ctxid_cmp . attr ,
& dev_attr_etmsr . attr ,
& dev_attr_reset . attr ,
& dev_attr_mode . attr ,
& dev_attr_trigger_event . attr ,
& dev_attr_enable_event . attr ,
& dev_attr_fifofull_level . attr ,
& dev_attr_addr_idx . attr ,
& dev_attr_addr_single . attr ,
& dev_attr_addr_range . attr ,
& dev_attr_addr_start . attr ,
& dev_attr_addr_stop . attr ,
& dev_attr_addr_acctype . attr ,
& dev_attr_cntr_idx . attr ,
& dev_attr_cntr_rld_val . attr ,
& dev_attr_cntr_event . attr ,
& dev_attr_cntr_rld_event . attr ,
& dev_attr_cntr_val . attr ,
& dev_attr_seq_12_event . attr ,
& dev_attr_seq_21_event . attr ,
& dev_attr_seq_23_event . attr ,
& dev_attr_seq_31_event . attr ,
& dev_attr_seq_32_event . attr ,
& dev_attr_seq_13_event . attr ,
& dev_attr_seq_curr_state . attr ,
& dev_attr_ctxid_idx . attr ,
& dev_attr_ctxid_pid . attr ,
& dev_attr_ctxid_mask . attr ,
& dev_attr_sync_freq . attr ,
& dev_attr_timestamp_event . attr ,
& dev_attr_traceid . attr ,
& dev_attr_cpu . attr ,
NULL ,
} ;
2017-08-02 19:22:06 +03:00
# define coresight_etm3x_reg(name, offset) \
coresight_simple_reg32 ( struct etm_drvdata , name , offset )
coresight_etm3x_reg ( etmccr , ETMCCR ) ;
coresight_etm3x_reg ( etmccer , ETMCCER ) ;
coresight_etm3x_reg ( etmscr , ETMSCR ) ;
coresight_etm3x_reg ( etmidr , ETMIDR ) ;
coresight_etm3x_reg ( etmcr , ETMCR ) ;
coresight_etm3x_reg ( etmtraceidr , ETMTRACEIDR ) ;
coresight_etm3x_reg ( etmteevr , ETMTEEVR ) ;
coresight_etm3x_reg ( etmtssvr , ETMTSSCR ) ;
coresight_etm3x_reg ( etmtecr1 , ETMTECR1 ) ;
coresight_etm3x_reg ( etmtecr2 , ETMTECR2 ) ;
2016-02-18 03:51:49 +03:00
static struct attribute * coresight_etm_mgmt_attrs [ ] = {
& dev_attr_etmccr . attr ,
& dev_attr_etmccer . attr ,
& dev_attr_etmscr . attr ,
& dev_attr_etmidr . attr ,
& dev_attr_etmcr . attr ,
& dev_attr_etmtraceidr . attr ,
& dev_attr_etmteevr . attr ,
& dev_attr_etmtssvr . attr ,
& dev_attr_etmtecr1 . attr ,
& dev_attr_etmtecr2 . attr ,
NULL ,
} ;
static const struct attribute_group coresight_etm_group = {
. attrs = coresight_etm_attrs ,
} ;
static const struct attribute_group coresight_etm_mgmt_group = {
. attrs = coresight_etm_mgmt_attrs ,
. name = " mgmt " ,
} ;
const struct attribute_group * coresight_etm_groups [ ] = {
& coresight_etm_group ,
& coresight_etm_mgmt_group ,
NULL ,
} ;