From 5489913baf23ef2f4f348d2156a5a8438cd49b72 Mon Sep 17 00:00:00 2001 From: mssonicbld <79238446+mssonicbld@users.noreply.github.com> Date: Sun, 1 Jan 2023 12:27:55 +0800 Subject: [PATCH] The Sensor driver framework module complies with s3ip sysfs specification (#12890) (#13219) --- .../s3ip_sysfs_frame/curr_sensor_sysfs.c | 391 ++++++++++++++++ .../include/curr_sensor_sysfs.h | 17 + .../include/temp_sensor_sysfs.h | 17 + .../include/vol_sensor_sysfs.h | 19 + .../s3ip_sysfs_frame/temp_sensor_sysfs.c | 392 ++++++++++++++++ .../s3ip_sysfs_frame/vol_sensor_sysfs.c | 434 ++++++++++++++++++ 6 files changed, 1270 insertions(+) create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/curr_sensor_sysfs.c create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/include/curr_sensor_sysfs.h create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/include/temp_sensor_sysfs.h create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/include/vol_sensor_sysfs.h create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/temp_sensor_sysfs.c create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/vol_sensor_sysfs.c diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/curr_sensor_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/curr_sensor_sysfs.c new file mode 100644 index 0000000000..7972dd9b3e --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/curr_sensor_sysfs.c @@ -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 + +#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"); diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/curr_sensor_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/curr_sensor_sysfs.h new file mode 100644 index 0000000000..7a0b85a0fc --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/curr_sensor_sysfs.h @@ -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_ */ diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/temp_sensor_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/temp_sensor_sysfs.h new file mode 100644 index 0000000000..db03a96a0c --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/temp_sensor_sysfs.h @@ -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_ */ diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/vol_sensor_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/vol_sensor_sysfs.h new file mode 100644 index 0000000000..b2d7d615c4 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/vol_sensor_sysfs.h @@ -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_ */ diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/temp_sensor_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/temp_sensor_sysfs.c new file mode 100644 index 0000000000..0e794dcf19 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/temp_sensor_sysfs.c @@ -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 + +#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"); diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/vol_sensor_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/vol_sensor_sysfs.c new file mode 100644 index 0000000000..41e21512f0 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/vol_sensor_sysfs.c @@ -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 + +#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");