sonic-buildimage/platform/s3ip-sysfs/s3ip_sysfs_frame/watchdog_sysfs.c
tianshangfei 8f124dc56d
The LED and watchdog driver framework module complies with s3ip sysfs specification (#12892)
Why I did it
Provide SYSLED and watchdog driver framework that complies with s3ip sysfs specification

How I did it
1、 The framework module provides register and unregister interface and implementation.
2、 The framework will help you create the sysfs node

How to verify it
A demo driver base on this framework will display the sysfs node wich conform to the s3ip sysfs specification
2022-12-14 22:33:52 +08:00

264 lines
7.9 KiB
C
Executable File

/*
* 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 <linux/slab.h>
#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");