The Sensor driver framework module complies with s3ip sysfs specification (#12890) (#13219)

This commit is contained in:
mssonicbld 2023-01-01 12:27:55 +08:00 committed by GitHub
parent 29e7348c7b
commit 5489913baf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1270 additions and 0 deletions

View File

@ -0,0 +1,391 @@
/*
* curr_sensor_sysfs.c
*
* This module create curr sensor kobjects and attributes in /sys/s3ip/curr_sensor
*
* History
* [Version] [Date] [Description]
* * v1.0 2021-08-31 S3IP sysfs
*/
#include <linux/slab.h>
#include "switch.h"
#include "curr_sensor_sysfs.h"
static int g_curr_sensor_loglevel = 0;
#define CURR_SENSOR_INFO(fmt, args...) do { \
if (g_curr_sensor_loglevel & INFO) { \
printk(KERN_INFO "[CURR_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
#define CURR_SENSOR_ERR(fmt, args...) do { \
if (g_curr_sensor_loglevel & ERR) { \
printk(KERN_ERR "[CURR_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
#define CURR_SENSOR_DBG(fmt, args...) do { \
if (g_curr_sensor_loglevel & DBG) { \
printk(KERN_DEBUG "[CURR_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
struct curr_sensor_obj_s {
struct switch_obj *obj;
};
struct curr_sensor_s {
unsigned int curr_number;
struct curr_sensor_obj_s *curr;
};
static struct s3ip_sysfs_curr_sensor_drivers_s *g_curr_sensor_drv = NULL;
static struct curr_sensor_s g_curr_sensor;
static struct switch_obj *g_curr_sensor_obj = NULL;
static ssize_t curr_sensor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
char *buf)
{
return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_curr_sensor.curr_number);
}
static ssize_t curr_sensor_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->get_main_board_curr_value);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->get_main_board_curr_value(curr_index, buf, PAGE_SIZE);
if (ret < 0) {
CURR_SENSOR_ERR("get curr%u value failed, ret: %d\n", curr_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t curr_sensor_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->get_main_board_curr_alias);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->get_main_board_curr_alias(curr_index, buf, PAGE_SIZE);
if (ret < 0) {
CURR_SENSOR_ERR("get curr%u alias failed, ret: %d\n", curr_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t curr_sensor_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->get_main_board_curr_type);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->get_main_board_curr_type(curr_index, buf, PAGE_SIZE);
if (ret < 0) {
CURR_SENSOR_ERR("get curr%u type failed, ret: %d\n", curr_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t curr_sensor_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->get_main_board_curr_max);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->get_main_board_curr_max(curr_index, buf, PAGE_SIZE);
if (ret < 0) {
CURR_SENSOR_ERR("get curr%u max threshold failed, ret: %d\n", curr_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t curr_sensor_max_store(struct switch_obj *obj, struct switch_attribute *attr,
const char* buf, size_t count)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->set_main_board_curr_max);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->set_main_board_curr_max(curr_index, buf, count);
if (ret < 0) {
CURR_SENSOR_ERR("set curr%u max threshold failed, value: %s, count: %lu, ret: %d\n",
curr_index, buf, count, ret);
return -EIO;
}
CURR_SENSOR_DBG("set curr%u max threshold success, value: %s, count: %lu, ret: %d\n",
curr_index, buf, count, ret);
return count;
}
static ssize_t curr_sensor_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->get_main_board_curr_min);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->get_main_board_curr_min(curr_index, buf, PAGE_SIZE);
if (ret < 0) {
CURR_SENSOR_ERR("get curr%u min threshold failed, ret: %d\n", curr_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t curr_sensor_min_store(struct switch_obj *obj, struct switch_attribute *attr,
const char* buf, size_t count)
{
unsigned int curr_index;
int ret;
check_p(g_curr_sensor_drv);
check_p(g_curr_sensor_drv->set_main_board_curr_min);
curr_index = obj->index;
CURR_SENSOR_DBG("curr index: %u\n", curr_index);
ret = g_curr_sensor_drv->set_main_board_curr_min(curr_index, buf, count);
if (ret < 0) {
CURR_SENSOR_ERR("set curr%u min threshold failed, value: %s, count: %lu, ret: %d\n",
curr_index, buf, count, ret);
return -EIO;
}
CURR_SENSOR_DBG("set curr%u min threshold success, value: %s, count: %lu, ret: %d\n",
curr_index, buf, count, ret);
return count;
}
/************************************curr_sensor dir and attrs*******************************************/
static struct switch_attribute num_curr_att = __ATTR(number, S_IRUGO, curr_sensor_number_show, NULL);
static struct attribute *curr_sensor_dir_attrs[] = {
&num_curr_att.attr,
NULL,
};
static struct attribute_group curr_sensor_root_attr_group = {
.attrs = curr_sensor_dir_attrs,
};
/*******************************curr1 curr2 dir and attrs*******************************************/
static struct switch_attribute curr_value_attr = __ATTR(value, S_IRUGO, curr_sensor_value_show, NULL);
static struct switch_attribute curr_alias_attr = __ATTR(alias, S_IRUGO, curr_sensor_alias_show, NULL);
static struct switch_attribute curr_type_attr = __ATTR(type, S_IRUGO, curr_sensor_type_show, NULL);
static struct switch_attribute curr_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, curr_sensor_max_show, curr_sensor_max_store);
static struct switch_attribute curr_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, curr_sensor_min_show, curr_sensor_min_store);
static struct attribute *curr_sensor_attrs[] = {
&curr_value_attr.attr,
&curr_alias_attr.attr,
&curr_type_attr.attr,
&curr_max_attr.attr,
&curr_min_attr.attr,
NULL,
};
static struct attribute_group curr_sensor_attr_group = {
.attrs = curr_sensor_attrs,
};
static int curr_sensor_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
{
char name[DIR_NAME_MAX_LEN];
struct curr_sensor_obj_s *curr_sensor;
curr_sensor = &g_curr_sensor.curr[index - 1];
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "curr%u", index);
curr_sensor->obj = switch_kobject_create(name, parent);
if (!curr_sensor->obj) {
CURR_SENSOR_ERR("create %s object error.\n", name);
return -ENOMEM;
}
curr_sensor->obj->index = index;
if (sysfs_create_group(&curr_sensor->obj->kobj, &curr_sensor_attr_group) != 0) {
CURR_SENSOR_ERR("create %s attrs error.\n", name);
switch_kobject_delete(&curr_sensor->obj);
return -EBADRQC;
}
CURR_SENSOR_DBG("create %s dir and attrs success.\n", name);
return 0;
}
static void curr_sensor_sub_single_remove_kobj_and_attrs(unsigned int index)
{
struct curr_sensor_obj_s *curr_sensor;
curr_sensor = &g_curr_sensor.curr[index - 1];
if (curr_sensor->obj) {
sysfs_remove_group(&curr_sensor->obj->kobj, &curr_sensor_attr_group);
switch_kobject_delete(&curr_sensor->obj);
CURR_SENSOR_DBG("delete curr%u dir and attrs success.\n", index);
}
return;
}
static int curr_sensor_sub_create_kobj_and_attrs(struct kobject *parent, int curr_num)
{
unsigned int curr_index, i;
g_curr_sensor.curr = kzalloc(sizeof(struct curr_sensor_obj_s) * curr_num, GFP_KERNEL);
if (!g_curr_sensor.curr) {
CURR_SENSOR_ERR("kzalloc g_curr_sensor.curr error, curr number: %d.\n", curr_num);
return -ENOMEM;
}
for (curr_index = 1; curr_index <= curr_num; curr_index++) {
if (curr_sensor_sub_single_create_kobj_and_attrs(parent, curr_index) != 0) {
goto error;
}
}
return 0;
error:
for (i = curr_index; i > 0; i--) {
curr_sensor_sub_single_remove_kobj_and_attrs(i);
}
kfree(g_curr_sensor.curr);
g_curr_sensor.curr = NULL;
return -EBADRQC;
}
/* create curr[1-n] directory and attributes*/
static int curr_sensor_sub_create(void)
{
int ret;
ret = curr_sensor_sub_create_kobj_and_attrs(&g_curr_sensor_obj->kobj,
g_curr_sensor.curr_number);
return ret;
}
/* delete curr[1-n] directory and attributes*/
static void curr_sensor_sub_remove(void)
{
unsigned int curr_index;
if (g_curr_sensor.curr) {
for (curr_index = g_curr_sensor.curr_number; curr_index > 0; curr_index--) {
curr_sensor_sub_single_remove_kobj_and_attrs(curr_index);
}
kfree(g_curr_sensor.curr);
g_curr_sensor.curr = NULL;
}
g_curr_sensor.curr_number = 0;
return;
}
/* create curr_sensor directory and number attributes */
static int curr_sensor_root_create(void)
{
g_curr_sensor_obj = switch_kobject_create("curr_sensor", NULL);
if (!g_curr_sensor_obj) {
CURR_SENSOR_ERR("switch_kobject_create curr_sensor error!\n");
return -ENOMEM;
}
if (sysfs_create_group(&g_curr_sensor_obj->kobj, &curr_sensor_root_attr_group) != 0) {
switch_kobject_delete(&g_curr_sensor_obj);
CURR_SENSOR_ERR("create curr_sensor dir attrs error!\n");
return -EBADRQC;
}
return 0;
}
/* delete curr_sensor directory and number attributes */
static void curr_sensor_root_remove(void)
{
if (g_curr_sensor_obj) {
sysfs_remove_group(&g_curr_sensor_obj->kobj, &curr_sensor_root_attr_group);
switch_kobject_delete(&g_curr_sensor_obj);
}
return;
}
int s3ip_sysfs_curr_sensor_drivers_register(struct s3ip_sysfs_curr_sensor_drivers_s *drv)
{
int ret, curr_num;
CURR_SENSOR_INFO("s3ip_sysfs_curr_sensor_drivers_register...\n");
if (g_curr_sensor_drv) {
CURR_SENSOR_ERR("g_curr_sensor_drv is not NULL, can't register\n");
return -EPERM;
}
check_p(drv);
check_p(drv->get_main_board_curr_number);
g_curr_sensor_drv = drv;
curr_num = g_curr_sensor_drv->get_main_board_curr_number();
if (curr_num <= 0) {
CURR_SENSOR_ERR("curr sensor number: %d, don't need to create curr_sensor dirs and attrs.\n",
curr_num);
return -EINVAL;
}
memset(&g_curr_sensor, 0, sizeof(struct curr_sensor_s));
g_curr_sensor.curr_number = curr_num;
ret = curr_sensor_root_create();
if (ret < 0) {
CURR_SENSOR_ERR("create curr_sensor root dir and attrs failed, ret: %d\n", ret);
g_curr_sensor_drv = NULL;
return ret;
}
ret = curr_sensor_sub_create();
if (ret < 0) {
CURR_SENSOR_ERR("create curr_sensor sub dir and attrs failed, ret: %d\n", ret);
curr_sensor_root_remove();
g_curr_sensor_drv = NULL;
return ret;
}
CURR_SENSOR_INFO("s3ip_sysfs_curr_sensor_drivers_register success\n");
return ret;
}
void s3ip_sysfs_curr_sensor_drivers_unregister(void)
{
if (g_curr_sensor_drv) {
curr_sensor_sub_remove();
curr_sensor_root_remove();
g_curr_sensor_drv = NULL;
CURR_SENSOR_DBG("s3ip_sysfs_curr_sensor_drivers_unregister success.\n");
}
return;
}
EXPORT_SYMBOL(s3ip_sysfs_curr_sensor_drivers_register);
EXPORT_SYMBOL(s3ip_sysfs_curr_sensor_drivers_unregister);
module_param(g_curr_sensor_loglevel, int, 0644);
MODULE_PARM_DESC(g_curr_sensor_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");

View File

@ -0,0 +1,17 @@
#ifndef _CURR_SENSOR_SYSFS_H_
#define _CURR_SENSOR_SYSFS_H_
struct s3ip_sysfs_curr_sensor_drivers_s {
int (*get_main_board_curr_number)(void);
ssize_t (*get_main_board_curr_alias)(unsigned int curr_index, char *buf, size_t count);
ssize_t (*get_main_board_curr_type)(unsigned int curr_index, char *buf, size_t count);
ssize_t (*get_main_board_curr_max)(unsigned int curr_index, char *buf, size_t count);
int (*set_main_board_curr_max)(unsigned int curr_index, const char *buf, size_t count);
ssize_t (*get_main_board_curr_min)(unsigned int curr_index, char *buf, size_t count);
int (*set_main_board_curr_min)(unsigned int curr_index, const char *buf, size_t count);
ssize_t (*get_main_board_curr_value)(unsigned int curr_index, char *buf, size_t count);
};
extern int s3ip_sysfs_curr_sensor_drivers_register(struct s3ip_sysfs_curr_sensor_drivers_s *drv);
extern void s3ip_sysfs_curr_sensor_drivers_unregister(void);
#endif /*_CURR_SENSOR_SYSFS_H_ */

View File

@ -0,0 +1,17 @@
#ifndef _TEMP_SENSOR_SYSFS_H_
#define _TEMP_SENSOR_SYSFS_H_
struct s3ip_sysfs_temp_sensor_drivers_s {
int (*get_main_board_temp_number)(void);
ssize_t (*get_main_board_temp_alias)(unsigned int temp_index, char *buf, size_t count);
ssize_t (*get_main_board_temp_type)(unsigned int temp_index, char *buf, size_t count);
ssize_t (*get_main_board_temp_max)(unsigned int temp_index, char *buf, size_t count);
int (*set_main_board_temp_max)(unsigned int temp_index, const char *buf, size_t count);
ssize_t (*get_main_board_temp_min)(unsigned int temp_index, char *buf, size_t count);
int (*set_main_board_temp_min)(unsigned int temp_index, const char *buf, size_t count);
ssize_t (*get_main_board_temp_value)(unsigned int temp_index, char *buf, size_t count);
};
extern int s3ip_sysfs_temp_sensor_drivers_register(struct s3ip_sysfs_temp_sensor_drivers_s *drv);
extern void s3ip_sysfs_temp_sensor_drivers_unregister(void);
#endif /*_TEMP_SENSOR_SYSFS_H_ */

View File

@ -0,0 +1,19 @@
#ifndef _VOL_SENSOR_SYSFS_H_
#define _VOL_SENSOR_SYSFS_H_
struct s3ip_sysfs_vol_sensor_drivers_s {
int (*get_main_board_vol_number)(void);
ssize_t (*get_main_board_vol_alias)(unsigned int vol_index, char *buf, size_t count);
ssize_t (*get_main_board_vol_type)(unsigned int vol_index, char *buf, size_t count);
ssize_t (*get_main_board_vol_max)(unsigned int vol_index, char *buf, size_t count);
int (*set_main_board_vol_max)(unsigned int vol_index, const char *buf, size_t count);
ssize_t (*get_main_board_vol_min)(unsigned int vol_index, char *buf, size_t count);
int (*set_main_board_vol_min)(unsigned int vol_index, const char *buf, size_t count);
ssize_t (*get_main_board_vol_range)(unsigned int vol_index, char *buf, size_t count);
ssize_t (*get_main_board_vol_nominal_value)(unsigned int vol_index, char *buf, size_t count);
ssize_t (*get_main_board_vol_value)(unsigned int vol_index, char *buf, size_t count);
};
extern int s3ip_sysfs_vol_sensor_drivers_register(struct s3ip_sysfs_vol_sensor_drivers_s *drv);
extern void s3ip_sysfs_vol_sensor_drivers_unregister(void);
#endif /*_VOL_SENSOR_SYSFS_H_ */

View File

@ -0,0 +1,392 @@
/*
* temp_sensor_sysfs.c
*
* This module create temp sensor kobjects and attributes in /sys/s3ip/temp_sensor
*
* History
* [Version] [Date] [Description]
* * v1.0 2021-08-31 S3IP sysfs
*/
#include <linux/slab.h>
#include "switch.h"
#include "temp_sensor_sysfs.h"
static int g_temp_sensor_loglevel = 0;
#define TEMP_SENSOR_INFO(fmt, args...) do { \
if (g_temp_sensor_loglevel & INFO) { \
printk(KERN_INFO "[TEMP_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
#define TEMP_SENSOR_ERR(fmt, args...) do { \
if (g_temp_sensor_loglevel & ERR) { \
printk(KERN_ERR "[TEMP_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
#define TEMP_SENSOR_DBG(fmt, args...) do { \
if (g_temp_sensor_loglevel & DBG) { \
printk(KERN_DEBUG "[TEMP_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
struct temp_sensor_obj_s {
struct switch_obj *obj;
};
struct temp_sensor_s {
unsigned int temp_number;
struct temp_sensor_obj_s *temp;
};
static struct s3ip_sysfs_temp_sensor_drivers_s *g_temp_sensor_drv = NULL;
static struct temp_sensor_s g_temp_sensor;
static struct switch_obj *g_temp_sensor_obj = NULL;
static ssize_t temp_sensor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
char *buf)
{
return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_temp_sensor.temp_number);
}
static ssize_t temp_sensor_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->get_main_board_temp_value);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->get_main_board_temp_value(temp_index, buf, PAGE_SIZE);
if (ret < 0) {
TEMP_SENSOR_ERR("get temp%u value failed, ret: %d\n", temp_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t temp_sensor_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->get_main_board_temp_alias);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->get_main_board_temp_alias(temp_index, buf, PAGE_SIZE);
if (ret < 0) {
TEMP_SENSOR_ERR("get temp%u alias failed, ret: %d\n", temp_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t temp_sensor_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->get_main_board_temp_type);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->get_main_board_temp_type(temp_index, buf, PAGE_SIZE);
if (ret < 0) {
TEMP_SENSOR_ERR("get temp%u type failed, ret: %d\n", temp_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t temp_sensor_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->get_main_board_temp_max);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->get_main_board_temp_max(temp_index, buf, PAGE_SIZE);
if (ret < 0) {
TEMP_SENSOR_ERR("get temp%u max threshold failed, ret: %d\n", temp_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t temp_sensor_max_store(struct switch_obj *obj, struct switch_attribute *attr,
const char* buf, size_t count)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->set_main_board_temp_max);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->set_main_board_temp_max(temp_index, buf, count);
if (ret < 0) {
TEMP_SENSOR_ERR("set temp%u max threshold failed, value: %s, count: %lu, ret: %d\n",
temp_index, buf, count, ret);
return -EIO;
}
TEMP_SENSOR_DBG("set temp%u max threshold success, value: %s, count: %lu, ret: %d\n",
temp_index, buf, count, ret);
return count;
}
static ssize_t temp_sensor_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->get_main_board_temp_min);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->get_main_board_temp_min(temp_index, buf, PAGE_SIZE);
if (ret < 0) {
TEMP_SENSOR_ERR("get temp%u min threshold failed, ret: %d\n", temp_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t temp_sensor_min_store(struct switch_obj *obj, struct switch_attribute *attr,
const char* buf, size_t count)
{
unsigned int temp_index;
int ret;
check_p(g_temp_sensor_drv);
check_p(g_temp_sensor_drv->set_main_board_temp_min);
temp_index = obj->index;
TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
ret = g_temp_sensor_drv->set_main_board_temp_min(temp_index, buf, count);
if (ret < 0) {
TEMP_SENSOR_ERR("set temp%u min threshold failed, value: %s, count: %lu, ret: %d\n",
temp_index, buf, count, ret);
return -EIO;
}
TEMP_SENSOR_DBG("set temp%u min threshold success, value: %s, count: %lu, ret: %d\n",
temp_index, buf, count, ret);
return count;
}
/************************************temp_sensor dir and attrs*******************************************/
static struct switch_attribute num_temp_att = __ATTR(number, S_IRUGO, temp_sensor_number_show, NULL);
static struct attribute *temp_sensor_dir_attrs[] = {
&num_temp_att.attr,
NULL,
};
static struct attribute_group temp_sensor_root_attr_group = {
.attrs = temp_sensor_dir_attrs,
};
/*******************************temp1 temp2 dir and attrs*******************************************/
static struct switch_attribute temp_value_attr = __ATTR(value, S_IRUGO, temp_sensor_value_show, NULL);
static struct switch_attribute temp_alias_attr = __ATTR(alias, S_IRUGO, temp_sensor_alias_show, NULL);
static struct switch_attribute temp_type_attr = __ATTR(type, S_IRUGO, temp_sensor_type_show, NULL);
static struct switch_attribute temp_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, temp_sensor_max_show, temp_sensor_max_store);
static struct switch_attribute temp_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, temp_sensor_min_show, temp_sensor_min_store);
static struct attribute *temp_sensor_attrs[] = {
&temp_value_attr.attr,
&temp_alias_attr.attr,
&temp_type_attr.attr,
&temp_max_attr.attr,
&temp_min_attr.attr,
NULL,
};
static struct attribute_group temp_sensor_attr_group = {
.attrs = temp_sensor_attrs,
};
static int temp_sensor_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
{
char name[DIR_NAME_MAX_LEN];
struct temp_sensor_obj_s *temp_sensor;
temp_sensor = &g_temp_sensor.temp[index - 1];
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "temp%u", index);
temp_sensor->obj = switch_kobject_create(name, parent);
if (!temp_sensor->obj) {
TEMP_SENSOR_ERR("create %s object error.\n", name);
return -ENOMEM;
}
temp_sensor->obj->index = index;
if (sysfs_create_group(&temp_sensor->obj->kobj, &temp_sensor_attr_group) != 0) {
TEMP_SENSOR_ERR("create %s attrs error.\n", name);
switch_kobject_delete(&temp_sensor->obj);
return -EBADRQC;
}
TEMP_SENSOR_DBG("create %s dir and attrs success.\n", name);
return 0;
}
static void temp_sensor_sub_single_remove_kobj_and_attrs(unsigned int index)
{
struct temp_sensor_obj_s *temp_sensor;
temp_sensor = &g_temp_sensor.temp[index - 1];
if (temp_sensor->obj) {
sysfs_remove_group(&temp_sensor->obj->kobj, &temp_sensor_attr_group);
switch_kobject_delete(&temp_sensor->obj);
TEMP_SENSOR_DBG("delete temp%u dir and attrs success.\n", index);
}
return;
}
static int temp_sensor_sub_create_kobj_and_attrs(struct kobject *parent, int temp_num)
{
unsigned int temp_index, i;
g_temp_sensor.temp = kzalloc(sizeof(struct temp_sensor_obj_s) * temp_num, GFP_KERNEL);
if (!g_temp_sensor.temp) {
TEMP_SENSOR_ERR("kzalloc g_temp_sensor.temp error, temp number: %d.\n", temp_num);
return -ENOMEM;
}
for (temp_index = 1; temp_index <= temp_num; temp_index++) {
if (temp_sensor_sub_single_create_kobj_and_attrs(parent, temp_index) != 0) {
goto error;
}
}
return 0;
error:
for (i = temp_index; i > 0; i--) {
temp_sensor_sub_single_remove_kobj_and_attrs(i);
}
kfree(g_temp_sensor.temp);
g_temp_sensor.temp = NULL;
return -EBADRQC;
}
/* create temp[1-n] directory and attributes*/
static int temp_sensor_sub_create(void)
{
int ret;
ret = temp_sensor_sub_create_kobj_and_attrs(&g_temp_sensor_obj->kobj,
g_temp_sensor.temp_number);
return ret;
}
/* delete temp[1-n] directory and attributes*/
static void temp_sensor_sub_remove(void)
{
unsigned int temp_index;
if (g_temp_sensor.temp) {
for (temp_index = g_temp_sensor.temp_number; temp_index > 0; temp_index--) {
temp_sensor_sub_single_remove_kobj_and_attrs(temp_index);
}
kfree(g_temp_sensor.temp);
g_temp_sensor.temp = NULL;
}
return;
}
/* create temp_sensor directory and number attributes */
static int temp_sensor_root_create(void)
{
g_temp_sensor_obj = switch_kobject_create("temp_sensor", NULL);
if (!g_temp_sensor_obj) {
TEMP_SENSOR_ERR("switch_kobject_create temp_sensor error!\n");
return -ENOMEM;
}
if (sysfs_create_group(&g_temp_sensor_obj->kobj, &temp_sensor_root_attr_group) != 0) {
switch_kobject_delete(&g_temp_sensor_obj);
TEMP_SENSOR_ERR("create temp_sensor dir attrs error!\n");
return -EBADRQC;
}
return 0;
}
/* delete temp_sensor directory and number attributes */
static void temp_sensor_root_remove(void)
{
if (g_temp_sensor_obj) {
sysfs_remove_group(&g_temp_sensor_obj->kobj, &temp_sensor_root_attr_group);
switch_kobject_delete(&g_temp_sensor_obj);
}
return;
}
int s3ip_sysfs_temp_sensor_drivers_register(struct s3ip_sysfs_temp_sensor_drivers_s *drv)
{
int ret, temp_num;
TEMP_SENSOR_INFO("s3ip_sysfs_temp_sensor_drivers_register...\n");
if (g_temp_sensor_drv) {
TEMP_SENSOR_ERR("g_temp_sensor_drv is not NULL, can't register\n");
return -EPERM;
}
check_p(drv);
check_p(drv->get_main_board_temp_number);
g_temp_sensor_drv = drv;
temp_num = g_temp_sensor_drv->get_main_board_temp_number();
if (temp_num <= 0) {
TEMP_SENSOR_ERR("temp sensor number: %d, don't need to create temp_sensor dirs and attrs.\n",
temp_num);
return -EINVAL;
}
memset(&g_temp_sensor, 0, sizeof(struct temp_sensor_s));
g_temp_sensor.temp_number = temp_num;
ret = temp_sensor_root_create();
if (ret < 0) {
TEMP_SENSOR_ERR("create temp_sensor root dir and attrs failed, ret: %d\n", ret);
g_temp_sensor_drv = NULL;
return ret;
}
ret = temp_sensor_sub_create();
if (ret < 0) {
TEMP_SENSOR_ERR("create temp_sensor sub dir and attrs failed, ret: %d\n", ret);
temp_sensor_root_remove();
g_temp_sensor_drv = NULL;
return ret;
}
TEMP_SENSOR_INFO("s3ip_sysfs_temp_sensor_drivers_register success\n");
return ret;
}
void s3ip_sysfs_temp_sensor_drivers_unregister(void)
{
if (g_temp_sensor_drv) {
temp_sensor_sub_remove();
temp_sensor_root_remove();
g_temp_sensor_drv = NULL;
TEMP_SENSOR_DBG("s3ip_sysfs_temp_sensor_drivers_unregister success.\n");
}
return;
}
EXPORT_SYMBOL(s3ip_sysfs_temp_sensor_drivers_register);
EXPORT_SYMBOL(s3ip_sysfs_temp_sensor_drivers_unregister);
module_param(g_temp_sensor_loglevel, int, 0644);
MODULE_PARM_DESC(g_temp_sensor_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");

View File

@ -0,0 +1,434 @@
/*
* vol_sensor_sysfs.c
*
* This module create vol sensor kobjects and attributes in /sys/s3ip/vol_sensor
*
* History
* [Version] [Date] [Description]
* * v1.0 2021-08-31 S3IP sysfs
*/
#include <linux/slab.h>
#include "switch.h"
#include "vol_sensor_sysfs.h"
static int g_vol_sensor_loglevel = 0;
#define VOL_SENSOR_INFO(fmt, args...) do { \
if (g_vol_sensor_loglevel & INFO) { \
printk(KERN_INFO "[VOL_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
#define VOL_SENSOR_ERR(fmt, args...) do { \
if (g_vol_sensor_loglevel & ERR) { \
printk(KERN_ERR "[VOL_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
#define VOL_SENSOR_DBG(fmt, args...) do { \
if (g_vol_sensor_loglevel & DBG) { \
printk(KERN_DEBUG "[VOL_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
} \
} while (0)
struct vol_sensor_obj_s {
struct switch_obj *obj;
};
struct vol_sensor_s {
unsigned int vol_number;
struct vol_sensor_obj_s *vol;
};
static struct s3ip_sysfs_vol_sensor_drivers_s *g_vol_sensor_drv = NULL;
static struct vol_sensor_s g_vol_sensor;
static struct switch_obj *g_vol_sensor_obj = NULL;
static ssize_t vol_sensor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
char *buf)
{
return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_vol_sensor.vol_number);
}
static ssize_t vol_sensor_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_value);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_value(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u value failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t vol_sensor_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_alias);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_alias(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u alias failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t vol_sensor_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_type);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_type(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u type failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t vol_sensor_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_max);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_max(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u max threshold failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t vol_sensor_max_store(struct switch_obj *obj, struct switch_attribute *attr,
const char* buf, size_t count)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->set_main_board_vol_max);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->set_main_board_vol_max(vol_index, buf, count);
if (ret < 0) {
VOL_SENSOR_ERR("set vol%u max threshold failed, value: %s, count: %lu, ret: %d\n",
vol_index, buf, count, ret);
return -EIO;
}
VOL_SENSOR_DBG("set vol%u max threshold success, value: %s, count: %lu, ret: %d\n",
vol_index, buf, count, ret);
return count;
}
static ssize_t vol_sensor_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_min);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_min(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u min threshold failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t vol_sensor_min_store(struct switch_obj *obj, struct switch_attribute *attr,
const char* buf, size_t count)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->set_main_board_vol_min);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->set_main_board_vol_min(vol_index, buf, count);
if (ret < 0) {
VOL_SENSOR_ERR("set vol%u min threshold failed, value: %s, count: %lu, ret: %d\n",
vol_index, buf, count, ret);
return -EIO;
}
VOL_SENSOR_DBG("set vol%u min threshold success, value: %s, count: %lu, ret: %d\n",
vol_index, buf, count, ret);
return count;
}
static ssize_t vol_sensor_range_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_range);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_range(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u range failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
static ssize_t vol_sensor_nominal_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
{
unsigned int vol_index;
int ret;
check_p(g_vol_sensor_drv);
check_p(g_vol_sensor_drv->get_main_board_vol_nominal_value);
vol_index = obj->index;
VOL_SENSOR_DBG("vol index: %u\n", vol_index);
ret = g_vol_sensor_drv->get_main_board_vol_nominal_value(vol_index, buf, PAGE_SIZE);
if (ret < 0) {
VOL_SENSOR_ERR("get vol%u nominal value failed, ret: %d\n", vol_index, ret);
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
}
return ret;
}
/************************************vol_sensor dir and attrs*******************************************/
static struct switch_attribute num_vol_att = __ATTR(number, S_IRUGO, vol_sensor_number_show, NULL);
static struct attribute *vol_sensor_dir_attrs[] = {
&num_vol_att.attr,
NULL,
};
static struct attribute_group vol_sensor_root_attr_group = {
.attrs = vol_sensor_dir_attrs,
};
/*******************************vol1 vol2 dir and attrs*******************************************/
static struct switch_attribute vol_value_attr = __ATTR(value, S_IRUGO, vol_sensor_value_show, NULL);
static struct switch_attribute vol_alias_attr = __ATTR(alias, S_IRUGO, vol_sensor_alias_show, NULL);
static struct switch_attribute vol_type_attr = __ATTR(type, S_IRUGO, vol_sensor_type_show, NULL);
static struct switch_attribute vol_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, vol_sensor_max_show, vol_sensor_max_store);
static struct switch_attribute vol_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, vol_sensor_min_show, vol_sensor_min_store);
static struct switch_attribute vol_range_attr = __ATTR(range, S_IRUGO, vol_sensor_range_show, NULL);
static struct switch_attribute vol_nominal_value_attr = __ATTR(nominal_value, S_IRUGO, vol_sensor_nominal_value_show, NULL);
static struct attribute *vol_sensor_attrs[] = {
&vol_value_attr.attr,
&vol_alias_attr.attr,
&vol_type_attr.attr,
&vol_max_attr.attr,
&vol_min_attr.attr,
&vol_range_attr.attr,
&vol_nominal_value_attr.attr,
NULL,
};
static struct attribute_group vol_sensor_attr_group = {
.attrs = vol_sensor_attrs,
};
static int vol_sensor_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
{
char name[DIR_NAME_MAX_LEN];
struct vol_sensor_obj_s *vol_sensor;
vol_sensor = &g_vol_sensor.vol[index - 1];
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "vol%u", index);
vol_sensor->obj = switch_kobject_create(name, parent);
if (!vol_sensor->obj) {
VOL_SENSOR_ERR("create %s object error.\n", name);
return -ENOMEM;
}
vol_sensor->obj->index = index;
if (sysfs_create_group(&vol_sensor->obj->kobj, &vol_sensor_attr_group) != 0) {
VOL_SENSOR_ERR("create %s attrs error.\n", name);
switch_kobject_delete(&vol_sensor->obj);
return -EBADRQC;
}
VOL_SENSOR_DBG("create %s dir and attrs success.\n", name);
return 0;
}
static void vol_sensor_sub_single_remove_kobj_and_attrs(unsigned int index)
{
struct vol_sensor_obj_s *vol_sensor;
vol_sensor = &g_vol_sensor.vol[index - 1];
if (vol_sensor->obj) {
sysfs_remove_group(&vol_sensor->obj->kobj, &vol_sensor_attr_group);
switch_kobject_delete(&vol_sensor->obj);
VOL_SENSOR_DBG("delete vol%u dir and attrs success.\n", index);
}
return;
}
static int vol_sensor_sub_create_kobj_and_attrs(struct kobject *parent, int vol_num)
{
unsigned int vol_index, i;
g_vol_sensor.vol = kzalloc(sizeof(struct vol_sensor_obj_s) * vol_num, GFP_KERNEL);
if (!g_vol_sensor.vol) {
VOL_SENSOR_ERR("kzalloc g_vol_sensor.vol error, vol number: %d.\n", vol_num);
return -ENOMEM;
}
for (vol_index = 1; vol_index <= vol_num; vol_index++) {
if (vol_sensor_sub_single_create_kobj_and_attrs(parent, vol_index) != 0) {
goto error;
}
}
return 0;
error:
for (i = vol_index; i > 0; i--) {
vol_sensor_sub_single_remove_kobj_and_attrs(i);
}
kfree(g_vol_sensor.vol);
g_vol_sensor.vol = NULL;
return -EBADRQC;
}
/* create vol[1-n] directory and attributes*/
static int vol_sensor_sub_create(void)
{
int ret;
ret = vol_sensor_sub_create_kobj_and_attrs(&g_vol_sensor_obj->kobj, g_vol_sensor.vol_number);
return ret;
}
/* delete vol[1-n] directory and attributes*/
static void vol_sensor_sub_remove(void)
{
unsigned int vol_index;
if (g_vol_sensor.vol) {
for (vol_index = g_vol_sensor.vol_number; vol_index > 0; vol_index--) {
vol_sensor_sub_single_remove_kobj_and_attrs(vol_index);
}
kfree(g_vol_sensor.vol);
g_vol_sensor.vol = NULL;
}
return;
}
/* create vol_sensor directory and number attributes */
static int vol_sensor_root_create(void)
{
g_vol_sensor_obj = switch_kobject_create("vol_sensor", NULL);
if (!g_vol_sensor_obj) {
VOL_SENSOR_ERR("switch_kobject_create vol_sensor error!\n");
return -ENOMEM;
}
if (sysfs_create_group(&g_vol_sensor_obj->kobj, &vol_sensor_root_attr_group) != 0) {
switch_kobject_delete(&g_vol_sensor_obj);
VOL_SENSOR_ERR("create vol_sensor dir attrs error!\n");
return -EBADRQC;
}
return 0;
}
/* delete vol_sensor directory and number attributes */
static void vol_sensor_root_remove(void)
{
if (g_vol_sensor_obj) {
sysfs_remove_group(&g_vol_sensor_obj->kobj, &vol_sensor_root_attr_group);
switch_kobject_delete(&g_vol_sensor_obj);
}
return;
}
int s3ip_sysfs_vol_sensor_drivers_register(struct s3ip_sysfs_vol_sensor_drivers_s *drv)
{
int ret, vol_num;
VOL_SENSOR_INFO("s3ip_sysfs_vol_sensor_drivers_register...\n");
if (g_vol_sensor_drv) {
VOL_SENSOR_ERR("g_vol_sensor_drv is not NULL, can't register\n");
return -EPERM;
}
check_p(drv);
check_p(drv->get_main_board_vol_number);
g_vol_sensor_drv = drv;
vol_num = g_vol_sensor_drv->get_main_board_vol_number();
if (vol_num <= 0) {
VOL_SENSOR_ERR("vol sensor number: %d, don't need to create vol_sensor dirs and attrs.\n",
vol_num);
return -EINVAL;
}
memset(&g_vol_sensor, 0, sizeof(struct vol_sensor_s));
g_vol_sensor.vol_number = vol_num;
ret = vol_sensor_root_create();
if (ret < 0) {
VOL_SENSOR_ERR("create vol_sensor root dir and attrs failed, ret: %d\n", ret);
g_vol_sensor_drv = NULL;
return ret;
}
ret = vol_sensor_sub_create();
if (ret < 0) {
VOL_SENSOR_ERR("create vol_sensor sub dir and attrs failed, ret: %d\n", ret);
vol_sensor_root_remove();
g_vol_sensor_drv = NULL;
return ret;
}
VOL_SENSOR_INFO("s3ip_sysfs_vol_sensor_drivers_register success\n");
return ret;
}
void s3ip_sysfs_vol_sensor_drivers_unregister(void)
{
if (g_vol_sensor_drv) {
vol_sensor_sub_remove();
vol_sensor_root_remove();
g_vol_sensor_drv = NULL;
VOL_SENSOR_DBG("s3ip_sysfs_vol_sensor_drivers_unregister success.\n");
}
return;
}
EXPORT_SYMBOL(s3ip_sysfs_vol_sensor_drivers_register);
EXPORT_SYMBOL(s3ip_sysfs_vol_sensor_drivers_unregister);
module_param(g_vol_sensor_loglevel, int, 0644);
MODULE_PARM_DESC(g_vol_sensor_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");