From 04b3a726d424e0a3ffd7e7b645b0a9e1de59eb7d Mon Sep 17 00:00:00 2001 From: tianshangfei Date: Wed, 30 Nov 2022 23:30:59 +0800 Subject: [PATCH] The LED and watchdog driver framework module complies with s3ip sysfs specification Signed-off-by: tianshangfei --- .../s3ip_sysfs_frame/include/sysled_sysfs.h | 19 ++ .../s3ip_sysfs_frame/include/watchdog_sysfs.h | 16 + .../s3ip_sysfs_frame/sysled_sysfs.c | 314 ++++++++++++++++++ .../s3ip_sysfs_frame/watchdog_sysfs.c | 263 +++++++++++++++ 4 files changed, 612 insertions(+) create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/include/sysled_sysfs.h create mode 100755 platform/s3ip-sysfs/s3ip_sysfs_frame/include/watchdog_sysfs.h create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/sysled_sysfs.c create mode 100755 platform/s3ip-sysfs/s3ip_sysfs_frame/watchdog_sysfs.c diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/sysled_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/sysled_sysfs.h new file mode 100644 index 000000000000..e4383a4eea27 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/sysled_sysfs.h @@ -0,0 +1,19 @@ +#ifndef _SYSLED_SYSFS_H_ +#define _SYSLED_SYSFS_H_ + +struct s3ip_sysfs_sysled_drivers_s { + ssize_t (*get_sys_led_status)(char *buf, size_t count); + int (*set_sys_led_status)(int status); + ssize_t (*get_bmc_led_status)(char *buf, size_t count); + int (*set_bmc_led_status)(int status); + ssize_t (*get_sys_fan_led_status)(char *buf, size_t count); + int (*set_sys_fan_led_status)(int status); + ssize_t (*get_sys_psu_led_status)(char *buf, size_t count); + int (*set_sys_psu_led_status)(int status); + ssize_t (*get_id_led_status)(char *buf, size_t count); + int (*set_id_led_status)(int status); +}; + +extern int s3ip_sysfs_sysled_drivers_register(struct s3ip_sysfs_sysled_drivers_s *drv); +extern void s3ip_sysfs_sysled_drivers_unregister(void); +#endif /*_SYSLED_SYSFS_H_ */ diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/watchdog_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/watchdog_sysfs.h new file mode 100755 index 000000000000..7e86e4c006d9 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/watchdog_sysfs.h @@ -0,0 +1,16 @@ +#ifndef _WATCHDOG_SYSFS_H_ +#define _WATCHDOG_SYSFS_H_ + +struct s3ip_sysfs_watchdog_drivers_s { + ssize_t (*get_watchdog_identify)(char *buf, size_t count); + ssize_t (*get_watchdog_timeleft)(char *buf, size_t count); + ssize_t (*get_watchdog_timeout)(char *buf, size_t count); + int (*set_watchdog_timeout)(int value); + ssize_t (*get_watchdog_enable_status)(char *buf, size_t count); + int (*set_watchdog_enable_status)(int value); + int (*set_watchdog_reset)(int value); +}; + +extern int s3ip_sysfs_watchdog_drivers_register(struct s3ip_sysfs_watchdog_drivers_s *drv); +extern void s3ip_sysfs_watchdog_drivers_unregister(void); +#endif /*_WATCHDOG_SYSFS_H_ */ diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/sysled_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/sysled_sysfs.c new file mode 100644 index 000000000000..e42d40a755a2 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/sysled_sysfs.c @@ -0,0 +1,314 @@ +/* + * sysled_sysfs.c + * + * This module create sysled kobjects and attributes in /sys/s3ip/sysled + * + * History + * [Version] [Date] [Description] + * * v1.0 2021-08-31 S3IP sysfs + */ + +#include + +#include "switch.h" +#include "sysled_sysfs.h" + +static int g_sysled_loglevel = 0; + +#define SYSLED_INFO(fmt, args...) do { \ + if (g_sysled_loglevel & INFO) { \ + printk(KERN_INFO "[SYSLED_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define SYSLED_ERR(fmt, args...) do { \ + if (g_sysled_loglevel & ERR) { \ + printk(KERN_ERR "[SYSLED_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define SYSLED_DBG(fmt, args...) do { \ + if (g_sysled_loglevel & DBG) { \ + printk(KERN_DEBUG "[SYSLED_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +static struct switch_obj *g_sysled_obj = NULL; +static struct s3ip_sysfs_sysled_drivers_s *g_sysled_drv = NULL; + +static ssize_t sys_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->get_sys_led_status); + + ret = g_sysled_drv->get_sys_led_status(buf, PAGE_SIZE); + if (ret < 0) { + SYSLED_ERR("get sys led status failed, ret: %d:\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + SYSLED_DBG("get sys led status success:\n"); + return ret; +} + +static ssize_t sys_led_status_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->set_sys_led_status); + + sscanf(buf, "%d", &value); + if (value < 0) { + SYSLED_ERR("invaild led status value: %d, can't set sys led status\n", value); + return -EINVAL; + } + ret = g_sysled_drv->set_sys_led_status(value); + if (ret < 0) { + SYSLED_ERR("set sys led status %d faield, ret: %d\n", value, ret); + return -EIO; + } + SYSLED_DBG("set sys led status %d success\n", value); + return count; +} + +static ssize_t bmc_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->get_bmc_led_status); + + ret = g_sysled_drv->get_bmc_led_status(buf, PAGE_SIZE); + if (ret < 0) { + SYSLED_ERR("get bmc led status failed, ret: %d:\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + SYSLED_DBG("get bmc led status success:\n"); + return ret; +} + +static ssize_t bmc_led_status_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->set_bmc_led_status); + + sscanf(buf, "%d", &value); + if (value < 0) { + SYSLED_ERR("invaild led status value: %d, can't set bmc led status\n", value); + return -EINVAL; + } + ret = g_sysled_drv->set_bmc_led_status(value); + if (ret < 0) { + SYSLED_ERR("set bmc led status %d faield, ret: %d\n", value, ret); + return -EIO; + } + SYSLED_DBG("set bmc led status %d success\n", value); + return count; +} + +static ssize_t sys_fan_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->get_sys_fan_led_status); + + ret = g_sysled_drv->get_sys_fan_led_status(buf, PAGE_SIZE); + if (ret < 0) { + SYSLED_ERR("get sys fan led status failed, ret: %d:\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + SYSLED_DBG("get sys fan led status success:\n"); + return ret; +} + +static ssize_t sys_fan_led_status_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->set_sys_fan_led_status); + + sscanf(buf, "%d", &value); + if (value < 0) { + SYSLED_ERR("invaild led status value: %d, can't set sys fan led status\n", value); + return -EINVAL; + } + ret = g_sysled_drv->set_sys_fan_led_status(value); + if (ret < 0) { + SYSLED_ERR("set sys fan led status %d faield, ret: %d\n", value, ret); + return -EIO; + } + SYSLED_DBG("set sys fan led status %d success\n", value); + return count; +} + +static ssize_t sys_psu_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->get_sys_psu_led_status); + + ret = g_sysled_drv->get_sys_psu_led_status(buf, PAGE_SIZE); + if (ret < 0) { + SYSLED_ERR("get sys psu led status failed, ret: %d:\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + SYSLED_DBG("get sys psu led status success:\n"); + return ret; +} + +static ssize_t sys_psu_led_status_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->set_sys_psu_led_status); + + sscanf(buf, "%d", &value); + if (value < 0) { + SYSLED_ERR("invaild led status value: %d, can't set sys psu led status\n", value); + return -EINVAL; + } + ret = g_sysled_drv->set_sys_psu_led_status(value); + if (ret < 0) { + SYSLED_ERR("set sys psu led status %d faield, ret: %d\n", value, ret); + return -EIO; + } + SYSLED_DBG("set sys psu led status %d success\n", value); + return count; +} + +static ssize_t id_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->get_id_led_status); + + ret = g_sysled_drv->get_id_led_status(buf, PAGE_SIZE); + if (ret < 0) { + SYSLED_ERR("get id led status failed, ret: %d:\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + SYSLED_DBG("get id led status success:\n"); + return ret; +} + +static ssize_t id_led_status_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_sysled_drv); + check_p(g_sysled_drv->set_id_led_status); + + sscanf(buf, "%d", &value); + if (value < 0) { + SYSLED_ERR("invaild led status value: %d, can't set id led status\n", value); + return -EINVAL; + } + ret = g_sysled_drv->set_id_led_status(value); + if (ret < 0) { + SYSLED_ERR("set id led status %d faield, ret: %d\n", value, ret); + return -EIO; + } + SYSLED_DBG("set id led status %d success\n", value); + return count; +} + +/************************************syseeprom dir and attrs*******************************************/ +static struct switch_attribute sys_led_attr = __ATTR(sys_led_status, S_IRUGO | S_IWUSR, sys_led_status_show, sys_led_status_store); +static struct switch_attribute bmc_led_attr = __ATTR(bmc_led_status, S_IRUGO | S_IWUSR, bmc_led_status_show, bmc_led_status_store); +static struct switch_attribute fan_led_attr = __ATTR(fan_led_status, S_IRUGO | S_IWUSR, sys_fan_led_status_show, sys_fan_led_status_store); +static struct switch_attribute psu_led_attr = __ATTR(psu_led_status, S_IRUGO | S_IWUSR, sys_psu_led_status_show, sys_psu_led_status_store); +static struct switch_attribute id_led_attr = __ATTR(id_led_status, S_IRUGO | S_IWUSR, id_led_status_show, id_led_status_store); + +static struct attribute *sysled_dir_attrs[] = { + &sys_led_attr.attr, + &bmc_led_attr.attr, + &fan_led_attr.attr, + &psu_led_attr.attr, + &id_led_attr.attr, + NULL, +}; + +static struct attribute_group sysled_attr_group = { + .attrs = sysled_dir_attrs, +}; + +/* create syseled directory and attributes*/ +static int sysled_root_create(void) +{ + g_sysled_obj = switch_kobject_create("sysled", NULL); + if (!g_sysled_obj) { + SYSLED_ERR("switch_kobject_create sysled error!\n"); + return -ENOMEM; + } + + if (sysfs_create_group(&g_sysled_obj->kobj, &sysled_attr_group) != 0) { + switch_kobject_delete(&g_sysled_obj); + SYSLED_ERR("create sysled dir attrs error!\n"); + return -EBADRQC; + } + + return 0; +} + +/* delete syseled directory and attributes*/ +static void sysled_root_remove(void) +{ + if (g_sysled_obj) { + sysfs_remove_group(&g_sysled_obj->kobj, &sysled_attr_group); + switch_kobject_delete(&g_sysled_obj); + } + + return; +} + +int s3ip_sysfs_sysled_drivers_register(struct s3ip_sysfs_sysled_drivers_s *drv) +{ + int ret; + + SYSLED_INFO("s3ip_sysfs_sysled_drivers_register...\n"); + if (g_sysled_drv) { + SYSLED_ERR("g_sysled_drv is not NULL, can't register\n"); + return -EPERM; + } + + check_p(drv); + g_sysled_drv = drv; + + ret = sysled_root_create(); + if (ret < 0) { + SYSLED_ERR("sysled create error.\n"); + g_sysled_drv = NULL; + return ret; + } + SYSLED_INFO("s3ip_sysfs_sysled_drivers_register success\n"); + return 0; +} + +void s3ip_sysfs_sysled_drivers_unregister(void) +{ + if (g_sysled_drv) { + sysled_root_remove(); + g_sysled_drv = NULL; + SYSLED_DBG("s3ip_sysfs_sysled_drivers_unregister success.\n"); + } + return; +} + +EXPORT_SYMBOL(s3ip_sysfs_sysled_drivers_register); +EXPORT_SYMBOL(s3ip_sysfs_sysled_drivers_unregister); +module_param(g_sysled_loglevel, int, 0644); +MODULE_PARM_DESC(g_sysled_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n"); diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/watchdog_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/watchdog_sysfs.c new file mode 100755 index 000000000000..4487d5d19ac7 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/watchdog_sysfs.c @@ -0,0 +1,263 @@ +/* + * watchdog_sysfs.c + * + * This module create watchdog kobjects and attributes in /sys/s3ip/watchdog + * + * History + * [Version] [Date] [Description] + * * v1.0 2021-08-31 S3IP sysfs + */ + +#include + +#include "switch.h" +#include "watchdog_sysfs.h" + +static int g_wdt_loglevel = 0; + +#define WDT_INFO(fmt, args...) do { \ + if (g_wdt_loglevel & INFO) { \ + printk(KERN_INFO "[WDT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define WDT_ERR(fmt, args...) do { \ + if (g_wdt_loglevel & ERR) { \ + printk(KERN_ERR "[WDT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define WDT_DBG(fmt, args...) do { \ + if (g_wdt_loglevel & DBG) { \ + printk(KERN_DEBUG "[WDT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +typedef enum wdt_enable_status_e { + WDT_DISENABLE = 0, /* close watchdog */ + WDT_ENABLE = 1, /* open watchdog */ +} wdt_enable_status_t; + +static struct switch_obj *g_watchdog_obj = NULL; +static struct s3ip_sysfs_watchdog_drivers_s *g_wdt_drv = NULL; + +static ssize_t watchdog_identify_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->get_watchdog_identify); + + ret = g_wdt_drv->get_watchdog_identify(buf, PAGE_SIZE); + if (ret < 0) { + WDT_ERR("get watchdog identify failed, ret: %d\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + WDT_DBG("get watchdog identify success\n"); + return ret; +} + +static ssize_t watchdog_timeleft_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->get_watchdog_timeleft); + + ret = g_wdt_drv->get_watchdog_timeleft(buf, PAGE_SIZE); + if (ret < 0) { + WDT_ERR("get watchdog timeleft failed, ret: %d\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + WDT_DBG("get watchdog timeleft success\n"); + return ret; +} + +static ssize_t watchdog_timeout_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->get_watchdog_timeout); + + ret = g_wdt_drv->get_watchdog_timeout(buf, PAGE_SIZE); + if (ret < 0) { + WDT_ERR("get watchdog timeout failed, ret: %d\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + WDT_DBG("get watchdog timeout success\n"); + return ret; +} + +static ssize_t watchdog_timeout_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->set_watchdog_timeout); + + sscanf(buf, "%d", &value); + if (value < 0) { + WDT_ERR("invaild timeout value: %d, can't set watchdog timeout\n", value); + return -EINVAL; + } + + ret = g_wdt_drv->set_watchdog_timeout(value); + if (ret < 0) { + WDT_ERR("set watchdog timeout value: %d failed, ret: %d\n", value, ret); + return -EIO; + } + WDT_DBG("set watchdog timeout value: %d success\n", ret); + return count; +} + +static ssize_t watchdog_enable_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + int ret; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->get_watchdog_enable_status); + + ret = g_wdt_drv->get_watchdog_enable_status(buf, PAGE_SIZE); + if (ret < 0) { + WDT_ERR("get watchdog enable status failed, ret: %d\n", ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + WDT_DBG("get watchdog enable status success\n"); + return ret; +} + +static ssize_t watchdog_enable_status_store(struct switch_obj *obj, struct switch_attribute *attr, + const char *buf, size_t count) +{ + int ret, value; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->set_watchdog_enable_status); + + sscanf(buf, "%d", &value); + if ((value != WDT_DISENABLE) && (value != WDT_ENABLE)) { + WDT_ERR("invaild enable value: %d, can't set watchdog enable status\n", value); + return -EINVAL; + } + + ret = g_wdt_drv->set_watchdog_enable_status(value); + if (ret < 0) { + WDT_ERR("set watchdog enable status %d failed, ret: %d\n", value, ret); + return -EIO; + } + WDT_DBG("set watchdog enable status %d success\n", ret); + return count; +} + +static ssize_t watchdog_reset_store(struct switch_obj *obj, struct switch_attribute *attr, + const char* buf, size_t count) +{ + int ret, value; + + check_p(g_wdt_drv); + check_p(g_wdt_drv->set_watchdog_reset); + + ret = kstrtoint(buf, 0, &value); + if (ret) { + WDT_ERR("invalid value: %s \n", buf); + return -EINVAL; + } + + ret = g_wdt_drv->set_watchdog_reset(value); + if (ret < 0) { + WDT_ERR("set watchdog reset %d failed, ret: %d\n", value, ret); + return -EIO; + } + WDT_DBG("set watchdog reset %d success\n", ret); + return count; +} + +/************************************watchdog*******************************************/ +static struct switch_attribute watchdog_identify_attr = __ATTR(identify, S_IRUGO, watchdog_identify_show, NULL); +static struct switch_attribute watchdog_timeleft_attr = __ATTR(timeleft, S_IRUGO, watchdog_timeleft_show, NULL); +static struct switch_attribute watchdog_timeout_attr = __ATTR(timeout, S_IRUGO | S_IWUSR, watchdog_timeout_show, watchdog_timeout_store); +static struct switch_attribute watchdog_enable_attr = __ATTR(enable, S_IRUGO | S_IWUSR, watchdog_enable_status_show, watchdog_enable_status_store); +static struct switch_attribute watchdog_reset_attr = __ATTR(reset, S_IWUSR, NULL, watchdog_reset_store); + +static struct attribute *watchdog_dir_attrs[] = { + &watchdog_identify_attr.attr, + &watchdog_timeleft_attr.attr, + &watchdog_timeout_attr.attr, + &watchdog_enable_attr.attr, + &watchdog_reset_attr.attr, + NULL, +}; + +static struct attribute_group watchdog_attr_group = { + .attrs = watchdog_dir_attrs, +}; + +/* create watchdog directory and attributes */ +static int watchdog_root_create(void) +{ + g_watchdog_obj = switch_kobject_create("watchdog", NULL); + if (!g_watchdog_obj) { + WDT_ERR("switch_kobject_create watchdog error!\n"); + return -ENOMEM; + } + + if (sysfs_create_group(&g_watchdog_obj->kobj, &watchdog_attr_group) != 0) { + switch_kobject_delete(&g_watchdog_obj); + WDT_ERR("create fan dir attrs error!\n"); + return -EBADRQC; + } + + return 0; +} + +/* delete watchdog directory and attributes */ +static void watchdog_root_remove(void) +{ + if (g_watchdog_obj) { + sysfs_remove_group(&g_watchdog_obj->kobj, &watchdog_attr_group); + switch_kobject_delete(&g_watchdog_obj); + } + + return; +} + +int s3ip_sysfs_watchdog_drivers_register(struct s3ip_sysfs_watchdog_drivers_s *drv) +{ + int ret; + + WDT_INFO("s3ip_sysfs_watchdog_drivers_register...\n"); + if (g_wdt_drv) { + WDT_ERR("g_wdt_drv is not NULL, can't register\n"); + return -EPERM; + } + + check_p(drv); + g_wdt_drv = drv; + + ret = watchdog_root_create(); + if (ret < 0) { + WDT_ERR("watchdog create error.\n"); + g_wdt_drv = NULL; + return ret; + } + WDT_INFO("s3ip_sysfs_watchdog_drivers_register success\n"); + return 0; +} + +void s3ip_sysfs_watchdog_drivers_unregister(void) +{ + if (g_wdt_drv) { + watchdog_root_remove(); + g_wdt_drv = NULL; + WDT_DBG("s3ip_sysfs_watchdog_drivers_unregister success.\n"); + } + + return; +} + +EXPORT_SYMBOL(s3ip_sysfs_watchdog_drivers_register); +EXPORT_SYMBOL(s3ip_sysfs_watchdog_drivers_unregister); +module_param(g_wdt_loglevel, int, 0644); +MODULE_PARM_DESC(g_wdt_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");