From a2885b31edbc73c3af4e60376482aededfa20c5b Mon Sep 17 00:00:00 2001 From: tianshangfei <31125751+tianshangfei@users.noreply.github.com> Date: Fri, 16 Dec 2022 22:05:53 +0800 Subject: [PATCH] The CPLD and FPGA driver framework module complies with s3ip sysfs specification (#12891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why I did it Provide CPLD and FPGA 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 --- .../s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c | 365 +++++++++++++++++ .../s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c | 366 ++++++++++++++++++ .../s3ip_sysfs_frame/include/cpld_sysfs.h | 16 + .../s3ip_sysfs_frame/include/fpga_sysfs.h | 16 + 4 files changed, 763 insertions(+) create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/include/cpld_sysfs.h create mode 100644 platform/s3ip-sysfs/s3ip_sysfs_frame/include/fpga_sysfs.h diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c new file mode 100644 index 000000000000..9e3efaca497a --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c @@ -0,0 +1,365 @@ +/* + * cpld_sysfs.c + * + * This module create cpld kobjects and attributes in /sys/s3ip/cpld + * + * History + * [Version] [Date] [Description] + * * v1.0 2021-08-31 S3IP sysfs + */ + +#include + +#include "switch.h" +#include "cpld_sysfs.h" + +static int g_cpld_loglevel = 0; + +#define CPLD_INFO(fmt, args...) do { \ + if (g_cpld_loglevel & INFO) { \ + printk(KERN_INFO "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define CPLD_ERR(fmt, args...) do { \ + if (g_cpld_loglevel & ERR) { \ + printk(KERN_ERR "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define CPLD_DBG(fmt, args...) do { \ + if (g_cpld_loglevel & DBG) { \ + printk(KERN_DEBUG "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +struct cpld_obj_s { + struct switch_obj *obj; +}; + +struct cpld_s { + unsigned int cpld_number; + struct cpld_obj_s *cpld; +}; + +static struct cpld_s g_cpld; +static struct switch_obj *g_cpld_obj = NULL; +static struct s3ip_sysfs_cpld_drivers_s *g_cpld_drv = NULL; + +static ssize_t cpld_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_cpld.cpld_number); +} + +static ssize_t cpld_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int cpld_index; + int ret; + + check_p(g_cpld_drv); + check_p(g_cpld_drv->get_main_board_cpld_alias); + + cpld_index = obj->index; + CPLD_DBG("cpld index: %u\n", cpld_index); + ret = g_cpld_drv->get_main_board_cpld_alias(cpld_index, buf, PAGE_SIZE); + if (ret < 0) { + CPLD_ERR("get cpld%u alias failed, ret: %d\n", cpld_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t cpld_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int cpld_index; + int ret; + + check_p(g_cpld_drv); + check_p(g_cpld_drv->get_main_board_cpld_type); + + cpld_index = obj->index; + CPLD_DBG("cpld index: %u\n", cpld_index); + ret = g_cpld_drv->get_main_board_cpld_type(cpld_index, buf, PAGE_SIZE); + if (ret < 0) { + CPLD_ERR("get cpld%u type failed, ret: %d\n", cpld_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t cpld_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int cpld_index; + int ret; + + check_p(g_cpld_drv); + check_p(g_cpld_drv->get_main_board_cpld_firmware_version); + + cpld_index = obj->index; + CPLD_DBG("cpld index: %u\n", cpld_index); + ret = g_cpld_drv->get_main_board_cpld_firmware_version(cpld_index, buf, PAGE_SIZE); + if (ret < 0) { + CPLD_ERR("get cpld%u firmware version failed, ret: %d\n", cpld_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t cpld_board_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int cpld_index; + int ret; + + check_p(g_cpld_drv); + check_p(g_cpld_drv->get_main_board_cpld_board_version); + + cpld_index = obj->index; + CPLD_DBG("cpld index: %u\n", cpld_index); + ret = g_cpld_drv->get_main_board_cpld_board_version(cpld_index, buf, PAGE_SIZE); + if (ret < 0) { + CPLD_ERR("get cpld%u board version failed, ret: %d\n", cpld_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t cpld_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int cpld_index; + int ret; + + check_p(g_cpld_drv); + check_p(g_cpld_drv->get_main_board_cpld_test_reg); + + cpld_index = obj->index; + CPLD_DBG("cpld index: %u\n", cpld_index); + ret = g_cpld_drv->get_main_board_cpld_test_reg(cpld_index, buf, PAGE_SIZE); + if (ret < 0) { + CPLD_ERR("get cpld%u test register failed, ret: %d\n", cpld_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t cpld_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr, + const char* buf, size_t count) +{ + unsigned int cpld_index, value; + int ret; + + check_p(g_cpld_drv); + check_p(g_cpld_drv->set_main_board_cpld_test_reg); + + cpld_index = obj->index; + sscanf(buf, "0x%x", &value); + ret = g_cpld_drv->set_main_board_cpld_test_reg(cpld_index, value); + if (ret < 0) { + CPLD_ERR("set cpld%u test reg failed, value:0x%x, ret: %d.\n", cpld_index, value, ret); + return -EIO; + } + CPLD_DBG("set cpld%u test reg success, value: 0x%x.\n", cpld_index, value); + return count; +} + +/************************************cpld dir and attrs*******************************************/ +static struct switch_attribute cpld_number_att = __ATTR(number, S_IRUGO, cpld_number_show, NULL); + +static struct attribute *cpld_dir_attrs[] = { + &cpld_number_att.attr, + NULL, +}; + +static struct attribute_group cpld_root_attr_group = { + .attrs = cpld_dir_attrs, +}; + +/*******************************cpld[1-n] dir and attrs*******************************************/ +static struct switch_attribute cpld_alias_attr = __ATTR(alias, S_IRUGO, cpld_alias_show, NULL); +static struct switch_attribute cpld_type_attr = __ATTR(type, S_IRUGO, cpld_type_show, NULL); +static struct switch_attribute cpld_fw_version_attr = __ATTR(firmware_version, S_IRUGO, cpld_fw_version_show, NULL); +static struct switch_attribute cpld_board_version_attr = __ATTR(board_version, S_IRUGO, cpld_board_version_show, NULL); +static struct switch_attribute cpld_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, cpld_test_reg_show, cpld_test_reg_store); + +static struct attribute *cpld_attrs[] = { + &cpld_alias_attr.attr, + &cpld_type_attr.attr, + &cpld_fw_version_attr.attr, + &cpld_board_version_attr.attr, + &cpld_test_reg_attr.attr, + NULL, +}; + +static struct attribute_group cpld_attr_group = { + .attrs = cpld_attrs, +}; + +static int cpld_sub_single_remove_kobj_and_attrs(unsigned int index) +{ + struct cpld_obj_s *curr_cpld; + + curr_cpld = &g_cpld.cpld[index - 1]; + if (curr_cpld->obj) { + sysfs_remove_group(&curr_cpld->obj->kobj, &cpld_attr_group); + switch_kobject_delete(&curr_cpld->obj); + CPLD_DBG("delete cpld%u dir and attrs success.\n", index); + } + + return 0; +} + +static int cpld_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index) +{ + char name[8]; + struct cpld_obj_s *curr_cpld; + + curr_cpld = &g_cpld.cpld[index - 1]; + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name), "cpld%u", index); + curr_cpld->obj = switch_kobject_create(name, parent); + if (!curr_cpld->obj) { + CPLD_ERR("create %s object error!\n", name); + return -EBADRQC; + } + curr_cpld->obj->index = index; + if (sysfs_create_group(&curr_cpld->obj->kobj, &cpld_attr_group) != 0) { + CPLD_ERR("create %s attrs error.\n", name); + switch_kobject_delete(&curr_cpld->obj); + return -EBADRQC; + } + CPLD_DBG("create %s dir and attrs success.\n", name); + return 0; +} + +static int cpld_sub_create_kobj_and_attrs(struct kobject *parent, int cpld_num) +{ + unsigned int cpld_index, i; + + g_cpld.cpld = kzalloc(sizeof(struct cpld_obj_s) * cpld_num, GFP_KERNEL); + if (!g_cpld.cpld) { + CPLD_ERR("kzalloc g_cpld.cpld error, cpld number = %d.\n", cpld_num); + return -ENOMEM; + } + + for(cpld_index = 1; cpld_index <= cpld_num; cpld_index++) { + if(cpld_sub_single_create_kobj_and_attrs(parent, cpld_index) != 0) { + goto error; + } + } + return 0; +error: + for(i = cpld_index; i > 0; i--) { + cpld_sub_single_remove_kobj_and_attrs(i); + } + kfree(g_cpld.cpld); + g_cpld.cpld = NULL; + return -EBADRQC; +} + +/* create cpld[1-n] directory and attributes*/ +static int cpld_sub_create(void) +{ + int ret; + + ret = cpld_sub_create_kobj_and_attrs(&g_cpld_obj->kobj, g_cpld.cpld_number); + return ret; +} + +/* delete cpld[1-n] directory and attributes*/ +static void cpld_sub_remove(void) +{ + unsigned int cpld_index; + + if (g_cpld.cpld) { + for (cpld_index = g_cpld.cpld_number; cpld_index > 0; cpld_index--) { + cpld_sub_single_remove_kobj_and_attrs(cpld_index); + } + kfree(g_cpld.cpld); + g_cpld.cpld = NULL; + } + g_cpld.cpld_number = 0; + return; +} + +/* create cpld directory and number attributes */ +static int cpld_root_create(void) +{ + g_cpld_obj = switch_kobject_create("cpld", NULL); + if (!g_cpld_obj) { + CPLD_ERR("switch_kobject_create cpld error!\n"); + return -ENOMEM; + } + + if (sysfs_create_group(&g_cpld_obj->kobj, &cpld_root_attr_group) != 0) { + switch_kobject_delete(&g_cpld_obj); + CPLD_ERR("create cpld dir attrs error!\n"); + return -EBADRQC; + } + return 0; +} + +/* delete cpld directory and number attributes */ +static void cpld_root_remove(void) +{ + if (g_cpld_obj) { + sysfs_remove_group(&g_cpld_obj->kobj, &cpld_root_attr_group); + switch_kobject_delete(&g_cpld_obj); + } + + return; +} + +int s3ip_sysfs_cpld_drivers_register(struct s3ip_sysfs_cpld_drivers_s *drv) +{ + int ret, cpld_num; + + CPLD_INFO("s3ip_sysfs_cpld_drivers_register...\n"); + if (g_cpld_drv) { + CPLD_ERR("g_cpld_drv is not NULL, can't register\n"); + return -EPERM; + } + + check_p(drv); + check_p(drv->get_main_board_cpld_number); + g_cpld_drv = drv; + + cpld_num = g_cpld_drv->get_main_board_cpld_number(); + if (cpld_num <= 0) { + CPLD_ERR("cpld number: %d, don't need to create cpld dirs and attrs.\n", cpld_num); + g_cpld_drv = NULL; + return -EINVAL; + } + + memset(&g_cpld, 0, sizeof(struct cpld_s)); + g_cpld.cpld_number = cpld_num; + ret = cpld_root_create(); + if (ret < 0) { + CPLD_ERR("create cpld root dir and attrs failed, ret: %d\n", ret); + g_cpld_drv = NULL; + return ret; + } + ret = cpld_sub_create(); + if (ret < 0) { + CPLD_ERR("create cpld sub dir and attrs failed, ret: %d\n", ret); + cpld_root_remove(); + g_cpld_drv = NULL; + return ret; + } + CPLD_INFO("s3ip_sysfs_cpld_drivers_register success\n"); + return 0; +} + +void s3ip_sysfs_cpld_drivers_unregister(void) +{ + if (g_cpld_drv) { + cpld_sub_remove(); + cpld_root_remove(); + g_cpld_drv = NULL; + CPLD_DBG("s3ip_sysfs_cpld_drivers_unregister success.\n"); + } + return; +} + +EXPORT_SYMBOL(s3ip_sysfs_cpld_drivers_register); +EXPORT_SYMBOL(s3ip_sysfs_cpld_drivers_unregister); +module_param(g_cpld_loglevel, int, 0644); +MODULE_PARM_DESC(g_cpld_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n"); diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c b/platform/s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c new file mode 100644 index 000000000000..8fc5736c0154 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c @@ -0,0 +1,366 @@ +/* + * fpga_sysfs.c + * + * This module create fpga kobjects and attributes in /sys/s3ip/fpga + * + * History + * [Version] [Date] [Description] + * * v1.0 2021-08-31 S3IP sysfs + */ + +#include + +#include "switch.h" +#include "fpga_sysfs.h" + +static int g_fpga_loglevel = 0; + +#define FPGA_INFO(fmt, args...) do { \ + if (g_fpga_loglevel & INFO) { \ + printk(KERN_INFO "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define FPGA_ERR(fmt, args...) do { \ + if (g_fpga_loglevel & ERR) { \ + printk(KERN_ERR "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +#define FPGA_DBG(fmt, args...) do { \ + if (g_fpga_loglevel & DBG) { \ + printk(KERN_DEBUG "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \ + } \ +} while (0) + +struct fpga_obj_s { + struct switch_obj *obj; +}; + +struct fpga_s { + unsigned int fpga_number; + struct fpga_obj_s *fpga; +}; + +static struct fpga_s g_fpga; +static struct switch_obj *g_fpga_obj = NULL; +static struct s3ip_sysfs_fpga_drivers_s *g_fpga_drv = NULL; + +static ssize_t fpga_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_fpga.fpga_number); +} + +static ssize_t fpga_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int fpga_index; + int ret; + + check_p(g_fpga_drv); + check_p(g_fpga_drv->get_main_board_fpga_alias); + + fpga_index = obj->index; + FPGA_DBG("fpga index: %u\n", fpga_index); + ret = g_fpga_drv->get_main_board_fpga_alias(fpga_index, buf, PAGE_SIZE); + if (ret < 0) { + FPGA_ERR("get fpga%u alias failed, ret: %d\n", fpga_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t fpga_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int fpga_index; + int ret; + + check_p(g_fpga_drv); + check_p(g_fpga_drv->get_main_board_fpga_type); + + fpga_index = obj->index; + FPGA_DBG("fpga index: %u\n", fpga_index); + ret = g_fpga_drv->get_main_board_fpga_type(fpga_index, buf, PAGE_SIZE); + if (ret < 0) { + FPGA_ERR("get fpga%u type failed, ret: %d\n", fpga_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t fpga_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int fpga_index; + int ret; + + check_p(g_fpga_drv); + check_p(g_fpga_drv->get_main_board_fpga_firmware_version); + + fpga_index = obj->index; + FPGA_DBG("fpga index: %u\n", fpga_index); + ret = g_fpga_drv->get_main_board_fpga_firmware_version(fpga_index, buf, PAGE_SIZE); + if (ret < 0) { + FPGA_ERR("get fpga%u firmware version failed, ret: %d\n", fpga_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t fpga_board_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int fpga_index; + int ret; + + check_p(g_fpga_drv); + check_p(g_fpga_drv->get_main_board_fpga_board_version); + + fpga_index = obj->index; + FPGA_DBG("fpga index: %u\n", fpga_index); + ret = g_fpga_drv->get_main_board_fpga_board_version(fpga_index, buf, PAGE_SIZE); + if (ret < 0) { + FPGA_ERR("get fpga%u board version failed, ret: %d\n", fpga_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t fpga_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf) +{ + unsigned int fpga_index; + int ret; + + check_p(g_fpga_drv); + check_p(g_fpga_drv->get_main_board_fpga_test_reg); + + fpga_index = obj->index; + FPGA_DBG("fpga index: %u\n", fpga_index); + ret = g_fpga_drv->get_main_board_fpga_test_reg(fpga_index, buf, PAGE_SIZE); + if (ret < 0) { + FPGA_ERR("get fpga%u test register failed, ret: %d\n", fpga_index, ret); + return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR); + } + return ret; +} + +static ssize_t fpga_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr, + const char* buf, size_t count) +{ + unsigned int fpga_index, value; + int ret; + + check_p(g_fpga_drv); + check_p(g_fpga_drv->set_main_board_fpga_test_reg); + + fpga_index = obj->index; + sscanf(buf, "0x%x", &value); + ret = g_fpga_drv->set_main_board_fpga_test_reg(fpga_index, value); + if (ret < 0) { + FPGA_ERR("set fpga%u test reg failed, value:0x%x, ret: %d.\n", fpga_index, value, ret); + return -EIO; + } + FPGA_DBG("set fpga%u test reg success, value: 0x%x.\n", fpga_index, value); + return count; +} + +/************************************fpga dir and attrs*******************************************/ +static struct switch_attribute fpga_number_att = __ATTR(number, S_IRUGO, fpga_number_show, NULL); + +static struct attribute *fpga_dir_attrs[] = { + &fpga_number_att.attr, + NULL, +}; + +static struct attribute_group fpga_root_attr_group = { + .attrs = fpga_dir_attrs, +}; + +/*******************************fpga[1-n] dir and attrs*******************************************/ +static struct switch_attribute fpga_alias_attr = __ATTR(alias, S_IRUGO, fpga_alias_show, NULL); +static struct switch_attribute fpga_type_attr = __ATTR(type, S_IRUGO, fpga_type_show, NULL); +static struct switch_attribute fpga_fw_version_attr = __ATTR(firmware_version, S_IRUGO, fpga_fw_version_show, NULL); +static struct switch_attribute fpga_board_version_attr = __ATTR(board_version, S_IRUGO, fpga_board_version_show, NULL); +static struct switch_attribute fpga_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, fpga_test_reg_show, fpga_test_reg_store); + +static struct attribute *fpga_attrs[] = { + &fpga_alias_attr.attr, + &fpga_type_attr.attr, + &fpga_fw_version_attr.attr, + &fpga_board_version_attr.attr, + &fpga_test_reg_attr.attr, + NULL, +}; + +static struct attribute_group fpga_attr_group = { + .attrs = fpga_attrs, +}; + +static int fpga_sub_single_remove_kobj_and_attrs(unsigned int index) +{ + struct fpga_obj_s *curr_fpga; + + curr_fpga = &g_fpga.fpga[index - 1]; + if (curr_fpga->obj) { + sysfs_remove_group(&curr_fpga->obj->kobj, &fpga_attr_group); + switch_kobject_delete(&curr_fpga->obj); + FPGA_DBG("delete fpga%u dir and attrs success.\n", index); + } + return 0; +} + +static int fpga_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index) +{ + char name[8]; + struct fpga_obj_s *curr_fpga; + + curr_fpga = &g_fpga.fpga[index - 1]; + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name), "fpga%u", index); + curr_fpga->obj = switch_kobject_create(name, parent); + if (!curr_fpga->obj) { + FPGA_ERR("create %s object error!\n", name); + return -EBADRQC; + } + curr_fpga->obj->index = index; + if (sysfs_create_group(&curr_fpga->obj->kobj, &fpga_attr_group) != 0) { + FPGA_ERR("create %s attrs error.\n", name); + switch_kobject_delete(&curr_fpga->obj); + return -EBADRQC; + } + FPGA_DBG("create %s dir and attrs success.\n", name); + return 0; +} + +static int fpga_sub_create_kobj_and_attrs(struct kobject *parent, int fpga_num) +{ + unsigned int fpga_index, i; + + g_fpga.fpga = kzalloc(sizeof(struct fpga_obj_s) * fpga_num, GFP_KERNEL); + if (!g_fpga.fpga) { + FPGA_ERR("kzalloc g_fpga.fpga error, fpga number = %d.\n", fpga_num); + return -ENOMEM; + } + + for(fpga_index = 1; fpga_index <= fpga_num; fpga_index++) { + if(fpga_sub_single_create_kobj_and_attrs(parent, fpga_index) != 0 ) { + goto error; + } + } + return 0; +error: + for(i = fpga_index; i > 0; i--) { + fpga_sub_single_remove_kobj_and_attrs(i); + } + kfree(g_fpga.fpga); + g_fpga.fpga = NULL; + return -EBADRQC; +} + +/* create fpga[1-n] directory and attributes*/ +static int fpga_sub_create(void) +{ + int ret; + + ret = fpga_sub_create_kobj_and_attrs(&g_fpga_obj->kobj, g_fpga.fpga_number); + return ret; +} + +/* delete fpga[1-n] directory and attributes*/ +static void fpga_sub_remove(void) +{ + unsigned int fpga_index; + + if (g_fpga.fpga) { + for (fpga_index = g_fpga.fpga_number; fpga_index > 0; fpga_index--) { + fpga_sub_single_remove_kobj_and_attrs(fpga_index); + } + kfree(g_fpga.fpga); + g_fpga.fpga = NULL; + } + g_fpga.fpga_number = 0; + return; +} + +/* create fpga directory and number attributes */ +static int fpga_root_create(void) +{ + g_fpga_obj = switch_kobject_create("fpga", NULL); + if (!g_fpga_obj) { + FPGA_ERR("switch_kobject_create fpga error!\n"); + return -ENOMEM; + } + + if (sysfs_create_group(&g_fpga_obj->kobj, &fpga_root_attr_group) != 0) { + switch_kobject_delete(&g_fpga_obj); + FPGA_ERR("create fpga dir attrs error!\n"); + return -EBADRQC; + } + return 0; +} + +/* delete fpga directory and number attributes */ +static void fpga_root_remove(void) +{ + if (g_fpga_obj) { + sysfs_remove_group(&g_fpga_obj->kobj, &fpga_root_attr_group); + switch_kobject_delete(&g_fpga_obj); + } + + return; +} + +int s3ip_sysfs_fpga_drivers_register(struct s3ip_sysfs_fpga_drivers_s *drv) +{ + int ret, fpga_num; + + FPGA_INFO("s3ip_sysfs_fpga_drivers_register...\n"); + if (g_fpga_drv) { + FPGA_ERR("g_fpga_drv is not NULL, can't register\n"); + return -EPERM; + } + + check_p(drv); + check_p(drv->get_main_board_fpga_number); + g_fpga_drv = drv; + + fpga_num = g_fpga_drv->get_main_board_fpga_number(); + if (fpga_num <= 0) { + FPGA_ERR("fpga number: %d, don't need to create fpga dirs and attrs.\n", fpga_num); + g_fpga_drv = NULL; + return -EINVAL; + } + + memset(&g_fpga, 0, sizeof(struct fpga_s)); + g_fpga.fpga_number = fpga_num; + ret = fpga_root_create(); + if (ret < 0) { + FPGA_ERR("create fpga root dir and attrs failed, ret: %d\n", ret); + g_fpga_drv = NULL; + return ret; + } + ret = fpga_sub_create(); + if (ret < 0) { + FPGA_ERR("create fpga sub dir and attrs failed, ret: %d\n", ret); + fpga_root_remove(); + g_fpga_drv = NULL; + return ret; + } + FPGA_INFO("s3ip_sysfs_fpga_drivers_register success\n"); + return 0; +} + +void s3ip_sysfs_fpga_drivers_unregister(void) +{ + if (g_fpga_drv) { + fpga_sub_remove(); + fpga_root_remove(); + g_fpga_drv = NULL; + FPGA_DBG("s3ip_sysfs_fpga_drivers_unregister success.\n"); + } + + return; +} + +EXPORT_SYMBOL(s3ip_sysfs_fpga_drivers_register); +EXPORT_SYMBOL(s3ip_sysfs_fpga_drivers_unregister); +module_param(g_fpga_loglevel, int, 0644); +MODULE_PARM_DESC(g_fpga_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n"); + diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/cpld_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/cpld_sysfs.h new file mode 100644 index 000000000000..3d47a422ae01 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/cpld_sysfs.h @@ -0,0 +1,16 @@ +#ifndef _CPLD_SYSFS_H_ +#define _CPLD_SYSFS_H_ + +struct s3ip_sysfs_cpld_drivers_s { + int (*get_main_board_cpld_number)(void); + ssize_t (*get_main_board_cpld_alias)(unsigned int cpld_index, char *buf, size_t count); + ssize_t (*get_main_board_cpld_type)(unsigned int cpld_index, char *buf, size_t count); + ssize_t (*get_main_board_cpld_firmware_version)(unsigned int cpld_index, char *buf, size_t count); + ssize_t (*get_main_board_cpld_board_version)(unsigned int cpld_index, char *buf, size_t count); + ssize_t (*get_main_board_cpld_test_reg)(unsigned int cpld_index, char *buf, size_t count); + int (*set_main_board_cpld_test_reg)(unsigned int cpld_index, unsigned int value); +}; + +extern int s3ip_sysfs_cpld_drivers_register(struct s3ip_sysfs_cpld_drivers_s *drv); +extern void s3ip_sysfs_cpld_drivers_unregister(void); +#endif /*_CPLD_SYSFS_H_ */ diff --git a/platform/s3ip-sysfs/s3ip_sysfs_frame/include/fpga_sysfs.h b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/fpga_sysfs.h new file mode 100644 index 000000000000..c8a6935e4638 --- /dev/null +++ b/platform/s3ip-sysfs/s3ip_sysfs_frame/include/fpga_sysfs.h @@ -0,0 +1,16 @@ +#ifndef _FPGA_SYSFS_H_ +#define _FPGA_SYSFS_H_ + +struct s3ip_sysfs_fpga_drivers_s { + int (*get_main_board_fpga_number)(void); + ssize_t (*get_main_board_fpga_alias)(unsigned int fpga_index, char *buf, size_t count); + ssize_t (*get_main_board_fpga_type)(unsigned int fpga_index, char *buf, size_t count); + ssize_t (*get_main_board_fpga_firmware_version)(unsigned int fpga_index, char *buf, size_t count); + ssize_t (*get_main_board_fpga_board_version)(unsigned int fpga_index, char *buf, size_t count); + ssize_t (*get_main_board_fpga_test_reg)(unsigned int fpga_index, char *buf, size_t count); + int (*set_main_board_fpga_test_reg)(unsigned int fpga_index, unsigned int value); +}; + +extern int s3ip_sysfs_fpga_drivers_register(struct s3ip_sysfs_fpga_drivers_s *drv); +extern void s3ip_sysfs_fpga_drivers_unregister(void); +#endif /*_FPGA_SYSFS_H_ */