2019-05-23 12:14:51 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-07-08 13:08:38 +04:00
/*
* IBM PowerNV platform sensors for temperature / fan / voltage / power
* Copyright ( C ) 2014 IBM
*/
# define DRVNAME "ibmpowernv"
# define pr_fmt(fmt) DRVNAME ": " fmt
# include <linux/init.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/hwmon.h>
# include <linux/hwmon-sysfs.h>
# include <linux/of.h>
# include <linux/slab.h>
# include <linux/platform_device.h>
# include <asm/opal.h>
# include <linux/err.h>
2015-04-08 20:19:50 +03:00
# include <asm/cputhreads.h>
2015-04-09 07:02:47 +03:00
# include <asm/smp.h>
2014-07-08 13:08:38 +04:00
# define MAX_ATTR_LEN 32
2015-04-08 20:19:49 +03:00
# define MAX_LABEL_LEN 64
2014-07-08 13:08:38 +04:00
/* Sensor suffix name from DT */
# define DT_FAULT_ATTR_SUFFIX "faulted"
# define DT_DATA_ATTR_SUFFIX "data"
# define DT_THRESHOLD_ATTR_SUFFIX "thrs"
/*
* Enumerates all the types of sensors in the POWERNV platform and does index
* into ' struct sensor_group '
*/
enum sensors {
FAN ,
2015-03-19 20:44:41 +03:00
TEMP ,
2014-07-08 13:08:38 +04:00
POWER_SUPPLY ,
POWER_INPUT ,
2017-06-20 08:08:13 +03:00
CURRENT ,
2018-05-07 13:25:38 +03:00
ENERGY ,
2014-07-08 13:08:38 +04:00
MAX_SENSOR_TYPE ,
} ;
2015-04-08 20:19:48 +03:00
# define INVALID_INDEX (-1U)
2017-06-20 08:08:12 +03:00
/*
* ' compatible ' string properties for sensor types as defined in old
* PowerNV firmware ( skiboot ) . These are ordered as ' enum sensors ' .
*/
static const char * const legacy_compatibles [ ] = {
" ibm,opal-sensor-cooling-fan " ,
" ibm,opal-sensor-amb-temp " ,
" ibm,opal-sensor-power-supply " ,
" ibm,opal-sensor-power "
} ;
2014-07-08 13:08:38 +04:00
static struct sensor_group {
2017-06-20 08:08:12 +03:00
const char * name ; /* matches property 'sensor-type' */
2014-07-08 13:08:38 +04:00
struct attribute_group group ;
u32 attr_count ;
2015-03-19 20:44:45 +03:00
u32 hwmon_index ;
2014-07-08 13:08:38 +04:00
} sensor_groups [ ] = {
2017-06-20 08:08:12 +03:00
{ " fan " } ,
{ " temp " } ,
{ " in " } ,
2017-06-20 08:08:13 +03:00
{ " power " } ,
{ " curr " } ,
2018-05-07 13:25:38 +03:00
{ " energy " } ,
2014-07-08 13:08:38 +04:00
} ;
struct sensor_data {
u32 id ; /* An opaque id of the firmware for each sensor */
2015-03-19 20:44:45 +03:00
u32 hwmon_index ;
u32 opal_index ;
2014-07-08 13:08:38 +04:00
enum sensors type ;
2015-04-08 20:19:49 +03:00
char label [ MAX_LABEL_LEN ] ;
2014-07-08 13:08:38 +04:00
char name [ MAX_ATTR_LEN ] ;
struct device_attribute dev_attr ;
2018-07-24 12:13:09 +03:00
struct sensor_group_data * sgrp_data ;
} ;
struct sensor_group_data {
struct mutex mutex ;
u32 gid ;
bool enable ;
2014-07-08 13:08:38 +04:00
} ;
struct platform_data {
const struct attribute_group * attr_groups [ MAX_SENSOR_TYPE + 1 ] ;
2018-07-24 12:13:09 +03:00
struct sensor_group_data * sgrp_data ;
2014-07-08 13:08:38 +04:00
u32 sensors_count ; /* Total count of sensors from each group */
2018-07-24 12:13:09 +03:00
u32 nr_sensor_groups ; /* Total number of sensor groups */
2014-07-08 13:08:38 +04:00
} ;
static ssize_t show_sensor ( struct device * dev , struct device_attribute * devattr ,
char * buf )
{
struct sensor_data * sdata = container_of ( devattr , struct sensor_data ,
dev_attr ) ;
ssize_t ret ;
2018-05-07 13:25:37 +03:00
u64 x ;
2018-07-24 12:13:09 +03:00
if ( sdata - > sgrp_data & & ! sdata - > sgrp_data - > enable )
return - ENODATA ;
2018-05-07 13:25:37 +03:00
ret = opal_get_sensor_data_u64 ( sdata - > id , & x ) ;
2014-07-08 13:08:38 +04:00
if ( ret )
return ret ;
/* Convert temperature to milli-degrees */
2015-03-19 20:44:41 +03:00
if ( sdata - > type = = TEMP )
2014-07-08 13:08:38 +04:00
x * = 1000 ;
/* Convert power to micro-watts */
else if ( sdata - > type = = POWER_INPUT )
x * = 1000000 ;
2018-05-07 13:25:37 +03:00
return sprintf ( buf , " %llu \n " , x ) ;
2014-07-08 13:08:38 +04:00
}
2018-07-24 12:13:09 +03:00
static ssize_t show_enable ( struct device * dev ,
struct device_attribute * devattr , char * buf )
{
struct sensor_data * sdata = container_of ( devattr , struct sensor_data ,
dev_attr ) ;
return sprintf ( buf , " %u \n " , sdata - > sgrp_data - > enable ) ;
}
static ssize_t store_enable ( struct device * dev ,
struct device_attribute * devattr ,
const char * buf , size_t count )
{
struct sensor_data * sdata = container_of ( devattr , struct sensor_data ,
dev_attr ) ;
struct sensor_group_data * sgrp_data = sdata - > sgrp_data ;
int ret ;
bool data ;
ret = kstrtobool ( buf , & data ) ;
if ( ret )
return ret ;
ret = mutex_lock_interruptible ( & sgrp_data - > mutex ) ;
if ( ret )
return ret ;
if ( data ! = sgrp_data - > enable ) {
ret = sensor_group_enable ( sgrp_data - > gid , data ) ;
if ( ! ret )
sgrp_data - > enable = data ;
}
if ( ! ret )
ret = count ;
mutex_unlock ( & sgrp_data - > mutex ) ;
return ret ;
}
2015-04-08 20:19:49 +03:00
static ssize_t show_label ( struct device * dev , struct device_attribute * devattr ,
char * buf )
{
struct sensor_data * sdata = container_of ( devattr , struct sensor_data ,
dev_attr ) ;
return sprintf ( buf , " %s \n " , sdata - > label ) ;
}
2018-10-28 20:16:51 +03:00
static int get_logical_cpu ( int hwcpu )
2015-04-08 20:19:50 +03:00
{
int cpu ;
for_each_possible_cpu ( cpu )
if ( get_hard_smp_processor_id ( cpu ) = = hwcpu )
return cpu ;
return - ENOENT ;
}
2018-10-28 20:16:51 +03:00
static void make_sensor_label ( struct device_node * np ,
struct sensor_data * sdata , const char * label )
2015-04-08 20:19:49 +03:00
{
2015-04-08 20:19:50 +03:00
u32 id ;
2015-04-08 20:19:49 +03:00
size_t n ;
2020-03-11 10:39:44 +03:00
n = scnprintf ( sdata - > label , sizeof ( sdata - > label ) , " %s " , label ) ;
2015-04-08 20:19:50 +03:00
/*
* Core temp pretty print
*/
if ( ! of_property_read_u32 ( np , " ibm,pir " , & id ) ) {
int cpuid = get_logical_cpu ( id ) ;
if ( cpuid > = 0 )
/*
* The digital thermal sensors are associated
2016-09-13 08:47:41 +03:00
* with a core .
2015-04-08 20:19:50 +03:00
*/
2020-03-11 10:39:44 +03:00
n + = scnprintf ( sdata - > label + n ,
2016-09-13 08:47:41 +03:00
sizeof ( sdata - > label ) - n , " %d " ,
cpuid ) ;
2015-04-08 20:19:50 +03:00
else
2020-03-11 10:39:44 +03:00
n + = scnprintf ( sdata - > label + n ,
2015-04-08 20:19:50 +03:00
sizeof ( sdata - > label ) - n , " phy%d " , id ) ;
}
/*
* Membuffer pretty print
*/
if ( ! of_property_read_u32 ( np , " ibm,chip-id " , & id ) )
2020-03-11 10:39:44 +03:00
n + = scnprintf ( sdata - > label + n , sizeof ( sdata - > label ) - n ,
2015-04-08 20:19:50 +03:00
" %d " , id & 0xffff ) ;
2015-04-08 20:19:49 +03:00
}
static int get_sensor_index_attr ( const char * name , u32 * index , char * attr )
2014-07-08 13:08:38 +04:00
{
char * hash_pos = strchr ( name , ' # ' ) ;
char buf [ 8 ] = { 0 } ;
char * dash_pos ;
u32 copy_len ;
int err ;
if ( ! hash_pos )
return - EINVAL ;
dash_pos = strchr ( hash_pos , ' - ' ) ;
if ( ! dash_pos )
return - EINVAL ;
copy_len = dash_pos - hash_pos - 1 ;
if ( copy_len > = sizeof ( buf ) )
return - EINVAL ;
strncpy ( buf , hash_pos + 1 , copy_len ) ;
err = kstrtou32 ( buf , 10 , index ) ;
if ( err )
return err ;
2020-11-12 12:57:15 +03:00
strscpy ( attr , dash_pos + 1 , MAX_ATTR_LEN ) ;
2014-07-08 13:08:38 +04:00
return 0 ;
}
2015-03-19 20:44:43 +03:00
static const char * convert_opal_attr_name ( enum sensors type ,
const char * opal_attr )
{
const char * attr_name = NULL ;
if ( ! strcmp ( opal_attr , DT_FAULT_ATTR_SUFFIX ) ) {
attr_name = " fault " ;
} else if ( ! strcmp ( opal_attr , DT_DATA_ATTR_SUFFIX ) ) {
attr_name = " input " ;
} else if ( ! strcmp ( opal_attr , DT_THRESHOLD_ATTR_SUFFIX ) ) {
if ( type = = TEMP )
attr_name = " max " ;
else if ( type = = FAN )
attr_name = " min " ;
}
return attr_name ;
}
2014-07-08 13:08:38 +04:00
/*
* This function translates the DT node name into the ' hwmon ' attribute name .
* IBMPOWERNV device node appear like cooling - fan # 2 - data , amb - temp # 1 - thrs etc .
* which need to be mapped as fan2_input , temp1_max respectively before
* populating them inside hwmon device class .
*/
2015-03-19 20:44:44 +03:00
static const char * parse_opal_node_name ( const char * node_name ,
enum sensors type , u32 * index )
2014-07-08 13:08:38 +04:00
{
char attr_suffix [ MAX_ATTR_LEN ] ;
2015-03-19 20:44:43 +03:00
const char * attr_name ;
2014-07-08 13:08:38 +04:00
int err ;
2015-03-19 20:44:44 +03:00
err = get_sensor_index_attr ( node_name , index , attr_suffix ) ;
if ( err )
return ERR_PTR ( err ) ;
2014-07-08 13:08:38 +04:00
2015-03-19 20:44:43 +03:00
attr_name = convert_opal_attr_name ( type , attr_suffix ) ;
if ( ! attr_name )
2015-03-19 20:44:44 +03:00
return ERR_PTR ( - ENOENT ) ;
2014-07-08 13:08:38 +04:00
2015-03-19 20:44:44 +03:00
return attr_name ;
2014-07-08 13:08:38 +04:00
}
2015-03-19 20:44:42 +03:00
static int get_sensor_type ( struct device_node * np )
{
enum sensors type ;
2015-04-08 20:19:48 +03:00
const char * str ;
2015-03-19 20:44:42 +03:00
2017-06-20 08:08:12 +03:00
for ( type = 0 ; type < ARRAY_SIZE ( legacy_compatibles ) ; type + + ) {
if ( of_device_is_compatible ( np , legacy_compatibles [ type ] ) )
2015-03-19 20:44:42 +03:00
return type ;
}
2015-04-08 20:19:48 +03:00
/*
* Let ' s check if we have a newer device tree
*/
if ( ! of_device_is_compatible ( np , " ibm,opal-sensor " ) )
return MAX_SENSOR_TYPE ;
if ( of_property_read_string ( np , " sensor-type " , & str ) )
return MAX_SENSOR_TYPE ;
for ( type = 0 ; type < MAX_SENSOR_TYPE ; type + + )
if ( ! strcmp ( str , sensor_groups [ type ] . name ) )
return type ;
2015-03-19 20:44:42 +03:00
return MAX_SENSOR_TYPE ;
}
2015-03-19 20:44:45 +03:00
static u32 get_sensor_hwmon_index ( struct sensor_data * sdata ,
struct sensor_data * sdata_table , int count )
{
int i ;
2015-04-08 20:19:48 +03:00
/*
* We don ' t use the OPAL index on newer device trees
*/
if ( sdata - > opal_index ! = INVALID_INDEX ) {
for ( i = 0 ; i < count ; i + + )
if ( sdata_table [ i ] . opal_index = = sdata - > opal_index & &
sdata_table [ i ] . type = = sdata - > type )
return sdata_table [ i ] . hwmon_index ;
}
2015-03-19 20:44:45 +03:00
return + + sensor_groups [ sdata - > type ] . hwmon_index ;
}
2018-07-24 12:13:09 +03:00
static int init_sensor_group_data ( struct platform_device * pdev ,
struct platform_data * pdata )
{
struct sensor_group_data * sgrp_data ;
struct device_node * groups , * sgrp ;
int count = 0 , ret = 0 ;
enum sensors type ;
groups = of_find_compatible_node ( NULL , NULL , " ibm,opal-sensor-group " ) ;
if ( ! groups )
return ret ;
for_each_child_of_node ( groups , sgrp ) {
type = get_sensor_type ( sgrp ) ;
if ( type ! = MAX_SENSOR_TYPE )
pdata - > nr_sensor_groups + + ;
}
if ( ! pdata - > nr_sensor_groups )
goto out ;
sgrp_data = devm_kcalloc ( & pdev - > dev , pdata - > nr_sensor_groups ,
sizeof ( * sgrp_data ) , GFP_KERNEL ) ;
if ( ! sgrp_data ) {
ret = - ENOMEM ;
goto out ;
}
for_each_child_of_node ( groups , sgrp ) {
u32 gid ;
type = get_sensor_type ( sgrp ) ;
if ( type = = MAX_SENSOR_TYPE )
continue ;
if ( of_property_read_u32 ( sgrp , " sensor-group-id " , & gid ) )
continue ;
if ( of_count_phandle_with_args ( sgrp , " sensors " , NULL ) < = 0 )
continue ;
sensor_groups [ type ] . attr_count + + ;
sgrp_data [ count ] . gid = gid ;
mutex_init ( & sgrp_data [ count ] . mutex ) ;
sgrp_data [ count + + ] . enable = false ;
}
pdata - > sgrp_data = sgrp_data ;
out :
of_node_put ( groups ) ;
return ret ;
}
static struct sensor_group_data * get_sensor_group ( struct platform_data * pdata ,
struct device_node * node ,
enum sensors gtype )
{
struct sensor_group_data * sgrp_data = pdata - > sgrp_data ;
struct device_node * groups , * sgrp ;
groups = of_find_compatible_node ( NULL , NULL , " ibm,opal-sensor-group " ) ;
if ( ! groups )
return NULL ;
for_each_child_of_node ( groups , sgrp ) {
struct of_phandle_iterator it ;
u32 gid ;
int rc , i ;
enum sensors type ;
type = get_sensor_type ( sgrp ) ;
if ( type ! = gtype )
continue ;
if ( of_property_read_u32 ( sgrp , " sensor-group-id " , & gid ) )
continue ;
of_for_each_phandle ( & it , rc , sgrp , " sensors " , NULL , 0 )
if ( it . phandle = = node - > phandle ) {
of_node_put ( it . node ) ;
break ;
}
if ( rc )
continue ;
for ( i = 0 ; i < pdata - > nr_sensor_groups ; i + + )
if ( gid = = sgrp_data [ i ] . gid ) {
of_node_put ( sgrp ) ;
of_node_put ( groups ) ;
return & sgrp_data [ i ] ;
}
}
of_node_put ( groups ) ;
return NULL ;
}
2014-11-05 14:15:14 +03:00
static int populate_attr_groups ( struct platform_device * pdev )
2014-07-08 13:08:38 +04:00
{
struct platform_data * pdata = platform_get_drvdata ( pdev ) ;
const struct attribute_group * * pgroups = pdata - > attr_groups ;
struct device_node * opal , * np ;
enum sensors type ;
2018-07-24 12:13:09 +03:00
int ret ;
ret = init_sensor_group_data ( pdev , pdata ) ;
if ( ret )
return ret ;
2014-07-08 13:08:38 +04:00
opal = of_find_node_by_path ( " /ibm,opal/sensors " ) ;
for_each_child_of_node ( opal , np ) {
2015-04-08 20:19:49 +03:00
const char * label ;
2015-03-19 20:44:42 +03:00
type = get_sensor_type ( np ) ;
2015-04-08 20:19:49 +03:00
if ( type = = MAX_SENSOR_TYPE )
continue ;
sensor_groups [ type ] . attr_count + + ;
/*
2017-05-29 07:46:01 +03:00
* add attributes for labels , min and max
2015-04-08 20:19:49 +03:00
*/
if ( ! of_property_read_string ( np , " label " , & label ) )
2015-03-19 20:44:42 +03:00
sensor_groups [ type ] . attr_count + + ;
2017-05-29 07:46:01 +03:00
if ( of_find_property ( np , " sensor-data-min " , NULL ) )
sensor_groups [ type ] . attr_count + + ;
if ( of_find_property ( np , " sensor-data-max " , NULL ) )
sensor_groups [ type ] . attr_count + + ;
2014-07-08 13:08:38 +04:00
}
of_node_put ( opal ) ;
for ( type = 0 ; type < MAX_SENSOR_TYPE ; type + + ) {
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
sensor_groups [ type ] . group . attrs = devm_kcalloc ( & pdev - > dev ,
sensor_groups [ type ] . attr_count + 1 ,
sizeof ( struct attribute * ) ,
2014-07-08 13:08:38 +04:00
GFP_KERNEL ) ;
if ( ! sensor_groups [ type ] . group . attrs )
return - ENOMEM ;
pgroups [ type ] = & sensor_groups [ type ] . group ;
pdata - > sensors_count + = sensor_groups [ type ] . attr_count ;
sensor_groups [ type ] . attr_count = 0 ;
}
return 0 ;
}
2015-04-08 20:19:47 +03:00
static void create_hwmon_attr ( struct sensor_data * sdata , const char * attr_name ,
ssize_t ( * show ) ( struct device * dev ,
struct device_attribute * attr ,
2018-07-24 12:13:09 +03:00
char * buf ) ,
ssize_t ( * store ) ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count ) )
2015-04-08 20:19:47 +03:00
{
snprintf ( sdata - > name , MAX_ATTR_LEN , " %s%d_%s " ,
sensor_groups [ sdata - > type ] . name , sdata - > hwmon_index ,
attr_name ) ;
sysfs_attr_init ( & sdata - > dev_attr . attr ) ;
sdata - > dev_attr . attr . name = sdata - > name ;
sdata - > dev_attr . show = show ;
2018-07-24 12:13:09 +03:00
if ( store ) {
sdata - > dev_attr . store = store ;
sdata - > dev_attr . attr . mode = 0664 ;
} else {
sdata - > dev_attr . attr . mode = 0444 ;
}
2015-04-08 20:19:47 +03:00
}
2017-05-29 07:46:01 +03:00
static void populate_sensor ( struct sensor_data * sdata , int od , int hd , int sid ,
const char * attr_name , enum sensors type ,
const struct attribute_group * pgroup ,
2018-07-24 12:13:09 +03:00
struct sensor_group_data * sgrp_data ,
2017-05-29 07:46:01 +03:00
ssize_t ( * show ) ( struct device * dev ,
struct device_attribute * attr ,
2018-07-24 12:13:09 +03:00
char * buf ) ,
ssize_t ( * store ) ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count ) )
2017-05-29 07:46:01 +03:00
{
sdata - > id = sid ;
sdata - > type = type ;
sdata - > opal_index = od ;
sdata - > hwmon_index = hd ;
2018-07-24 12:13:09 +03:00
create_hwmon_attr ( sdata , attr_name , show , store ) ;
2017-05-29 07:46:01 +03:00
pgroup - > attrs [ sensor_groups [ type ] . attr_count + + ] = & sdata - > dev_attr . attr ;
2018-07-24 12:13:09 +03:00
sdata - > sgrp_data = sgrp_data ;
2017-05-29 07:46:01 +03:00
}
static char * get_max_attr ( enum sensors type )
{
switch ( type ) {
case POWER_INPUT :
return " input_highest " ;
default :
return " highest " ;
}
}
static char * get_min_attr ( enum sensors type )
{
switch ( type ) {
case POWER_INPUT :
return " input_lowest " ;
default :
return " lowest " ;
}
}
2014-07-08 13:08:38 +04:00
/*
* Iterate through the device tree for each child of ' sensors ' node , create
* a sysfs attribute file , the file is named by translating the DT node name
* to the name required by the higher ' hwmon ' driver like fan1_input , temp1_max
* etc . .
*/
2014-11-05 14:15:14 +03:00
static int create_device_attrs ( struct platform_device * pdev )
2014-07-08 13:08:38 +04:00
{
struct platform_data * pdata = platform_get_drvdata ( pdev ) ;
const struct attribute_group * * pgroups = pdata - > attr_groups ;
struct device_node * opal , * np ;
struct sensor_data * sdata ;
u32 count = 0 ;
2018-07-24 12:13:09 +03:00
u32 group_attr_id [ MAX_SENSOR_TYPE ] = { 0 } ;
2014-07-08 13:08:38 +04:00
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
sdata = devm_kcalloc ( & pdev - > dev ,
pdata - > sensors_count , sizeof ( * sdata ) ,
2014-07-08 13:08:38 +04:00
GFP_KERNEL ) ;
2018-07-24 12:13:09 +03:00
if ( ! sdata )
return - ENOMEM ;
2014-07-08 13:08:38 +04:00
2018-07-24 12:13:09 +03:00
opal = of_find_node_by_path ( " /ibm,opal/sensors " ) ;
2014-07-08 13:08:38 +04:00
for_each_child_of_node ( opal , np ) {
2018-07-24 12:13:09 +03:00
struct sensor_group_data * sgrp_data ;
2015-03-19 20:44:44 +03:00
const char * attr_name ;
2018-07-24 12:13:09 +03:00
u32 opal_index , hw_id ;
u32 sensor_id ;
2015-04-08 20:19:49 +03:00
const char * label ;
2018-07-24 12:13:09 +03:00
enum sensors type ;
2015-03-19 20:44:44 +03:00
2015-03-19 20:44:42 +03:00
type = get_sensor_type ( np ) ;
2014-07-08 13:08:38 +04:00
if ( type = = MAX_SENSOR_TYPE )
continue ;
2015-04-08 20:19:48 +03:00
/*
* Newer device trees use a " sensor-data " property
* name for input .
*/
if ( of_property_read_u32 ( np , " sensor-id " , & sensor_id ) & &
of_property_read_u32 ( np , " sensor-data " , & sensor_id ) ) {
2014-07-08 13:08:38 +04:00
dev_info ( & pdev - > dev ,
2018-08-28 04:52:21 +03:00
" 'sensor-id' missing in the node '%pOFn' \n " ,
np ) ;
2014-07-08 13:08:38 +04:00
continue ;
}
2014-08-01 08:38:47 +04:00
sdata [ count ] . id = sensor_id ;
2014-07-08 13:08:38 +04:00
sdata [ count ] . type = type ;
2015-03-19 20:44:44 +03:00
2015-04-08 20:19:48 +03:00
/*
* If we can not parse the node name , it means we are
* running on a newer device tree . We can just forget
* about the OPAL index and use a defaut value for the
* hwmon attribute name
*/
2015-03-19 20:44:44 +03:00
attr_name = parse_opal_node_name ( np - > name , type , & opal_index ) ;
if ( IS_ERR ( attr_name ) ) {
2015-04-08 20:19:48 +03:00
attr_name = " input " ;
opal_index = INVALID_INDEX ;
2015-03-19 20:44:44 +03:00
}
2018-07-24 12:13:09 +03:00
hw_id = get_sensor_hwmon_index ( & sdata [ count ] , sdata , count ) ;
sgrp_data = get_sensor_group ( pdata , np , type ) ;
populate_sensor ( & sdata [ count ] , opal_index , hw_id , sensor_id ,
attr_name , type , pgroups [ type ] , sgrp_data ,
show_sensor , NULL ) ;
count + + ;
2015-04-08 20:19:49 +03:00
if ( ! of_property_read_string ( np , " label " , & label ) ) {
/*
* For the label attribute , we can reuse the
* " properties " of the previous " input "
* attribute . They are related to the same
* sensor .
*/
make_sensor_label ( np , & sdata [ count ] , label ) ;
2018-07-24 12:13:09 +03:00
populate_sensor ( & sdata [ count ] , opal_index , hw_id ,
2017-05-29 07:46:01 +03:00
sensor_id , " label " , type , pgroups [ type ] ,
2018-07-24 12:13:09 +03:00
NULL , show_label , NULL ) ;
2017-05-29 07:46:01 +03:00
count + + ;
}
2015-04-08 20:19:49 +03:00
2017-05-29 07:46:01 +03:00
if ( ! of_property_read_u32 ( np , " sensor-data-max " , & sensor_id ) ) {
attr_name = get_max_attr ( type ) ;
2018-07-24 12:13:09 +03:00
populate_sensor ( & sdata [ count ] , opal_index , hw_id ,
2017-05-29 07:46:01 +03:00
sensor_id , attr_name , type ,
2018-07-24 12:13:09 +03:00
pgroups [ type ] , sgrp_data , show_sensor ,
NULL ) ;
2017-05-29 07:46:01 +03:00
count + + ;
}
2015-04-08 20:19:49 +03:00
2017-05-29 07:46:01 +03:00
if ( ! of_property_read_u32 ( np , " sensor-data-min " , & sensor_id ) ) {
attr_name = get_min_attr ( type ) ;
2018-07-24 12:13:09 +03:00
populate_sensor ( & sdata [ count ] , opal_index , hw_id ,
2017-05-29 07:46:01 +03:00
sensor_id , attr_name , type ,
2018-07-24 12:13:09 +03:00
pgroups [ type ] , sgrp_data , show_sensor ,
NULL ) ;
count + + ;
}
if ( sgrp_data & & ! sgrp_data - > enable ) {
sgrp_data - > enable = true ;
hw_id = + + group_attr_id [ type ] ;
populate_sensor ( & sdata [ count ] , opal_index , hw_id ,
sgrp_data - > gid , " enable " , type ,
pgroups [ type ] , sgrp_data , show_enable ,
store_enable ) ;
2017-05-29 07:46:01 +03:00
count + + ;
2015-04-08 20:19:49 +03:00
}
2014-07-08 13:08:38 +04:00
}
of_node_put ( opal ) ;
2018-07-24 12:13:09 +03:00
return 0 ;
2014-07-08 13:08:38 +04:00
}
2014-11-05 14:15:14 +03:00
static int ibmpowernv_probe ( struct platform_device * pdev )
2014-07-08 13:08:38 +04:00
{
struct platform_data * pdata ;
struct device * hwmon_dev ;
int err ;
pdata = devm_kzalloc ( & pdev - > dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
if ( ! pdata )
return - ENOMEM ;
platform_set_drvdata ( pdev , pdata ) ;
pdata - > sensors_count = 0 ;
2018-07-24 12:13:09 +03:00
pdata - > nr_sensor_groups = 0 ;
2014-07-08 13:08:38 +04:00
err = populate_attr_groups ( pdev ) ;
if ( err )
return err ;
/* Create sysfs attribute data for each sensor found in the DT */
err = create_device_attrs ( pdev ) ;
if ( err )
return err ;
/* Finally, register with hwmon */
hwmon_dev = devm_hwmon_device_register_with_groups ( & pdev - > dev , DRVNAME ,
pdata ,
pdata - > attr_groups ) ;
return PTR_ERR_OR_ZERO ( hwmon_dev ) ;
}
2014-11-05 14:15:14 +03:00
static const struct platform_device_id opal_sensor_driver_ids [ ] = {
{
. name = " opal-sensor " ,
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( platform , opal_sensor_driver_ids ) ;
2015-09-23 15:44:48 +03:00
static const struct of_device_id opal_sensor_match [ ] = {
{ . compatible = " ibm,opal-sensor " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , opal_sensor_match ) ;
2014-07-08 13:08:38 +04:00
static struct platform_driver ibmpowernv_driver = {
2014-11-05 14:15:14 +03:00
. probe = ibmpowernv_probe ,
. id_table = opal_sensor_driver_ids ,
. driver = {
. name = DRVNAME ,
2015-09-23 15:44:48 +03:00
. of_match_table = opal_sensor_match ,
2014-07-08 13:08:38 +04:00
} ,
} ;
2014-11-12 11:36:47 +03:00
module_platform_driver ( ibmpowernv_driver ) ;
2014-07-08 13:08:38 +04:00
MODULE_AUTHOR ( " Neelesh Gupta <neelegup@linux.vnet.ibm.com> " ) ;
MODULE_DESCRIPTION ( " IBM POWERNV platform sensors " ) ;
MODULE_LICENSE ( " GPL " ) ;