2013-04-05 23:10:34 +04:00
/*
*
* Intel Management Engine Interface ( Intel MEI ) Linux driver
* Copyright ( c ) 2012 - 2013 , Intel Corporation .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
*/
# include <linux/slab.h>
# include <linux/kernel.h>
# include <linux/device.h>
# include <linux/debugfs.h>
# include <linux/mei.h>
# include "mei_dev.h"
2015-01-11 01:07:16 +03:00
# include "client.h"
2013-04-05 23:10:34 +04:00
# include "hw.h"
static ssize_t mei_dbgfs_read_meclients ( struct file * fp , char __user * ubuf ,
size_t cnt , loff_t * ppos )
{
struct mei_device * dev = fp - > private_data ;
2015-02-10 11:39:31 +03:00
struct mei_me_client * me_cl ;
2014-09-29 17:31:34 +04:00
size_t bufsz = 1 ;
char * buf ;
2014-08-21 15:29:13 +04:00
int i = 0 ;
2013-04-05 23:10:34 +04:00
int pos = 0 ;
int ret ;
2015-01-11 01:07:16 +03:00
# define HDR \
" |id|fix| UUID |con|msg len|sb|refc| \n "
2013-04-05 23:10:34 +04:00
2015-02-10 11:39:31 +03:00
down_read ( & dev - > me_clients_rwsem ) ;
2014-09-29 17:31:34 +04:00
list_for_each_entry ( me_cl , & dev - > me_clients , list )
bufsz + + ;
bufsz * = sizeof ( HDR ) + 1 ;
buf = kzalloc ( bufsz , GFP_KERNEL ) ;
if ( ! buf ) {
2015-02-10 11:39:31 +03:00
up_read ( & dev - > me_clients_rwsem ) ;
2014-09-29 17:31:34 +04:00
return - ENOMEM ;
}
pos + = scnprintf ( buf + pos , bufsz - pos , HDR ) ;
2014-01-09 00:31:46 +04:00
/* if the driver is not enabled the list won't be consistent */
2013-04-05 23:10:34 +04:00
if ( dev - > dev_state ! = MEI_DEV_ENABLED )
goto out ;
2015-02-10 11:39:31 +03:00
list_for_each_entry ( me_cl , & dev - > me_clients , list ) {
2013-04-05 23:10:34 +04:00
2015-02-10 11:39:31 +03:00
if ( mei_me_cl_get ( me_cl ) ) {
2015-01-11 01:07:16 +03:00
pos + = scnprintf ( buf + pos , bufsz - pos ,
" %2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d| \n " ,
i + + , me_cl - > client_id ,
me_cl - > props . fixed_address ,
& me_cl - > props . protocol_name ,
me_cl - > props . max_number_of_connections ,
me_cl - > props . max_msg_length ,
me_cl - > props . single_recv_buf ,
atomic_read ( & me_cl - > refcnt . refcount ) ) ;
2015-02-10 11:39:31 +03:00
mei_me_cl_put ( me_cl ) ;
}
2013-04-05 23:10:34 +04:00
}
2015-02-10 11:39:31 +03:00
2013-04-05 23:10:34 +04:00
out :
2015-02-10 11:39:31 +03:00
up_read ( & dev - > me_clients_rwsem ) ;
2013-04-05 23:10:34 +04:00
ret = simple_read_from_buffer ( ubuf , cnt , ppos , buf , pos ) ;
kfree ( buf ) ;
return ret ;
}
static const struct file_operations mei_dbgfs_fops_meclients = {
2013-04-09 10:30:19 +04:00
. open = simple_open ,
2013-04-05 23:10:34 +04:00
. read = mei_dbgfs_read_meclients ,
. llseek = generic_file_llseek ,
} ;
2014-01-15 01:21:41 +04:00
static ssize_t mei_dbgfs_read_active ( struct file * fp , char __user * ubuf ,
size_t cnt , loff_t * ppos )
{
struct mei_device * dev = fp - > private_data ;
struct mei_cl * cl ;
const size_t bufsz = 1024 ;
char * buf ;
int i = 0 ;
int pos = 0 ;
int ret ;
if ( ! dev )
return - ENODEV ;
buf = kzalloc ( bufsz , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
pos + = scnprintf ( buf + pos , bufsz - pos ,
" |me|host|state|rd|wr| \n " ) ;
mutex_lock ( & dev - > device_lock ) ;
2014-09-29 17:31:47 +04:00
/* if the driver is not enabled the list won't be consistent */
2014-01-15 01:21:41 +04:00
if ( dev - > dev_state ! = MEI_DEV_ENABLED )
goto out ;
list_for_each_entry ( cl , & dev - > file_list , link ) {
pos + = scnprintf ( buf + pos , bufsz - pos ,
" %2d|%2d|%4d|%5d|%2d|%2d| \n " ,
i , cl - > me_client_id , cl - > host_client_id , cl - > state ,
cl - > reading_state , cl - > writing_state ) ;
i + + ;
}
out :
mutex_unlock ( & dev - > device_lock ) ;
ret = simple_read_from_buffer ( ubuf , cnt , ppos , buf , pos ) ;
kfree ( buf ) ;
return ret ;
}
static const struct file_operations mei_dbgfs_fops_active = {
. open = simple_open ,
. read = mei_dbgfs_read_active ,
. llseek = generic_file_llseek ,
} ;
2013-04-05 23:10:34 +04:00
static ssize_t mei_dbgfs_read_devstate ( struct file * fp , char __user * ubuf ,
size_t cnt , loff_t * ppos )
{
struct mei_device * dev = fp - > private_data ;
const size_t bufsz = 1024 ;
char * buf = kzalloc ( bufsz , GFP_KERNEL ) ;
int pos = 0 ;
int ret ;
if ( ! buf )
return - ENOMEM ;
2014-09-29 17:31:33 +04:00
pos + = scnprintf ( buf + pos , bufsz - pos , " dev: %s \n " ,
2013-04-05 23:10:34 +04:00
mei_dev_state_str ( dev - > dev_state ) ) ;
2014-09-29 17:31:33 +04:00
pos + = scnprintf ( buf + pos , bufsz - pos , " hbm: %s \n " ,
mei_hbm_state_str ( dev - > hbm_state ) ) ;
pos + = scnprintf ( buf + pos , bufsz - pos , " pg: %s, %s \n " ,
mei_pg_is_enabled ( dev ) ? " ENABLED " : " DISABLED " ,
mei_pg_state_str ( mei_pg_state ( dev ) ) ) ;
2013-04-05 23:10:34 +04:00
ret = simple_read_from_buffer ( ubuf , cnt , ppos , buf , pos ) ;
kfree ( buf ) ;
return ret ;
}
static const struct file_operations mei_dbgfs_fops_devstate = {
2013-04-09 10:30:19 +04:00
. open = simple_open ,
2013-04-05 23:10:34 +04:00
. read = mei_dbgfs_read_devstate ,
. llseek = generic_file_llseek ,
} ;
/**
* mei_dbgfs_deregister - Remove the debugfs files and directories
2014-09-29 17:31:49 +04:00
*
* @ dev : the mei device structure
2013-04-05 23:10:34 +04:00
*/
void mei_dbgfs_deregister ( struct mei_device * dev )
{
if ( ! dev - > dbgfs_dir )
return ;
debugfs_remove_recursive ( dev - > dbgfs_dir ) ;
dev - > dbgfs_dir = NULL ;
}
/**
2014-09-29 17:31:49 +04:00
* mei_dbgfs_register - Add the debugfs files
2013-04-05 23:10:34 +04:00
*
2014-09-29 17:31:49 +04:00
* @ dev : the mei device structure
* @ name : the mei device name
2014-09-29 17:31:50 +04:00
*
* Return : 0 on success , < 0 on failure .
2013-04-05 23:10:34 +04:00
*/
int mei_dbgfs_register ( struct mei_device * dev , const char * name )
{
struct dentry * dir , * f ;
2014-09-29 17:31:37 +04:00
2013-04-05 23:10:34 +04:00
dir = debugfs_create_dir ( name , NULL ) ;
if ( ! dir )
return - ENOMEM ;
f = debugfs_create_file ( " meclients " , S_IRUSR , dir ,
dev , & mei_dbgfs_fops_meclients ) ;
if ( ! f ) {
2014-09-29 17:31:42 +04:00
dev_err ( dev - > dev , " meclients: registration failed \n " ) ;
2013-04-05 23:10:34 +04:00
goto err ;
}
2014-01-15 01:21:41 +04:00
f = debugfs_create_file ( " active " , S_IRUSR , dir ,
dev , & mei_dbgfs_fops_active ) ;
if ( ! f ) {
2014-09-29 17:31:42 +04:00
dev_err ( dev - > dev , " meclients: registration failed \n " ) ;
2014-01-15 01:21:41 +04:00
goto err ;
}
2013-04-05 23:10:34 +04:00
f = debugfs_create_file ( " devstate " , S_IRUSR , dir ,
dev , & mei_dbgfs_fops_devstate ) ;
if ( ! f ) {
2014-09-29 17:31:42 +04:00
dev_err ( dev - > dev , " devstate: registration failed \n " ) ;
2013-04-05 23:10:34 +04:00
goto err ;
}
dev - > dbgfs_dir = dir ;
return 0 ;
err :
mei_dbgfs_deregister ( dev ) ;
return - ENODEV ;
}