2019-01-28 10:23:23 -06:00
// SPDX-License-Identifier: GPL-2.0+
// Copyright IBM Corp 2019
2018-11-08 15:05:29 -06:00
# include <linux/bitops.h>
# include <linux/device.h>
2019-04-10 12:47:26 +02:00
# include <linux/export.h>
2018-11-08 15:05:29 -06:00
# include <linux/hwmon-sysfs.h>
# include <linux/kernel.h>
# include <linux/sysfs.h>
# include "common.h"
/* OCC status register */
# define OCC_STAT_MASTER BIT(7)
# define OCC_STAT_ACTIVE BIT(0)
/* OCC extended status register */
# define OCC_EXT_STAT_DVFS_OT BIT(7)
# define OCC_EXT_STAT_DVFS_POWER BIT(6)
# define OCC_EXT_STAT_MEM_THROTTLE BIT(5)
# define OCC_EXT_STAT_QUICK_DROP BIT(4)
static ssize_t occ_sysfs_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
int rc ;
int val = 0 ;
struct occ * occ = dev_get_drvdata ( dev ) ;
struct occ_poll_response_header * header ;
struct sensor_device_attribute * sattr = to_sensor_dev_attr ( attr ) ;
rc = occ_update_response ( occ ) ;
if ( rc )
return rc ;
header = ( struct occ_poll_response_header * ) occ - > resp . data ;
switch ( sattr - > index ) {
case 0 :
val = ! ! ( header - > status & OCC_STAT_MASTER ) ;
break ;
case 1 :
val = ! ! ( header - > status & OCC_STAT_ACTIVE ) ;
break ;
case 2 :
2019-04-15 18:37:20 +08:00
val = ! ! ( header - > ext_status & OCC_EXT_STAT_DVFS_OT ) ;
2018-11-08 15:05:29 -06:00
break ;
case 3 :
2019-04-15 18:37:20 +08:00
val = ! ! ( header - > ext_status & OCC_EXT_STAT_DVFS_POWER ) ;
2018-11-08 15:05:29 -06:00
break ;
case 4 :
2019-04-15 18:37:20 +08:00
val = ! ! ( header - > ext_status & OCC_EXT_STAT_MEM_THROTTLE ) ;
2018-11-08 15:05:29 -06:00
break ;
case 5 :
2019-04-15 18:37:20 +08:00
val = ! ! ( header - > ext_status & OCC_EXT_STAT_QUICK_DROP ) ;
2018-11-08 15:05:29 -06:00
break ;
case 6 :
val = header - > occ_state ;
break ;
case 7 :
if ( header - > status & OCC_STAT_MASTER )
val = hweight8 ( header - > occs_present ) ;
else
val = 1 ;
break ;
default :
return - EINVAL ;
}
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " %d \n " , val ) ;
2018-11-08 15:05:29 -06:00
}
2019-04-16 15:43:49 +00:00
static ssize_t occ_error_show ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct occ * occ = dev_get_drvdata ( dev ) ;
occ_update_response ( occ ) ;
hwmon: replace snprintf in show functions with sysfs_emit
coccicheck complains about the use of snprintf() in sysfs
show functions.
drivers/hwmon/ina3221.c:701:8-16: WARNING: use scnprintf or sprintf
This results in a large number of patch submissions. Fix it all in
one go using the following coccinelle rules. Use sysfs_emit instead
of scnprintf or sprintf since that makes more sense.
@depends on patch@
identifier show, dev, attr, buf;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
return
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
@depends on patch@
identifier show, dev, attr, buf, rc;
@@
ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
{
<...
rc =
- snprintf(buf, \( PAGE_SIZE \| PAGE_SIZE - 1 \),
+ sysfs_emit(buf,
...);
...>
}
While at it, remove unnecessary braces and as well as unnecessary
else after return statements to address checkpatch warnings in the
resulting patch.
Cc: Zihao Tang <tangzihao1@hisilicon.com>
Cc: Jay Fang <f.fangjian@huawei.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2021-03-21 20:49:10 -07:00
return sysfs_emit ( buf , " %d \n " , occ - > error ) ;
2019-04-16 15:43:49 +00:00
}
2018-11-08 15:05:29 -06:00
static SENSOR_DEVICE_ATTR ( occ_master , 0444 , occ_sysfs_show , NULL , 0 ) ;
static SENSOR_DEVICE_ATTR ( occ_active , 0444 , occ_sysfs_show , NULL , 1 ) ;
static SENSOR_DEVICE_ATTR ( occ_dvfs_overtemp , 0444 , occ_sysfs_show , NULL , 2 ) ;
static SENSOR_DEVICE_ATTR ( occ_dvfs_power , 0444 , occ_sysfs_show , NULL , 3 ) ;
static SENSOR_DEVICE_ATTR ( occ_mem_throttle , 0444 , occ_sysfs_show , NULL , 4 ) ;
static SENSOR_DEVICE_ATTR ( occ_quick_pwr_drop , 0444 , occ_sysfs_show , NULL , 5 ) ;
static SENSOR_DEVICE_ATTR ( occ_state , 0444 , occ_sysfs_show , NULL , 6 ) ;
static SENSOR_DEVICE_ATTR ( occs_present , 0444 , occ_sysfs_show , NULL , 7 ) ;
2019-04-16 15:43:49 +00:00
static DEVICE_ATTR_RO ( occ_error ) ;
2018-11-08 15:05:29 -06:00
static struct attribute * occ_attributes [ ] = {
& sensor_dev_attr_occ_master . dev_attr . attr ,
& sensor_dev_attr_occ_active . dev_attr . attr ,
& sensor_dev_attr_occ_dvfs_overtemp . dev_attr . attr ,
& sensor_dev_attr_occ_dvfs_power . dev_attr . attr ,
& sensor_dev_attr_occ_mem_throttle . dev_attr . attr ,
& sensor_dev_attr_occ_quick_pwr_drop . dev_attr . attr ,
& sensor_dev_attr_occ_state . dev_attr . attr ,
& sensor_dev_attr_occs_present . dev_attr . attr ,
2019-04-16 15:43:49 +00:00
& dev_attr_occ_error . attr ,
2018-11-08 15:05:29 -06:00
NULL
} ;
static const struct attribute_group occ_sysfs = {
. attrs = occ_attributes ,
} ;
void occ_sysfs_poll_done ( struct occ * occ )
{
const char * name ;
struct occ_poll_response_header * header =
( struct occ_poll_response_header * ) occ - > resp . data ;
/*
* On the first poll response , we haven ' t yet created the sysfs
* attributes , so don ' t make any notify calls .
*/
if ( ! occ - > hwmon )
goto done ;
if ( ( header - > status & OCC_STAT_MASTER ) ! =
( occ - > prev_stat & OCC_STAT_MASTER ) ) {
name = sensor_dev_attr_occ_master . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( ( header - > status & OCC_STAT_ACTIVE ) ! =
( occ - > prev_stat & OCC_STAT_ACTIVE ) ) {
name = sensor_dev_attr_occ_active . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( ( header - > ext_status & OCC_EXT_STAT_DVFS_OT ) ! =
( occ - > prev_ext_stat & OCC_EXT_STAT_DVFS_OT ) ) {
name = sensor_dev_attr_occ_dvfs_overtemp . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( ( header - > ext_status & OCC_EXT_STAT_DVFS_POWER ) ! =
( occ - > prev_ext_stat & OCC_EXT_STAT_DVFS_POWER ) ) {
name = sensor_dev_attr_occ_dvfs_power . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( ( header - > ext_status & OCC_EXT_STAT_MEM_THROTTLE ) ! =
( occ - > prev_ext_stat & OCC_EXT_STAT_MEM_THROTTLE ) ) {
name = sensor_dev_attr_occ_mem_throttle . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( ( header - > ext_status & OCC_EXT_STAT_QUICK_DROP ) ! =
( occ - > prev_ext_stat & OCC_EXT_STAT_QUICK_DROP ) ) {
name = sensor_dev_attr_occ_quick_pwr_drop . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( ( header - > status & OCC_STAT_MASTER ) & &
header - > occs_present ! = occ - > prev_occs_present ) {
name = sensor_dev_attr_occs_present . dev_attr . attr . name ;
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
if ( occ - > error & & occ - > error ! = occ - > prev_error ) {
2019-04-16 15:43:49 +00:00
name = dev_attr_occ_error . attr . name ;
2018-11-08 15:05:29 -06:00
sysfs_notify ( & occ - > bus_dev - > kobj , NULL , name ) ;
}
/* no notifications for OCC state; doesn't indicate error condition */
done :
occ - > prev_error = occ - > error ;
occ - > prev_stat = header - > status ;
occ - > prev_ext_stat = header - > ext_status ;
occ - > prev_occs_present = header - > occs_present ;
}
int occ_setup_sysfs ( struct occ * occ )
{
return sysfs_create_group ( & occ - > bus_dev - > kobj , & occ_sysfs ) ;
}
void occ_shutdown ( struct occ * occ )
{
sysfs_remove_group ( & occ - > bus_dev - > kobj , & occ_sysfs ) ;
}
2019-04-10 12:47:26 +02:00
EXPORT_SYMBOL_GPL ( occ_shutdown ) ;