The slot and switch_rootsysfs driver framework module complies with s3ip sysfs specification (#12893)
Why I did it Provide slot and switch_rootsysfs 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
This commit is contained in:
parent
8f124dc56d
commit
8fe4fab89f
57
platform/s3ip-sysfs/s3ip_sysfs_frame/include/slot_sysfs.h
Normal file
57
platform/s3ip-sysfs/s3ip_sysfs_frame/include/slot_sysfs.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef _SLOT_SYSFS_H_
|
||||
#define _SLOT_SYSFS_H_
|
||||
|
||||
struct s3ip_sysfs_slot_drivers_s {
|
||||
int (*get_slot_number)(void);
|
||||
int (*get_slot_temp_number)(unsigned int slot_index);
|
||||
int (*get_slot_vol_number)(unsigned int slot_index);
|
||||
int (*get_slot_curr_number)(unsigned int slot_index);
|
||||
int (*get_slot_cpld_number)(unsigned int slot_index);
|
||||
int (*get_slot_fpga_number)(unsigned int slot_index);
|
||||
ssize_t (*get_slot_model_name)(unsigned int slot_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_serial_number)(unsigned int slot_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_part_number)(unsigned int slot_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_hardware_version)(unsigned int slot_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_status)(unsigned int slot_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_led_status)(unsigned int slot_index, char *buf, size_t count);
|
||||
int (*set_slot_led_status)(unsigned int slot_index, int status);
|
||||
ssize_t (*get_slot_temp_alias)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_temp_type)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_temp_max)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
|
||||
int (*set_slot_temp_max)(unsigned int slot_index, unsigned int temp_index, const char *buf, size_t count);
|
||||
ssize_t (*get_slot_temp_min)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
|
||||
int (*set_slot_temp_min)(unsigned int slot_index, unsigned int temp_index, const char *buf, size_t count);
|
||||
ssize_t (*get_slot_temp_value)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_alias)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_type)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_max)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
int (*set_slot_vol_max)(unsigned int slot_index, unsigned int vol_index, const char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_min)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
int (*set_slot_vol_min)(unsigned int slot_index, unsigned int vol_index, const char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_range)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_nominal_value)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_vol_value)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_curr_alias)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_curr_type)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_curr_max)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
|
||||
int (*set_slot_curr_max)(unsigned int slot_index, unsigned int curr_index, const char *buf, size_t count);
|
||||
ssize_t (*get_slot_curr_min)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
|
||||
int (*set_slot_curr_min)(unsigned int slot_index, unsigned int curr_index, const char *buf, size_t count);
|
||||
ssize_t (*get_slot_curr_value)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_fpga_alias)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_fpga_type)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_fpga_firmware_version)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_fpga_board_version)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_fpga_test_reg)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
|
||||
int (*set_slot_fpga_test_reg)(unsigned int slot_index, unsigned int fpga_index, unsigned int value);
|
||||
ssize_t (*get_slot_cpld_alias)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_cpld_type)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_cpld_firmware_version)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_cpld_board_version)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
|
||||
ssize_t (*get_slot_cpld_test_reg)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
|
||||
int (*set_slot_cpld_test_reg)(unsigned int slot_index, unsigned int cpld_index, unsigned int value);
|
||||
};
|
||||
|
||||
extern int s3ip_sysfs_slot_drivers_register(struct s3ip_sysfs_slot_drivers_s *drv);
|
||||
extern void s3ip_sysfs_slot_drivers_unregister(void);
|
||||
#endif /*_SLOT_SYSFS_H_ */
|
68
platform/s3ip-sysfs/s3ip_sysfs_frame/include/switch.h
Normal file
68
platform/s3ip-sysfs/s3ip_sysfs_frame/include/switch.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef _SWITCH_H_
|
||||
#define _SWITCH_H_
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define DIR_NAME_MAX_LEN (64)
|
||||
#define SYSFS_DEV_ERROR "NA"
|
||||
|
||||
enum LOG_LEVEL{
|
||||
INFO = 0x1,
|
||||
ERR = 0x2,
|
||||
DBG = 0x4,
|
||||
ALL = 0xf
|
||||
};
|
||||
|
||||
extern int g_switch_loglevel;
|
||||
|
||||
#define check_pfun(p) do { \
|
||||
if (p == NULL) { \
|
||||
if (g_switch_loglevel & ERR) { \
|
||||
printk( KERN_ERR "%s, %s is NULL.\n", __FUNCTION__, #p); \
|
||||
} \
|
||||
return -ENOSYS; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define check_p(p) check_pfun(p)
|
||||
|
||||
#define to_switch_obj(x) container_of(x, struct switch_obj, kobj)
|
||||
#define to_switch_attr(x) container_of(x, struct switch_attribute, attr)
|
||||
#define to_switch_device_attr(x) container_of(x, struct switch_device_attribute, switch_attr)
|
||||
|
||||
#define SWITCH_ATTR(_name, _mode, _show, _store, _type) \
|
||||
{ .switch_attr = __ATTR(_name, _mode, _show, _store), \
|
||||
.type = _type }
|
||||
|
||||
#define SWITCH_DEVICE_ATTR(_name, _mode, _show, _store, _type) \
|
||||
struct switch_device_attribute switch_dev_attr_##_name \
|
||||
= SWITCH_ATTR(_name, _mode, _show, _store, _type)
|
||||
|
||||
struct switch_obj {
|
||||
struct kobject kobj;
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
/* a custom attribute that works just for a struct switch_obj. */
|
||||
struct switch_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct switch_obj *foo, struct switch_attribute *attr, char *buf);
|
||||
ssize_t (*store)(struct switch_obj *foo, struct switch_attribute *attr, const char *buf, size_t count);
|
||||
};
|
||||
|
||||
struct switch_device_attribute {
|
||||
struct switch_attribute switch_attr;
|
||||
int type;
|
||||
};
|
||||
|
||||
struct switch_obj *switch_kobject_create(const char *name, struct kobject *parent);
|
||||
void switch_kobject_delete(struct switch_obj **obj);
|
||||
|
||||
#endif /* _SWITCH_H_ */
|
@ -0,0 +1,12 @@
|
||||
#ifndef _SYSEEPROM_SYSFS_H_
|
||||
#define _SYSEEPROM_SYSFS_H_
|
||||
|
||||
struct s3ip_sysfs_syseeprom_drivers_s {
|
||||
int (*get_syseeprom_size)(void);
|
||||
ssize_t (*read_syseeprom_data)(char *buf, loff_t offset, size_t count);
|
||||
ssize_t (*write_syseeprom_data)(char *buf, loff_t offset, size_t count);
|
||||
};
|
||||
|
||||
extern int s3ip_sysfs_syseeprom_drivers_register(struct s3ip_sysfs_syseeprom_drivers_s *drv);
|
||||
extern void s3ip_sysfs_syseeprom_drivers_unregister(void);
|
||||
#endif /*_SYSEEPROM_SYSFS_H_ */
|
2099
platform/s3ip-sysfs/s3ip_sysfs_frame/slot_sysfs.c
Normal file
2099
platform/s3ip-sysfs/s3ip_sysfs_frame/slot_sysfs.c
Normal file
File diff suppressed because it is too large
Load Diff
270
platform/s3ip-sysfs/s3ip_sysfs_frame/switch.c
Normal file
270
platform/s3ip-sysfs/s3ip_sysfs_frame/switch.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* switch.c
|
||||
*
|
||||
* This module create a kset in sysfs called /sys/s3ip
|
||||
* Then other switch kobjects are created and assigned to this kset,
|
||||
* such as "cpld", "fan", "psu", ...
|
||||
*
|
||||
* History
|
||||
* [Version] [Date] [Description]
|
||||
* * v1.0 2021-08-31 S3IP sysfs
|
||||
*/
|
||||
|
||||
#include "switch.h"
|
||||
#include "syseeprom_sysfs.h"
|
||||
|
||||
int g_switch_loglevel = 0;
|
||||
|
||||
#define SWITCH_INFO(fmt, args...) do { \
|
||||
if (g_switch_loglevel & INFO) { \
|
||||
printk(KERN_INFO "[SWITCH][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SWITCH_ERR(fmt, args...) do { \
|
||||
if (g_switch_loglevel & ERR) { \
|
||||
printk(KERN_ERR "[SWITCH][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SWITCH_DBG(fmt, args...) do { \
|
||||
if (g_switch_loglevel & DBG) { \
|
||||
printk(KERN_DEBUG "[SWITCH][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct syseeprom_s {
|
||||
struct bin_attribute bin;
|
||||
int creat_eeprom_bin_flag;
|
||||
};
|
||||
|
||||
static struct s3ip_sysfs_syseeprom_drivers_s *g_syseeprom_drv = NULL;
|
||||
static struct kset *switch_kset;
|
||||
static struct syseeprom_s g_syseeprom;
|
||||
|
||||
static ssize_t switch_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
|
||||
{
|
||||
struct switch_attribute *attribute;
|
||||
struct switch_obj *device;
|
||||
|
||||
attribute = to_switch_attr(attr);
|
||||
device = to_switch_obj(kobj);
|
||||
|
||||
if (!attribute->show) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return attribute->show(device, attribute, buf);
|
||||
}
|
||||
|
||||
static ssize_t switch_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct switch_attribute *attribute;
|
||||
struct switch_obj *obj;
|
||||
|
||||
attribute = to_switch_attr(attr);
|
||||
obj = to_switch_obj(kobj);
|
||||
|
||||
if (!attribute->store) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return attribute->store(obj, attribute, buf, len);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops switch_sysfs_ops = {
|
||||
.show = switch_attr_show,
|
||||
.store = switch_attr_store,
|
||||
};
|
||||
|
||||
static void switch_obj_release(struct kobject *kobj)
|
||||
{
|
||||
struct switch_obj *obj;
|
||||
|
||||
obj = to_switch_obj(kobj);
|
||||
kfree(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct kobj_type switch_ktype = {
|
||||
.sysfs_ops = &switch_sysfs_ops,
|
||||
.release = switch_obj_release,
|
||||
.default_attrs = NULL,
|
||||
};
|
||||
|
||||
static ssize_t syseeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
|
||||
char *buf, loff_t offset, size_t count)
|
||||
{
|
||||
ssize_t rd_len;
|
||||
|
||||
check_p(g_syseeprom_drv);
|
||||
check_p(g_syseeprom_drv->read_syseeprom_data);
|
||||
|
||||
memset(buf, 0, count);
|
||||
rd_len = g_syseeprom_drv->read_syseeprom_data(buf, offset, count);
|
||||
if (rd_len < 0) {
|
||||
SWITCH_ERR("read syseeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
|
||||
offset, count, rd_len);
|
||||
return -EIO;
|
||||
}
|
||||
SWITCH_DBG("read syseeprom data success, offset:0x%llx, read len:%lu, really read len:%ld.\n",
|
||||
offset, count, rd_len);
|
||||
return rd_len;
|
||||
}
|
||||
|
||||
static ssize_t syseeprom_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
|
||||
char *buf, loff_t offset, size_t count)
|
||||
{
|
||||
ssize_t wr_len;
|
||||
|
||||
check_p(g_syseeprom_drv);
|
||||
check_p(g_syseeprom_drv->write_syseeprom_data);
|
||||
|
||||
wr_len = g_syseeprom_drv->write_syseeprom_data(buf, offset, count);
|
||||
if (wr_len < 0) {
|
||||
SWITCH_ERR("write syseeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
|
||||
offset, count, wr_len);
|
||||
return -EIO;
|
||||
}
|
||||
SWITCH_DBG("write syseeprom data success, offset:0x%llx, write len:%lu, really write len:%ld.\n",
|
||||
offset, count, wr_len);
|
||||
return wr_len;
|
||||
}
|
||||
|
||||
static int syseeprom_create_eeprom_attrs(void)
|
||||
{
|
||||
int ret, eeprom_size;
|
||||
|
||||
eeprom_size = g_syseeprom_drv->get_syseeprom_size();
|
||||
if (eeprom_size <= 0) {
|
||||
SWITCH_ERR("syseeprom size: %d, invalid.\n", eeprom_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sysfs_bin_attr_init(&g_syseeprom.bin);
|
||||
g_syseeprom.bin.attr.name = "syseeprom";
|
||||
g_syseeprom.bin.attr.mode = 0644;
|
||||
g_syseeprom.bin.read = syseeprom_read;
|
||||
g_syseeprom.bin.write = syseeprom_write;
|
||||
g_syseeprom.bin.size = eeprom_size;
|
||||
|
||||
ret = sysfs_create_bin_file(&switch_kset->kobj, &g_syseeprom.bin);
|
||||
if (ret) {
|
||||
SWITCH_ERR("create syseeprom bin error, ret: %d. \n", ret);
|
||||
return -EBADRQC;
|
||||
}
|
||||
SWITCH_DBG("create syseeprom bin file success, eeprom size:%d.\n", eeprom_size);
|
||||
g_syseeprom.creat_eeprom_bin_flag = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void syseeprom_remove_eeprom_attrs(void)
|
||||
{
|
||||
if (g_syseeprom.creat_eeprom_bin_flag) {
|
||||
sysfs_remove_bin_file(&switch_kset->kobj, &g_syseeprom.bin);
|
||||
g_syseeprom.creat_eeprom_bin_flag = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int s3ip_sysfs_syseeprom_drivers_register(struct s3ip_sysfs_syseeprom_drivers_s *drv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
SWITCH_INFO("s3ip_sysfs_syseeprom_drivers_register...\n");
|
||||
if (g_syseeprom_drv) {
|
||||
SWITCH_ERR("g_syseeprom_drv is not NULL, can't register\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
check_p(drv);
|
||||
check_p(drv->get_syseeprom_size);
|
||||
g_syseeprom_drv = drv;
|
||||
|
||||
ret = syseeprom_create_eeprom_attrs();
|
||||
if (ret < 0) {
|
||||
SWITCH_ERR("create syseeprom attributes failed, ret: %d\n", ret);
|
||||
g_syseeprom_drv = NULL;
|
||||
return ret;
|
||||
}
|
||||
SWITCH_INFO("s3ip_sysfs_syseeprom_drivers_register success.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void s3ip_sysfs_syseeprom_drivers_unregister(void)
|
||||
{
|
||||
if (g_syseeprom_drv) {
|
||||
syseeprom_remove_eeprom_attrs();
|
||||
g_syseeprom_drv = NULL;
|
||||
SWITCH_DBG("s3ip_sysfs_syseeprom_drivers_unregister success.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct switch_obj *switch_kobject_create(const char *name, struct kobject *parent)
|
||||
{
|
||||
struct switch_obj *obj;
|
||||
int ret;
|
||||
|
||||
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
|
||||
if (!obj) {
|
||||
SWITCH_DBG("switch_kobject_create %s kzalloc error", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj->kobj.kset = switch_kset;
|
||||
|
||||
ret = kobject_init_and_add(&obj->kobj, &switch_ktype, parent, "%s", name);
|
||||
if (ret) {
|
||||
kobject_put(&obj->kobj);
|
||||
SWITCH_DBG("kobject_init_and_add %s error", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void switch_kobject_delete(struct switch_obj **obj)
|
||||
{
|
||||
if (*obj) {
|
||||
SWITCH_DBG("%s delete %s.\n", (*obj)->kobj.parent->name, (*obj)->kobj.name);
|
||||
kobject_put(&((*obj)->kobj));
|
||||
*obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init switch_init(void)
|
||||
{
|
||||
SWITCH_INFO("switch_init...\n");
|
||||
|
||||
switch_kset = kset_create_and_add("s3ip", NULL, NULL);
|
||||
if (!switch_kset) {
|
||||
SWITCH_ERR("create switch_kset error.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
SWITCH_INFO("switch_init success.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit switch_exit(void)
|
||||
{
|
||||
if (switch_kset) {
|
||||
kset_unregister(switch_kset);
|
||||
}
|
||||
|
||||
SWITCH_INFO("switch_exit success.\n");
|
||||
}
|
||||
|
||||
module_init(switch_init);
|
||||
module_exit(switch_exit);
|
||||
EXPORT_SYMBOL(s3ip_sysfs_syseeprom_drivers_register);
|
||||
EXPORT_SYMBOL(s3ip_sysfs_syseeprom_drivers_unregister);
|
||||
module_param(g_switch_loglevel, int, 0644);
|
||||
MODULE_PARM_DESC(g_switch_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("sonic S3IP sysfs");
|
||||
MODULE_DESCRIPTION("switch driver");
|
Loading…
Reference in New Issue
Block a user