From f1753f8b17480bdb750cbd33fbaa358aef5dbb23 Mon Sep 17 00:00:00 2001 From: WenChen Date: Fri, 17 May 2024 15:05:19 +0800 Subject: [PATCH 1/6] urma: upload kernel patch for 20240219_Spring driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I91DSN CVE: NA -------------------------------- Upload kernel patch for 20240103_Happy_New_Year, detailed fixes are as follows: 1. Fix add sip netlink msg payload len problem 2. Replace client ctx and event handler lock with rwsem 3. Bug fix of use-after-free 4. Adjustment for kmod code check 5. Addition of debug info in data plane 6. Add ubcore device sysfs files 7. Fix dip table multi-thread problem Fixes: 329bf7f33128 ("ubcore: fix the bug of tp negotiation concurrency") Signed-off-by: WenChen Signed-off-by: Weibo Zhao --- drivers/ub/urma/ubcore/Makefile | 8 +- drivers/ub/urma/ubcore/ubcore_cdev_file.c | 902 ++++++++++++++ drivers/ub/urma/ubcore/ubcore_cdev_file.h | 56 + drivers/ub/urma/ubcore/ubcore_cgroup.c | 6 + drivers/ub/urma/ubcore/ubcore_cmd.h | 5 +- drivers/ub/urma/ubcore/ubcore_ctp.c | 4 +- drivers/ub/urma/ubcore/ubcore_device.c | 891 ++++++++++--- .../ubcore_device.h} | 43 +- drivers/ub/urma/ubcore/ubcore_genl.c | 123 ++ .../uburma_main.h => ubcore/ubcore_genl.h} | 21 +- drivers/ub/urma/ubcore/ubcore_genl_admin.c | 1047 ++++++++++++++++ drivers/ub/urma/ubcore/ubcore_genl_admin.h | 38 + drivers/ub/urma/ubcore/ubcore_genl_define.h | 41 + drivers/ub/urma/ubcore/ubcore_jetty.c | 189 +-- drivers/ub/urma/ubcore/ubcore_log.c | 24 + drivers/ub/urma/ubcore/ubcore_log.h | 39 +- drivers/ub/urma/ubcore/ubcore_main.c | 987 +++++---------- drivers/ub/urma/ubcore/ubcore_msg.c | 78 +- drivers/ub/urma/ubcore/ubcore_netdev.c | 23 +- drivers/ub/urma/ubcore/ubcore_netdev.h | 5 - drivers/ub/urma/ubcore/ubcore_netlink.c | 29 +- drivers/ub/urma/ubcore/ubcore_netlink.h | 5 +- drivers/ub/urma/ubcore/ubcore_priv.h | 17 +- drivers/ub/urma/ubcore/ubcore_segment.c | 43 +- drivers/ub/urma/ubcore/ubcore_tp.c | 122 +- drivers/ub/urma/ubcore/ubcore_tp.h | 4 +- drivers/ub/urma/ubcore/ubcore_tpg.c | 10 +- drivers/ub/urma/ubcore/ubcore_umem.c | 16 +- drivers/ub/urma/ubcore/ubcore_utp.c | 3 +- drivers/ub/urma/ubcore/ubcore_uvs_cmd.c | 330 ++++- drivers/ub/urma/ubcore/ubcore_uvs_cmd.h | 54 + drivers/ub/urma/ubcore/ubcore_vtp.c | 274 +++- drivers/ub/urma/ubcore/ubcore_vtp.h | 15 + drivers/ub/urma/ubcore/ubcore_workqueue.c | 78 ++ drivers/ub/urma/ubcore/ubcore_workqueue.h | 44 + drivers/ub/urma/uburma/Makefile | 3 +- drivers/ub/urma/uburma/uburma_cdev_file.c | 1107 ----------------- drivers/ub/urma/uburma/uburma_cdev_file.h | 76 -- drivers/ub/urma/uburma/uburma_cmd.c | 30 +- drivers/ub/urma/uburma/uburma_dev_ops.c | 9 +- drivers/ub/urma/uburma/uburma_event.c | 2 +- drivers/ub/urma/uburma/uburma_log.c | 24 + drivers/ub/urma/uburma/uburma_log.h | 39 +- drivers/ub/urma/uburma/uburma_main.c | 558 +-------- drivers/ub/urma/uburma/uburma_netlink.c | 133 -- drivers/ub/urma/uburma/uburma_types.h | 35 +- drivers/ub/urma/uburma/uburma_uobj.c | 3 +- drivers/ub/urma/uburma/uburma_uobj.h | 2 +- include/urma/ubcore_types.h | 56 +- include/urma/ubcore_uapi.h | 10 +- include/urma/uboib_user_ctl.h | 116 -- 51 files changed, 4587 insertions(+), 3190 deletions(-) create mode 100644 drivers/ub/urma/ubcore/ubcore_cdev_file.c create mode 100644 drivers/ub/urma/ubcore/ubcore_cdev_file.h rename drivers/ub/urma/{uburma/uburma_netlink.h => ubcore/ubcore_device.h} (47%) create mode 100644 drivers/ub/urma/ubcore/ubcore_genl.c rename drivers/ub/urma/{uburma/uburma_main.h => ubcore/ubcore_genl.h} (55%) create mode 100644 drivers/ub/urma/ubcore/ubcore_genl_admin.c create mode 100644 drivers/ub/urma/ubcore/ubcore_genl_admin.h create mode 100644 drivers/ub/urma/ubcore/ubcore_genl_define.h create mode 100644 drivers/ub/urma/ubcore/ubcore_log.c create mode 100644 drivers/ub/urma/ubcore/ubcore_workqueue.c create mode 100644 drivers/ub/urma/ubcore/ubcore_workqueue.h delete mode 100644 drivers/ub/urma/uburma/uburma_cdev_file.c delete mode 100644 drivers/ub/urma/uburma/uburma_cdev_file.h create mode 100644 drivers/ub/urma/uburma/uburma_log.c delete mode 100644 drivers/ub/urma/uburma/uburma_netlink.c delete mode 100644 include/urma/uboib_user_ctl.h diff --git a/drivers/ub/urma/ubcore/Makefile b/drivers/ub/urma/ubcore/Makefile index 5806ca76cdf2..fe16b6f91532 100644 --- a/drivers/ub/urma/ubcore/Makefile +++ b/drivers/ub/urma/ubcore/Makefile @@ -20,6 +20,10 @@ ubcore-objs := ubcore_main.o \ ubcore_utp.o \ ubcore_uvs_cmd.o \ ubcore_vtp.o \ - ubcore_cgroup.o - + ubcore_cgroup.o \ + ubcore_cdev_file.o \ + ubcore_genl_admin.o \ + ubcore_genl.o \ + ubcore_log.o \ + ubcore_workqueue.o obj-$(CONFIG_UB) += ubcore.o diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.c b/drivers/ub/urma/ubcore/ubcore_cdev_file.c new file mode 100644 index 000000000000..5f8815f585ca --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.c @@ -0,0 +1,902 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore cdev file + * Author: Qian Guoxin + * Create: 2024-02-05 + * Note: + * History: 2024-02-05: Create file + */ + +#include +#include +#include + +#include "urma/ubcore_types.h" +#include "urma/ubcore_uapi.h" + +#include "ubcore_log.h" +#include "ubcore_cdev_file.h" + +#define UBCORE_MAX_VALUE_LEN 24 + +/* callback information */ +typedef ssize_t (*ubcore_show_attr_cb)(struct ubcore_device *dev, + char *buf); +typedef ssize_t (*ubcore_store_attr_cb)(struct ubcore_device *dev, + const char *buf, size_t len); +typedef ssize_t (*ubcore_show_port_attr_cb)(struct ubcore_device *dev, + char *buf, uint8_t port_id); +typedef ssize_t (*ubcore_show_eid_attr_cb)(struct ubcore_device *dev, + char *buf, uint16_t idx, struct net *net); + +static inline struct ubcore_device *get_ubcore_device(struct ubcore_logic_device *ldev) +{ + return ldev == NULL ? NULL : ldev->ub_dev; +} + +static ssize_t ubcore_show_dev_attr(struct device *dev, struct device_attribute *attr, + char *buf, ubcore_show_attr_cb show_cb) +{ + struct ubcore_logic_device *ldev = dev_get_drvdata(dev); + struct ubcore_device *ub_dev = get_ubcore_device(ldev); + + if (!ldev || !ub_dev || !buf) { + ubcore_log_err("Invalid argument.\n"); + return -EINVAL; + } + + return show_cb(ub_dev, buf); +} + +static ssize_t ubcore_store_dev_attr(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len, ubcore_store_attr_cb store_cb) +{ + struct ubcore_logic_device *ldev = dev_get_drvdata(dev); + struct ubcore_device *ub_dev = get_ubcore_device(ldev); + + if (!ldev || !ub_dev || !buf) { + ubcore_log_err("Invalid argument.\n"); + return -EINVAL; + } + + return store_cb(ub_dev, buf, len); +} + +/* interface for exporting device attributes */ +static ssize_t ubdev_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_DEV_NAME, "%s\n", dev->dev_name); +} + +static ssize_t ubdev_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, ubdev_show_cb); +} + +static DEVICE_ATTR_RO(ubdev); + +static ssize_t guid_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", + EID_ARGS(dev->attr.guid)); // The format of GUID is the same as EID. +} + +static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, guid_show_cb); +} + +static DEVICE_ATTR_RO(guid); + +static ssize_t max_upi_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_upi_cnt); +} + +static ssize_t max_upi_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_upi_cnt_show_cb); +} + +static DEVICE_ATTR_RO(max_upi_cnt); + + +static ssize_t feature_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "0x%x\n", dev->attr.dev_cap.feature.value); +} + +static ssize_t feature_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, feature_show_cb); +} + +static DEVICE_ATTR_RO(feature); + +static ssize_t max_jfc_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfc); +} + +static ssize_t max_jfc_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfc_show_cb); +} + +static DEVICE_ATTR_RO(max_jfc); + +static ssize_t max_jfs_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfs); +} + +static ssize_t max_jfs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfs_show_cb); +} + +static DEVICE_ATTR_RO(max_jfs); + +static ssize_t max_jfr_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfr); +} + +static ssize_t max_jfr_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfr_show_cb); +} + +static DEVICE_ATTR_RO(max_jfr); + +static ssize_t max_jetty_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jetty); +} + +static ssize_t max_jetty_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jetty_show_cb); +} + +static DEVICE_ATTR_RO(max_jetty); + +static ssize_t show_max_jetty_grp_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jetty_grp); +} +static ssize_t max_jetty_grp_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_max_jetty_grp_cb); +} +static DEVICE_ATTR_RO(max_jetty_grp); + +static ssize_t show_max_jetty_in_jetty_grp_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf( + buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jetty_in_jetty_grp); +} +static ssize_t max_jetty_in_jetty_grp_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_max_jetty_in_jetty_grp_cb); +} +static DEVICE_ATTR_RO(max_jetty_in_jetty_grp); + +static ssize_t max_jfc_depth_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfc_depth); +} + +static ssize_t max_jfc_depth_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfc_depth_show_cb); +} + +static DEVICE_ATTR_RO(max_jfc_depth); + +static ssize_t max_jfs_depth_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfs_depth); +} + +static ssize_t max_jfs_depth_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfs_depth_show_cb); +} + +static DEVICE_ATTR_RO(max_jfs_depth); + +static ssize_t max_jfr_depth_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfr_depth); +} + +static ssize_t max_jfr_depth_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfr_depth_show_cb); +} + +static DEVICE_ATTR_RO(max_jfr_depth); + +static ssize_t show_max_jfs_inline_size_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfs_inline_size); +} + +static ssize_t max_jfs_inline_size_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_max_jfs_inline_size_cb); +} + +static DEVICE_ATTR_RO(max_jfs_inline_size); + +static ssize_t max_jfs_sge_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfs_sge); +} + +static ssize_t max_jfs_sge_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfs_sge_show_cb); +} + +static DEVICE_ATTR_RO(max_jfs_sge); + +static ssize_t max_jfs_rsge_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfs_rsge); +} + +static ssize_t max_jfs_rsge_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfs_rsge_show_cb); +} + +static DEVICE_ATTR_RO(max_jfs_rsge); + +static ssize_t max_jfr_sge_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_jfr_sge); +} + +static ssize_t max_jfr_sge_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_jfr_sge_show_cb); +} + +static DEVICE_ATTR_RO(max_jfr_sge); + +static ssize_t max_msg_size_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%llu\n", dev->attr.dev_cap.max_msg_size); +} + +static ssize_t max_msg_size_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_msg_size_show_cb); +} + +static DEVICE_ATTR_RO(max_msg_size); + +static ssize_t show_max_atomic_size_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_atomic_size); +} +static ssize_t max_atomic_size_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_max_atomic_size_cb); +} +static DEVICE_ATTR_RO(max_atomic_size); + +static ssize_t show_atomic_feat_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.atomic_feat.value); +} +static ssize_t atomic_feat_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_atomic_feat_cb); +} +static DEVICE_ATTR_RO(atomic_feat); + +static ssize_t max_rc_outstd_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%llu\n", dev->attr.dev_cap.max_rc_outstd_cnt); +} + +static ssize_t max_rc_outstd_cnt_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_rc_outstd_cnt_show_cb); +} + +static DEVICE_ATTR_RO(max_rc_outstd_cnt); + +static ssize_t trans_mode_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.trans_mode); +} + +static ssize_t trans_mode_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, trans_mode_show_cb); +} + +static DEVICE_ATTR_RO(trans_mode); + +static ssize_t congestion_ctrl_alg_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.congestion_ctrl_alg); +} + +static ssize_t congestion_ctrl_alg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, congestion_ctrl_alg_show_cb); +} + +static ssize_t congestion_ctrl_alg_store_cb(struct ubcore_device *dev, const char *buf, + size_t len) +{ + uint16_t value; + int ret; + + ret = kstrtou16(buf, 0, &value); + if (ret != 0) + return -EINVAL; + + dev->attr.dev_cap.congestion_ctrl_alg = value; + return (ssize_t)len; +} + +static ssize_t congestion_ctrl_alg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + return ubcore_store_dev_attr(dev, attr, buf, len, congestion_ctrl_alg_store_cb); +} + +static DEVICE_ATTR_RW(congestion_ctrl_alg); // 0644 + +static ssize_t ceq_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.ceq_cnt); +} + +static ssize_t ceq_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, ceq_cnt_show_cb); +} + +static DEVICE_ATTR_RO(ceq_cnt); + +static ssize_t utp_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.utp_cnt); +} + +static ssize_t utp_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, utp_cnt_show_cb); +} + +static DEVICE_ATTR_RO(utp_cnt); + +static ssize_t max_tp_in_tpg_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_tp_in_tpg); +} + +static ssize_t max_tp_in_tpg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_tp_in_tpg_show_cb); +} + +static DEVICE_ATTR_RO(max_tp_in_tpg); + +static ssize_t port_count_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.port_cnt); +} + +static ssize_t port_count_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, port_count_show_cb); +} + +static DEVICE_ATTR_RO(port_count); + +static ssize_t virtualization_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf( + buf, UBCORE_MAX_VALUE_LEN, "%s\n", dev->attr.virtualization ? "true" : "false"); +} +static ssize_t virtualization_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, virtualization_show_cb); +} +static DEVICE_ATTR_RO(virtualization); + +static ssize_t show_fe_cnt_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_fe_cnt); +} +static ssize_t fe_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_fe_cnt_cb); +} +static DEVICE_ATTR_RO(fe_cnt); + +static ssize_t show_dynamic_eid_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%d\n", dev->dynamic_eid); +} +static ssize_t dynamic_eid_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_dynamic_eid_cb); +} +static DEVICE_ATTR_RO(dynamic_eid); + +static ssize_t max_eid_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_eid_cnt); +} + +static ssize_t max_eid_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_eid_cnt_show_cb); +} + +static DEVICE_ATTR_RO(max_eid_cnt); + +static ssize_t transport_type_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%d\n", (int)dev->transport_type); +} + +static ssize_t transport_type_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, transport_type_show_cb); +} + +static DEVICE_ATTR_RO(transport_type); + +static ssize_t driver_name_show_cb(struct ubcore_device *dev, char *buf) +{ + if (dev->ops == NULL) + return -EINVAL; + + return snprintf(buf, UBCORE_MAX_DRIVER_NAME, "%s\n", dev->ops->driver_name); +} + +static ssize_t driver_name_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, driver_name_show_cb); +} + +static DEVICE_ATTR_RO(driver_name); + +static struct attribute *ubcore_dev_attrs[] = { + &dev_attr_ubdev.attr, + &dev_attr_guid.attr, + &dev_attr_max_upi_cnt.attr, + &dev_attr_feature.attr, + &dev_attr_max_jfc.attr, + &dev_attr_max_jfs.attr, + &dev_attr_max_jfr.attr, + &dev_attr_max_jetty.attr, + &dev_attr_max_jetty_grp.attr, + &dev_attr_max_jetty_in_jetty_grp.attr, + &dev_attr_max_jfc_depth.attr, + &dev_attr_max_jfs_depth.attr, + &dev_attr_max_jfr_depth.attr, + &dev_attr_max_jfs_inline_size.attr, + &dev_attr_max_jfs_sge.attr, + &dev_attr_max_jfs_rsge.attr, + &dev_attr_max_jfr_sge.attr, + &dev_attr_max_msg_size.attr, + &dev_attr_max_atomic_size.attr, + &dev_attr_atomic_feat.attr, + &dev_attr_max_rc_outstd_cnt.attr, + &dev_attr_trans_mode.attr, + &dev_attr_congestion_ctrl_alg.attr, + &dev_attr_ceq_cnt.attr, + &dev_attr_utp_cnt.attr, + &dev_attr_max_tp_in_tpg.attr, + &dev_attr_port_count.attr, + &dev_attr_fe_cnt.attr, + &dev_attr_max_eid_cnt.attr, + &dev_attr_dynamic_eid.attr, + &dev_attr_virtualization.attr, + &dev_attr_transport_type.attr, + &dev_attr_driver_name.attr, + NULL, +}; + +static const struct attribute_group ubcore_dev_attr_group = { + .attrs = ubcore_dev_attrs, +}; + +static ssize_t ubcore_show_port_attr( + struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, + char *buf, ubcore_show_port_attr_cb show_cb) +{ + struct ubcore_device *dev = p->dev; + + if (!dev || !buf) { + ubcore_log_err("Invalid argument.\n"); + return -EINVAL; + } + + return show_cb(dev, buf, p->port_id); +} + +static ssize_t max_mtu_show_cb(struct ubcore_device *dev, char *buf, uint8_t port_id) +{ + return snprintf( + buf, UBCORE_MAX_VALUE_LEN, "%d\n", (int)dev->attr.port_attr[port_id].max_mtu); +} + +static ssize_t max_mtu_show(struct ubcore_port_kobj *p, + struct ubcore_port_attribute *attr, char *buf) +{ + return ubcore_show_port_attr(p, attr, buf, max_mtu_show_cb); +} + +static PORT_ATTR_RO(max_mtu); + +static ssize_t state_show_cb(struct ubcore_device *dev, char *buf, uint8_t port_id) +{ + struct ubcore_device_status status; + + if (ubcore_query_device_status(dev, &status) != 0) { + ubcore_log_err("query device status for state failed.\n"); + return -EPERM; + } + + return snprintf( + buf, UBCORE_MAX_VALUE_LEN, "%u\n", (uint32_t)status.port_status[port_id].state); +} + +static ssize_t state_show( + struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, char *buf) +{ + return ubcore_show_port_attr(p, attr, buf, state_show_cb); +} + +static PORT_ATTR_RO(state); + +static ssize_t active_speed_show_cb(struct ubcore_device *dev, char *buf, + uint8_t port_id) +{ + struct ubcore_device_status status; + + if (ubcore_query_device_status(dev, &status) != 0) { + ubcore_log_err("query device status for active speed failed.\n"); + return -EPERM; + } + + return snprintf( + buf, UBCORE_MAX_VALUE_LEN, "%u\n", status.port_status[port_id].active_speed); +} + +static ssize_t active_speed_show(struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, + char *buf) +{ + return ubcore_show_port_attr(p, attr, buf, active_speed_show_cb); +} + +static PORT_ATTR_RO(active_speed); + +static ssize_t active_width_show_cb(struct ubcore_device *dev, char *buf, + uint8_t port_id) +{ + struct ubcore_device_status status; + + if (ubcore_query_device_status(dev, &status) != 0) { + ubcore_log_err("query device status for active width failed.\n"); + return -EPERM; + } + + return snprintf( + buf, UBCORE_MAX_VALUE_LEN, "%u\n", status.port_status[port_id].active_width); +} + +static ssize_t active_width_show(struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, + char *buf) +{ + return ubcore_show_port_attr(p, attr, buf, active_width_show_cb); +} + +static PORT_ATTR_RO(active_width); + +static ssize_t active_mtu_show_cb(struct ubcore_device *dev, char *buf, uint8_t port_id) +{ + struct ubcore_device_status status; + + if (ubcore_query_device_status(dev, &status) != 0) { + ubcore_log_err("query device status for active mtu failed.\n"); + return -EPERM; + } + + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", + (uint32_t)status.port_status[port_id].active_mtu); +} + +static ssize_t active_mtu_show(struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, + char *buf) +{ + return ubcore_show_port_attr(p, attr, buf, active_mtu_show_cb); +} + +static PORT_ATTR_RO(active_mtu); + +static struct attribute *ubcore_port_attrs[] = { + &port_attr_max_mtu.attr, &port_attr_state.attr, &port_attr_active_speed.attr, + &port_attr_active_width.attr, &port_attr_active_mtu.attr, NULL, +}; + +static ssize_t ubcore_port_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct ubcore_port_attribute *port_attr = + container_of(attr, struct ubcore_port_attribute, attr); + struct ubcore_port_kobj *p = container_of(kobj, struct ubcore_port_kobj, kobj); + + if (!port_attr->show) + return -EIO; + + return port_attr->show(p, port_attr, buf); +} + +static ssize_t ubcore_port_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct ubcore_port_attribute *port_attr = + container_of(attr, struct ubcore_port_attribute, attr); + struct ubcore_port_kobj *p = container_of(kobj, struct ubcore_port_kobj, kobj); + + if (!port_attr->store) + return -EIO; + + return port_attr->store(p, port_attr, buf, count); +} + +static const struct sysfs_ops ubcore_port_sysfs_ops = { .show = ubcore_port_attr_show, + .store = ubcore_port_attr_store }; + +static void ubcore_port_release(struct kobject *kobj) +{ +} + +// ATTRIBUTE_GROUPS defined in 3.11, but must be consistent with kobj_type->default_groups +ATTRIBUTE_GROUPS(ubcore_port); + +static struct kobj_type ubcore_port_type = { .release = ubcore_port_release, + .sysfs_ops = &ubcore_port_sysfs_ops, + .default_groups = ubcore_port_groups +}; + +int ubcore_create_port_attr_files(struct ubcore_logic_device *ldev, + struct ubcore_device *dev, uint8_t port_id) +{ + struct ubcore_port_kobj *p; + + p = &ldev->port[port_id]; + p->dev = dev; + p->port_id = port_id; + + return kobject_init_and_add(&p->kobj, &ubcore_port_type, &ldev->dev->kobj, + "port%hhu", port_id); +} + +static ssize_t ubcore_show_eid_attr(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, + char *buf, ubcore_show_eid_attr_cb show_cb) +{ + struct ubcore_logic_device *ldev = eid->ldev; + struct ubcore_device *dev = get_ubcore_device(ldev); + + if (!ldev || !dev) { + ubcore_log_err("Invalid argument in show_fe_attr.\n"); + return -EINVAL; + } + + return show_cb(dev, buf, eid->eid_idx, read_pnet(&ldev->net)); +} + +static ssize_t show_eid_cb(struct ubcore_device *dev, char *buf, uint16_t idx, struct net *net) +{ + union ubcore_eid eid; + + if (net_eq(dev->eid_table.eid_entries[idx].net, net)) { + return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", + EID_ARGS(dev->eid_table.eid_entries[idx].eid)); + } else { + memset(&eid, 0, sizeof(union ubcore_eid)); + return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", + EID_ARGS(eid)); + } +} + +static ssize_t eid_show(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, char *buf) +{ + return ubcore_show_eid_attr(eid, attr, buf, show_eid_cb); +} + +static EID_ATTR_RO(eid); + +static struct attribute *ubcore_eid_attrs[] = { + &eid_attr_eid.attr, + NULL, +}; + +static ssize_t ubcore_eid_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct ubcore_eid_attribute *eid_attr = + container_of(attr, struct ubcore_eid_attribute, attr); + struct ubcore_eid_kobj *eid = container_of(kobj, struct ubcore_eid_kobj, kobj); + + if (!eid_attr->show) + return -EIO; + + return eid_attr->show(eid, eid_attr, buf); +} + +static ssize_t ubcore_eid_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct ubcore_eid_attribute *eid_attr = + container_of(attr, struct ubcore_eid_attribute, attr); + struct ubcore_eid_kobj *eid = container_of(kobj, struct ubcore_eid_kobj, kobj); + + if (!eid_attr->store) + return -EIO; + return eid_attr->store(eid, eid_attr, buf, count); +} + +static const struct sysfs_ops ubcore_eid_sysfs_ops = { + .show = ubcore_eid_attr_show, + .store = ubcore_eid_attr_store +}; + +static void ubcore_eid_release(struct kobject *kobj) +{ +} + +// ATTRIBUTE_GROUPS defined in 3.11, but must be consistent with kobj_type->default_groups +ATTRIBUTE_GROUPS(ubcore_eid); + +static struct kobj_type ubcore_eid_type = { + .release = ubcore_eid_release, + .sysfs_ops = &ubcore_eid_sysfs_ops, + .default_groups = ubcore_eid_groups +}; + +int ubcore_create_eid_attr_files(struct ubcore_logic_device *ldev, uint32_t eid_num) +{ + struct ubcore_eid_kobj *eid; + + eid = &ldev->eid[eid_num]; + eid->ldev = ldev; + eid->eid_idx = eid_num; + + return kobject_init_and_add(&eid->kobj, &ubcore_eid_type, &ldev->dev->kobj, + "eid%u", eid_num); +} + +int ubcore_create_dev_attr_files(struct ubcore_logic_device *ldev) +{ + int ret; + + ret = sysfs_create_group(&ldev->dev->kobj, &ubcore_dev_attr_group); + if (ret != 0) { + ubcore_log_err("sysfs create group failed, ret:%d.\n", ret); + return -1; + } + + return 0; +} + +void ubcore_remove_port_attr_files(struct ubcore_logic_device *ldev, uint8_t port_id) +{ + kobject_put(&ldev->port[port_id].kobj); +} + +void ubcore_remove_eid_attr_files(struct ubcore_logic_device *ldev, uint32_t eid_num) +{ + kobject_put(&ldev->eid[eid_num].kobj); +} + +void ubcore_remove_dev_attr_files(struct ubcore_logic_device *ldev) +{ + sysfs_remove_group(&ldev->dev->kobj, &ubcore_dev_attr_group); +} + +static int ubcore_create_eid_table(struct ubcore_logic_device *ldev, struct ubcore_device *dev) +{ + struct ubcore_eid_kobj *eid_list; + + eid_list = kcalloc( + 1, dev->attr.dev_cap.max_eid_cnt * sizeof(struct ubcore_eid_kobj), GFP_ATOMIC); + if (eid_list == NULL) + return -ENOMEM; + + ldev->eid = eid_list; + return 0; +} + +static void ubcore_destroy_eid_table(struct ubcore_logic_device *ldev) +{ + if (ldev->eid != NULL) { + kfree(ldev->eid); + ldev->eid = NULL; + } +} + +int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, + struct ubcore_device *dev) +{ + uint32_t e1, e2; /* eid */ + uint8_t p1, p2; /* port */ + + if (ubcore_create_dev_attr_files(ldev) != 0) { + ubcore_log_err("failed to fill attributes, device:%s.\n", dev->dev_name); + return -EPERM; + } + + /* create /sys/class/ubcore/dev_name>/port* */ + for (p1 = 0; p1 < dev->attr.port_cnt; p1++) { + if (ubcore_create_port_attr_files(ldev, dev, p1) != 0) + goto err_port_attr; + } + + /* create /sys/class/ubcore/dev_name>/eid* */ + if (ubcore_create_eid_table(ldev, dev) != 0) + goto err_port_attr; + + for (e1 = 0; e1 < dev->attr.dev_cap.max_eid_cnt; e1++) { + if (ubcore_create_eid_attr_files(ldev, e1) != 0) + goto err_eid_attr; + } + return 0; + +err_eid_attr: + for (e2 = 0; e2 < e1; e2++) + ubcore_remove_eid_attr_files(ldev, e2); + + ubcore_destroy_eid_table(ldev); + +err_port_attr: + for (p2 = 0; p2 < p1; p2++) + ubcore_remove_port_attr_files(ldev, p2); + + ubcore_remove_dev_attr_files(ldev); + return -EPERM; +} + +void ubcore_unfill_logic_device_attr(struct ubcore_logic_device *ldev, + struct ubcore_device *dev) +{ + uint32_t e; + uint8_t p; + + for (e = 0; e < dev->attr.dev_cap.max_eid_cnt; e++) + ubcore_remove_eid_attr_files(ldev, e); + + ubcore_destroy_eid_table(ldev); + + for (p = 0; p < dev->attr.port_cnt; p++) + ubcore_remove_port_attr_files(ldev, p); + + ubcore_remove_dev_attr_files(ldev); +} diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.h b/drivers/ub/urma/ubcore/ubcore_cdev_file.h new file mode 100644 index 000000000000..eaa63c659d12 --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore device file ops file + * Author: Qian Guoxin + * Create: 2024-02-05 + * Note: + * History: 2024-02-05: Create file + */ + +#ifndef UBCORE_CDEV_FILE_H +#define UBCORE_CDEV_FILE_H + +#include "urma/ubcore_types.h" + +struct ubcore_port_attribute { + struct attribute attr; + ssize_t (*show)(struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, char *buf); + ssize_t (*store)(struct ubcore_port_kobj *p, struct ubcore_port_attribute *attr, + const char *buf, size_t count); +}; + +#define PORT_ATTR(_name, _mode, _show, _store) \ + struct ubcore_port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store) + +#define PORT_ATTR_RO(_name) struct ubcore_port_attribute port_attr_##_name = __ATTR_RO(_name) + +struct ubcore_eid_attribute { + struct attribute attr; + ssize_t (*show)(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, char *buf); + ssize_t (*store)(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, + const char *buf, size_t count); +}; + +#define EID_ATTR(_name, _mode, _show, _store) \ +struct ubcore_eid_attribute eid_attr_##_name = __ATTR(_name, _mode, _show, _store) + +#define EID_ATTR_RO(_name) \ +struct ubcore_eid_attribute eid_attr_##_name = __ATTR_RO(_name) + +int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, + struct ubcore_device *dev); +void ubcore_unfill_logic_device_attr(struct ubcore_logic_device *ldev, + struct ubcore_device *dev); + +#endif /* UBCORE_CDEV_FILE_H */ diff --git a/drivers/ub/urma/ubcore/ubcore_cgroup.c b/drivers/ub/urma/ubcore/ubcore_cgroup.c index 1963f775cf2c..f5cac5c2fa44 100644 --- a/drivers/ub/urma/ubcore/ubcore_cgroup.c +++ b/drivers/ub/urma/ubcore/ubcore_cgroup.c @@ -68,6 +68,9 @@ int ubcore_cgroup_try_charge(struct ubcore_cg_object *cg_obj, struct ubcore_devi { enum rdmacg_resource_type rdma_cg_type; + if (cg_obj == NULL || cg_obj->cg == NULL) + return 0; + if (!ubcore_is_use_cg(dev)) return 0; @@ -84,6 +87,9 @@ void ubcore_cgroup_uncharge(struct ubcore_cg_object *cg_obj, struct ubcore_devic { enum rdmacg_resource_type rdma_cg_type; + if (cg_obj == NULL || cg_obj->cg == NULL) + return; + if (!ubcore_is_use_cg(dev)) return; diff --git a/drivers/ub/urma/ubcore/ubcore_cmd.h b/drivers/ub/urma/ubcore/ubcore_cmd.h index 31070b0f960f..24d3f44d3b0f 100644 --- a/drivers/ub/urma/ubcore/ubcore_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_cmd.h @@ -45,7 +45,10 @@ enum ubcore_cmd { UBCORE_CMD_QUERY_RES, UBCORE_CMD_ADD_EID, UBCORE_CMD_DEL_EID, - UBCORE_CMD_SET_EID_MODE + UBCORE_CMD_SET_EID_MODE, + UBCORE_CMD_SET_NS_MODE, + UBCORE_CMD_SET_DEV_NS, + UBCORE_CMD_MAX }; struct ubcore_cmd_query_stats { diff --git a/drivers/ub/urma/ubcore/ubcore_ctp.c b/drivers/ub/urma/ubcore/ubcore_ctp.c index 82e2bd26fef0..28075c212c30 100644 --- a/drivers/ub/urma/ubcore/ubcore_ctp.c +++ b/drivers/ub/urma/ubcore/ubcore_ctp.c @@ -28,7 +28,7 @@ struct ubcore_ctp *ubcore_create_ctp(struct ubcore_device *dev, struct ubcore_ct struct ubcore_ctp *ctp; int ret; - if (dev->ops == NULL || dev->ops->create_ctp == NULL) + if (dev == NULL || dev->ops == NULL || dev->ops->create_ctp == NULL) return NULL; ctp = dev->ops->create_ctp(dev, cfg, NULL); @@ -58,7 +58,7 @@ int ubcore_destroy_ctp(struct ubcore_ctp *ctp) uint32_t ctp_idx = ctp->ctpn; int ret; - if (dev->ops == NULL || dev->ops->destroy_ctp == NULL) + if (dev == NULL || dev->ops == NULL || dev->ops->destroy_ctp == NULL) return -EINVAL; if (atomic_dec_return(&ctp->use_cnt) > 0) { diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index ced2ec0cfbd1..bed9d45c0e5f 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -18,6 +18,8 @@ * History: 2021-08-03: create file */ +#include +#include #include #include #include @@ -28,7 +30,9 @@ #include #include #include +#include +#include "urma/ubcore_types.h" #include "ubcore_log.h" #include #include @@ -40,36 +44,89 @@ #include "ubcore_netdev.h" #include "ubcore_vtp.h" #include "ubcore_netlink.h" +#include "ubcore_workqueue.h" +#include "ubcore_cdev_file.h" +#include "ubcore_device.h" static LIST_HEAD(g_client_list); static LIST_HEAD(g_device_list); /* - * g_device_mutex and g_lists_rwsem protect both g_device_list and g_client_list. - * g_device_mutex protects writer access by device and client - * g_lists_rwsem protects reader access to these lists. - * Iterators of these lists must lock it for read, while updates - * to the lists must be done with a write lock. + * g_device_mutex protects writer access by device */ static DEFINE_MUTEX(g_device_mutex); -static DECLARE_RWSEM(g_lists_rwsem); + +/* + * g_clients_rwsem protect g_client_list. + */ +static DECLARE_RWSEM(g_clients_rwsem); static struct ubcore_device *g_tpf; static DEFINE_MUTEX(g_upi_lock); static LIST_HEAD(g_upi_list); +static unsigned int g_ubcore_net_id; +static LIST_HEAD(g_ubcore_net_list); +static DEFINE_SPINLOCK(g_ubcore_net_lock); +static DECLARE_RWSEM(g_ubcore_net_rwsem); + +static bool g_shared_ns = true; + +static const void *ubcore_net_namespace(struct device *dev) +{ + struct ubcore_logic_device *ldev = dev_get_drvdata(dev); + struct ubcore_device *ubc_dev; + + if (ldev == NULL || ldev->ub_dev == NULL) { + ubcore_log_info("init net %p", ldev); + return &init_net; + } + + ubc_dev = ldev->ub_dev; + if (ubc_dev->transport_type == UBCORE_TRANSPORT_UB) { + return read_pnet(&ldev->net); + } else if (ubc_dev->transport_type == UBCORE_TRANSPORT_IP) { + if (ubc_dev->netdev) + return dev_net(ubc_dev->netdev); + else + return &init_net; + } else { /* URMA IB device not support namespace yet */ + return &init_net; + } +} + +static struct class g_ubcore_class = { + .name = "ubcore", + .ns_type = &net_ns_type_operations, + .namespace = ubcore_net_namespace +}; + +struct ubcore_net { + possible_net_t net; + struct list_head node; +}; + struct ubcore_upi_entry { struct ubcore_device *dev; uint32_t upi; struct list_head node; }; +struct ubcore_event_work { + struct work_struct work; + struct ubcore_event event; +}; + void ubcore_set_client_ctx_data(struct ubcore_device *dev, struct ubcore_client *client, void *data) { struct ubcore_client_ctx *ctx; - unsigned long flags; - spin_lock_irqsave(&dev->client_ctx_lock, flags); + if (dev == NULL || client == NULL) { + ubcore_log_err("dev or client is null"); + return; + } + + down_read(&dev->client_ctx_rwsem); list_for_each_entry(ctx, &dev->client_ctx_list, list_node) { if (ctx->client == client) { ctx->data = data; @@ -80,94 +137,96 @@ void ubcore_set_client_ctx_data(struct ubcore_device *dev, struct ubcore_client client->client_name); out: - spin_unlock_irqrestore(&dev->client_ctx_lock, flags); + up_read(&dev->client_ctx_rwsem); } EXPORT_SYMBOL(ubcore_set_client_ctx_data); -void *ubcore_get_client_ctx_data(struct ubcore_device *dev, struct ubcore_client *client) +static struct ubcore_client_ctx *ubcore_lookup_client_context(struct ubcore_device *dev, + struct ubcore_client *client) { struct ubcore_client_ctx *found_ctx = NULL; struct ubcore_client_ctx *ctx, *tmp; - unsigned long flags; - spin_lock_irqsave(&dev->client_ctx_lock, flags); + down_read(&dev->client_ctx_rwsem); list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) { if (ctx->client == client) { found_ctx = ctx; break; } } + up_read(&dev->client_ctx_rwsem); + return found_ctx; +} +void *ubcore_get_client_ctx_data(struct ubcore_device *dev, struct ubcore_client *client) +{ + struct ubcore_client_ctx *found_ctx = NULL; + + if (dev == NULL || client == NULL) { + ubcore_log_err("dev or client is null"); + return NULL; + } + + found_ctx = ubcore_lookup_client_context(dev, client); if (found_ctx == NULL) { - spin_unlock_irqrestore(&dev->client_ctx_lock, flags); ubcore_log_warn("no client ctx found, dev_name: %s, client_name: %s.\n", dev->dev_name, client->client_name); return NULL; + } else { + return found_ctx->data; } - spin_unlock_irqrestore(&dev->client_ctx_lock, flags); - - return found_ctx->data; } EXPORT_SYMBOL(ubcore_get_client_ctx_data); -static struct ubcore_client_ctx *create_client_ctx(struct ubcore_device *dev, - struct ubcore_client *client) +static int create_client_ctx(struct ubcore_device *dev, struct ubcore_client *client) { struct ubcore_client_ctx *ctx; - unsigned long flags; ctx = kmalloc(sizeof(struct ubcore_client_ctx), GFP_KERNEL); if (!ctx) - return NULL; + return -ENOMEM; ctx->data = NULL; ctx->client = client; - down_write(&g_lists_rwsem); - spin_lock_irqsave(&dev->client_ctx_lock, flags); + down_write(&dev->client_ctx_rwsem); list_add(&ctx->list_node, &dev->client_ctx_list); - spin_unlock_irqrestore(&dev->client_ctx_lock, flags); - up_write(&g_lists_rwsem); - - return ctx; + downgrade_write(&dev->client_ctx_rwsem); + if (client->add && client->add(dev) != 0) { + list_del(&ctx->list_node); + kfree(ctx); + up_read(&dev->client_ctx_rwsem); + return -EPERM; + } + up_read(&dev->client_ctx_rwsem); + return 0; } static void destroy_client_ctx(struct ubcore_device *dev, struct ubcore_client_ctx *ctx) { - unsigned long flags; - if (dev == NULL || ctx == NULL) return; - down_write(&g_lists_rwsem); - spin_lock_irqsave(&dev->client_ctx_lock, flags); + down_write(&dev->client_ctx_rwsem); list_del(&ctx->list_node); - spin_unlock_irqrestore(&dev->client_ctx_lock, flags); - up_write(&g_lists_rwsem); kfree(ctx); + up_write(&dev->client_ctx_rwsem); } int ubcore_register_client(struct ubcore_client *new_client) { struct ubcore_device *dev; - struct ubcore_client_ctx *ctx = NULL; mutex_lock(&g_device_mutex); list_for_each_entry(dev, &g_device_list, list_node) { - ctx = create_client_ctx(dev, new_client); - if (ctx == NULL) - continue; - - if (new_client->add && new_client->add(dev) != 0) { - destroy_client_ctx(dev, ctx); - ubcore_log_err("ubcore client: %s register dev:%s failed.\n", - new_client->client_name, dev->dev_name); - } + if (create_client_ctx(dev, new_client) != 0) + ubcore_log_warn("ubcore device: %s add client:%s context failed.\n", + dev->dev_name, new_client->client_name); } - down_write(&g_lists_rwsem); + down_write(&g_clients_rwsem); list_add_tail(&new_client->list_node, &g_client_list); - up_write(&g_lists_rwsem); + up_write(&g_clients_rwsem); mutex_unlock(&g_device_mutex); @@ -178,30 +237,17 @@ EXPORT_SYMBOL(ubcore_register_client); void ubcore_unregister_client(struct ubcore_client *rm_client) { - struct ubcore_client_ctx *ctx, *tmp; + struct ubcore_client_ctx *found_ctx = NULL; struct ubcore_device *dev; - unsigned long flags; mutex_lock(&g_device_mutex); - down_write(&g_lists_rwsem); + down_write(&g_clients_rwsem); list_del(&rm_client->list_node); - up_write(&g_lists_rwsem); + up_write(&g_clients_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { - struct ubcore_client_ctx *found_ctx = NULL; - - down_write(&g_lists_rwsem); - spin_lock_irqsave(&dev->client_ctx_lock, flags); - list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) { - if (ctx->client == rm_client) { - found_ctx = ctx; - break; - } - } - spin_unlock_irqrestore(&dev->client_ctx_lock, flags); - up_write(&g_lists_rwsem); - + found_ctx = ubcore_lookup_client_context(dev, rm_client); if (found_ctx == NULL) { ubcore_log_warn("no client ctx found, dev_name: %s, client_name: %s.\n", dev->dev_name, rm_client->client_name); @@ -277,7 +323,7 @@ struct ubcore_device *ubcore_find_upi_with_dev_name(const char *dev_name, uint32 int ubcore_add_upi_list(struct ubcore_device *dev, uint32_t upi) { - struct ubcore_upi_entry *entry, *new_entry; + struct ubcore_upi_entry *entry = NULL, *new_entry = NULL; mutex_lock(&g_upi_lock); list_for_each_entry(entry, &g_upi_list, node) { @@ -429,6 +475,42 @@ struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name, return ubcore_find_tpf_device_legacy(); } +static uint32_t ubcore_get_all_tpf_device_cnt(enum ubcore_transport_type type) +{ + struct ubcore_device *dev; + uint32_t cnt = 0; + + mutex_lock(&g_device_mutex); + list_for_each_entry(dev, &g_device_list, list_node) { + if (dev->attr.tp_maintainer && dev->transport_type == type) + ++cnt; + } + mutex_unlock(&g_device_mutex); + return cnt; +} + +struct ubcore_device **ubcore_get_all_tpf_device(enum ubcore_transport_type type, uint32_t *dev_cnt) +{ + struct ubcore_device **dev_list; + struct ubcore_device *dev; + int i = 0; + + *dev_cnt = ubcore_get_all_tpf_device_cnt(type); + dev_list = kcalloc(1, (*dev_cnt) * (uint32_t)sizeof(struct ubcore_device *), GFP_KERNEL); + if (dev_list == NULL) + return NULL; + + mutex_lock(&g_device_mutex); + list_for_each_entry(dev, &g_device_list, list_node) { + if (dev->attr.tp_maintainer && dev->transport_type == type) { + dev_list[i++] = dev; + ubcore_get_device(dev); + } + } + mutex_unlock(&g_device_mutex); + return dev_list; +} + struct ubcore_device *ubcore_find_tpf_device(struct ubcore_net_addr *netaddr, enum ubcore_transport_type type) { @@ -486,7 +568,6 @@ static struct ubcore_ht_param g_ht_params[] = { [UBCORE_HT_JFR] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfr, hnode), offsetof(struct ubcore_jfr, id), sizeof(uint32_t), NULL, NULL }, - [UBCORE_HT_JFC] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfc, hnode), offsetof(struct ubcore_jfc, id), sizeof(uint32_t), NULL, NULL }, @@ -516,7 +597,7 @@ static struct ubcore_ht_param g_ht_params[] = { /* key: src_eid + des_eid */ [UBCORE_HT_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), - offsetof(struct ubcore_vtpn, local_eid), sizeof(union ubcore_eid) * 2, NULL, NULL}, + offsetof(struct ubcore_vtpn, trans_mode), VTPN_KEY_SIZE, NULL, NULL}, /* key: utp idx */ [UBCORE_HT_UTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_utp, hnode), @@ -717,13 +798,50 @@ int ubcore_query_all_device_tpf_dev_info(void) dev->dev_name); ret = -1; } - ubcore_log_info("query tpf_dev %s to notify uvs", dev->dev_name); } } mutex_unlock(&g_device_mutex); return ret; } +static int ubcore_create_main_device(struct ubcore_device *dev, struct net *net) +{ + struct ubcore_logic_device *ldev = &dev->ldev; + int ret; + + /* create /sys/class/ubcore/dev_name> */ + write_pnet(&ldev->net, net); + ldev->ub_dev = dev; + ldev->dev = &dev->dev; + + device_initialize(&dev->dev); + dev->dev.class = &g_ubcore_class; + dev->dev.release = ubcore_device_release; + dev_set_name(&dev->dev, "%s", dev->dev_name); + dev_set_drvdata(&dev->dev, ldev); + ret = device_add(&dev->dev); + if (ret) + return ret; + + if (ubcore_fill_logic_device_attr(ldev, dev) != 0) { + device_del(&dev->dev); + ldev->dev = NULL; + ubcore_log_err("failed to fill attributes, device:%s.\n", dev->dev_name); + return -EPERM; + } + + return 0; +} + +static void ubcore_destroy_main_device(struct ubcore_device *dev) +{ + struct ubcore_logic_device *ldev = &dev->ldev; + + ubcore_unfill_logic_device_attr(ldev, dev); + device_del(ldev->dev); + ldev->dev = NULL; +} + static int init_ubcore_device(struct ubcore_device *dev) { if (dev->ops->query_device_attr != NULL && @@ -739,16 +857,11 @@ static int init_ubcore_device(struct ubcore_device *dev) if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) ubcore_sip_table_init(&dev->sip_table); - device_initialize(&dev->dev); - dev_set_drvdata(&dev->dev, dev); - dev_set_name(&dev->dev, "%s", dev->dev_name); - dev->dev.release = ubcore_device_release; - INIT_LIST_HEAD(&dev->list_node); - spin_lock_init(&dev->client_ctx_lock); + init_rwsem(&dev->client_ctx_rwsem); INIT_LIST_HEAD(&dev->client_ctx_list); INIT_LIST_HEAD(&dev->port_list); - spin_lock_init(&dev->event_handler_lock); + init_rwsem(&dev->event_handler_rwsem); INIT_LIST_HEAD(&dev->event_handler_list); if (!dev->attr.virtualization) @@ -776,6 +889,9 @@ static int init_ubcore_device(struct ubcore_device *dev) return -1; } ubcore_update_default_eid(dev, true); + + mutex_init(&dev->ldev_mutex); + INIT_LIST_HEAD(&dev->ldev_list); return 0; } @@ -799,6 +915,8 @@ static void ubcore_remove_uvs_sip_info(struct ubcore_device *dev) static void uninit_ubcore_device(struct ubcore_device *dev) { + mutex_destroy(&dev->ldev_mutex); + ubcore_put_port_netdev(dev); ubcore_update_default_eid(dev, false); ubcore_free_hash_tables(dev); @@ -816,8 +934,6 @@ static void uninit_ubcore_device(struct ubcore_device *dev) if (ubcore_get_netlink_valid() && ubcore_send_remove_tpf_dev_info(dev) != 0) ubcore_log_warn("failed to remove tpf dev info %s", dev->dev_name); } - - put_device(&dev->dev); } static int ubcore_config_device_rsp_msg_cb(struct ubcore_device *dev, @@ -893,7 +1009,7 @@ static int ubcore_config_device_in_register(struct ubcore_device *dev) if (dev->transport_type != UBCORE_TRANSPORT_UB) return 0; - if (ubcore_get_netlink_valid() == false) { + if (ubcore_get_netlink_valid() == false && !dev->attr.virtualization) { ubcore_log_info("UVS is not connected, and use default config. dev: %s.\n", dev->dev_name); return ubcore_config_device_default(dev); @@ -904,6 +1020,9 @@ static int ubcore_config_device_in_register(struct ubcore_device *dev) if (req_msg == NULL) return -ENOMEM; + /* Should not send UBCORE_MSG_CONFIG_DEVICE after register dev + * It will clear fe resource in uvs + */ req_msg->opcode = UBCORE_MSG_CONFIG_DEVICE; req_msg->len = (uint32_t)sizeof(struct ubcore_msg_config_device_req); @@ -913,6 +1032,7 @@ static int ubcore_config_device_in_register(struct ubcore_device *dev) data->max_rc_depth = dev->attr.dev_cap.max_rc_depth; data->min_slice = dev->attr.dev_cap.min_slice; data->max_slice = dev->attr.dev_cap.max_slice; + data->virtualization = dev->attr.virtualization; /* New TPF devices need to be query suspend info. */ data->is_tpf_dev = dev->attr.tp_maintainer; @@ -926,13 +1046,165 @@ static int ubcore_config_device_in_register(struct ubcore_device *dev) return ret; } -int ubcore_register_device(struct ubcore_device *dev) +static void ubcore_clients_add(struct ubcore_device *dev) { struct ubcore_client *client = NULL; - struct ubcore_client_ctx *ctx = NULL; + + down_read(&g_clients_rwsem); + list_for_each_entry(client, &g_client_list, list_node) { + if (create_client_ctx(dev, client) != 0) + ubcore_log_warn("ubcore device: %s add client:%s context failed.\n", + dev->dev_name, client->client_name); + } + up_read(&g_clients_rwsem); +} + +static void ubcore_clients_remove(struct ubcore_device *dev) +{ + struct ubcore_client_ctx *ctx, *tmp; + + down_read(&dev->client_ctx_rwsem); + list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) { + if (ctx->client && ctx->client->remove) + ctx->client->remove(dev, ctx->data); + } + up_read(&dev->client_ctx_rwsem); + + down_write(&dev->client_ctx_rwsem); + list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) { + list_del(&ctx->list_node); + kfree(ctx); + } + up_write(&dev->client_ctx_rwsem); +} + +static int ubcore_create_logic_device(struct ubcore_logic_device *ldev, + struct ubcore_device *dev, struct net *net) +{ + /* create /sys/class/ubcore/dev_name> */ + write_pnet(&ldev->net, net); + ldev->ub_dev = dev; + + ldev->dev = device_create(&g_ubcore_class, dev->dev.parent, + MKDEV(0, 0), ldev, "%s", dev->dev_name); + if (IS_ERR(ldev->dev)) { + ubcore_log_err("device create failed, device:%s.\n", dev->dev_name); + return -ENOMEM; + } + + if (ubcore_fill_logic_device_attr(ldev, dev) != 0) { + device_unregister(ldev->dev); + ldev->dev = NULL; + ubcore_log_err("failed to fill attributes, device:%s.\n", dev->dev_name); + return -EPERM; + } + + return 0; +} + +static void ubcore_destroy_logic_device(struct ubcore_logic_device *ldev, struct ubcore_device *dev) +{ + ubcore_unfill_logic_device_attr(ldev, dev); + device_unregister(ldev->dev); + ldev->dev = NULL; +} + +static void ubcore_remove_one_logic_device(struct ubcore_device *dev, struct net *net) +{ + struct ubcore_logic_device *ldev, *tmp; + + mutex_lock(&dev->ldev_mutex); + list_for_each_entry_safe(ldev, tmp, &dev->ldev_list, node) { + if (net_eq(read_pnet(&ldev->net), net)) { + ubcore_destroy_logic_device(ldev, dev); + list_del(&ldev->node); + kfree(ldev); + break; + } + } + mutex_unlock(&dev->ldev_mutex); +} + +static void ubcore_remove_logic_devices(struct ubcore_device *dev) +{ + struct ubcore_logic_device *ldev, *tmp; + + if (dev->transport_type != UBCORE_TRANSPORT_UB) + return; + + mutex_lock(&dev->ldev_mutex); + list_for_each_entry_safe(ldev, tmp, &dev->ldev_list, node) { + ubcore_destroy_logic_device(ldev, dev); + list_del(&ldev->node); + kfree(ldev); + } + mutex_unlock(&dev->ldev_mutex); +} + +static int ubcore_add_one_logic_device(struct ubcore_device *dev, struct net *net) +{ + struct ubcore_logic_device *ldev; + int ret; + + mutex_lock(&dev->ldev_mutex); + list_for_each_entry(ldev, &dev->ldev_list, node) { + if (net_eq(read_pnet(&dev->ldev.net), net)) { + mutex_unlock(&dev->ldev_mutex); + return 0; + } + } + + ldev = kzalloc(sizeof(struct ubcore_logic_device), GFP_KERNEL); + if (ldev == NULL) { + mutex_unlock(&dev->ldev_mutex); + return -ENOMEM; + } + + ret = ubcore_create_logic_device(ldev, dev, net); + if (ret) { + kfree(ldev); + mutex_unlock(&dev->ldev_mutex); + ubcore_log_err("add device failed %s in net %u", dev->dev_name, net->ns.inum); + return ret; + } + + list_add_tail(&ldev->node, &dev->ldev_list); + mutex_unlock(&dev->ldev_mutex); + ubcore_log_info("add device %s in net %u", dev->dev_name, net->ns.inum); + return 0; +} + +static int ubcore_copy_logic_devices(struct ubcore_device *dev) +{ + struct ubcore_net *unet; + int ret = 0; + + if (dev->transport_type != UBCORE_TRANSPORT_UB) + return 0; + + down_read(&g_ubcore_net_rwsem); + list_for_each_entry(unet, &g_ubcore_net_list, node) { + if (net_eq(read_pnet(&unet->net), read_pnet(&dev->ldev.net))) + continue; + ret = ubcore_add_one_logic_device(dev, read_pnet(&unet->net)); + if (ret != 0) + break; + } + up_read(&g_ubcore_net_rwsem); + + if (ret) + ubcore_remove_logic_devices(dev); + + return ret; +} + +int ubcore_register_device(struct ubcore_device *dev) +{ struct ubcore_device *find_dev = NULL; + int ret; - if (dev == NULL || dev->ops == NULL || strlen(dev->dev_name) == 0) { + if (dev == NULL || dev->ops == NULL || strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) == 0 || + strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) > UBCORE_MAX_DEV_NAME - 1) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } @@ -949,65 +1221,69 @@ int ubcore_register_device(struct ubcore_device *dev) return -EINVAL; } + ret = ubcore_create_main_device(dev, &init_net); + if (ret) { + uninit_ubcore_device(dev); + ubcore_log_err("create main device failed.\n"); + return ret; + } + if (ubcore_config_device_in_register(dev) != 0) { ubcore_log_err("failed to config ubcore device.\n"); - uninit_ubcore_device(dev); - return -EPERM; + ret = -EPERM; + goto destroy_mdev; } ubcore_cgroup_reg_dev(dev); + mutex_lock(&g_device_mutex); + ubcore_clients_add(dev); + ret = ubcore_copy_logic_devices(dev); + if (ret) { + ubcore_clients_remove(dev); + mutex_unlock(&g_device_mutex); - list_for_each_entry(client, &g_client_list, list_node) { - ctx = create_client_ctx(dev, client); - if (ctx == NULL) - continue; - if (client->add && client->add(dev) != 0) { - destroy_client_ctx(dev, ctx); - ubcore_log_err("ubcore device: %s register client:%s failed.\n", - dev->dev_name, client->client_name); - } + ubcore_log_err("copy logic device failed, device:%s.\n", dev->dev_name); + goto err; } - down_write(&g_lists_rwsem); list_add_tail(&dev->list_node, &g_device_list); - up_write(&g_lists_rwsem); - mutex_unlock(&g_device_mutex); ubcore_log_info("ubcore device: %s register success.\n", dev->dev_name); return 0; + +err: + ubcore_cgroup_unreg_dev(dev); +destroy_mdev: + ubcore_destroy_main_device(dev); + uninit_ubcore_device(dev); + return ret; } EXPORT_SYMBOL(ubcore_register_device); void ubcore_unregister_device(struct ubcore_device *dev) { - struct ubcore_client_ctx *ctx, *tmp; - mutex_lock(&g_device_mutex); /* Remove device from g_device_list */ - down_write(&g_lists_rwsem); list_del(&dev->list_node); /* Destroy uburma device, may be scheduled. * This should not be done within a spin_lock_irqsave */ - list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) { - if (ctx->client != NULL && ctx->client->remove != NULL) - ctx->client->remove(dev, ctx->data); - } - up_write(&g_lists_rwsem); + ubcore_clients_remove(dev); + + ubcore_flush_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); + ubcore_flush_workqueue((int)UBCORE_SIP_NOTIFY_WQ); ubcore_cgroup_unreg_dev(dev); + ubcore_remove_logic_devices(dev); + ubcore_destroy_main_device(dev); uninit_ubcore_device(dev); mutex_unlock(&g_device_mutex); - /* Finally, free client ctx */ - list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) - destroy_client_ctx(dev, ctx); - /* Pair with set use_cnt = 1 when init device */ ubcore_put_device(dev); /* Wait for use cnt == 0 */ @@ -1019,46 +1295,72 @@ EXPORT_SYMBOL(ubcore_unregister_device); void ubcore_register_event_handler(struct ubcore_device *dev, struct ubcore_event_handler *handler) { - unsigned long flags; - if (dev == NULL || handler == NULL) { ubcore_log_err("Invalid argument.\n"); return; } - spin_lock_irqsave(&dev->event_handler_lock, flags); + down_write(&dev->event_handler_rwsem); list_add_tail(&handler->node, &dev->event_handler_list); - spin_unlock_irqrestore(&dev->event_handler_lock, flags); + up_write(&dev->event_handler_rwsem); } EXPORT_SYMBOL(ubcore_register_event_handler); +static void ubcore_dispatch_event_clients(struct ubcore_event *event) +{ + struct ubcore_event_handler *handler; + struct ubcore_device *dev = event->ub_dev; + + down_read(&dev->event_handler_rwsem); + list_for_each_entry(handler, &dev->event_handler_list, node) + handler->event_callback(event, handler); + up_read(&dev->event_handler_rwsem); +} + +static void ubcore_dispatch_event_task(struct work_struct *work) +{ + struct ubcore_event_work *l_ubcore_event = + container_of(work, struct ubcore_event_work, work); + + ubcore_dispatch_event_clients(&l_ubcore_event->event); + kfree(l_ubcore_event); +} + +int ubcore_dispatch_event(struct ubcore_event *event) +{ + struct ubcore_event_work *l_ubcore_event; + + l_ubcore_event = kzalloc(sizeof(*l_ubcore_event), GFP_ATOMIC); + if (!l_ubcore_event) + return -ENOMEM; + + INIT_WORK(&l_ubcore_event->work, ubcore_dispatch_event_task); + l_ubcore_event->event = *event; + + if (ubcore_queue_work((int)UBCORE_DISPATCH_EVENT_WQ, &l_ubcore_event->work) != 0) { + kfree(l_ubcore_event); + ubcore_log_err("Queue work failed"); + } + + return 0; +} + void ubcore_unregister_event_handler(struct ubcore_device *dev, struct ubcore_event_handler *handler) { - unsigned long flags; - if (dev == NULL || handler == NULL) { ubcore_log_err("Invalid argument.\n"); return; } - spin_lock_irqsave(&dev->event_handler_lock, flags); + down_write(&dev->event_handler_rwsem); list_del(&handler->node); - spin_unlock_irqrestore(&dev->event_handler_lock, flags); + up_write(&dev->event_handler_rwsem); } EXPORT_SYMBOL(ubcore_unregister_event_handler); -void ubcore_dispatch_async_event(struct ubcore_event *event) +static bool ubcore_preprocess_event(struct ubcore_event *event) { - struct ubcore_event_handler *handler; - struct ubcore_device *dev; - unsigned long flags; - - if (event == NULL || event->ub_dev == NULL) { - ubcore_log_err("Invalid argument.\n"); - return; - } - if (event->event_type == UBCORE_EVENT_TP_ERR && event->element.tp != NULL) { ubcore_log_info("ubcore detect tp error event"); if (event->ub_dev->transport_type == UBCORE_TRANSPORT_IB) { @@ -1068,49 +1370,59 @@ void ubcore_dispatch_async_event(struct ubcore_event *event) event->element.tp->state == UBCORE_TP_STATE_RESET) { ubcore_log_warn("Tp already in state %d, ignore err event", (int32_t)event->element.tp->state); - return; + return true; } if (ubcore_change_tp_to_err(event->ub_dev, event->element.tp) != 0) ubcore_log_info("ubcore change tp to error failed"); } - return; + return true; } else if (event->event_type == UBCORE_EVENT_TP_SUSPEND && event->element.tp != NULL) { ubcore_log_info("ubcore detect tp suspend event"); ubcore_report_tp_suspend(event->ub_dev, event->element.tp); - return; + return true; } else if (event->event_type == UBCORE_EVENT_MIGRATE_VTP_SWITCH && event->element.vtp != NULL) { ubcore_log_info("ubcore detect migrate vtp switch event"); ubcore_report_migrate_vtp(event->ub_dev, event->element.vtp, UBCORE_EVENT_MIGRATE_VTP_SWITCH); - return; + return true; } else if (event->event_type == UBCORE_EVENT_MIGRATE_VTP_ROLLBACK && event->element.vtp != NULL) { ubcore_log_info("ubcore detect migrate vtp rollback event"); ubcore_report_migrate_vtp(event->ub_dev, event->element.vtp, UBCORE_EVENT_MIGRATE_VTP_ROLLBACK); - return; - } else if (event->event_type == UBCORE_EVENT_TP_FLUSH_DONE) { + return true; + } else if (event->event_type == UBCORE_EVENT_TP_FLUSH_DONE && + event->element.tp != NULL) { ubcore_log_info("ubcore detect tp flush done event"); if (event->element.tp->state == UBCORE_TP_STATE_RESET) { ubcore_log_warn("Tp already in state %d, ignore flush done event", (int32_t)event->element.tp->state); - return; + return true; } /* flush done means tp already in error, * and all pkt have been send need uvs to restore */ if (event->ub_dev->transport_type == UBCORE_TRANSPORT_UB) ubcore_report_tp_error(event->ub_dev, event->element.tp); + return true; + } + return false; +} + +void ubcore_dispatch_async_event(struct ubcore_event *event) +{ + if (event == NULL || event->ub_dev == NULL) { + ubcore_log_err("Invalid argument.\n"); return; } - dev = event->ub_dev; - spin_lock_irqsave(&dev->event_handler_lock, flags); - list_for_each_entry(handler, &dev->event_handler_list, node) - handler->event_callback(event, handler); - spin_unlock_irqrestore(&dev->event_handler_lock, flags); + if (ubcore_preprocess_event(event)) + return; + + if (ubcore_dispatch_event(event) != 0) + ubcore_log_err("ubcore_dispatch_event failed"); } EXPORT_SYMBOL(ubcore_dispatch_async_event); @@ -1118,10 +1430,18 @@ static bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index) { struct net *net; - if (IS_ERR_OR_NULL(dev->eid_table.eid_entries)) + if (eid_index >= dev->eid_table.eid_cnt) { + ubcore_log_err("eid_indx: %u is over the up limit: %u", + eid_index, dev->eid_table.eid_cnt); return false; + } spin_lock(&dev->eid_table.lock); + if (IS_ERR_OR_NULL(dev->eid_table.eid_entries)) { + spin_unlock(&dev->eid_table.lock); + return false; + } + if (!dev->eid_table.eid_entries[eid_index].valid) { spin_unlock(&dev->eid_table.lock); return false; @@ -1131,6 +1451,11 @@ static bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index) return net_eq(net, current->nsproxy->net_ns); } +bool ubcore_dev_accessible(struct ubcore_device *dev) +{ + return (g_shared_ns || net_eq(current->nsproxy->net_ns, read_pnet(&dev->ldev.net))); +} + struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_t eid_index, struct ubcore_udrv_priv *udrv_data) { @@ -1138,12 +1463,13 @@ struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_ struct ubcore_cg_object cg_obj; int ret; - if (dev == NULL || dev->ops == NULL || dev->ops->alloc_ucontext == NULL) { - ubcore_log_err("alloc_ucontext not registered.\n"); + if (dev == NULL || dev->ops == NULL || dev->ops->alloc_ucontext == NULL || + eid_index >= UBCORE_MAX_EID_CNT) { + ubcore_log_err("Invalid argument.\n"); return NULL; } - if (!ubcore_eid_accessible(dev, eid_index)) { + if (!ubcore_dev_accessible(dev) || !ubcore_eid_accessible(dev, eid_index)) { ubcore_log_err("eid is not accessible by current ns.\n"); return NULL; } @@ -1175,7 +1501,7 @@ void ubcore_free_ucontext(struct ubcore_device *dev, struct ubcore_ucontext *uco struct ubcore_cg_object cg_obj; if (dev == NULL || ucontext == NULL || dev->ops == NULL || - dev->ops->free_ucontext == NULL) { + dev->ops->free_ucontext == NULL) { ubcore_log_err("Invalid argument.\n"); return; } @@ -1189,60 +1515,73 @@ void ubcore_free_ucontext(struct ubcore_device *dev, struct ubcore_ucontext *uco } EXPORT_SYMBOL(ubcore_free_ucontext); -int ubcore_set_upi(struct ubcore_device *dev, uint16_t fe_idx, uint16_t idx, uint32_t upi) +static struct ubcore_device *ubcore_get_ueid_op_dev(struct ubcore_device *dev) { - int ret; + if (dev == NULL) + return NULL; - if (dev == NULL || dev->ops == NULL || dev->ops->set_upi == NULL) { - ubcore_log_err("Invalid argument.\n"); - return -EINVAL; + if (dev->transport_type != UBCORE_TRANSPORT_UB) { + ubcore_get_device(dev); + return dev; } - ret = dev->ops->set_upi(dev, fe_idx, idx, upi); - if (ret != 0) { - ubcore_log_err("failed to set fe%hu upi%hu, ret: %d.\n", fe_idx, idx, ret); - return -EPERM; - } - return 0; + /* For UB dev, add_ueid and delete_ueid ops should operate on tpf */ + return ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); } -EXPORT_SYMBOL(ubcore_set_upi); int ubcore_add_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ueid_cfg *cfg) { + struct ubcore_device *op_dev = NULL; int ret; - if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->add_ueid == NULL) { + op_dev = ubcore_get_ueid_op_dev(dev); + if (op_dev == NULL || cfg == NULL || op_dev->ops == NULL || op_dev->ops->add_ueid == NULL + || fe_idx >= UBCORE_MAX_FE_CNT) { ubcore_log_err("Invalid argument.\n"); - return -EINVAL; + ret = -EINVAL; + goto put_dev; } - ret = dev->ops->add_ueid(dev, fe_idx, cfg); + ret = op_dev->ops->add_ueid(op_dev, fe_idx, cfg); if (ret != 0) { - ubcore_log_err("failed to add ueid, fe_idx:%hu, eid:"EID_FMT", upi:%u, eid_idx:%u", - fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index); - ubcore_log_err("failed to add ueid, ret: %d", ret); - return -EPERM; + ubcore_log_err( + "failed to add ueid, fe_idx:%hu, eid:"EID_FMT", upi:%u, eid_idx:%u, ret:%d", + fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); + goto put_dev; } + +put_dev: + if (op_dev) + ubcore_put_device(op_dev); return ret; } EXPORT_SYMBOL(ubcore_add_ueid); int ubcore_delete_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ueid_cfg *cfg) { + struct ubcore_device *op_dev = NULL; int ret; - if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->delete_ueid == NULL) { + op_dev = ubcore_get_ueid_op_dev(dev); + if (op_dev == NULL || cfg == NULL || op_dev->ops == NULL || + op_dev->ops->delete_ueid == NULL || + fe_idx >= UBCORE_MAX_FE_CNT) { ubcore_log_err("Invalid argument.\n"); - return -EINVAL; + ret = -EINVAL; + goto put_dev; } - ret = dev->ops->delete_ueid(dev, fe_idx, cfg); + ret = op_dev->ops->delete_ueid(op_dev, fe_idx, cfg); if (ret != 0) { - ubcore_log_err("failed to add ueid, fe_idx:%hu, eid:"EID_FMT", upi:%u, eid_idx:%u", - fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index); - ubcore_log_err("failed to add ueid, ret: %d", ret); - return -EPERM; + ubcore_log_err( + "failed to add ueid, fe_idx:%hu, eid:"EID_FMT", upi:%u, eid_idx:%u, ret:%d", + fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); + goto put_dev; } + +put_dev: + if (op_dev) + ubcore_put_device(op_dev); return ret; } EXPORT_SYMBOL(ubcore_delete_ueid); @@ -1402,8 +1741,10 @@ static int ubcore_del_device_sip(struct ubcore_device *dev, struct ubcore_sip_in { uint32_t index; - if (ubcore_lookup_sip_idx(&dev->sip_table, sip, &index) != 0) + if (ubcore_lookup_sip_idx(&dev->sip_table, sip, &index) != 0) { + ubcore_log_err("sip not exists\n"); return -1; + } (void)ubcore_del_sip_entry(&dev->sip_table, index); @@ -1469,11 +1810,17 @@ EXPORT_SYMBOL(ubcore_delete_sip); struct ubcore_eid_info *ubcore_get_eid_list(struct ubcore_device *dev, uint32_t *cnt) { - struct ubcore_eid_info *tmp; struct ubcore_eid_info *eid_list; + struct ubcore_eid_info *tmp; uint32_t count; uint32_t i; + if (dev == NULL || dev->attr.dev_cap.max_eid_cnt == 0 || + dev->attr.dev_cap.max_eid_cnt > UBCORE_MAX_EID_CNT || cnt == NULL) { + ubcore_log_err("invalid input parameter.\n"); + return NULL; + } + tmp = vmalloc(dev->attr.dev_cap.max_eid_cnt * sizeof(struct ubcore_eid_info)); if (tmp == NULL) return NULL; @@ -1570,3 +1917,213 @@ struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(struct ubcore_net_addr *addr return target; } + +static int ubcore_modify_dev_ns(struct ubcore_device *dev, struct net *net) +{ + struct net *cur; + int ret; + + cur = read_pnet(&dev->ldev.net); + if (net_eq(net, cur)) + return 0; + + kobject_uevent(&dev->ldev.dev->kobj, KOBJ_REMOVE); + ubcore_clients_remove(dev); + write_pnet(&dev->ldev.net, net); + ret = device_rename(dev->ldev.dev, dev_name(dev->ldev.dev)); + if (ret) { + write_pnet(&dev->ldev.net, cur); + ubcore_log_err("Failed to rename device in the new ns.\n"); + } + ubcore_clients_add(dev); + kobject_uevent(&dev->ldev.dev->kobj, KOBJ_ADD); + return ret; +} + +int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd) +{ + struct ubcore_device *dev = NULL, *tmp; + struct net *net; + int ret = 0; + + if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { + ubcore_log_err("current user does not have net admin capability"); + return -EPERM; + } + + if (g_shared_ns) { + ubcore_log_err("Can not set device to ns under shared ns mode.\n"); + return -EPERM; + } + + net = get_net_ns_by_fd(ns_fd); + if (IS_ERR(net)) { + ubcore_log_err("Failed to get ns by fd.\n"); + return PTR_ERR(net); + } + + /* Find device by name */ + mutex_lock(&g_device_mutex); + list_for_each_entry(tmp, &g_device_list, list_node) { + if (strcmp(dev_name(tmp->ldev.dev), device_name) == 0) { + dev = tmp; + break; + } + } + if (dev == NULL) { + ret = -EINVAL; + ubcore_log_err("Failed to find device.\n"); + goto out; + } + + /* Put device in the new ns */ + ret = ubcore_modify_dev_ns(dev, net); + +out: + mutex_unlock(&g_device_mutex); + put_net(net); + return ret; +} + +int ubcore_set_ns_mode(bool shared) +{ + unsigned long flags; + + if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { + ubcore_log_err("current user does not have net admin capability"); + return -EPERM; + } + + down_write(&g_ubcore_net_rwsem); + if (g_shared_ns == shared) { + up_write(&g_ubcore_net_rwsem); + return 0; + } + spin_lock_irqsave(&g_ubcore_net_lock, flags); + if (!list_empty(&g_ubcore_net_list)) { + spin_unlock_irqrestore(&g_ubcore_net_lock, flags); + up_write(&g_ubcore_net_rwsem); + ubcore_log_err("Failed to modify ns mode with existing ns"); + return -EPERM; + } + g_shared_ns = shared; + spin_unlock_irqrestore(&g_ubcore_net_lock, flags); + up_write(&g_ubcore_net_rwsem); + return 0; +} + +void ubcore_net_exit(struct net *net) +{ + struct ubcore_net *unet = net_generic(net, g_ubcore_net_id); + struct ubcore_device *dev; + unsigned long flags; + + if (unet == NULL) + return; + + ubcore_log_info("net exit %u", net->ns.inum); + down_write(&g_ubcore_net_rwsem); + spin_lock_irqsave(&g_ubcore_net_lock, flags); + if (list_empty(&unet->node)) { + spin_unlock_irqrestore(&g_ubcore_net_lock, flags); + up_write(&g_ubcore_net_rwsem); + return; + } + list_del_init(&unet->node); + spin_unlock_irqrestore(&g_ubcore_net_lock, flags); + up_write(&g_ubcore_net_rwsem); + + if (!g_shared_ns) { + mutex_lock(&g_device_mutex); + list_for_each_entry(dev, &g_device_list, list_node) { + (void)ubcore_modify_dev_ns(dev, &init_net); + } + mutex_unlock(&g_device_mutex); + } else { + mutex_lock(&g_device_mutex); + list_for_each_entry(dev, &g_device_list, list_node) { + if (dev->transport_type != UBCORE_TRANSPORT_UB) + continue; + ubcore_remove_one_logic_device(dev, net); + } + mutex_unlock(&g_device_mutex); + } +} + +static int ubcore_net_init(struct net *net) +{ + struct ubcore_net *unet = net_generic(net, g_ubcore_net_id); + struct ubcore_device *dev; + unsigned long flags; + int ret = 0; + + if (unet == NULL) + return 0; + + ubcore_log_info("net init %u", net->ns.inum); + write_pnet(&unet->net, net); + if (net_eq(net, &init_net)) { + INIT_LIST_HEAD(&unet->node); + return 0; + } + + spin_lock_irqsave(&g_ubcore_net_lock, flags); + list_add_tail(&unet->node, &g_ubcore_net_list); + spin_unlock_irqrestore(&g_ubcore_net_lock, flags); + + if (!g_shared_ns) + return 0; + + mutex_lock(&g_device_mutex); + list_for_each_entry(dev, &g_device_list, list_node) { + if (dev->transport_type != UBCORE_TRANSPORT_UB) + continue; + + down_read(&g_ubcore_net_rwsem); + ret = ubcore_add_one_logic_device(dev, net); + up_read(&g_ubcore_net_rwsem); + if (ret) + break; + } + mutex_unlock(&g_device_mutex); + if (ret) + ubcore_net_exit(net); + + /* return ret will cause error starting a container */ + return 0; +} + +static struct pernet_operations g_ubcore_net_ops = { + .init = ubcore_net_init, + .exit = ubcore_net_exit, + .id = &g_ubcore_net_id, + .size = sizeof(struct ubcore_net) +}; + +int ubcore_register_pnet_ops(void) +{ + return register_pernet_device(&g_ubcore_net_ops); +} +void ubcore_unregister_pnet_ops(void) +{ + unregister_pernet_device(&g_ubcore_net_ops); +} + +int ubcore_class_register(struct class **ubcore_class) +{ + int ret; + + ret = class_register(&g_ubcore_class); + if (!ret) + *ubcore_class = &g_ubcore_class; + + return ret; +} + +void ubcore_class_unregister(struct class *ubcore_class) +{ + if (ubcore_class != &g_ubcore_class) + return; + + class_unregister(&g_ubcore_class); +} diff --git a/drivers/ub/urma/uburma/uburma_netlink.h b/drivers/ub/urma/ubcore/ubcore_device.h similarity index 47% rename from drivers/ub/urma/uburma/uburma_netlink.h rename to drivers/ub/urma/ubcore/ubcore_device.h index 674982d491c6..fd37e509c78b 100644 --- a/drivers/ub/urma/uburma/uburma_netlink.h +++ b/drivers/ub/urma/ubcore/ubcore_device.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -11,38 +11,21 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * Description: uburma netlink header + * Description: ubcore device head file * Author: Yan Fangfang - * Create: 2023-12-06 + * Create: 2024-02-05 * Note: - * History: 2023-12-06: create file + * History: 2024-02-05: Create file */ -#ifndef UBURMA_NETLINK_H -#define UBURMA_NETLINK_H +#ifndef UBCORE_DEVICE_H +#define UBCORE_DEVICE_H -#include -#include +int ubcore_register_pnet_ops(void); +void ubcore_unregister_pnet_ops(void); +int ubcore_class_register(struct class **ubcore_class); +void ubcore_class_unregister(struct class *ubcore_class); +int ubcore_set_ns_mode(bool shared); +int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd); -enum uburma_nlmsg_type { - UBURMA_NL_SET_NS_MODE = NLMSG_MIN_TYPE, /* 0x10 */ - UBURMA_NL_SET_DEV_NS -}; - -struct uburma_nl_set_ns_mode { - uint8_t ns_mode; -}; - -struct uburma_nl_set_dev_ns { - char dev_name[UBCORE_MAX_DEV_NAME]; - int ns_fd; -}; - -struct uburma_nl_resp { - int ret; -}; - -int uburma_netlink_init(void); -void uburma_netlink_exit(void); - -#endif +#endif // UBCORE_DEVICE_H diff --git a/drivers/ub/urma/ubcore/ubcore_genl.c b/drivers/ub/urma/ubcore/ubcore_genl.c new file mode 100644 index 000000000000..245508516ac6 --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_genl.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore kernel module + * Author: Yanchao Zhao + * Create: 2024-01-18 + * Note: + * History: 2024-01-18: create file + */ + +#include +#include +#include +#include +#include +#include + +#include "urma/ubcore_api.h" +#include "ubcore_msg.h" +#include "ubcore_cmd.h" +#include "ubcore_device.h" +#include "ubcore_genl_admin.h" +#include "ubcore_genl_define.h" +#include "ubcore_genl.h" + +static const struct nla_policy ubcore_policy[NUM_UBCORE_ATTR] = { + [UBCORE_ATTR_UNSPEC] = {0}, + [UBCORE_HDR_COMMAND] = { .type = NLA_U32 }, + [UBCORE_HDR_ARGS_LEN] = { .type = NLA_U32 }, + [UBCORE_HDR_ARGS_ADDR] = { .type = NLA_U64 }, + [UBCORE_ATTR_NS_MODE] = { .type = NLA_U8 }, + [UBCORE_ATTR_DEV_NAME] = { .type = NLA_STRING, .len = UBCORE_MAX_DEV_NAME - 1}, + [UBCORE_ATTR_NS_FD] = { .type = NLA_U32 }, +}; + +static const struct genl_ops ubcore_genl_ops[] = { + { + .cmd = UBCORE_CMD_SHOW_UTP, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .doit = ubcore_show_utp_ops + }, + { + .cmd = UBCORE_CMD_QUERY_STATS, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .doit = ubcore_query_stats_ops + }, + { + .cmd = UBCORE_CMD_QUERY_RES, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .start = ubcore_query_res_start, + .dumpit = ubcore_query_res_dump, + .done = ubcore_query_res_done + }, + { + .cmd = UBCORE_CMD_ADD_EID, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .doit = ubcore_add_eid_ops + }, + { + .cmd = UBCORE_CMD_DEL_EID, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .flags = GENL_ADMIN_PERM, + .doit = ubcore_delete_eid_ops + }, + { + .cmd = UBCORE_CMD_SET_EID_MODE, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .doit = ubcore_set_eid_mode_ops + }, + { + .cmd = UBCORE_CMD_SET_NS_MODE, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .doit = ubcore_set_ns_mode_ops + }, + { + .cmd = UBCORE_CMD_SET_DEV_NS, + .policy = ubcore_policy, + .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .doit = ubcore_set_dev_ns_ops + }, +}; + + /* ubcore family definition */ + +struct genl_family ubcore_genl_family __ro_after_init = { + .hdrsize = 0, + .name = UBCORE_GENL_FAMILY_NAME, + .version = UBCORE_GENL_FAMILY_VERSION, + .maxattr = UBCORE_ATTR_MAX, + .policy = ubcore_policy, + .netnsok = true, + .module = THIS_MODULE, + .ops = ubcore_genl_ops, + .n_ops = ARRAY_SIZE(ubcore_genl_ops) +}; + +int __init ubcore_genl_init(void) +{ + return genl_register_family(&ubcore_genl_family); +} + +/* exit network namespace */ +void ubcore_genl_exit(void) +{ + (void)genl_unregister_family(&ubcore_genl_family); +} diff --git a/drivers/ub/urma/uburma/uburma_main.h b/drivers/ub/urma/ubcore/ubcore_genl.h similarity index 55% rename from drivers/ub/urma/uburma/uburma_main.h rename to drivers/ub/urma/ubcore/ubcore_genl.h index 767c3a6ade4b..c3c05abeb336 100644 --- a/drivers/ub/urma/uburma/uburma_main.h +++ b/drivers/ub/urma/ubcore/ubcore_genl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -11,19 +11,18 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * Description: uburma main header - * Author: Yan Fangfang - * Create: 2023-12-12 + * Description: define hash table ops + * Author: Zhao Yanchao + * Create: 2024-01-18 * Note: - * History: 2023-12-12: Create file + * History: 2024-01-18 Zhao Yanchao Add base code */ -#ifndef UBURMA_MAIN_H -#define UBURMA_MAIN_H +#ifndef UBCORE_GENL_H +#define UBCORE_GENL_H -#include "uburma_types.h" +#include "urma/ubcore_types.h" +int ubcore_genl_init(void) __init; +void ubcore_genl_exit(void); -int uburma_set_ns_mode(bool shared); -int uburma_set_dev_ns(char *device_name, int ns_fd); -bool uburma_dev_accessible_by_ns(struct uburma_device *ubu_dev, struct net *net); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_genl_admin.c b/drivers/ub/urma/ubcore/ubcore_genl_admin.c new file mode 100644 index 000000000000..2f867d428aab --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_genl_admin.c @@ -0,0 +1,1047 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore kernel module + * Author: Yanchao Zhao + * Create: 2024-01-18 + * Note: + * History: 2024-01-18: create file + */ +#include +#include +#include +#include +#include "ubcore_genl_define.h" +#include "urma/ubcore_api.h" +#include "ubcore_msg.h" +#include "urma/ubcore_uapi.h" +#include "ubcore_priv.h" +#include "ubcore_cmd.h" +#include "ubcore_device.h" +#include "ubcore_genl_admin.h" + +#define CB_ARGS_DEV_BUF 0 +#define CB_ARGS_CMD_TYPE 1 +#define CB_ARGS_SART_IDX 2 +#define CB_ARGS_NEXT_TYPE 3 +#define CB_ARGS_BUF_LEN 4 + +enum { + UBCORE_RES_TPG_TP_CNT, + UBCORE_RES_TPG_DSCP, + UBCORE_RES_TPG_TP_VAL, + UBCORE_RES_JTGRP_JETTY_CNT, + UBCORE_RES_JTGRP_JETTY_VAL, + UBCORE_RES_SEGVAL_SEG_CNT, + UBCORE_RES_SEGVAL_SEG_VAL, + UBCORE_RES_DEV_SEG_CNT, + UBCORE_RES_DEV_SEG_VAL, + UBCORE_RES_DEV_JFS_CNT, + UBCORE_RES_DEV_JFS_VAL, + UBCORE_RES_DEV_JFR_CNT, + UBCORE_RES_DEV_JFR_VAL, + UBCORE_RES_DEV_JFC_CNT, + UBCORE_RES_DEV_JFC_VAL, + UBCORE_RES_DEV_JETTY_CNT, + UBCORE_RES_DEV_JETTY_VAL, + UBCORE_RES_DEV_JTGRP_CNT, + UBCORE_RES_DEV_JTGRP_VAL, + UBCORE_RES_DEV_RC_CNT, + UBCORE_RES_DEV_RC_VAL, + UBCORE_RES_DEV_VTP_CNT, + UBCORE_RES_DEV_VTP_VAL, + UBCORE_RES_DEV_TP_CNT, + UBCORE_RES_DEV_TP_VAL, + UBCORE_RES_DEV_TPG_CNT, + UBCORE_RES_DEV_TPG_VAL, + UBCORE_RES_DEV_UTP_CNT, + UBCORE_RES_DEV_UTP_VAL, + UBCORE_RES_UPI_VAL, + UBCORE_RES_VTP_VAL, + UBCORE_RES_TP_VAL, + UBCORE_RES_UTP_VAL, + UBCORE_RES_JFS_VAL, + UBCORE_RES_JFR_VAL, + UBCORE_RES_JETTY_VAL, + UBCORE_RES_JFC_VAL, + UBCORE_RES_RC_VAL, + UBCORE_ATTR_RES_LAST +}; + +static void ubcore_update_pattern1_eid(struct ubcore_device *dev, + union ubcore_eid *eid, bool is_add) +{ + struct ubcore_ueid_cfg cfg; + uint32_t eid_idx = 0; + + if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) + return; + + cfg.eid = *eid; + cfg.eid_index = eid_idx; + cfg.upi = 0; + if (is_add) + (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); + else + (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); +} + +static void ubcore_update_pattern3_eid(struct ubcore_device *dev, + union ubcore_eid *eid, bool is_add) +{ + struct ubcore_ueid_cfg cfg; + uint32_t pattern3_upi = 0; + uint32_t eid_idx = 0; + + if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) + return; + + if (dev->attr.virtualization || + ubcore_find_upi_with_dev_name(dev->dev_name, &pattern3_upi) == NULL) + return; + + if (pattern3_upi != (uint32_t)UCBORE_INVALID_UPI) { + cfg.eid = *eid; + cfg.eid_index = eid_idx; + cfg.upi = pattern3_upi; + if (is_add) + (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); + else + (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); + } else { + ubcore_log_err("upi not configured\n"); + } +} + +int ubcore_show_utp_ops(struct sk_buff *skb, struct genl_info *info) +{ + struct ubcore_res_utp_val utp_info = {0}; + struct ubcore_res_key key = {0}; + struct ubcore_res_val val = {0}; + struct ubcore_cmd_show_utp arg; + struct ubcore_device *dev; + uint64_t args_addr; + int ret = -EINVAL; + + if (!info->attrs[UBCORE_HDR_ARGS_LEN] || !info->attrs[UBCORE_HDR_ARGS_ADDR]) + return ret; + args_addr = nla_get_u64(info->attrs[UBCORE_HDR_ARGS_ADDR]); + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)args_addr, + sizeof(struct ubcore_cmd_show_utp)); + if (ret != 0) + return -EPERM; + + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", + dev == NULL ? "NULL" : dev->dev_name, arg.in.dev_name); + return -EINVAL; + } + + key.type = UBCORE_RES_KEY_UTP; + key.key = arg.in.utpn; + val.addr = (uint64_t)&utp_info; + val.len = (uint32_t)sizeof(struct ubcore_res_utp_val); + if (dev->ops != NULL && dev->ops->query_res != NULL && + dev->ops->query_res(dev, &key, &val) != 0) { + ubcore_put_device(dev); + ubcore_log_err("failed to query res.\n"); + return -1; + } + ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)arg.out.addr, &utp_info, + sizeof(struct ubcore_res_utp_val)); + + ubcore_put_device(dev); + return ret; +} + +int ubcore_query_stats_ops(struct sk_buff *skb, struct genl_info *info) +{ + struct ubcore_cmd_query_stats arg = {0}; + struct ubcore_stats_com_val com_val; + struct ubcore_stats_key key = {0}; + struct ubcore_stats_val val; + struct ubcore_device *dev; + uint64_t args_addr; + int ret = -EINVAL; + + if (!info->attrs[UBCORE_HDR_ARGS_LEN] || !info->attrs[UBCORE_HDR_ARGS_ADDR]) + return ret; + args_addr = nla_get_u64(info->attrs[UBCORE_HDR_ARGS_ADDR]); + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)args_addr, + sizeof(struct ubcore_cmd_query_stats)); + if (ret != 0) + return ret; + + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", + dev == NULL ? "NULL" : dev->dev_name, arg.in.dev_name); + return -EINVAL; + } + + key.type = (uint8_t)arg.in.type; + key.key = arg.in.key; + val.addr = (uint64_t)&com_val; + val.len = (uint32_t)sizeof(struct ubcore_stats_com_val); + + ret = ubcore_query_stats(dev, &key, &val); + if (ret != 0) { + ubcore_put_device(dev); + return ret; + } + + ubcore_put_device(dev); + (void)memcpy(&arg.out, &com_val, sizeof(struct ubcore_stats_com_val)); + return ubcore_copy_to_user((void __user *)(uintptr_t)args_addr, &arg, + sizeof(struct ubcore_cmd_query_stats)); +} + +static int ubcore_update_ueid(struct genl_info *info, enum ubcore_msg_opcode op) +{ + struct ubcore_cmd_update_ueid arg; + struct net *net = &init_net; + struct ubcore_device *dev; + uint64_t args_addr; + int ret = -EINVAL; + + if (!info->attrs[UBCORE_HDR_ARGS_LEN] || !info->attrs[UBCORE_HDR_ARGS_ADDR]) + return ret; + args_addr = nla_get_u64(info->attrs[UBCORE_HDR_ARGS_ADDR]); + if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { + ubcore_log_err("current user does not have net admin capability"); + return -EPERM; + } + + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)args_addr, + sizeof(struct ubcore_cmd_update_ueid)); + if (ret != 0) + return -EPERM; + + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); + return -EPERM; + } + + if (dev->dynamic_eid) { + ubcore_log_err("The dynamic mode of pf does not support eid change\n"); + ubcore_put_device(dev); + return -EPERM; + } + if (dev->attr.tp_maintainer && ubcore_get_netlink_valid() == false) { + ubcore_put_device(dev); + return -EPERM; + } + + if (arg.in.ns_fd >= 0) { + net = get_net_ns_by_fd(arg.in.ns_fd); + if (IS_ERR(net)) { + ubcore_put_device(dev); + ubcore_log_err("Failed to get ns by fd.\n"); + return (int)PTR_ERR(net); + } + } + + if (ubcore_msg_discover_eid(dev, arg.in.eid_index, op, net) != 0) + ret = -EPERM; + + if (arg.in.ns_fd >= 0) + put_net(net); + ubcore_put_device(dev); + return ret; +} + +int ubcore_delete_eid_ops(struct sk_buff *skb, struct genl_info *info) +{ + return ubcore_update_ueid(info, UBCORE_MSG_DEALLOC_EID); +} + +int ubcore_add_eid_ops(struct sk_buff *skb, struct genl_info *info) +{ + return ubcore_update_ueid(info, UBCORE_MSG_ALLOC_EID); +} + +int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) +{ + struct ubcore_cmd_set_eid_mode arg; + struct ubcore_device *dev; + struct ubcore_event event; + union ubcore_eid eid; + uint64_t args_addr; + int ret = -EINVAL; + uint32_t i; + + if (!info->attrs[UBCORE_HDR_ARGS_LEN] || !info->attrs[UBCORE_HDR_ARGS_ADDR]) + return ret; + args_addr = nla_get_u64(info->attrs[UBCORE_HDR_ARGS_ADDR]); + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)args_addr, + sizeof(struct ubcore_cmd_set_eid_mode)); + if (ret != 0) + return -EPERM; + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); + return -EPERM; + } + if (dev->dynamic_eid == arg.in.eid_mode) { + ubcore_put_device(dev); + return 0; + } + + /* change eid mode, need to flush eids */ + event.ub_dev = dev; + event.event_type = UBCORE_EVENT_EID_CHANGE; + for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { + if (dev->eid_table.eid_entries[i].valid == true) { + eid = dev->eid_table.eid_entries[i].eid; + if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) + ubcore_update_pattern1_eid(dev, &eid, false); + else + ubcore_update_pattern3_eid(dev, &eid, false); + event.element.eid_idx = i; + ubcore_dispatch_async_event(&event); + } + } + dev->dynamic_eid = arg.in.eid_mode; + ubcore_put_device(dev); + return 0; +} + +int ubcore_set_ns_mode_ops(struct sk_buff *skb, struct genl_info *info) +{ + uint8_t ns_mode; + + if (!info->attrs[UBCORE_ATTR_NS_MODE]) + return -EINVAL; + + ns_mode = nla_get_u8(info->attrs[UBCORE_ATTR_NS_MODE]); + return ubcore_set_ns_mode((ns_mode == 0 ? false : true)); +} + +int ubcore_set_dev_ns_ops(struct sk_buff *skb, struct genl_info *info) +{ + if (!info->attrs[UBCORE_ATTR_DEV_NAME] || !info->attrs[UBCORE_ATTR_NS_FD]) + return -EINVAL; + + return ubcore_set_dev_ns((char *)nla_data(info->attrs[UBCORE_ATTR_DEV_NAME]), + nla_get_u32(info->attrs[UBCORE_ATTR_NS_FD])); +} + +static void ubcore_fill_res_binary(void *res_buf, struct sk_buff *msg, + struct netlink_callback *cb, int attrtype) +{ + if (nla_put(msg, attrtype, (int)cb->args[CB_ARGS_BUF_LEN], res_buf)) + return; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; +} + +static void ubcore_fill_res_tpg(void *res_buf, struct sk_buff *msg, struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + struct ubcore_res_tpg_val *tpg_val = res_buf; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_TPG_TP_CNT) { + if (nla_put_u32(msg, UBCORE_RES_TPG_TP_CNT, tpg_val->tp_cnt)) + return; + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_TPG_DSCP; + } + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_TPG_DSCP) { + if (nla_put_u8(msg, UBCORE_RES_TPG_DSCP, tpg_val->dscp)) + return; + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_TPG_TP_VAL; + } + + for (; idx < tpg_val->tp_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_TPG_TP_VAL, tpg_val->tp_list[idx])) + return; + cb->args[CB_ARGS_SART_IDX] = idx; + } + if (idx == tpg_val->tp_cnt) + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; +} + +static void ubcore_fill_res_jtgrp(void *res_buf, struct sk_buff *msg, struct netlink_callback *cb) +{ + struct ubcore_res_jetty_group_val *jtgrp_val = res_buf; + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_JTGRP_JETTY_CNT) { + if (nla_put_u32(msg, UBCORE_RES_JTGRP_JETTY_CNT, jtgrp_val->jetty_cnt)) + return; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_JTGRP_JETTY_VAL; + } + + for (; idx < jtgrp_val->jetty_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_JTGRP_JETTY_VAL, jtgrp_val->jetty_list[idx])) + return; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == jtgrp_val->jetty_cnt) + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; +} + +static void ubcore_fill_res_seg(void *res_buf, struct sk_buff *msg, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + struct ubcore_res_seg_val *seg_val = res_buf; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_SEGVAL_SEG_CNT) { + if (nla_put_u32(msg, UBCORE_RES_SEGVAL_SEG_CNT, seg_val->seg_cnt)) + return; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_SEGVAL_SEG_VAL; + } + for (; idx < seg_val->seg_cnt; ++idx) { + if (nla_put(msg, UBCORE_RES_SEGVAL_SEG_VAL, sizeof(struct ubcore_seg_info), + seg_val->seg_list + idx)) + return; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == seg_val->seg_cnt) + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; +} + +static int ubcore_fill_dev_seg(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_SEG_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_SEG_CNT, dev_val->seg_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_SEG_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_SEG_VAL) + return 0; + + for (; idx < dev_val->seg_cnt; ++idx) { + if (nla_put(msg, UBCORE_RES_DEV_SEG_VAL, sizeof(struct ubcore_seg_info), + dev_val->seg_list + idx)) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->seg_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFS_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_jfs(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JFS_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JFS_CNT, dev_val->jfs_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFS_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JFS_VAL) + return 0; + + for (; idx < dev_val->jfs_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JFS_VAL, dev_val->jfs_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->jfs_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFR_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_jfr(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JFR_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JFR_CNT, dev_val->jfr_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFR_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JFR_VAL) + return 0; + + for (; idx < dev_val->jfr_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JFR_VAL, dev_val->jfr_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->jfr_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFC_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_jfc(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JFC_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JFC_CNT, dev_val->jfc_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFC_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JFC_VAL) + return 0; + + for (; idx < dev_val->jfc_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JFC_VAL, dev_val->jfc_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->jfc_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JETTY_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_jetty(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JETTY_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JETTY_CNT, dev_val->jetty_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JETTY_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JETTY_VAL) + return 0; + + for (; idx < dev_val->jetty_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JETTY_VAL, dev_val->jetty_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + if (idx == dev_val->jetty_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JTGRP_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_jettygrp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JTGRP_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JTGRP_CNT, dev_val->jetty_group_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JTGRP_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JTGRP_VAL) + return 0; + + for (; idx < dev_val->jetty_group_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_JTGRP_VAL, dev_val->jetty_group_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->jetty_group_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_RC_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_rc(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_RC_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_RC_CNT, dev_val->rc_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_RC_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_RC_VAL) + return 0; + + for (; idx < dev_val->rc_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_RC_VAL, dev_val->rc_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + if (idx == dev_val->rc_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_vtp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_VTP_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_VTP_CNT, dev_val->vtp_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_VTP_VAL) + return 0; + + for (; idx < dev_val->vtp_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_VTP_VAL, dev_val->vtp_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->vtp_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TP_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_tp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_TP_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_TP_CNT, dev_val->tp_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TP_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_TP_VAL) + return 0; + + for (; idx < dev_val->tp_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_TP_VAL, dev_val->tp_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->tp_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TPG_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_tpg(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_TPG_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_TPG_CNT, dev_val->tpg_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TPG_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_TPG_VAL) + return 0; + + for (; idx < dev_val->tpg_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_TPG_VAL, dev_val->tpg_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->tpg_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_UTP_CNT; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static int ubcore_fill_dev_utp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, + struct netlink_callback *cb) +{ + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_UTP_CNT) { + if (nla_put_u32(msg, UBCORE_RES_DEV_UTP_CNT, dev_val->utp_cnt)) + return -1; + + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_UTP_VAL; + } + + if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_UTP_VAL) + return 0; + + for (; idx < dev_val->utp_cnt; ++idx) { + if (nla_put_u32(msg, UBCORE_RES_DEV_UTP_VAL, dev_val->utp_list[idx])) + return -1; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + + if (idx == dev_val->utp_cnt) { + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; + cb->args[CB_ARGS_SART_IDX] = 0; + } + return 0; +} + +static void ubcore_fill_res_dev(void *res_buf, struct sk_buff *msg, struct netlink_callback *cb) +{ + struct ubcore_res_dev_val *dev_val = res_buf; + int ret; + + ret = ubcore_fill_dev_seg(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_jfs(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_jfr(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_jfc(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_jetty(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_jettygrp(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_rc(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_vtp(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_tp(msg, dev_val, cb); + if (ret != 0) + return; + + ret = ubcore_fill_dev_tpg(msg, dev_val, cb); + if (ret != 0) + return; + + (void)ubcore_fill_dev_utp(msg, dev_val, cb); +} + +static int ubcore_fill_res(uint32_t type, void *res_buf, struct sk_buff *skb, + struct netlink_callback *cb) +{ + switch (type) { + case UBCORE_RES_KEY_TPG: + ubcore_fill_res_tpg(res_buf, skb, cb); + break; + case UBCORE_RES_KEY_JETTY_GROUP: + ubcore_fill_res_jtgrp(res_buf, skb, cb); + break; + case UBCORE_RES_KEY_SEG: + ubcore_fill_res_seg(res_buf, skb, cb); + break; + case UBCORE_RES_KEY_URMA_DEV: + ubcore_fill_res_dev(res_buf, skb, cb); + break; + case UBCORE_RES_KEY_UPI: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_UPI_VAL); + break; + case UBCORE_RES_KEY_VTP: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_VTP_VAL); + break; + case UBCORE_RES_KEY_TP: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_TP_VAL); + break; + case UBCORE_RES_KEY_UTP: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_UTP_VAL); + break; + case UBCORE_RES_KEY_JFS: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_JFS_VAL); + break; + case UBCORE_RES_KEY_JFR: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_JFR_VAL); + break; + case UBCORE_RES_KEY_JETTY: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_JETTY_VAL); + break; + case UBCORE_RES_KEY_JFC: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_JFC_VAL); + break; + case UBCORE_RES_KEY_RC: + ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_RC_VAL); + break; + default: + ubcore_log_err("key type :%u no support.\n", type); + return -1; + } + return 0; +} + +static uint32_t ubcore_get_query_res_len(uint32_t type, struct netlink_callback *cb) +{ + switch (type) { + case UBCORE_RES_KEY_UPI: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_UPI_VAL; + return (uint32_t)sizeof(struct ubcore_res_upi_val); + case UBCORE_RES_KEY_VTP: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_VTP_VAL; + return (uint32_t)sizeof(struct ubcore_res_vtp_val); + case UBCORE_RES_KEY_TP: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_TP_VAL; + return (uint32_t)sizeof(struct ubcore_res_tp_val); + case UBCORE_RES_KEY_TPG: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_TPG_TP_CNT; + return (uint32_t)sizeof(struct ubcore_res_tpg_val); + case UBCORE_RES_KEY_UTP: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_UTP_VAL; + return (uint32_t)sizeof(struct ubcore_res_utp_val); + case UBCORE_RES_KEY_JFS: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_JFS_VAL; + return (uint32_t)sizeof(struct ubcore_res_jfs_val); + case UBCORE_RES_KEY_JFR: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_JFR_VAL; + return (uint32_t)sizeof(struct ubcore_res_jfr_val); + case UBCORE_RES_KEY_JETTY: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_JETTY_VAL; + return (uint32_t)sizeof(struct ubcore_res_jetty_val); + case UBCORE_RES_KEY_JETTY_GROUP: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_JTGRP_JETTY_CNT; + return (uint32_t)sizeof(struct ubcore_res_jetty_group_val); + case UBCORE_RES_KEY_JFC: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_JFC_VAL; + return (uint32_t)sizeof(struct ubcore_res_jfc_val); + case UBCORE_RES_KEY_RC: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_RC_VAL; + return (uint32_t)sizeof(struct ubcore_res_rc_val); + case UBCORE_RES_KEY_SEG: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_SEGVAL_SEG_CNT; + return (uint32_t)sizeof(struct ubcore_res_seg_val); + case UBCORE_RES_KEY_URMA_DEV: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_SEG_CNT; + return (uint32_t)sizeof(struct ubcore_res_dev_val); + default: + break; + } + return 0; +} + +static void *ubcore_query_dev_info(struct ubcore_device *dev, struct ubcore_cmd_query_res *arg, + uint32_t res_len) +{ + struct ubcore_res_key key = {0}; + struct ubcore_res_val val = {0}; + void *res_buf; + int ret; + + res_buf = kzalloc(res_len, GFP_KERNEL); + if (res_buf == NULL) + return NULL; + + key.type = (uint8_t)arg->in.type; + key.key = arg->in.key; + key.key_ext = arg->in.key_ext; + key.key_cnt = arg->in.key_cnt; + val.addr = (uint64_t)res_buf; + val.len = res_len; + + // urma only alloc memory for the struct + // driver will alloc memory for the list pointer in the struct; urma need to vfree it later + + ret = ubcore_query_resource(dev, &key, &val); + if (ret != 0) { + kfree(res_buf); + res_buf = NULL; + } + + return res_buf; +} + +static int parse_query_res_cmd(struct netlink_callback *cb, struct ubcore_cmd_query_res *arg) +{ + struct nlattr **attrs = genl_dumpit_info(cb)->attrs; + uint64_t args_addr; + + if (!attrs[UBCORE_HDR_ARGS_LEN] || !attrs[UBCORE_HDR_ARGS_ADDR]) + return -EINVAL; + + args_addr = nla_get_u64(attrs[UBCORE_HDR_ARGS_ADDR]); + + return ubcore_copy_from_user(arg, (void __user *)(uintptr_t)args_addr, + sizeof(struct ubcore_cmd_query_res)); +} + +int ubcore_query_res_start(struct netlink_callback *cb) +{ + struct ubcore_cmd_query_res arg = {0}; + struct ubcore_device *dev; + int ret = -EINVAL; + uint32_t res_len; + void *res_buf; + + ret = parse_query_res_cmd(cb, &arg); + if (ret) + return ret; + + res_len = ubcore_get_query_res_len((uint32_t)arg.in.type, cb); + if (res_len == 0) { + ubcore_log_err("Failed to check res len, type: %u, res_len: %u.\n", + (uint32_t)arg.in.type, res_len); + return -EINVAL; + } + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_err("find dev failed, arg_in: %s.\n", arg.in.dev_name); + return -EINVAL; + } + + if (arg.in.type == (uint32_t)UBCORE_RES_KEY_VTP && dev->attr.virtualization == true) { + ubcore_log_warn("FE device do not support query VTP, dev: %s, type: %u.\n", + dev->dev_name, arg.in.type); + ubcore_put_device(dev); + return -EINVAL; + } + + res_buf = ubcore_query_dev_info(dev, &arg, res_len); + if (!res_buf) { + ubcore_put_device(dev); + ubcore_log_err("Failed to query res by arg\n"); + return -1; + } + ubcore_put_device(dev); + cb->args[CB_ARGS_DEV_BUF] = (long)res_buf; + cb->args[CB_ARGS_CMD_TYPE] = (long)arg.in.type; + cb->args[CB_ARGS_SART_IDX] = 0; + cb->args[CB_ARGS_BUF_LEN] = res_len; + return 0; +} + +static void ubcore_free_res_dev_list(struct ubcore_res_dev_val *kernal_addr) +{ + vfree(kernal_addr->seg_list); + vfree(kernal_addr->jfs_list); + vfree(kernal_addr->jfr_list); + vfree(kernal_addr->jfc_list); + vfree(kernal_addr->jetty_list); + vfree(kernal_addr->jetty_group_list); + vfree(kernal_addr->rc_list); + vfree(kernal_addr->vtp_list); + vfree(kernal_addr->tp_list); + vfree(kernal_addr->tpg_list); + vfree(kernal_addr->utp_list); +} + +int ubcore_query_res_done(struct netlink_callback *cb) +{ + uint32_t type = (uint32_t)(unsigned long)cb->args[CB_ARGS_CMD_TYPE]; + void *res_buf = (void *)cb->args[CB_ARGS_DEV_BUF]; + struct ubcore_res_jetty_group_val *jtgrp_val; + struct ubcore_res_seg_val *seg_val; + struct ubcore_res_dev_val *dev_val; + struct ubcore_res_tpg_val *tpg_val; + + switch (type) { + case UBCORE_RES_KEY_TPG: + tpg_val = res_buf; + vfree(tpg_val->tp_list); + break; + case UBCORE_RES_KEY_JETTY_GROUP: + jtgrp_val = res_buf; + vfree(jtgrp_val->jetty_list); + break; + case UBCORE_RES_KEY_SEG: + seg_val = res_buf; + vfree(seg_val->seg_list); + break; + case UBCORE_RES_KEY_URMA_DEV: + dev_val = res_buf; + ubcore_free_res_dev_list(dev_val); + break; + default: + break; + } + kfree(res_buf); + + return 0; +} + +int ubcore_query_res_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + uint32_t type = (uint32_t)cb->args[CB_ARGS_CMD_TYPE]; + void *res_buf = (void *)cb->args[CB_ARGS_DEV_BUF]; + void *hdr; + int ret; + + if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_ATTR_RES_LAST) + return 0; + + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, &ubcore_genl_family, + NLM_F_MULTI, UBCORE_CMD_QUERY_RES); + if (!hdr) + return 0; + + ret = ubcore_fill_res(type, res_buf, skb, cb); + if (ret < 0) + genlmsg_cancel(skb, hdr); + else + genlmsg_end(skb, hdr); + + return (int)skb->len; +} diff --git a/drivers/ub/urma/ubcore/ubcore_genl_admin.h b/drivers/ub/urma/ubcore/ubcore_genl_admin.h new file mode 100644 index 000000000000..84932736e37e --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_genl_admin.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: define hash table ops for admin + * Author: Zhao Yanchao + * Create: 2024-01-18 + * Note: + * History: 2024-01-18 Zhao Yanchao + */ + +#ifndef UBCORE_GENL_ADMIN_H +#define UBCORE_GENL_ADMIN_H + +#include + +int ubcore_show_utp_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_query_stats_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_query_res_start(struct netlink_callback *cb); +int ubcore_query_res_dump(struct sk_buff *skb, struct netlink_callback *cb); +int ubcore_query_res_done(struct netlink_callback *cb); +int ubcore_add_eid_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_delete_eid_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_set_ns_mode_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_set_dev_ns_ops(struct sk_buff *skb, struct genl_info *info); +extern struct genl_family ubcore_genl_family; + +#endif // UBCORE_GENERIC_NETLINK_ADMIN_H diff --git a/drivers/ub/urma/ubcore/ubcore_genl_define.h b/drivers/ub/urma/ubcore/ubcore_genl_define.h new file mode 100644 index 000000000000..930518f20d80 --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_genl_define.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore GENERIC NETLINK + * Author: Zhao yanchao + * Create: 2024-01-25 + * Note: + * History: 2024-01-25 Zhao yanchao Add base code + */ + +#ifndef UBCORE_GENERIC_NETLINK_DEFINE_H +#define UBCORE_GENERIC_NETLINK_DEFINE_H + +/* NETLINK_GENERIC related info */ +#define UBCORE_GENL_FAMILY_NAME "UBCORE_GENL" +#define UBCORE_GENL_FAMILY_VERSION 1 + +enum { + UBCORE_ATTR_UNSPEC, + UBCORE_HDR_COMMAND, + UBCORE_HDR_ARGS_LEN, + UBCORE_HDR_ARGS_ADDR, + UBCORE_ATTR_NS_MODE, + UBCORE_ATTR_DEV_NAME, + UBCORE_ATTR_NS_FD, + UBCORE_ATTR_AFTER_LAST, + NUM_UBCORE_ATTR = UBCORE_ATTR_AFTER_LAST, + UBCORE_ATTR_MAX = UBCORE_ATTR_AFTER_LAST - 1 +}; + +#endif // UBCORE_GENERIC_NETLINK_DEFINE_H diff --git a/drivers/ub/urma/ubcore/ubcore_jetty.c b/drivers/ub/urma/ubcore/ubcore_jetty.c index c8b63db5d5af..6cb7b410d350 100644 --- a/drivers/ub/urma/ubcore/ubcore_jetty.c +++ b/drivers/ub/urma/ubcore/ubcore_jetty.c @@ -36,18 +36,30 @@ struct ubcore_jfc *ubcore_find_jfc(struct ubcore_device *dev, uint32_t jfc_id) { + if (dev == NULL) { + ubcore_log_err("dev is NULL\n"); + return NULL; + } return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_JFC], jfc_id, &jfc_id); } EXPORT_SYMBOL(ubcore_find_jfc); struct ubcore_jfs *ubcore_find_jfs(struct ubcore_device *dev, uint32_t jfs_id) { + if (dev == NULL) { + ubcore_log_err("dev is NULL\n"); + return NULL; + } return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_JFS], jfs_id, &jfs_id); } EXPORT_SYMBOL(ubcore_find_jfs); struct ubcore_jfr *ubcore_find_jfr(struct ubcore_device *dev, uint32_t jfr_id) { + if (dev == NULL) { + ubcore_log_err("dev is NULL\n"); + return NULL; + } return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_JFR], jfr_id, &jfr_id); } EXPORT_SYMBOL(ubcore_find_jfr); @@ -69,7 +81,7 @@ struct ubcore_jfc *ubcore_create_jfc(struct ubcore_device *dev, struct ubcore_jf { struct ubcore_jfc *jfc; - if (dev == NULL || cfg == NULL || dev->ops->create_jfc == NULL || + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jfc == NULL || dev->ops->destroy_jfc == NULL) return NULL; @@ -106,14 +118,15 @@ int ubcore_modify_jfc(struct ubcore_jfc *jfc, struct ubcore_jfc_attr *attr, uint32_t jfc_id; int ret; - if (jfc == NULL || jfc->ub_dev == NULL || jfc->ub_dev->ops->modify_jfc == NULL) + if (jfc == NULL || jfc->ub_dev == NULL || jfc->ub_dev->ops == NULL || + jfc->ub_dev->ops->modify_jfc == NULL) return -EINVAL; jfc_id = jfc->id; dev = jfc->ub_dev; ret = dev->ops->modify_jfc(jfc, attr, udata); - if (ret < 0) + if (ret != 0) ubcore_log_err("UBEP failed to modify jfc, jfc_id:%u.\n", jfc_id); return ret; @@ -126,7 +139,8 @@ int ubcore_delete_jfc(struct ubcore_jfc *jfc) uint32_t jfc_id; int ret; - if (jfc == NULL || jfc->ub_dev == NULL || jfc->ub_dev->ops->destroy_jfc == NULL) + if (jfc == NULL || jfc->ub_dev == NULL || jfc->ub_dev->ops == NULL || + jfc->ub_dev->ops->destroy_jfc == NULL) return -1; if (atomic_read(&jfc->use_cnt)) { @@ -138,7 +152,7 @@ int ubcore_delete_jfc(struct ubcore_jfc *jfc) dev = jfc->ub_dev; ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFC], &jfc->hnode); ret = dev->ops->destroy_jfc(jfc); - if (ret < 0) { + if (ret != 0) { ubcore_log_err("UBEP failed to destroy jfc, jfc_id:%u.\n", jfc_id); goto rollback; } @@ -202,7 +216,7 @@ struct ubcore_jfs *ubcore_create_jfs(struct ubcore_device *dev, struct ubcore_jf { struct ubcore_jfs *jfs; - if (dev == NULL || cfg == NULL || dev->ops->create_jfs == NULL || + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jfs == NULL || dev->ops->destroy_jfs == NULL) return NULL; @@ -257,13 +271,14 @@ int ubcore_modify_jfs(struct ubcore_jfs *jfs, struct ubcore_jfs_attr *attr, uint32_t jfs_id; int ret; - if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops->modify_jfs == NULL) + if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops == NULL || + jfs->ub_dev->ops->modify_jfs == NULL) return -EINVAL; jfs_id = jfs->id; dev = jfs->ub_dev; ret = dev->ops->modify_jfs(jfs, attr, udata); - if (ret < 0) + if (ret != 0) ubcore_log_err("UBEP failed to modify jfs, jfs_id:%u.\n", jfs_id); return ret; @@ -277,13 +292,14 @@ int ubcore_query_jfs(struct ubcore_jfs *jfs, struct ubcore_jfs_cfg *cfg, uint32_t jfs_id; int ret; - if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops->query_jfs == NULL) + if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops == NULL + || jfs->ub_dev->ops->query_jfs == NULL) return -EINVAL; jfs_id = jfs->id; dev = jfs->ub_dev; ret = dev->ops->query_jfs(jfs, cfg, attr); - if (ret < 0) + if (ret != 0) ubcore_log_err("UBEP failed to query jfs, jfs_id:%u.\n", jfs_id); return ret; @@ -297,7 +313,8 @@ int ubcore_delete_jfs(struct ubcore_jfs *jfs) uint32_t jfs_id; int ret; - if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops->destroy_jfs == NULL) + if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops == NULL || + jfs->ub_dev->ops->destroy_jfs == NULL) return -EINVAL; jfc = jfs->jfs_cfg.jfc; @@ -306,7 +323,7 @@ int ubcore_delete_jfs(struct ubcore_jfs *jfs) ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFS], &jfs->hnode); ubcore_destroy_tptable(&jfs->tptable); ret = dev->ops->destroy_jfs(jfs); - if (ret < 0) { + if (ret != 0) { ubcore_log_err("UBEP failed to destroy jfs, jfs_id:%u.\n", jfs_id); goto rollback; } else { @@ -359,7 +376,7 @@ struct ubcore_jfr *ubcore_create_jfr(struct ubcore_device *dev, struct ubcore_jf { struct ubcore_jfr *jfr; - if (dev == NULL || cfg == NULL || dev->ops->create_jfr == NULL || + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jfr == NULL || dev->ops->destroy_jfr == NULL) return NULL; @@ -406,13 +423,14 @@ int ubcore_modify_jfr(struct ubcore_jfr *jfr, struct ubcore_jfr_attr *attr, uint32_t jfr_id; int ret; - if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops->modify_jfr == NULL) + if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops == NULL || + jfr->ub_dev->ops->modify_jfr == NULL) return -EINVAL; jfr_id = jfr->id; dev = jfr->ub_dev; ret = dev->ops->modify_jfr(jfr, attr, udata); - if (ret < 0) + if (ret != 0) ubcore_log_err("UBEP failed to modify jfr, jfr_id:%u.\n", jfr_id); return ret; @@ -426,13 +444,14 @@ int ubcore_query_jfr(struct ubcore_jfr *jfr, struct ubcore_jfr_cfg *cfg, uint32_t jfr_id; int ret; - if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops->query_jfr == NULL) + if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops == NULL || + jfr->ub_dev->ops->query_jfr == NULL) return -EINVAL; jfr_id = jfr->id; dev = jfr->ub_dev; ret = dev->ops->query_jfr(jfr, cfg, attr); - if (ret < 0) + if (ret != 0) ubcore_log_err("UBEP failed to query jfr, jfr_id:%u.\n", jfr_id); return ret; @@ -446,7 +465,8 @@ int ubcore_delete_jfr(struct ubcore_jfr *jfr) uint32_t jfr_id; int ret; - if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops->destroy_jfr == NULL) + if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops == NULL || + jfr->ub_dev->ops->destroy_jfr == NULL) return -EINVAL; if (atomic_read(&jfr->use_cnt)) { @@ -460,7 +480,7 @@ int ubcore_delete_jfr(struct ubcore_jfr *jfr) ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFR], &jfr->hnode); ubcore_destroy_tptable(&jfr->tptable); ret = dev->ops->destroy_jfr(jfr); - if (ret < 0) { + if (ret != 0) { ubcore_log_err("UBEP failed to destroy jfr, jfr_id:%u.\n", jfr_id); goto rollback; } else { @@ -483,8 +503,9 @@ struct ubcore_tjetty *ubcore_import_jfr(struct ubcore_device *dev, struct ubcore_vtp_param vtp_param; struct ubcore_tjetty *tjfr; - if (dev == NULL || cfg == NULL || dev->ops->import_jfr == NULL || - dev->ops->unimport_jfr == NULL || !ubcore_have_tp_ops(dev)) + if (!ubcore_have_tp_ops(dev) || dev->ops->import_jetty == NULL || + dev->ops->unimport_jfr == NULL || cfg == NULL || + dev->attr.dev_cap.max_eid_cnt < cfg->eid_index) return NULL; tjfr = dev->ops->import_jfr(dev, cfg, udata); @@ -525,7 +546,8 @@ int ubcore_unimport_jfr(struct ubcore_tjetty *tjfr) struct ubcore_device *dev; int ret; - if (tjfr == NULL || tjfr->ub_dev == NULL || tjfr->ub_dev->ops->unimport_jfr == NULL || + if (tjfr == NULL || tjfr->ub_dev == NULL || tjfr->ub_dev->ops == NULL || + tjfr->ub_dev->ops->unimport_jfr == NULL || !ubcore_have_tp_ops(tjfr->ub_dev)) return -EINVAL; @@ -542,8 +564,8 @@ int ubcore_unimport_jfr(struct ubcore_tjetty *tjfr) } tjfr->vtpn = NULL; mutex_unlock(&tjfr->lock); - mutex_destroy(&tjfr->lock); } + mutex_destroy(&tjfr->lock); return dev->ops->unimport_jfr(tjfr); } EXPORT_SYMBOL(ubcore_unimport_jfr); @@ -722,7 +744,7 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor { struct ubcore_jetty *jetty; - if (dev == NULL || cfg == NULL || dev->ops->create_jetty == NULL || + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jetty == NULL || dev->ops->destroy_jetty == NULL) return NULL; @@ -799,19 +821,18 @@ EXPORT_SYMBOL(ubcore_create_jetty); int ubcore_modify_jetty(struct ubcore_jetty *jetty, struct ubcore_jetty_attr *attr, struct ubcore_udata *udata) { - struct ubcore_device *dev; uint32_t jetty_id; int ret; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops->modify_jetty == NULL || + if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || + jetty->ub_dev->ops->modify_jetty == NULL || attr == NULL) return -EINVAL; jetty_id = jetty->id; - dev = jetty->ub_dev; - ret = dev->ops->modify_jetty(jetty, attr, udata); - if (ret < 0) + ret = jetty->ub_dev->ops->modify_jetty(jetty, attr, udata); + if (ret != 0) ubcore_log_err("UBEP failed to modify jetty, jetty_id:%u.\n", jetty_id); return ret; @@ -825,13 +846,14 @@ int ubcore_query_jetty(struct ubcore_jetty *jetty, struct ubcore_jetty_cfg *cfg, uint32_t jetty_id; int ret; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops->query_jetty == NULL) + if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || + jetty->ub_dev->ops->query_jetty == NULL) return -EINVAL; jetty_id = jetty->id; dev = jetty->ub_dev; ret = dev->ops->query_jetty(jetty, cfg, attr); - if (ret < 0) + if (ret != 0) ubcore_log_err("UBEP failed to query jetty, jetty_id:%u.\n", jetty_id); return ret; @@ -848,7 +870,8 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) uint32_t jetty_id; int ret; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops->destroy_jetty == NULL) + if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || + jetty->ub_dev->ops->destroy_jetty == NULL) return -1; if ((jetty->ub_dev->transport_type == UBCORE_TRANSPORT_UB && @@ -872,7 +895,7 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) (void)ubcore_disconnect_vtp(jetty->remote_jetty->vtpn); jetty->remote_jetty->vtpn = NULL; mutex_unlock(&jetty->remote_jetty->lock); - atomic_set(&jetty->remote_jetty->use_cnt, 0); + atomic_dec(&jetty->remote_jetty->use_cnt); /* The tjetty object will release remote jetty resources */ jetty->remote_jetty = NULL; ubcore_log_warn("jetty->remote_jetty != NULL and it has been handled"); @@ -906,16 +929,13 @@ EXPORT_SYMBOL(ubcore_delete_jetty); int ubcore_flush_jetty(struct ubcore_jetty *jetty, int cr_cnt, struct ubcore_cr *cr) { - struct ubcore_ops *dev_ops; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || jetty->ub_dev->ops->flush_jetty == NULL || cr == NULL) { ubcore_log_err("Invalid parameter"); return -EINVAL; } - dev_ops = jetty->ub_dev->ops; - return dev_ops->flush_jetty(jetty, cr_cnt, cr); + return jetty->ub_dev->ops->flush_jetty(jetty, cr_cnt, cr); } EXPORT_SYMBOL(ubcore_flush_jetty); @@ -925,8 +945,9 @@ struct ubcore_tjetty *ubcore_import_jetty(struct ubcore_device *dev, struct ubcore_vtp_param vtp_param; struct ubcore_tjetty *tjetty; - if (dev == NULL || cfg == NULL || dev->ops->import_jetty == NULL || - dev->ops->unimport_jetty == NULL || !ubcore_have_tp_ops(dev)) + if (!ubcore_have_tp_ops(dev) || dev->ops->import_jetty == NULL || + dev->ops->unimport_jfr == NULL || cfg == NULL || + dev->attr.dev_cap.max_eid_cnt < cfg->eid_index) return NULL; tjetty = dev->ops->import_jetty(dev, cfg, udata); @@ -968,7 +989,7 @@ int ubcore_unimport_jetty(struct ubcore_tjetty *tjetty) struct ubcore_device *dev; int ret; - if (tjetty == NULL || tjetty->ub_dev == NULL || + if (tjetty == NULL || tjetty->ub_dev == NULL || tjetty->ub_dev->ops == NULL || tjetty->ub_dev->ops->unimport_jetty == NULL || !ubcore_have_tp_ops(tjetty->ub_dev)) return -EINVAL; @@ -987,12 +1008,13 @@ int ubcore_unimport_jetty(struct ubcore_tjetty *tjetty) } tjetty->vtpn = NULL; mutex_unlock(&tjetty->lock); - mutex_destroy(&tjetty->lock); } if (tjetty->cfg.trans_mode == UBCORE_TP_RC && atomic_read(&tjetty->use_cnt)) return -EBUSY; + mutex_destroy(&tjetty->lock); + return dev->ops->unimport_jetty(tjetty); } EXPORT_SYMBOL(ubcore_unimport_jetty); @@ -1155,39 +1177,26 @@ int ubcore_unadvise_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjet } EXPORT_SYMBOL(ubcore_unadvise_jetty); -int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, - struct ubcore_udata *udata) +static int ubcore_inner_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, + struct ubcore_udata *udata) { struct ubcore_vtp_param vtp_param; struct ubcore_tp_advice advice; struct ubcore_device *dev; int ret; - if (jetty == NULL || tjetty == NULL || !ubcore_have_tp_ops(jetty->ub_dev)) { - ubcore_log_err("invalid parameter.\n"); - return -1; - } - if ((jetty->jetty_cfg.trans_mode != UBCORE_TP_RC) || - (tjetty->cfg.trans_mode != UBCORE_TP_RC)) { - ubcore_log_err("trans mode is not rc type.\n"); - return -1; - } - if (jetty->remote_jetty != NULL) { - ubcore_log_err("The same jetty, different tjetty, prevent duplicate bind.\n"); - return -1; - } - - if (tjetty->vtpn != NULL) { - ubcore_log_err("The tjetty, has already connect vtpn, prevent duplicate bind.\n"); - return -1; - } - dev = jetty->ub_dev; if (dev == NULL) { ubcore_log_err("Invalid parameter with dev null_ptr.\n"); return -1; } + if (dev->attr.dev_cap.max_eid_cnt < tjetty->cfg.eid_index) { + ubcore_log_err("eid_index:%u is beyond the max_eid_cnt:%u.\n", + tjetty->cfg.eid_index, dev->attr.dev_cap.max_eid_cnt); + return -EINVAL; + } + if (dev->transport_type == UBCORE_TRANSPORT_UB) { struct ubcore_vtpn *vtpn; /* IB devices don't need to call bind_jetty and unbind_jetty */ @@ -1224,7 +1233,7 @@ int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, ubcore_put_advice(&advice); if (ret != 0) { ubcore_log_err("Failed to setup tp connection.\n"); - goto unbind; + return ret; } } ubcore_log_info("jetty: %u bind tjetty: %u\n", jetty->id, tjetty->cfg.id.id); @@ -1240,6 +1249,36 @@ int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, return ret; } + +int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, + struct ubcore_udata *udata) +{ + if (jetty == NULL || tjetty == NULL || !ubcore_have_tp_ops(jetty->ub_dev)) { + ubcore_log_err("invalid parameter.\n"); + return -1; + } + if ((jetty->jetty_cfg.trans_mode != UBCORE_TP_RC) || + (tjetty->cfg.trans_mode != UBCORE_TP_RC)) { + ubcore_log_err("trans mode is not rc type.\n"); + return -1; + } + if (jetty->remote_jetty == tjetty) { + ubcore_log_info("bind reentry, jetty: %u bind tjetty: %u\n", + jetty->id, tjetty->cfg.id.id); + return 0; + } + if (jetty->remote_jetty != NULL) { + ubcore_log_err("The same jetty, different tjetty, prevent duplicate bind.\n"); + return -1; + } + + if (tjetty->vtpn != NULL) { + ubcore_log_err("The tjetty, has already connect vtpn, prevent duplicate bind.\n"); + return -1; + } + + return ubcore_inner_bind_jetty(jetty, tjetty, udata); +} EXPORT_SYMBOL(ubcore_bind_jetty); int ubcore_unbind_jetty(struct ubcore_jetty *jetty) @@ -1261,10 +1300,6 @@ int ubcore_unbind_jetty(struct ubcore_jetty *jetty) } dev = jetty->ub_dev; - if (dev == NULL) { - ubcore_log_err("invalid parameter.\n"); - return -1; - } if (dev->transport_type == UBCORE_TRANSPORT_UB) { if (tjetty->vtpn != NULL) { @@ -1315,6 +1350,11 @@ EXPORT_SYMBOL(ubcore_unbind_jetty); struct ubcore_jetty *ubcore_find_jetty(struct ubcore_device *dev, uint32_t jetty_id) { + if (dev == NULL) { + ubcore_log_err("invalid parameter.\n"); + return NULL; + } + return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_JETTY], jetty_id, &jetty_id); } EXPORT_SYMBOL(ubcore_find_jetty); @@ -1324,13 +1364,20 @@ struct ubcore_jetty_group *ubcore_create_jetty_grp(struct ubcore_device *dev, struct ubcore_udata *udata) { struct ubcore_jetty_group *jetty_grp; - uint32_t max_jetty_in_jetty_grp = dev->attr.dev_cap.max_jetty_in_jetty_grp; + uint32_t max_jetty_in_jetty_grp; uint32_t i; - if (dev == NULL || cfg == NULL || + if (dev == NULL || cfg == NULL || udata == NULL || dev->ops == NULL || dev->ops->create_jetty_grp == NULL || dev->ops->delete_jetty_grp == NULL) return NULL; + max_jetty_in_jetty_grp = dev->attr.dev_cap.max_jetty_in_jetty_grp; + if (max_jetty_in_jetty_grp == 0 || max_jetty_in_jetty_grp > UBCORE_MAX_JETTY_IN_JETTY_GRP) { + ubcore_log_err("max_jetty_in_jetty_grp %u is err, range is 1 to %u.\n", + max_jetty_in_jetty_grp, UBCORE_MAX_JETTY_IN_JETTY_GRP); + return NULL; + } + jetty_grp = dev->ops->create_jetty_grp(dev, (struct ubcore_jetty_grp_cfg *)cfg, udata); if (jetty_grp == NULL) { ubcore_log_err("failed to create jetty_grp.\n"); @@ -1364,7 +1411,7 @@ int ubcore_delete_jetty_grp(struct ubcore_jetty_group *jetty_grp) uint32_t jetty_grp_id; int ret; - if (jetty_grp == NULL || jetty_grp->ub_dev == NULL || + if (jetty_grp == NULL || jetty_grp->ub_dev == NULL || jetty_grp->ub_dev->ops == NULL || jetty_grp->ub_dev->ops->delete_jetty_grp == NULL) return -EINVAL; @@ -1385,7 +1432,7 @@ int ubcore_delete_jetty_grp(struct ubcore_jetty_group *jetty_grp) mutex_destroy(&jetty_grp->lock); ret = dev->ops->delete_jetty_grp(jetty_grp); - if (ret < 0) + if (ret != 0) ubcore_log_err( "UBEP failed to destroy jetty_grp, jetty_grp_id:%u.\n", jetty_grp_id); diff --git a/drivers/ub/urma/ubcore/ubcore_log.c b/drivers/ub/urma/ubcore/ubcore_log.c new file mode 100644 index 000000000000..995cba6cbff4 --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_log.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore log file + * Author: Qian Guoxin + * Create: 2024-2-5 + * Note: + * History: 2024-2-5: Create file + */ + +#include +#include "ubcore_log.h" + +uint32_t g_ubcore_log_level = UBCORE_LOG_LEVEL_INFO; diff --git a/drivers/ub/urma/ubcore/ubcore_log.h b/drivers/ub/urma/ubcore/ubcore_log.h index c9a8021d60eb..921663651df1 100644 --- a/drivers/ub/urma/ubcore/ubcore_log.h +++ b/drivers/ub/urma/ubcore/ubcore_log.h @@ -21,16 +21,45 @@ #ifndef UBCORE_LOG_H #define UBCORE_LOG_H +#include +#include + +enum ubcore_log_level { + UBCORE_LOG_LEVEL_EMERG = 0, + UBCORE_LOG_LEVEL_ALERT = 1, + UBCORE_LOG_LEVEL_CRIT = 2, + UBCORE_LOG_LEVEL_ERR = 3, + UBCORE_LOG_LEVEL_WARNING = 4, + UBCORE_LOG_LEVEL_NOTICE = 5, + UBCORE_LOG_LEVEL_INFO = 6, + UBCORE_LOG_LEVEL_DEBUG = 7, + UBCORE_LOG_LEVEL_MAX = 8, +}; + /* add log head info, "LogTag_UBCORE|function|[line]| */ #define UBCORE_LOG_TAG "LogTag_UBCORE" #define ubcore_log(l, format, args...) \ - ((void)pr_##l("%s|%s:[%d]|" format, UBCORE_LOG_TAG, __func__, __LINE__, ##args)) + pr_##l("%s|%s:[%d]|" format, UBCORE_LOG_TAG, __func__, __LINE__, ##args) + +extern uint32_t g_ubcore_log_level; -#define ubcore_log_info(...) ubcore_log(info, __VA_ARGS__) +#define ubcore_log_info(...) do { \ + if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_INFO) \ + ubcore_log(info, __VA_ARGS__); \ +} while (0) -#define ubcore_log_err(...) ubcore_log(err, __VA_ARGS__) +#define ubcore_log_err(...) do { \ + if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_ERR) \ + ubcore_log(err, __VA_ARGS__); \ +} while (0) -#define ubcore_log_warn(...) ubcore_log(warn, __VA_ARGS__) +#define ubcore_log_warn(...) do { \ + if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_WARNING) \ + ubcore_log(warn, __VA_ARGS__); \ +} while (0) -#define ubcore_log_debug(...) ubcore_log(debug, __VA_ARGS__) +#define ubcore_log_debug(...) do { \ + if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_DEBUG) \ + ubcore_log(debug, __VA_ARGS__); \ +} while (0) #endif diff --git a/drivers/ub/urma/ubcore/ubcore_main.c b/drivers/ub/urma/ubcore/ubcore_main.c index 677f1724943c..9b0a806a41ec 100644 --- a/drivers/ub/urma/ubcore/ubcore_main.c +++ b/drivers/ub/urma/ubcore/ubcore_main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "ubcore_cmd.h" #include "ubcore_uvs_cmd.h" @@ -39,14 +40,23 @@ #include "ubcore_priv.h" #include "ubcore_netdev.h" #include "ubcore_msg.h" +#include "ubcore_genl.h" +#include "ubcore_workqueue.h" +#include "ubcore_device.h" + +#define UBCORE_LOG_FILE_PERMISSION (0644) + +module_param(g_ubcore_log_level, uint, UBCORE_LOG_FILE_PERMISSION); +MODULE_PARM_DESC(g_ubcore_log_level, " 3: ERR, 4: WARNING, 6: INFO, 7: DEBUG"); /* ubcore create independent cdev and ioctl channels * to handle public work. */ #define UBCORE_DEVICE_NAME "ubcore" -#define UBCORE_CLASS_NAME "ubus" #define UBCORE_IPV4_MAP_IPV6_PREFIX 0x0000ffff #define UBCORE_LOCAL_SHUNET (0xfe80000000000000ULL) +#define SIP_MTU_BITS_BASE_SHIFT 7 + struct ubcore_ctx { dev_t ubcore_devno; @@ -63,141 +73,44 @@ struct ubcore_net_addr_node { uint32_t prefix_len; }; -int ubcore_open(struct inode *i_node, struct file *filp) -{ - return 0; -} - -static int ubcore_cmd_show_utp(struct ubcore_cmd_hdr *hdr) -{ - struct ubcore_res_utp_val utp_info = {0}; - struct ubcore_res_key key = {0}; - struct ubcore_res_val val = {0}; - struct ubcore_cmd_show_utp arg; - struct ubcore_device *dev; - int ret; - - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, - sizeof(struct ubcore_cmd_show_utp)); - if (ret != 0) - return -EPERM; - - dev = ubcore_find_device_with_name(arg.in.dev_name); - if (dev == NULL || ubcore_check_dev_name_invalid(dev, arg.in.dev_name)) { - ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", - dev == NULL ? "NULL" : dev->dev_name, arg.in.dev_name); - return -EINVAL; - } - - key.type = UBCORE_RES_KEY_UTP; - key.key = arg.in.utpn; - val.addr = (uint64_t)&utp_info; - val.len = (uint32_t)sizeof(struct ubcore_res_utp_val); - if (dev->ops != NULL && dev->ops->query_res != NULL && - dev->ops->query_res(dev, &key, &val) != 0) { - ubcore_put_device(dev); - ubcore_log_err("failed to query res.\n"); - return -1; - } - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)arg.out.addr, &utp_info, - sizeof(struct ubcore_res_utp_val)); - - ubcore_put_device(dev); - return ret; -} - -static int ubcore_cmd_query_stats(struct ubcore_cmd_hdr *hdr) -{ - struct ubcore_cmd_query_stats arg = {0}; - struct ubcore_stats_com_val com_val; - struct ubcore_stats_key key = {0}; - struct ubcore_stats_val val; - struct ubcore_device *dev; - int ret; - - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, - sizeof(struct ubcore_cmd_query_stats)); - if (ret != 0) - return ret; - - dev = ubcore_find_device_with_name(arg.in.dev_name); - if (dev == NULL || ubcore_check_dev_name_invalid(dev, arg.in.dev_name)) { - ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", - dev == NULL ? "NULL" : dev->dev_name, arg.in.dev_name); - return -EINVAL; - } +enum ubcore_bond_op_type { + UBCORE_BOND_ADD = 0, + UBCORE_BOND_REMOVE, + UBCORE_BOND_SLAVE_UPDATE +}; - key.type = (uint8_t)arg.in.type; - key.key = arg.in.key; - val.addr = (uint64_t)&com_val; - val.len = (uint32_t)sizeof(struct ubcore_stats_com_val); +struct ubcore_bond_event_work { + struct work_struct work; + struct netdev_lag_upper_info info_upper; + struct netdev_lag_lower_state_info info_lower; + enum ubcore_bond_op_type bond_op_type; + struct net_device *slave; + struct net_device *bond; + int (*bond_add)(struct net_device *bond, struct net_device *slave, + struct netdev_lag_upper_info *upper_info); + int (*bond_remove)(struct net_device *bond, struct net_device *slave); + int (*slave_update)(struct net_device *bond, struct net_device *slave, + struct netdev_lag_lower_state_info *lower_info); +}; - ret = ubcore_query_stats(dev, &key, &val); - if (ret != 0) { - ubcore_put_device(dev); - return ret; - } +enum ubcore_sip_op_type { + UBCORE_SIP_DEL = 0, + UBCORE_SIP_ADD, + UBCORE_SIP_UPDATE +}; - ubcore_put_device(dev); - (void)memcpy(&arg.out, &com_val, sizeof(struct ubcore_stats_com_val)); - return ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, - sizeof(struct ubcore_cmd_query_stats)); -} +struct ubcore_notify_uvs_sip_event_work { + struct work_struct work; + struct ubcore_device *tpf_dev; + struct ubcore_sip_info new_sip; + struct ubcore_sip_info old_sip; + enum ubcore_sip_op_type sip_op; + uint32_t index; +}; -static int ubcore_cmd_update_ueid(struct ubcore_cmd_hdr *hdr, enum ubcore_msg_opcode op) +int ubcore_open(struct inode *i_node, struct file *filp) { - struct ubcore_cmd_update_ueid arg; - struct net *net = &init_net; - struct ubcore_device *dev; - int ret = 0; - - if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { - ubcore_log_err("current user does not have net admin capability"); - return -EPERM; - } - - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, - sizeof(struct ubcore_cmd_update_ueid)); - if (ret != 0) - return -EPERM; - - dev = ubcore_find_device_with_name(arg.in.dev_name); - if (dev == NULL) { - ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); - return -EPERM; - } - - if (!dev->attr.virtualization && dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) { - ubcore_put_device(dev); - ubcore_log_err("pattern1 does not support static mode\n"); - return -1; - } - if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1 || dev->dynamic_eid) { - ubcore_log_err("The dynamic mode of pf does not support eid change\n"); - ubcore_put_device(dev); - return -EPERM; - } - if (dev->attr.tp_maintainer && ubcore_get_netlink_valid() == false) { - ubcore_put_device(dev); - return -EPERM; - } - - if (arg.in.ns_fd >= 0) { - net = get_net_ns_by_fd(arg.in.ns_fd); - if (IS_ERR(net)) { - ubcore_put_device(dev); - ubcore_log_err("Failed to get ns by fd.\n"); - return PTR_ERR(net); - } - } - - if (ubcore_msg_discover_eid(dev, arg.in.eid_index, op, net) != 0) - ret = -EPERM; - - if (arg.in.ns_fd >= 0) - put_net(net); - ubcore_put_device(dev); - return ret; + return 0; } static void ubcore_update_pattern1_eid(struct ubcore_device *dev, @@ -213,9 +126,9 @@ static void ubcore_update_pattern1_eid(struct ubcore_device *dev, cfg.eid_index = eid_idx; cfg.upi = 0; if (is_add) - (void)ubcore_add_ueid(dev, (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); else - (void)ubcore_delete_ueid(dev, (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); } static void ubcore_update_pattern3_eid(struct ubcore_device *dev, @@ -237,469 +150,19 @@ static void ubcore_update_pattern3_eid(struct ubcore_device *dev, cfg.eid_index = eid_idx; cfg.upi = pattern3_upi; if (is_add) - (void)ubcore_add_ueid(dev, - (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); else - (void)ubcore_delete_ueid(dev, - (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); } else { ubcore_log_err("upi not configured\n"); } } -static int ubcore_cmd_set_eid_mode(struct ubcore_cmd_hdr *hdr) -{ - struct ubcore_cmd_set_eid_mode arg; - struct ubcore_event event; - struct ubcore_device *dev; - union ubcore_eid eid = {0}; - uint32_t i; - int ret; - - ret = ubcore_copy_from_user(&arg, - (void __user *)(uintptr_t)hdr->args_addr, sizeof(struct ubcore_cmd_set_eid_mode)); - if (ret != 0) - return -EPERM; - - dev = ubcore_find_device_with_name(arg.in.dev_name); - if (dev == NULL) { - ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); - return -EPERM; - } - if (dev->dynamic_eid == arg.in.eid_mode) { - ubcore_put_device(dev); - return 0; - } - - if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1 && arg.in.eid_mode == 0) { - ubcore_put_device(dev); - ubcore_log_err("pattern1 not support static mode"); - return -1; - } - - /* change eid mode, need to flush eids */ - event.ub_dev = dev; - event.event_type = UBCORE_EVENT_EID_CHANGE; - for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { - if (dev->eid_table.eid_entries[i].valid == true) { - eid = dev->eid_table.eid_entries[i].eid; - if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) - ubcore_update_pattern1_eid(dev, &eid, false); - else - ubcore_update_pattern3_eid(dev, &eid, false); - event.element.eid_idx = i; - ubcore_dispatch_async_event(&event); - } - } - dev->dynamic_eid = arg.in.eid_mode; - ubcore_put_device(dev); - return 0; -} - -static uint32_t ubcore_get_query_res_len(uint32_t type) -{ - switch (type) { - case UBCORE_RES_KEY_UPI: - return (uint32_t)sizeof(struct ubcore_res_upi_val); - case UBCORE_RES_KEY_VTP: - return (uint32_t)sizeof(struct ubcore_res_vtp_val); - case UBCORE_RES_KEY_TP: - return (uint32_t)sizeof(struct ubcore_res_tp_val); - case UBCORE_RES_KEY_TPG: - return (uint32_t)sizeof(struct ubcore_res_tpg_val); - case UBCORE_RES_KEY_UTP: - return (uint32_t)sizeof(struct ubcore_res_utp_val); - case UBCORE_RES_KEY_JFS: - return (uint32_t)sizeof(struct ubcore_res_jfs_val); - case UBCORE_RES_KEY_JFR: - return (uint32_t)sizeof(struct ubcore_res_jfr_val); - case UBCORE_RES_KEY_JETTY: - return (uint32_t)sizeof(struct ubcore_res_jetty_val); - case UBCORE_RES_KEY_JETTY_GROUP: - return (uint32_t)sizeof(struct ubcore_res_jetty_group_val); - case UBCORE_RES_KEY_JFC: - return (uint32_t)sizeof(struct ubcore_res_jfc_val); - case UBCORE_RES_KEY_RC: - return (uint32_t)sizeof(struct ubcore_res_rc_val); - case UBCORE_RES_KEY_SEG: - return (uint32_t)sizeof(struct ubcore_res_seg_val); - case UBCORE_RES_KEY_URMA_DEV: - return (uint32_t)sizeof(struct ubcore_res_dev_val); - default: - break; - } - return 0; -} - -static int ubcore_fill_user_res_dev(struct ubcore_res_dev_val *user_addr, - struct ubcore_res_dev_val *kernal_addr) -{ - int ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->seg_list, - kernal_addr->seg_list, kernal_addr->seg_cnt * sizeof(struct ubcore_seg_info)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->jfs_list, - kernal_addr->jfs_list, kernal_addr->jfs_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->jfr_list, - kernal_addr->jfr_list, kernal_addr->jfr_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->jfc_list, - kernal_addr->jfc_list, kernal_addr->jfc_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->jetty_list, - kernal_addr->jetty_list, kernal_addr->jetty_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->jetty_group_list, - kernal_addr->jetty_group_list, kernal_addr->jetty_group_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->rc_list, - kernal_addr->rc_list, kernal_addr->rc_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->vtp_list, - kernal_addr->vtp_list, kernal_addr->vtp_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->tp_list, - kernal_addr->tp_list, kernal_addr->tp_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->tpg_list, - kernal_addr->tpg_list, kernal_addr->tpg_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)user_addr->utp_list, - kernal_addr->utp_list, kernal_addr->utp_cnt * sizeof(uint32_t)); - if (ret != 0) - return ret; - - return 0; -} - -static int ubcore_copy_to_usr_tp_list(uint64_t user_tp_list, struct ubcore_res_tpg_val *tpg) -{ - int ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)user_tp_list, - tpg->tp_list, sizeof(uint32_t) * tpg->tp_cnt); - if (ret != 0) - ubcore_log_err("ubcore_copy_to_user failed, cnt = %u\n", tpg->tp_cnt); - - vfree(tpg->tp_list); - return ret; -} - - -static int ubcore_copy_to_usr_jetty_list(uint64_t user_jetty_list, - struct ubcore_res_jetty_group_val *jetty_grp) -{ - int ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)user_jetty_list, jetty_grp->jetty_list, - sizeof(uint32_t) * jetty_grp->jetty_cnt); - if (ret != 0) - ubcore_log_err("ubcore_copy_to_user failed, cnt = %u\n", jetty_grp->jetty_cnt); - - vfree(jetty_grp->jetty_list); - return ret; -} - -static int ubcore_copy_to_usr_segment_list(uint64_t user_seg_list, - struct ubcore_res_seg_val *seg_info) -{ - int ret; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)user_seg_list, seg_info->seg_list, - sizeof(struct ubcore_seg_info) * seg_info->seg_cnt); - if (ret != 0) - ubcore_log_err("ubcore_copy_to_user failed, cnt = %u\n", seg_info->seg_cnt); - - vfree(seg_info->seg_list); - return ret; -} - -static void ubcore_query_copy_cnt(struct ubcore_cmd_query_res *arg, - uint64_t k_addr, uint64_t user_addr) -{ - struct ubcore_res_tpg_val *tpg_val; - struct ubcore_res_tpg_val *tpg_user_val; - - struct ubcore_res_jetty_group_val *jgrp_val; - struct ubcore_res_jetty_group_val *jgrp_user_val; - - struct ubcore_res_seg_val *seg_val; - struct ubcore_res_seg_val *seg_user_val; - - struct ubcore_res_dev_val *dev_val; - struct ubcore_res_dev_val *dev_user_val; - - switch (arg->in.type) { - case UBCORE_RES_KEY_TPG: - tpg_val = (struct ubcore_res_tpg_val *)k_addr; - tpg_user_val = (struct ubcore_res_tpg_val *)user_addr; - tpg_user_val->tp_cnt = tpg_val->tp_cnt; - return; - case UBCORE_RES_KEY_JETTY_GROUP: - jgrp_val = (struct ubcore_res_jetty_group_val *)k_addr; - jgrp_user_val = (struct ubcore_res_jetty_group_val *)user_addr; - jgrp_user_val->jetty_cnt = jgrp_val->jetty_cnt; - return; - case UBCORE_RES_KEY_SEG: - seg_val = (struct ubcore_res_seg_val *)k_addr; - seg_user_val = (struct ubcore_res_seg_val *)user_addr; - seg_user_val->seg_cnt = seg_val->seg_cnt; - return; - case UBCORE_RES_KEY_URMA_DEV: - dev_val = (struct ubcore_res_dev_val *)k_addr; - dev_user_val = (struct ubcore_res_dev_val *)user_addr; - dev_user_val->seg_cnt = dev_val->seg_cnt; - dev_user_val->jfs_cnt = dev_val->jfs_cnt; - dev_user_val->jfr_cnt = dev_val->jfr_cnt; - dev_user_val->jfc_cnt = dev_val->jfc_cnt; - dev_user_val->jetty_cnt = dev_val->jetty_cnt; - dev_user_val->jetty_group_cnt = dev_val->jetty_group_cnt; - dev_user_val->rc_cnt = dev_val->rc_cnt; - dev_user_val->vtp_cnt = dev_val->vtp_cnt; - dev_user_val->tp_cnt = dev_val->tp_cnt; - dev_user_val->tpg_cnt = dev_val->tpg_cnt; - dev_user_val->utp_cnt = dev_val->utp_cnt; - return; - default: - ubcore_log_info("Other types don't need query cnt"); - return; - } -} - -static int ubcore_query_cnt(struct ubcore_device *dev, struct ubcore_cmd_query_res *arg, - uint32_t res_len) -{ - struct ubcore_res_key key = {0}; - struct ubcore_res_val val = {0}; - void *kernal_addr; /* urma applies for memory; driver fills; kfree during 2nd ioctl */ - void *user_addr; - int ret; - - kernal_addr = kzalloc(res_len, GFP_KERNEL); - if (kernal_addr == NULL) - return -1; - - user_addr = kzalloc(res_len, GFP_KERNEL); - if (user_addr == NULL) { - kfree(kernal_addr); - return -1; - } - - ret = ubcore_copy_from_user(kernal_addr, (void __user *)(uintptr_t)arg->out.addr, res_len); - if (ret != 0) - goto kfree_addr; - - ret = ubcore_copy_from_user(user_addr, (void __user *)(uintptr_t)arg->out.addr, res_len); - if (ret != 0) - goto kfree_addr; - - if (arg->in.type == (uint32_t)UBCORE_RES_KEY_VTP && dev->attr.virtualization == true) { - ubcore_log_warn("FE device do not support query VTP, dev: %s, type: %u.\n", - dev->dev_name, arg->in.type); - goto kfree_addr; - } - - key.type = (uint8_t)arg->in.type; - key.key = arg->in.key; - key.key_ext = arg->in.key_ext; - key.key_cnt = arg->in.key_cnt; - val.addr = (uint64_t)kernal_addr; - val.len = res_len; - - // urma only alloc memory for the struct - // driver will alloc memory for the list pointer in the struct; urma need to vfree it later - - ret = ubcore_query_resource(dev, &key, &val); - if (ret != 0) - goto kfree_addr; - - ubcore_query_copy_cnt(arg, val.addr, (uint64_t)user_addr); - - arg->out.save_ptr = (uint64_t)kernal_addr; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)arg->out.addr, user_addr, res_len); - if (ret != 0) - goto kfree_addr; - - /* kernal_addr save for second ioctl */ - kfree(user_addr); - return ret; - -kfree_addr: - kfree(kernal_addr); - kfree(user_addr); - return ret; -} - -static void ubcore_query_list_free(struct ubcore_res_dev_val *kernal_addr) -{ - vfree(kernal_addr->seg_list); - vfree(kernal_addr->jfs_list); - vfree(kernal_addr->jfr_list); - vfree(kernal_addr->jfc_list); - vfree(kernal_addr->jetty_list); - vfree(kernal_addr->jetty_group_list); - vfree(kernal_addr->rc_list); - vfree(kernal_addr->vtp_list); - vfree(kernal_addr->tp_list); - vfree(kernal_addr->tpg_list); - vfree(kernal_addr->utp_list); -} - -static int ubcore_query_list(struct ubcore_device *dev, struct ubcore_cmd_query_res *arg, - uint32_t res_len) -{ - uint64_t kernal_addr; - void *user_addr; - void *k_addr; - int ret; - - kernal_addr = arg->out.save_ptr; - k_addr = (void *)kernal_addr; - user_addr = kzalloc(res_len, GFP_KERNEL); - if (user_addr == NULL) - return -1; - - ret = ubcore_copy_from_user(user_addr, (void __user *)(uintptr_t)arg->out.addr, res_len); - if (ret != 0) - goto kfree_addr; - - switch (arg->in.type) { - case UBCORE_RES_KEY_TPG: - ret = ubcore_copy_to_usr_tp_list( - (uint64_t)(((struct ubcore_res_tpg_val *)user_addr)->tp_list), - (struct ubcore_res_tpg_val *)kernal_addr); - break; - case UBCORE_RES_KEY_JETTY_GROUP: - ret = ubcore_copy_to_usr_jetty_list( - (uint64_t)(((struct ubcore_res_jetty_group_val *)user_addr)->jetty_list), - (struct ubcore_res_jetty_group_val *)kernal_addr); - break; - case UBCORE_RES_KEY_SEG: - ret = ubcore_copy_to_usr_segment_list( - (uint64_t)(((struct ubcore_res_seg_val *)user_addr)->seg_list), - (struct ubcore_res_seg_val *)kernal_addr); - break; - case UBCORE_RES_KEY_URMA_DEV: - ret = ubcore_fill_user_res_dev((struct ubcore_res_dev_val *)user_addr, - (struct ubcore_res_dev_val *)kernal_addr); - ubcore_query_list_free((struct ubcore_res_dev_val *)kernal_addr); - break; - default: - (void)memcpy(user_addr, k_addr, res_len); - break; - } - - if (ret != 0) - goto kfree_addr; - - ret = ubcore_copy_to_user((void __user *)(uintptr_t)arg->out.addr, user_addr, res_len); - -kfree_addr: - kfree(user_addr); - kfree(k_addr); /* release after second ioctl */ - return ret; -} - -static int ubcore_cmd_query_res(struct ubcore_cmd_hdr *hdr) -{ - struct ubcore_cmd_query_res arg = {0}; - struct ubcore_device *dev; - uint32_t res_len; - int ret; - - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, - sizeof(struct ubcore_cmd_query_res)); - if (ret != 0) - return ret; - - res_len = ubcore_get_query_res_len((uint32_t)arg.in.type); - if (res_len != arg.out.len) { - ubcore_log_err("Failed to check res len, type: %u, res_len: %u, len: %u.\n", - (uint32_t)arg.in.type, res_len, arg.out.len); - return -1; - } - dev = ubcore_find_device_with_name(arg.in.dev_name); - if (dev == NULL || ubcore_check_dev_name_invalid(dev, arg.in.dev_name)) { - ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", - dev == NULL ? "NULL" : dev->dev_name, arg.in.dev_name); - return -EINVAL; - } - - if (arg.in.query_cnt) - ret = ubcore_query_cnt(dev, &arg, res_len); - else - ret = ubcore_query_list(dev, &arg, res_len); - - if (ret != 0) { - ubcore_put_device(dev); - ubcore_log_err("Failed to query res by arg\n"); - return -1; - } - - ubcore_put_device(dev); - - return ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, - sizeof(struct ubcore_cmd_query_res)); -} - -static int ubcore_cmd_parse(struct ubcore_cmd_hdr *hdr) -{ - switch (hdr->command) { - case UBCORE_CMD_SHOW_UTP: - return ubcore_cmd_show_utp(hdr); - case UBCORE_CMD_QUERY_STATS: - return ubcore_cmd_query_stats(hdr); - case UBCORE_CMD_QUERY_RES: - return ubcore_cmd_query_res(hdr); - case UBCORE_CMD_ADD_EID: - return ubcore_cmd_update_ueid(hdr, UBCORE_MSG_ALLOC_EID); - case UBCORE_CMD_DEL_EID: - return ubcore_cmd_update_ueid(hdr, UBCORE_MSG_DEALLOC_EID); - case UBCORE_CMD_SET_EID_MODE: - return ubcore_cmd_set_eid_mode(hdr); - default: - ubcore_log_err("bad ubcore command: %d.\n", (int)hdr->command); - return -EINVAL; - } -} - static long ubcore_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ubcore_cmd_hdr hdr; int ret; - if (cmd == UBCORE_CMD) { - ret = ubcore_copy_from_user(&hdr, (void *)arg, sizeof(struct ubcore_cmd_hdr)); - if ((ret != 0) || (hdr.args_len > UBCORE_MAX_CMD_SIZE)) { - ubcore_log_err("length of ioctl input parameter is out of range.\n"); - return -EINVAL; - } - - return ubcore_cmd_parse(&hdr); - } - if (cmd == UBCORE_UVS_CMD) { ret = ubcore_copy_from_user(&hdr, (void *)arg, sizeof(struct ubcore_cmd_hdr)); if ((ret != 0) || (hdr.args_len > UBCORE_MAX_CMD_SIZE)) { @@ -730,10 +193,17 @@ static int ubcore_register_sysfs(void) { int ret; + /* /sys/class/ubus/ubcore */ + ret = ubcore_class_register(&g_ubcore_ctx.ubcore_class); + if (ret) { + ubcore_log_err("couldn't create class\n"); + return ret; + } + ret = alloc_chrdev_region(&g_ubcore_ctx.ubcore_devno, 0, 1, UBCORE_DEVICE_NAME); if (ret != 0) { ubcore_log_err("alloc chrdev region failed, ret:%d.\n", ret); - return ret; + goto unreg_class; } cdev_init(&g_ubcore_ctx.ubcore_cdev, &g_ubcore_ops); @@ -743,14 +213,6 @@ static int ubcore_register_sysfs(void) goto unreg_cdev_region; } - /* /sys/class/ubus/ubcore */ - g_ubcore_ctx.ubcore_class = class_create(THIS_MODULE, UBCORE_CLASS_NAME); - if (IS_ERR(g_ubcore_ctx.ubcore_class)) { - ret = (int)PTR_ERR(g_ubcore_ctx.ubcore_class); - ubcore_log_err("couldn't create class %s, ret:%d.\n", UBCORE_CLASS_NAME, ret); - goto del_cdev; - } - /* /dev/ubcore */ g_ubcore_ctx.ubcore_dev = device_create(g_ubcore_ctx.ubcore_class, NULL, g_ubcore_ctx.ubcore_devno, NULL, @@ -758,26 +220,26 @@ static int ubcore_register_sysfs(void) if (IS_ERR(g_ubcore_ctx.ubcore_dev)) { ret = (int)PTR_ERR(g_ubcore_ctx.ubcore_dev); ubcore_log_err("couldn't create device %s, ret:%d.\n", UBCORE_DEVICE_NAME, ret); - goto destroy_class; + goto del_cdev; } ubcore_log_info("ubcore device created success.\n"); return 0; -destroy_class: - class_destroy(g_ubcore_ctx.ubcore_class); del_cdev: cdev_del(&g_ubcore_ctx.ubcore_cdev); unreg_cdev_region: unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); +unreg_class: + ubcore_class_unregister(g_ubcore_ctx.ubcore_class); return ret; } static void ubcore_unregister_sysfs(void) { device_destroy(g_ubcore_ctx.ubcore_class, g_ubcore_ctx.ubcore_cdev.dev); - class_destroy(g_ubcore_ctx.ubcore_class); cdev_del(&g_ubcore_ctx.ubcore_cdev); unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); + ubcore_class_unregister(g_ubcore_ctx.ubcore_class); ubcore_log_info("ubcore device destroyed success.\n"); } @@ -788,6 +250,29 @@ static void ubcore_ipv4_to_netaddr(struct ubcore_net_addr *netaddr, __be32 ipv4) netaddr->net_addr.in4.addr = ipv4; } +static inline uint32_t sip_mtu_enum_to_int(enum ubcore_mtu mtu) +{ + return (uint32_t)(1 << ((uint32_t)mtu + SIP_MTU_BITS_BASE_SHIFT)); +} + +static enum ubcore_mtu sip_get_mtu(uint32_t mtu) +{ + if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_8192)) + return UBCORE_MTU_8192; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_4096)) + return UBCORE_MTU_4096; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_2048)) + return UBCORE_MTU_2048; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_1024)) + return UBCORE_MTU_1024; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_512)) + return UBCORE_MTU_512; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_256)) + return UBCORE_MTU_256; + else + return (enum ubcore_mtu)0; +} + static void ubcore_sip_init(struct ubcore_sip_info *sip, struct ubcore_device *tpf_dev, const struct ubcore_net_addr *netaddr, uint8_t *port_list, uint8_t port_cnt, uint32_t prefix_len, struct net_device *netdev) @@ -798,13 +283,97 @@ static void ubcore_sip_init(struct ubcore_sip_info *sip, struct ubcore_device *t (void)memcpy(sip->port_id, port_list, UBCORE_MAX_PORT_CNT); sip->port_cnt = port_cnt; sip->prefix_len = prefix_len; - sip->mtu = netdev->mtu; + sip->mtu = (uint32_t)sip_get_mtu(netdev->mtu); (void)memcpy(sip->netdev_name, netdev_name(netdev), UBCORE_MAX_DEV_NAME); } +static void ubcore_notify_uvs_update_sip( + struct ubcore_device *tpf_dev, struct ubcore_sip_info *new_sip, + struct ubcore_sip_info *old_sip, uint32_t index) +{ + (void)ubcore_notify_uvs_del_sip(tpf_dev, old_sip, index); + (void)ubcore_notify_uvs_add_sip(tpf_dev, new_sip, index); +} + +static bool ubcore_notify_uvs_update_sip_sync(struct ubcore_device *tpf_dev, + struct ubcore_sip_info *new_sip, struct ubcore_sip_info *old_sip, + enum ubcore_sip_op_type sip_op, uint32_t index) +{ + if (ubcore_get_netlink_valid() != true) + return true; + + switch (sip_op) { + case UBCORE_SIP_DEL: + (void)ubcore_notify_uvs_del_sip(tpf_dev, old_sip, index); + return true; + case UBCORE_SIP_ADD: + (void)ubcore_notify_uvs_add_sip(tpf_dev, new_sip, index); + return true; + case UBCORE_SIP_UPDATE: + ubcore_notify_uvs_update_sip(tpf_dev, new_sip, old_sip, index); + return true; + default: + ubcore_log_err("sip_op_type out of range"); + return false; + } +} + +static void ubcore_notify_uvs_update_sip_task(struct work_struct *work) +{ + struct ubcore_notify_uvs_sip_event_work *l_work = container_of( + work, struct ubcore_notify_uvs_sip_event_work, work); + + (void)ubcore_notify_uvs_update_sip_sync( + l_work->tpf_dev, &l_work->new_sip, &l_work->old_sip, l_work->sip_op, l_work->index); + kfree(l_work); +} + +static int ubcore_notify_uvs_update_sip_async(struct ubcore_device *tpf_dev, + struct ubcore_sip_info *new_sip, struct ubcore_sip_info *old_sip, + enum ubcore_sip_op_type sip_op, uint32_t index) +{ + struct ubcore_notify_uvs_sip_event_work *work; + + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return -ENOMEM; + + INIT_WORK(&work->work, ubcore_notify_uvs_update_sip_task); + work->tpf_dev = tpf_dev; + if (new_sip != NULL) + work->new_sip = *(new_sip); + if (old_sip != NULL) + work->old_sip = *(old_sip); + work->index = index; + work->sip_op = sip_op; + if (ubcore_queue_work((int)UBCORE_SIP_NOTIFY_WQ, &work->work) != 0) { + kfree(work); + ubcore_log_err("Queue work failed"); + return -1; + } + return 0; +} + +static int ubcore_notify_uvs_update_sip_manage(struct ubcore_device *tpf_dev, + struct ubcore_sip_info *new_sip, struct ubcore_sip_info *old_sip, + enum ubcore_sip_op_type sip_op, uint32_t index, bool async) +{ + int ret = 0; + + if (!async) { + (void)ubcore_notify_uvs_update_sip_sync(tpf_dev, new_sip, old_sip, sip_op, index); + return 0; + } + + ret = ubcore_notify_uvs_update_sip_async(tpf_dev, new_sip, old_sip, sip_op, index); + if (ret != 0) + ubcore_log_err("kzalloc failed or queue type err"); + return ret; +} + static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_device *pf_dev, - struct ubcore_net_addr *netaddr, struct net_device *netdev, uint32_t prefix_len) + struct ubcore_net_addr *netaddr, struct net_device *netdev, uint32_t prefix_len, bool async) { struct ubcore_sip_info sip = {0}; uint8_t *port_list = NULL; @@ -824,7 +393,7 @@ static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_dev } index = (uint32_t)ubcore_sip_idx_alloc(&tpf_dev->sip_table); - if (tpf_dev->ops->add_net_addr != NULL && + if (tpf_dev->ops != NULL && tpf_dev->ops->add_net_addr != NULL && tpf_dev->ops->add_net_addr(tpf_dev, netaddr, index) != 0) ubcore_log_err("Failed to set net addr"); @@ -832,8 +401,9 @@ static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_dev (void)ubcore_add_sip_entry(&tpf_dev->sip_table, &sip, index); /* nodify uvs add sip info */ - if (ubcore_get_netlink_valid() == true) - (void)ubcore_notify_uvs_add_sip(tpf_dev, &sip, index); + if (ubcore_notify_uvs_update_sip_manage(tpf_dev, &sip, NULL, + UBCORE_SIP_ADD, index, async) != 0) + ubcore_log_err("kzalloc failed or queue type err"); /* The ubcore sip table and up/down events are updated synchronously, and the uvs * is abnormally disconnected. After waiting for the pull-up, @@ -842,7 +412,7 @@ static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_dev } static void ubcore_delete_net_addr(struct ubcore_device *tpf_dev, struct ubcore_device *pf_dev, - struct ubcore_net_addr *netaddr, struct net_device *netdev, uint32_t prefix_len) + struct ubcore_net_addr *netaddr, struct net_device *netdev, uint32_t prefix_len, bool async) { struct ubcore_sip_info sip = {0}; uint8_t *port_list = NULL; @@ -856,15 +426,16 @@ static void ubcore_delete_net_addr(struct ubcore_device *tpf_dev, struct ubcore_ if (ubcore_lookup_sip_idx(&tpf_dev->sip_table, &sip, &index) != 0) return; - if (tpf_dev->ops->delete_net_addr != NULL && + if (tpf_dev->ops != NULL && tpf_dev->ops->delete_net_addr != NULL && tpf_dev->ops->delete_net_addr(tpf_dev, index) != 0) ubcore_log_err("Failed to delete net addr"); (void)ubcore_del_sip_entry(&tpf_dev->sip_table, index); (void)ubcore_sip_idx_free(&tpf_dev->sip_table, index); /* nodify uvs delete sip info */ - if (ubcore_get_netlink_valid() == true) - (void)ubcore_notify_uvs_del_sip(tpf_dev, &sip, index); + if (ubcore_notify_uvs_update_sip_manage(tpf_dev, NULL, &sip, + UBCORE_SIP_DEL, index, async) != 0) + ubcore_log_err("kzalloc failed or queue type err"); /* The ubcore sip table and up/down events are updated synchronously, * and the uvs is abnormally disconnected. After waiting for the pull-up, @@ -928,12 +499,14 @@ static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long switch (event) { case NETDEV_UP: if (tpf_dev) - ubcore_add_net_addr(tpf_dev, dev, netaddr, netdev, prefix_len); + ubcore_add_net_addr( + tpf_dev, dev, netaddr, netdev, prefix_len, true); ubcore_update_eid(dev, netaddr, true); break; case NETDEV_DOWN: if (tpf_dev) - ubcore_delete_net_addr(tpf_dev, dev, netaddr, netdev, prefix_len); + ubcore_delete_net_addr( + tpf_dev, dev, netaddr, netdev, prefix_len, true); ubcore_update_eid(dev, netaddr, false); break; default: @@ -1081,9 +654,9 @@ void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add) if (tpf_dev) is_add == true ? ubcore_add_net_addr(tpf_dev, dev, &na_entry->addr, - netdev, na_entry->prefix_len) : + netdev, na_entry->prefix_len, false) : ubcore_delete_net_addr(tpf_dev, dev, &na_entry->addr, - netdev, na_entry->prefix_len); + netdev, na_entry->prefix_len, false); ubcore_update_eid(dev, &na_entry->addr, is_add); list_del(&na_entry->node); kfree(na_entry); @@ -1104,11 +677,11 @@ void ubcore_update_netaddr(struct ubcore_device *dev, struct net_device *netdev, list_for_each_entry_safe(na_entry, next, &na_list, node) { if (add) { - if (dev->ops->add_net_addr != NULL && + if (dev != NULL && dev->ops != NULL && dev->ops->add_net_addr != NULL && dev->ops->add_net_addr(dev, &na_entry->addr, 0) != 0) ubcore_log_err("Failed to add net addr"); } else { - if (dev->ops->delete_net_addr != NULL && + if (dev != NULL && dev->ops != NULL && dev->ops->delete_net_addr != NULL && dev->ops->delete_net_addr(dev, 0) != 0) ubcore_log_err("Failed to delete net addr"); } @@ -1155,27 +728,78 @@ static void ubcore_change_mtu(struct ubcore_device *dev, struct net_device *netd UBCORE_MAX_DEV_NAME) != 0) continue; old_sip = *new_sip; - new_sip->mtu = netdev->mtu; - if (ubcore_get_netlink_valid() == true) { - (void)ubcore_notify_uvs_del_sip(tpf_dev, &old_sip, i); - (void)ubcore_notify_uvs_add_sip(tpf_dev, new_sip, i); - } - ubcore_log_info("dev_name: %s, netdev: %s mtu: %u change to mtu: %u\n", - dev->dev_name, netdev_name(netdev), old_sip.mtu, new_sip->mtu); + new_sip->mtu = (uint32_t)sip_get_mtu(netdev->mtu); + (void)ubcore_notify_uvs_update_sip_manage( + tpf_dev, new_sip, &old_sip, UBCORE_SIP_UPDATE, i, true); } mutex_unlock(&tpf_dev->sip_table.lock); ubcore_put_device(tpf_dev); } +static void ubcore_do_bond(struct ubcore_bond_event_work *l_bond_event) +{ + int ret = -1; + + switch (l_bond_event->bond_op_type) { + case UBCORE_BOND_ADD: + ret = l_bond_event->bond_add( + l_bond_event->bond, l_bond_event->slave, &l_bond_event->info_upper); + if (ret != 0) + ubcore_log_err("Failed to bond_add and ret value is %d", ret); + break; + case UBCORE_BOND_REMOVE: + ret = l_bond_event->bond_remove(l_bond_event->bond, l_bond_event->slave); + if (ret != 0) + ubcore_log_err("Failed to bond_remove and ret value is %d", ret); + break; + case UBCORE_BOND_SLAVE_UPDATE: + ret = l_bond_event->slave_update( + l_bond_event->bond, l_bond_event->slave, &l_bond_event->info_lower); + if (ret != 0) + ubcore_log_err("Failed to slave_update and ret value is %d", ret); + break; + default: + break; + } + if (l_bond_event->bond) + dev_put(l_bond_event->bond); + dev_put(l_bond_event->slave); + if (ret == 0) + ubcore_log_info("Success running bond_event with type %d", + (int)l_bond_event->bond_op_type); + kfree(l_bond_event); +} + +static void ubcore_do_bond_work(struct work_struct *work) +{ + struct ubcore_bond_event_work *l_bond_event = + container_of(work, struct ubcore_bond_event_work, work); + + ubcore_do_bond(l_bond_event); +} + +static void ubcore_queue_bond_work(struct ubcore_bond_event_work *l_bond_event) +{ + if (ubcore_queue_work((int)UBCORE_BOND_EVENT_WQ, &l_bond_event->work) != 0) { + dev_put(l_bond_event->slave); + if (l_bond_event->bond) + dev_put(l_bond_event->bond); + ubcore_log_err("Queue work type %d, op type %d failed", + (int)UBCORE_BOND_EVENT_WQ, + (int)l_bond_event->bond_op_type); + kfree(l_bond_event); + } +} + static int ubcore_netdev_event_change_upper(struct ubcore_device *dev, struct net_device *slave, struct netdev_notifier_changeupper_info *info) { struct netdev_lag_upper_info *lag_upper_info = NULL; + struct ubcore_bond_event_work *l_bond_event; struct net_device *bond = info->upper_dev; - int ret; - if (dev == NULL || dev->ops->bond_add == NULL || + if (dev == NULL || dev->ops == NULL || dev->ops->bond_add == NULL || dev->ops->bond_remove == NULL) { ubcore_log_err("Invalid parameter!\n"); ubcore_put_device(dev); @@ -1185,23 +809,31 @@ static int ubcore_netdev_event_change_upper(struct ubcore_device *dev, ubcore_log_info("Event with master netdev %s and slave netdev %s", netdev_name(bond), netdev_name(slave)); - /* dev may be unregistered so it has to be put_device here */ - ubcore_put_device(dev); + l_bond_event = kzalloc(sizeof(*l_bond_event), GFP_KERNEL); + if (!l_bond_event) { + ubcore_put_device(dev); + return -ENOMEM; + } + dev_hold(bond); + l_bond_event->bond = bond; + dev_hold(slave); + l_bond_event->slave = slave; if (info->linking) { lag_upper_info = info->upper_info; - ret = dev->ops->bond_add(bond, slave, lag_upper_info); - if (ret != 0) { - ubcore_log_err("Failed to bond_add and ret value is %d", ret); - return -EIO; - } + l_bond_event->info_upper = *lag_upper_info; + l_bond_event->bond_add = dev->ops->bond_add; + l_bond_event->bond_op_type = UBCORE_BOND_ADD; } else { - ret = dev->ops->bond_remove(bond, slave); - if (ret != 0) { - ubcore_log_err("Failed to bond_remove and ret value is %d", ret); - return -EIO; - } + l_bond_event->bond_op_type = UBCORE_BOND_REMOVE; + l_bond_event->bond_remove = dev->ops->bond_remove; } + + /* dev may be unregistered so it has to be put_device here */ + ubcore_put_device(dev); + + INIT_WORK(&l_bond_event->work, ubcore_do_bond_work); + ubcore_queue_bond_work(l_bond_event); ubcore_log_info("Success to deal with event NETDEV_CHANGEUPPER"); return 0; } @@ -1212,27 +844,34 @@ static int ubcore_netdev_event_change_lower_state(struct ubcore_device *dev, { struct netdev_lag_lower_state_info *lag_lower_info = NULL; struct net_device *bond = NULL; - int ret; + struct ubcore_bond_event_work *l_bond_event; - if (dev == NULL || dev->ops->slave_update == NULL) { + if (dev == NULL || dev->ops == NULL || dev->ops->slave_update == NULL) { ubcore_log_err("Invalid parameter!\n"); return -EINVAL; } - + l_bond_event = kzalloc(sizeof(*l_bond_event), GFP_KERNEL); + if (!l_bond_event) + return false; bond = netdev_master_upper_dev_get_rcu(slave); - if (bond) + if (bond) { + dev_hold(bond); + l_bond_event->bond = bond; ubcore_log_info("Event with master netdev %s and slave netdev %s", netdev_name(bond), netdev_name(slave)); - else + } else { + l_bond_event->bond = NULL; ubcore_log_info("Event with master netdev NULL and slave netdev %s", netdev_name(slave)); - - lag_lower_info = info->lower_state_info; - ret = dev->ops->slave_update(bond, slave, lag_lower_info); - if (ret != 0) { - ubcore_log_err("Failed to slave_update and ret value is %d", ret); - return -EIO; } + lag_lower_info = info->lower_state_info; + l_bond_event->info_lower = *lag_lower_info; + dev_hold(slave); + l_bond_event->slave = slave; + l_bond_event->slave_update = dev->ops->slave_update; + l_bond_event->bond_op_type = UBCORE_BOND_SLAVE_UPDATE; + INIT_WORK(&l_bond_event->work, ubcore_do_bond_work); + ubcore_queue_bond_work(l_bond_event); ubcore_log_info("Success to deal with event NETDEV_CHANGELOWERSTATE"); return 0; } @@ -1301,7 +940,6 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve struct net_device *netdev = netdev_notifier_info_to_dev(arg); struct ubcore_device **devices; struct net_device *real_netdev; - struct ubcore_device *dev; uint32_t num_devices = 0; uint32_t i; @@ -1336,10 +974,9 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve } } - for (i = 0; i < num_devices; i++) { - dev = devices[i]; - ubcore_do_netdev_notify(event, dev, netdev, arg); - } + for (i = 0; i < num_devices; i++) + ubcore_do_netdev_notify(event, devices[i], netdev, arg); + if (event != NETDEV_CHANGEUPPER) ubcore_put_devices(devices, num_devices); else @@ -1364,14 +1001,31 @@ static int ubcore_register_notifiers(void) { int ret; + ret = ubcore_alloc_workqueue((int)UBCORE_SIP_NOTIFY_WQ); + if (ret != 0) { + pr_err("Failed to alloc workqueue for sip notify, ret = %d\n", ret); + return -ENOMEM; + } + + ret = ubcore_alloc_workqueue((int)UBCORE_BOND_EVENT_WQ); + if (ret != 0) { + (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); + pr_err("Failed to alloc workqueue for bond event, ret = %d\n", ret); + return -ENOMEM; + } + ret = register_netdevice_notifier(&ubcore_net_notifier); if (ret != 0) { + (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); + (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); pr_err("Failed to register netdev notifier, ret = %d\n", ret); return ret; } ret = register_inetaddr_notifier(&ubcore_ipv4_notifier); if (ret != 0) { (void)unregister_netdevice_notifier(&ubcore_net_notifier); + (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); + (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); pr_err("Failed to register inetaddr notifier, ret = %d\n", ret); return -1; } @@ -1379,6 +1033,8 @@ static int ubcore_register_notifiers(void) if (ret != 0) { (void)unregister_inetaddr_notifier(&ubcore_ipv4_notifier); (void)unregister_netdevice_notifier(&ubcore_net_notifier); + (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); + (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); pr_err("Failed to register inet6addr notifier, ret = %d\n", ret); return -1; } @@ -1390,6 +1046,8 @@ static void ubcore_unregister_notifiers(void) (void)unregister_inet6addr_notifier(&ubcore_ipv6_notifier); (void)unregister_inetaddr_notifier(&ubcore_ipv4_notifier); (void)unregister_netdevice_notifier(&ubcore_net_notifier); + (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); + (void)ubcore_destroy_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); } static int __init ubcore_init(void) @@ -1400,7 +1058,15 @@ static int __init ubcore_init(void) if (ret != 0) return ret; + ret = ubcore_genl_init(); + if (ret != 0) { + (void)pr_err("Failed to ubcore genl init\n"); + ubcore_unregister_sysfs(); + return -1; + } + if (ubcore_netlink_init() != 0) { + ubcore_genl_exit(); ubcore_unregister_sysfs(); return -1; } @@ -1409,18 +1075,39 @@ static int __init ubcore_init(void) if (ret != 0) { pr_err("Failed to register notifiers\n"); ubcore_netlink_exit(); + ubcore_genl_exit(); ubcore_unregister_sysfs(); return -1; } + ret = ubcore_register_pnet_ops(); + if (ret != 0) { + ubcore_unregister_notifiers(); + ubcore_netlink_exit(); + ubcore_genl_exit(); + ubcore_unregister_sysfs(); + } + + ret = ubcore_alloc_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); + if (ret != 0) { + pr_err("Failed to alloc workqueue, ret = %d\n", ret); + ubcore_unregister_pnet_ops(); + ubcore_unregister_notifiers(); + ubcore_netlink_exit(); + ubcore_genl_exit(); + ubcore_unregister_sysfs(); + return ret; + } ubcore_log_info("ubcore module init success.\n"); return 0; } static void __exit ubcore_exit(void) { + ubcore_unregister_pnet_ops(); ubcore_unregister_notifiers(); ubcore_netlink_exit(); + ubcore_genl_exit(); ubcore_unregister_sysfs(); ubcore_log_info("ubcore module exits.\n"); } diff --git a/drivers/ub/urma/ubcore/ubcore_msg.c b/drivers/ub/urma/ubcore/ubcore_msg.c index 167344979bbf..478a557c7693 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.c +++ b/drivers/ub/urma/ubcore/ubcore_msg.c @@ -28,8 +28,6 @@ #include "ubcore_priv.h" #include "ubcore_msg.h" -#define UBCORE_MSG_TIMEOUT 10000 /* 10s */ - static LIST_HEAD(g_msg_session_list); static DEFINE_SPINLOCK(g_msg_session_lock); static atomic_t g_msg_seq = ATOMIC_INIT(0); @@ -164,39 +162,34 @@ static int ubcore_tpf2fe_msg(struct ubcore_device *dev, struct ubcore_resp *resp return 0; } + static void ubcore_fill_tpf_dev_name(struct ubcore_device *tpf_dev, struct ubcore_req_host *req_host) { - struct ubcore_create_vtp_req *create; - struct ubcore_create_vtp_req *destroy; - struct ubcore_msg_discover_eid_req *eid_req; - struct ubcore_msg_config_device_req *config_dev; + char *p = NULL; - /* for alpha dev */ - if (!tpf_dev->attr.tp_maintainer) + /* dev should report as tpf */ + if (!tpf_dev->attr.tp_maintainer) { + ubcore_log_err("dev:%s, Not tpf!", tpf_dev->dev_name); return; + } switch (req_host->req.opcode) { case UBCORE_MSG_CREATE_VTP: - create = (struct ubcore_create_vtp_req *)req_host->req.data; - (void)memcpy(create->tpfdev_name, tpf_dev->dev_name, - UBCORE_MAX_DEV_NAME); - break; case UBCORE_MSG_DESTROY_VTP: - destroy = (struct ubcore_create_vtp_req *)req_host->req.data; - (void)memcpy(destroy->tpfdev_name, tpf_dev->dev_name, - UBCORE_MAX_DEV_NAME); + if (req_host->req.len >= sizeof(struct ubcore_create_vtp_req)) + p = ((struct ubcore_create_vtp_req *)req_host->req.data)->tpfdev_name; break; case UBCORE_MSG_ALLOC_EID: case UBCORE_MSG_DEALLOC_EID: - eid_req = (struct ubcore_msg_discover_eid_req *)req_host->req.data; - (void)memcpy(eid_req->tpfdev_name, tpf_dev->dev_name, - UBCORE_MAX_DEV_NAME); + if (req_host->req.len >= sizeof(struct ubcore_msg_discover_eid_req)) + p = ((struct ubcore_msg_discover_eid_req *) + req_host->req.data)->tpfdev_name; break; case UBCORE_MSG_CONFIG_DEVICE: - config_dev = (struct ubcore_msg_config_device_req *)req_host->req.data; - (void)memcpy(config_dev->tpfdev_name, tpf_dev->dev_name, - UBCORE_MAX_DEV_NAME); + if (req_host->req.len >= sizeof(struct ubcore_msg_config_device_req)) + p = ((struct ubcore_msg_config_device_req *) + req_host->req.data)->tpfdev_name; break; case UBCORE_MSG_STOP_PROC_VTP_MSG: case UBCORE_MSG_QUERY_VTP_MIG_STATUS: @@ -208,6 +201,9 @@ static void ubcore_fill_tpf_dev_name(struct ubcore_device *tpf_dev, default: ubcore_log_err("Unrecognized type of opcode %d\n", (int)req_host->req.opcode); } + + if (p != NULL) + memcpy(p, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); } static struct ubcore_req_host *ubcore_copy_req_host(struct ubcore_req_host *req_host) @@ -270,7 +266,7 @@ int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req) struct ubcore_req_host *handle_req; int ret; - if (dev == NULL || req == NULL) { + if (dev == NULL || req == NULL || req->req.len > UBCORE_MAX_MSG) { ubcore_log_err("Invalid parameter.\n!"); return -EINVAL; } @@ -288,7 +284,6 @@ int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req) return -ENOMEM; } - /* fill tpf_dev name */ ubcore_fill_tpf_dev_name(dev, handle_req); } @@ -303,7 +298,7 @@ int ubcore_recv_resp(struct ubcore_device *dev, struct ubcore_resp *resp) struct ubcore_resp *handle_resp; int ret; - if (dev == NULL || resp == NULL) { + if (dev == NULL || resp == NULL || resp->len > UBCORE_MAX_MSG) { ubcore_log_err("Invalid parameter.\n!"); return -EINVAL; } @@ -325,7 +320,8 @@ int ubcore_send_req(struct ubcore_device *dev, struct ubcore_req *req) { int ret; - if (dev == NULL || dev->ops->send_req == NULL) { + if (dev == NULL || dev->ops == NULL || dev->ops->send_req == NULL || + req->len > UBCORE_MAX_MSG) { ubcore_log_err("Invalid parameter!\n"); return -EINVAL; } @@ -342,7 +338,8 @@ int ubcore_send_resp(struct ubcore_device *dev, struct ubcore_resp_host *resp_ho { int ret; - if (dev == NULL || dev->ops->send_resp == NULL) { + if (dev == NULL || dev->ops == NULL || dev->ops->send_resp == NULL || resp_host == NULL || + resp_host->resp.len > UBCORE_MAX_MSG) { ubcore_log_err("Invalid parameter!\n"); return -EINVAL; } @@ -378,7 +375,7 @@ int ubcore_send_fe2tpf_msg(struct ubcore_device *dev, struct ubcore_req *req, return -EIO; } - leavetime = wait_for_completion_timeout(&s->comp, msecs_to_jiffies(UBCORE_MSG_TIMEOUT)); + leavetime = wait_for_completion_timeout(&s->comp, msecs_to_jiffies(UBCORE_TIMEOUT)); if (leavetime == 0) { ubcore_log_err("Failed to wait req reply, msg_id = %u, opcode = %hu, leavetime = %lu.\n", req->msg_id, (uint16_t)req->opcode, leavetime); @@ -400,37 +397,24 @@ static int ubcore_msg_discover_eid_cb(struct ubcore_device *dev, { struct ubcore_msg_discover_eid_resp *data; struct net *net = (struct net *)msg_ctx; - struct ubcore_ueid_cfg cfg; + bool is_alloc_eid; - if (dev == NULL) { + if (dev == NULL || resp == NULL) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } data = (struct ubcore_msg_discover_eid_resp *)(void *)resp->data; - if (resp == NULL || data == NULL || data->ret != 0 || + if (data == NULL || data->ret != 0 || (resp->opcode != UBCORE_MSG_ALLOC_EID && resp->opcode != UBCORE_MSG_DEALLOC_EID)) { ubcore_log_err("Failed to query data from the UVS. Use the default value.\n"); return -EINVAL; } - cfg.eid = data->eid; - cfg.eid_index = data->eid_index; - cfg.upi = data->upi; - if (resp->opcode == UBCORE_MSG_ALLOC_EID) { - if (ubcore_update_eidtbl_by_idx(dev, &data->eid, data->eid_index, true, net) != 0) - return -1; - if (!dev->attr.virtualization && ubcore_add_ueid(dev, data->fe_idx, &cfg) != 0) { - (void)ubcore_update_eidtbl_by_idx( - dev, &data->eid, data->eid_index, false, net); - return -1; - } - } else { - if (!dev->attr.virtualization && ubcore_delete_ueid(dev, data->fe_idx, &cfg) != 0) - return -1; - if (ubcore_update_eidtbl_by_idx(dev, &data->eid, data->eid_index, false, net) != 0) - return -1; - } + is_alloc_eid = (resp->opcode == UBCORE_MSG_ALLOC_EID); + if (ubcore_update_eidtbl_by_idx(dev, &data->eid, data->eid_index, is_alloc_eid, net) != 0) + return -1; + return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.c b/drivers/ub/urma/ubcore/ubcore_netdev.c index f6fc428cc028..2ed0c02e91d4 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.c +++ b/drivers/ub/urma/ubcore/ubcore_netdev.c @@ -96,6 +96,8 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, sip_req = (struct ubcore_del_sip_req *)(void *)req_msg->payload; sip_req->index = index; + (void)memcpy(sip_req->dev_name, dev->dev_name, + UBCORE_MAX_DEV_NAME); resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { @@ -104,7 +106,8 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, return -1; } resp = (struct ubcore_del_sip_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_DEL_SIP_RESP || resp == NULL || + if (resp_msg->msg_type != UBCORE_NL_DEL_SIP_RESP || + resp_msg->payload_len != sizeof(struct ubcore_del_sip_resp) || resp->ret != UBCORE_NL_RESP_SUCCESS) { ubcore_log_err("del sip request is rejected with type %d ret %d", resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); @@ -140,6 +143,8 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, UBCORE_MAX_PORT_CNT); sip_req->prefix_len = sip_info->prefix_len; sip_req->mtu = sip_info->mtu; + (void)memcpy(sip_req->netdev_name, + sip_info->netdev_name, UBCORE_MAX_DEV_NAME); resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { @@ -149,7 +154,8 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, } resp = (struct ubcore_add_sip_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_ADD_SIP_RESP || resp == NULL || + if (resp_msg->msg_type != UBCORE_NL_ADD_SIP_RESP || + resp_msg->payload_len != sizeof(struct ubcore_add_sip_resp) || resp->ret != UBCORE_NL_RESP_SUCCESS) { ubcore_log_err("add sip request is rejected with type %d ret %d", resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); @@ -275,8 +281,8 @@ static void ubcore_sync_sip_port_list(struct ubcore_device *dev, ubcore_log_info("dev_name: %s, old port_cnt: %hhu, new port_cnt: %hhu\n", dev->dev_name, old_sip.port_cnt, new_sip->port_cnt); } - ubcore_put_device(tpf_dev); mutex_unlock(&tpf_dev->sip_table.lock); + ubcore_put_device(tpf_dev); } int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, @@ -323,8 +329,7 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, down_write(&g_port_list_lock); list_add_tail(&new_node->node, &dev->port_list); up_write(&g_port_list_lock); - ubcore_log_info("ndev:%s dev_name: %s bound port[0]: %hhu\n", netdev_name(ndev), - dev->dev_name, new_node->port_list[0]); + ubcore_log_info("ndev:%s bound port[0]: %hhu\n", netdev_name(ndev), new_node->port_list[0]); ubcore_sync_sip_port_list(dev, new_node->port_list, new_node->port_cnt); return 0; } @@ -397,6 +402,11 @@ void ubcore_put_port_netdev(struct ubcore_device *dev) { struct ubcore_ndev_port *port_info, *next; + if (dev == NULL) { + ubcore_log_warn("invalid input dev is null_ptr.\n"); + return; + } + down_write(&g_port_list_lock); list_for_each_entry_safe(port_info, next, &dev->port_list, node) { if (port_info != NULL) { @@ -439,6 +449,7 @@ void ubcore_sip_table_uninit(struct ubcore_sip_table *sip_table) } } mutex_unlock(&sip_table->lock); + mutex_destroy(&sip_table->lock); } int ubcore_sip_idx_alloc(struct ubcore_sip_table *sip_table) @@ -462,7 +473,7 @@ int ubcore_sip_idx_free(struct ubcore_sip_table *sip_table, uint32_t idx) mutex_lock(&sip_table->lock); if (test_bit(idx, sip_table->index_bitmap) == false) { mutex_unlock(&sip_table->lock); - ubcore_log_err("idx is used.\n"); + ubcore_log_err("idx:%u is not used.\n", idx); return -EINVAL; } clear_bit(idx, sip_table->index_bitmap); diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.h b/drivers/ub/urma/ubcore/ubcore_netdev.h index 66b871c4ad7f..12f500766ff1 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.h +++ b/drivers/ub/urma/ubcore/ubcore_netdev.h @@ -23,11 +23,6 @@ #include -struct ubcore_port_list_info { - uint8_t *port_list; - uint8_t port_cnt; -}; - int ubcore_check_port_state(struct ubcore_device *dev, uint8_t port_idx); void ubcore_find_port_netdev(struct ubcore_device *dev, struct net_device *ndev, uint8_t **port_list, uint8_t *port_cnt); diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.c b/drivers/ub/urma/ubcore/ubcore_netlink.c index a939ee3f7375..214778b339c9 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.c +++ b/drivers/ub/urma/ubcore/ubcore_netlink.c @@ -29,13 +29,12 @@ #include "ubcore_netlink.h" #define UBCORE_NL_TYPE 24 /* same with agent netlink type */ -#define UBCORE_NL_TIMEOUT 30000 /* 30s */ #define UBCORE_NL_INVALID_PORT 0 static struct sock *nl_sock; static LIST_HEAD(g_nl_session_list); static DEFINE_SPINLOCK(g_nl_session_lock); -atomic_t g_nlmsg_seq; +static atomic_t g_nlmsg_seq; static uint32_t g_agent_port = UBCORE_NL_INVALID_PORT; /* get agent pid */ static int ubcore_nl_unicast(struct ubcore_nlmsg *pbuf, uint32_t len); @@ -233,19 +232,20 @@ static void ubcore_nl_handle_update_tpf_dev_info_resp(struct nlmsghdr *nlh) complete(&s->comp); } -static void ubcore_nl_sync_table(void) +static void ubcore_sync_tpf_dev_info(void) { - ubcore_sync_sip_table(); + if (ubcore_query_all_device_tpf_dev_info() != 0) + ubcore_log_warn("Failed update tpf dev info after tpsa ready"); } -static void ubcore_nl_update_tpf_dev_info(void) +static void ubcore_nl_sync_table(void) { - if (ubcore_query_all_device_tpf_dev_info() != 0) - ubcore_log_warn("Failed update tpf dev info after tpsa ready"); + ubcore_sync_tpf_dev_info(); + ubcore_sync_sip_table(); } static struct ubcore_nlmsg *ubcore_get_migrate_vtp_req(struct ubcore_vtp *vtp, - enum ubcore_event_type event_type, char *dev_name) + enum ubcore_event_type event_type, struct ubcore_device *dev) { uint32_t payload_len = (uint32_t)sizeof(struct ubcore_migrate_vtp_req); struct ubcore_migrate_vtp_req *mig_req; @@ -261,11 +261,12 @@ static struct ubcore_nlmsg *ubcore_get_migrate_vtp_req(struct ubcore_vtp *vtp, } else if (event_type == UBCORE_EVENT_MIGRATE_VTP_ROLLBACK) { req->msg_type = UBCORE_NL_MIGRATE_VTP_ROLLBACK; } else { + kfree(req); ubcore_log_err("wrong event msg type"); return NULL; } mig_req = (struct ubcore_migrate_vtp_req *)(void *)req->payload; - (void)strncpy(mig_req->dev_name, dev_name, strlen(dev_name)); + (void)memcpy(mig_req->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME); mig_req->vtp_cfg.fe_idx = vtp->cfg.fe_idx; mig_req->vtp_cfg.vtpn = vtp->cfg.vtpn; @@ -285,7 +286,7 @@ void ubcore_report_migrate_vtp(struct ubcore_device *dev, struct ubcore_vtp *vtp struct ubcore_nlmsg *req_msg; int ret; - req_msg = ubcore_get_migrate_vtp_req(vtp, event_type, dev->dev_name); + req_msg = ubcore_get_migrate_vtp_req(vtp, event_type, dev); if (req_msg == NULL) { ubcore_log_err("Failed to get migrate vtp switch req"); return; @@ -328,9 +329,6 @@ static void ubcore_nl_cb_func(struct sk_buff *skb) g_agent_port = nlh->nlmsg_pid; ubcore_nl_sync_table(); break; - case UBCORE_NL_QUERY_TPF_DEV_INFO: - ubcore_nl_update_tpf_dev_info(); - break; case UBCORE_NL_UPDATE_TPF_DEV_INFO_RESP: ubcore_nl_handle_update_tpf_dev_info_resp(nlh); break; @@ -339,6 +337,9 @@ static void ubcore_nl_cb_func(struct sk_buff *skb) break; case UBCORE_NL_FE2TPF_REQ: case UBCORE_NL_QUERY_TP_REQ: + case UBCORE_NL_ADD_SIP_REQ: + case UBCORE_NL_DEL_SIP_REQ: + case UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ: default: ubcore_log_err("Unexpected nl msg type: %d received\n", nlh->nlmsg_type); break; @@ -396,7 +397,7 @@ struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_device *dev, struct ubcor return NULL; } - leavetime = wait_for_completion_timeout(&s->comp, msecs_to_jiffies(UBCORE_NL_TIMEOUT)); + leavetime = wait_for_completion_timeout(&s->comp, msecs_to_jiffies(UBCORE_TIMEOUT)); if (leavetime == 0) { ubcore_log_err("Failed to wait reply, ret: %d, leavetime: %lu\n", ret, leavetime); ubcore_destroy_nl_session(s); diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.h b/drivers/ub/urma/ubcore/ubcore_netlink.h index efb99b721c36..18202ef74f72 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.h +++ b/drivers/ub/urma/ubcore/ubcore_netlink.h @@ -50,7 +50,6 @@ enum ubcore_nlmsg_type { UBCORE_NL_TP_SUSPEND_REQ, UBCORE_NL_MIGRATE_VTP_SWITCH, UBCORE_NL_MIGRATE_VTP_ROLLBACK, - UBCORE_NL_QUERY_TPF_DEV_INFO, UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ, UBCORE_NL_UPDATE_TPF_DEV_INFO_RESP, }; @@ -169,6 +168,7 @@ struct ubcore_add_sip_req { uint8_t port_id[UBCORE_MAX_PORT_CNT]; uint32_t index; uint32_t mtu; + char netdev_name[UBCORE_MAX_DEV_NAME]; /* for change mtu */ }; struct ubcore_add_sip_resp { @@ -176,6 +176,7 @@ struct ubcore_add_sip_resp { }; struct ubcore_del_sip_req { + char dev_name[UBCORE_MAX_DEV_NAME]; uint32_t index; }; @@ -189,6 +190,7 @@ struct ubcore_tp_suspend_req { uint16_t data_udp_start; uint16_t ack_udp_start; uint32_t sip_idx; + char tpf_dev_name[UBCORE_MAX_DEV_NAME]; }; struct ubcore_tp_error_req { @@ -204,6 +206,7 @@ struct ubcore_tp_error_req { uint32_t local_jetty_id; union ubcore_eid peer_eid; uint32_t peer_jetty_id; + char tpf_dev_name[UBCORE_MAX_DEV_NAME]; }; struct ubcore_nl_function_mig_req { diff --git a/drivers/ub/urma/ubcore/ubcore_priv.h b/drivers/ub/urma/ubcore/ubcore_priv.h index 42d3193754bc..fe44501355c5 100644 --- a/drivers/ub/urma/ubcore/ubcore_priv.h +++ b/drivers/ub/urma/ubcore/ubcore_priv.h @@ -30,8 +30,8 @@ * On the Internet Assigned Numbers Authority, add Hardware Types: Unified Bus (UB) */ #define UBCORE_NETDEV_UB_TYPE (38) /* Unified Bus(UB) */ -#define UBCORE_NON_VIRTUALIZATION_FE_IDX 0xffff #define UCBORE_INVALID_UPI 0xffffffff +#define UBCORE_TIMEOUT 30000 /* 30s */ union ubcore_set_global_cfg_mask { struct { @@ -82,11 +82,6 @@ static inline struct ubcore_ucontext *ubcore_get_uctx(struct ubcore_udata *udata return udata == NULL ? NULL : udata->uctx; } -static inline bool ubcore_check_dev_name_invalid(struct ubcore_device *dev, char *dev_name) -{ - return (strcmp(dev->dev_name, dev_name) != 0); -} - static inline bool ubcore_check_trans_mode_valid(enum ubcore_transport_mode trans_mode) { return trans_mode == UBCORE_TP_RM || @@ -104,6 +99,9 @@ struct ubcore_device *ubcore_find_tpf_by_dev(struct ubcore_device *dev, enum ubcore_transport_type type); struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name, enum ubcore_transport_type type); +/* returned list should be freed by caller */ +struct ubcore_device **ubcore_get_all_tpf_device(enum ubcore_transport_type type, + uint32_t *dev_cnt); int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg); int ubcore_update_eidtbl_by_idx(struct ubcore_device *dev, union ubcore_eid *eid, @@ -156,9 +154,12 @@ static inline uint32_t ubcore_get_rc_vtp_hash(union ubcore_eid *peer_eid) return jhash(peer_eid, sizeof(union ubcore_eid) + sizeof(uint32_t), 0); } -static inline uint32_t ubcore_get_vtpn_hash(union ubcore_eid *key_addr) +#define VTPN_KEY_SIZE (offsetof(struct ubcore_vtpn, eid_index) - \ + offsetof(struct ubcore_vtpn, trans_mode)) + +static inline uint32_t ubcore_get_vtpn_hash(enum ubcore_transport_mode *key_addr) { - return jhash(key_addr, sizeof(union ubcore_eid) + sizeof(union ubcore_eid), 0); + return jhash(key_addr, VTPN_KEY_SIZE, 0); } static inline bool ubcore_jfs_need_advise(struct ubcore_jfs *jfs) diff --git a/drivers/ub/urma/ubcore/ubcore_segment.c b/drivers/ub/urma/ubcore/ubcore_segment.c index 0efe6a1761e8..41b9111a43c6 100644 --- a/drivers/ub/urma/ubcore/ubcore_segment.c +++ b/drivers/ub/urma/ubcore/ubcore_segment.c @@ -30,7 +30,8 @@ struct ubcore_token_id *ubcore_alloc_token_id(struct ubcore_device *dev, { struct ubcore_token_id *token_id; - if (dev == NULL || dev->ops->alloc_token_id == NULL || dev->ops->free_token_id == NULL) { + if (dev == NULL || dev->ops == NULL || dev->ops->alloc_token_id == NULL || + dev->ops->free_token_id == NULL) { ubcore_log_err("invalid parameter.\n"); return NULL; } @@ -51,10 +52,10 @@ int ubcore_free_token_id(struct ubcore_token_id *token_id) { struct ubcore_device *dev; - if (token_id == NULL || token_id->ub_dev == NULL || + if (token_id == NULL || token_id->ub_dev == NULL || token_id->ub_dev->ops == NULL || token_id->ub_dev->ops->free_token_id == NULL) { ubcore_log_err("invalid parameter.\n"); - return -1; + return -EINVAL; } dev = token_id->ub_dev; @@ -66,6 +67,16 @@ int ubcore_free_token_id(struct ubcore_token_id *token_id) } EXPORT_SYMBOL(ubcore_free_token_id); +static int ubcore_check_ops_register_seg(struct ubcore_device *dev, struct ubcore_seg_cfg *cfg) +{ + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->register_seg == NULL || + dev->ops->unregister_seg == NULL) { + ubcore_log_err("invalid parameter.\n"); + return -1; + } + return 0; +} + struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, struct ubcore_seg_cfg *cfg, struct ubcore_udata *udata) @@ -74,11 +85,8 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, struct ubcore_seg_cfg tmp_cfg; struct ubcore_target_seg *tseg; - if (dev == NULL || cfg == NULL || dev->ops->register_seg == NULL || - dev->ops->unregister_seg == NULL) { - ubcore_log_err("invalid parameter.\n"); + if (ubcore_check_ops_register_seg(dev, cfg) != 0) return NULL; - } if (dev->transport_type == UBCORE_TRANSPORT_UB && ((cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_VALID && cfg->token_id == NULL) || @@ -94,6 +102,11 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, "Local write must be set when either remote write or remote atomic is declared.\n"); return NULL; } + if (cfg->eid_index >= dev->eid_table.eid_cnt) { + ubcore_log_warn("eid_index:%u >= eid_table cnt:%u.\n", + cfg->eid_index, dev->eid_table.eid_cnt); + return NULL; + } if (udata == NULL && cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_INVALID && dev->transport_type == UBCORE_TRANSPORT_UB) @@ -110,7 +123,7 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, tseg = dev->ops->register_seg(dev, &tmp_cfg, udata); if (tseg == NULL) { - ubcore_log_err("UBEP failed to register segment with va:%llu\n", tmp_cfg.va); + ubcore_log_err("UBEP failed to register segment.\n"); if (alloc_token_id == true) (void)ubcore_free_token_id(tmp_cfg.token_id); return NULL; @@ -141,9 +154,10 @@ int ubcore_unregister_seg(struct ubcore_target_seg *tseg) struct ubcore_device *dev; int ret; - if (tseg == NULL || tseg->ub_dev == NULL || tseg->ub_dev->ops->unregister_seg == NULL) { + if (tseg == NULL || tseg->ub_dev == NULL || tseg->ub_dev->ops == NULL || + tseg->ub_dev->ops->unregister_seg == NULL) { ubcore_log_err("invalid parameter.\n"); - return -1; + return -EINVAL; } dev = tseg->ub_dev; @@ -172,7 +186,7 @@ struct ubcore_target_seg *ubcore_import_seg(struct ubcore_device *dev, { struct ubcore_target_seg *tseg; - if (dev == NULL || cfg == NULL || dev->ops->import_seg == NULL || + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->import_seg == NULL || dev->ops->unimport_seg == NULL) { ubcore_log_err("invalid parameter.\n"); return NULL; @@ -180,7 +194,7 @@ struct ubcore_target_seg *ubcore_import_seg(struct ubcore_device *dev, tseg = dev->ops->import_seg(dev, cfg, udata); if (tseg == NULL) { - ubcore_log_err("UBEP failed to import segment with va:%llu\n", cfg->seg.ubva.va); + ubcore_log_err("UBEP failed to import segment with va\n"); return NULL; } tseg->ub_dev = dev; @@ -196,9 +210,10 @@ int ubcore_unimport_seg(struct ubcore_target_seg *tseg) { struct ubcore_device *dev; - if (tseg == NULL || tseg->ub_dev == NULL || tseg->ub_dev->ops->unimport_seg == NULL) { + if (tseg == NULL || tseg->ub_dev == NULL || tseg->ub_dev->ops == NULL || + tseg->ub_dev->ops->unimport_seg == NULL) { ubcore_log_err("invalid parameter.\n"); - return -1; + return -EINVAL; } dev = tseg->ub_dev; diff --git a/drivers/ub/urma/ubcore/ubcore_tp.c b/drivers/ub/urma/ubcore/ubcore_tp.c index 4de75e0c6a5d..78c88cfaf2bd 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.c +++ b/drivers/ub/urma/ubcore/ubcore_tp.c @@ -44,7 +44,7 @@ static inline uint32_t get_udrv_in_len(struct ubcore_udata *udata) static inline int get_udrv_in_data(uint8_t *dst, uint32_t dst_len, struct ubcore_udata *udata) { - if (udata == NULL || udata->udrv_data == NULL || udata->udrv_data->in_len == 0) + if (get_udrv_in_len(udata) == 0) return 0; if (udata->uctx != NULL) { @@ -67,6 +67,9 @@ enum ubcore_mtu ubcore_get_mtu(int mtu) { int tmp_mtu = mtu - UB_PROTOCOL_HEAD_BYTES; + if (mtu < 0) + return 0; + if (tmp_mtu >= ubcore_mtu_enum_to_int(UBCORE_MTU_8192)) return UBCORE_MTU_8192; if (tmp_mtu >= ubcore_mtu_enum_to_int(UBCORE_MTU_4096)) @@ -115,6 +118,7 @@ static int ubcore_set_tp_peer_ext(struct ubcore_tp_attr *attr, uint64_t ext_addr void *peer_ext = NULL; int ret; + /* ext is unused */ if (ext_len == 0 || ext_addr == 0) return 0; @@ -145,6 +149,8 @@ static void ubcore_get_ta_data_from_ta(const struct ubcore_ta *ta, switch (ta->type) { case UBCORE_TA_JFS_TJFR: jfs = ta->jfs; + if (jfs->jfs_cfg.eid_index >= jfs->ub_dev->eid_table.eid_cnt) + return; ta_data->jetty_id.eid = jfs->ub_dev->eid_table.eid_entries[jfs->jfs_cfg.eid_index].eid; ta_data->jetty_id.id = jfs->id; @@ -152,6 +158,8 @@ static void ubcore_get_ta_data_from_ta(const struct ubcore_ta *ta, break; case UBCORE_TA_JETTY_TJETTY: jetty = ta->jetty; + if (jetty->jetty_cfg.eid_index >= jetty->ub_dev->eid_table.eid_cnt) + return; ta_data->jetty_id.eid = jetty->ub_dev->eid_table.eid_entries[jetty->jetty_cfg.eid_index].eid; ta_data->jetty_id.id = jetty->id; @@ -186,9 +194,11 @@ static int ubcore_nl_handle_create_tp_resp_cb(struct ubcore_device *dev, int ubcore_destroy_tp(struct ubcore_tp *tp) { + if (tp == NULL) + return -EINVAL; if (!ubcore_have_tp_ops(tp->ub_dev)) { ubcore_log_err("TP ops is NULL"); - return -1; + return -EINVAL; } if (tp->peer_ext.len > 0 && tp->peer_ext.addr != 0) kfree((void *)tp->peer_ext.addr); @@ -240,12 +250,17 @@ struct ubcore_tp *ubcore_create_tp(struct ubcore_device *dev, ubcore_log_err("Failed to create tp towards remote eid %pI6c", &cfg->peer_eid); return NULL; } + /* The driver may return the old tp pointer */ + if (tp->state != UBCORE_TP_STATE_RESET) + return tp; + tp->ub_dev = dev; ubcore_set_tp_init_cfg(tp, cfg); tp->state = UBCORE_TP_STATE_RESET; ubcore_log_info("tp state:(set to RESET) with tpn %u", tp->tpn); tp->priv = NULL; atomic_set(&tp->use_cnt, 0); + return tp; } @@ -401,7 +416,7 @@ int ubcore_modify_tp_state(struct ubcore_device *dev, struct ubcore_tp *tp, return 0; } - if (dev->ops->modify_tp(tp, attr, mask) != 0) { + if (dev == NULL || dev->ops == NULL || dev->ops->modify_tp(tp, attr, mask) != 0) { /* tp->peer_ext.addr will be freed when called ubcore_destroy_tp */ ubcore_log_err("Failed to modify tp to %u from state %u and tpn = %u", (uint32_t)new_state, (uint32_t)tp->state, tp->tpn); @@ -515,6 +530,12 @@ static struct ubcore_nlmsg *ubcore_get_create_tp_response(struct ubcore_tp *tp, struct ubcore_nl_create_tp_resp *create_resp; struct ubcore_nlmsg *resp = NULL; + if (payload_len < (uint32_t)sizeof(struct ubcore_nl_create_tp_resp)) { + /* If the value overflows, tp must exist */ + ubcore_log_err("tp_ext len %u is err", tp->tp_ext.len); + return NULL; + } + resp = ubcore_alloc_nlmsg(payload_len, &req->dst_eid, &req->src_eid); if (resp == NULL) { ubcore_log_err("Failed to alloc create tp response"); @@ -549,12 +570,15 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, struct ubcore_jetty *jetty; struct ubcore_jfs *jfs; + (void)memset(vtp_param, 0, sizeof(struct ubcore_vtp_param)); if (ta == NULL) return; switch (ta->type) { case UBCORE_TA_JFS_TJFR: jfs = ta->jfs; + if (jfs->jfs_cfg.eid_index >= jfs->ub_dev->eid_table.eid_cnt) + return; vtp_param->local_eid = jfs->ub_dev->eid_table.eid_entries[jfs->jfs_cfg.eid_index].eid; vtp_param->local_jetty = jfs->id; @@ -562,6 +586,8 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, break; case UBCORE_TA_JETTY_TJETTY: jetty = ta->jetty; + if (jetty->jetty_cfg.eid_index >= jetty->ub_dev->eid_table.eid_cnt) + return; vtp_param->local_eid = jetty->ub_dev->eid_table.eid_entries[jetty->jetty_cfg.eid_index].eid; vtp_param->local_jetty = jetty->id; @@ -796,11 +822,13 @@ static struct ubcore_tp *ubcore_bind_target_tp(struct ubcore_device *dev, struct ubcore_nlmsg *ubcore_handle_create_tp_req(struct ubcore_nlmsg *req) { - struct ubcore_nl_create_tp_req *create = - (struct ubcore_nl_create_tp_req *)(void *)req->payload; + struct ubcore_nl_create_tp_req *create; struct ubcore_tp *tp = NULL; struct ubcore_device *dev; + if (req == NULL) + return NULL; + create = (struct ubcore_nl_create_tp_req *)(void *)req->payload; if (req->payload_len < sizeof(struct ubcore_nl_create_tp_req)) { ubcore_log_err("Invalid create req"); return NULL; @@ -861,11 +889,15 @@ static int ubcore_unbind_target_tp(struct ubcore_device *dev, struct ubcore_nlmsg *ubcore_handle_destroy_tp_req(struct ubcore_nlmsg *req) { - struct ubcore_nl_destroy_tp_req *destroy = - (struct ubcore_nl_destroy_tp_req *)(void *)req->payload; + struct ubcore_nl_destroy_tp_req *destroy; struct ubcore_device *dev; int ret = -1; + if (req == NULL) { + ubcore_log_err("Failed to destroy tp req, req is NULL"); + return NULL; + } + if (req->payload_len != sizeof(struct ubcore_nl_destroy_tp_req)) { ubcore_log_err("Invalid destroy req"); return NULL; @@ -879,6 +911,7 @@ struct ubcore_nlmsg *ubcore_handle_destroy_tp_req(struct ubcore_nlmsg *req) return ubcore_get_destroy_tp_response(UBCORE_NL_RESP_FAIL, req); } + destroy = (struct ubcore_nl_destroy_tp_req *)(void *)req->payload; if (destroy->ta.ta_type == UBCORE_TA_VIRT) { } else if (destroy->trans_mode == UBCORE_TP_RC) { ret = ubcore_unbind_target_tp(dev, destroy); @@ -895,8 +928,7 @@ struct ubcore_tp *ubcore_create_vtp(struct ubcore_device *dev, union ubcore_eid enum ubcore_transport_mode trans_mode, struct ubcore_udata *udata) { - if (dev == NULL || dev->attr.virtualization || remote_eid == NULL || - !ubcore_have_tp_ops(dev)) { + if (!ubcore_have_tp_ops(dev) || dev->attr.virtualization || remote_eid == NULL) { ubcore_log_err("Invalid parameter"); return NULL; } @@ -979,10 +1011,17 @@ static int ubcore_send_create_tp_req(struct ubcore_device *dev, struct ubcore_vt struct ubcore_req *req_msg; struct ubcore_resp_cb cb; uint32_t payload_len; + uint32_t udata_len; + uint32_t tp_len; int ret; + tp_len = tp->tp_ext.len; + udata_len = get_udrv_in_len(udata); + if ((uint32_t)sizeof(struct ubcore_create_vtp_req) + tp_len > ULONG_MAX - udata_len) + return -ERANGE; + payload_len = (uint32_t)sizeof(struct ubcore_create_vtp_req) + - tp->tp_ext.len + get_udrv_in_len(udata); + tp_len + udata_len; req_msg = kcalloc(1, sizeof(struct ubcore_req) + payload_len, GFP_KERNEL); if (req_msg == NULL) return -ENOMEM; @@ -990,8 +1029,10 @@ static int ubcore_send_create_tp_req(struct ubcore_device *dev, struct ubcore_vt req_msg->opcode = UBCORE_MSG_CREATE_VTP; req_msg->len = payload_len; data = (struct ubcore_create_vtp_req *)req_msg->data; - if (ubcore_init_create_tp_req(dev, tp_param, tp, udata, data) != 0) - return -1; + if (ubcore_init_create_tp_req(dev, tp_param, tp, udata, data) != 0) { + kfree(req_msg); + return -ENOEXEC; + } /* for alpha end */ cb.callback = ubcore_nl_handle_create_tp_resp_cb; cb.user_arg = NULL; @@ -1069,7 +1110,7 @@ static struct ubcore_nlmsg *ubcore_get_query_tp_req(struct ubcore_device *dev, query = (struct ubcore_nl_query_tp_req *)req->payload; query->trans_mode = trans_mode; (void)memcpy(query->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME); - query->fe_idx = 0; /* Alpha version specific */ + query->fe_idx = dev->attr.fe_idx; return req; } @@ -1146,6 +1187,11 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, struct ubcore_tp *new_tp = NULL; struct ubcore_tp_cfg tp_cfg = { 0 }; + if (jetty == NULL || tjetty == NULL || advice == NULL || udata == NULL) { + ubcore_log_err("Invalid parameter.\n"); + return -EINVAL; + } + mutex_lock(&tjetty->lock); if (tjetty->tp != NULL) { mutex_unlock(&tjetty->lock); @@ -1191,10 +1237,19 @@ int ubcore_unbind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, { struct ubcore_vtp_param tp_param; + if (jetty == NULL || tjetty == NULL || advice == NULL) { + ubcore_log_err("Invalid parameter.\n"); + return -EINVAL; + } + + mutex_lock(&tjetty->lock); if (tjetty->tp == NULL) { + mutex_unlock(&tjetty->lock); ubcore_log_warn("TP is not found, already removed or under use\n"); return 0; } + mutex_unlock(&tjetty->lock); + ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RC, &tp_param); if (ubcore_send_del_tp_req(jetty->ub_dev, &tp_param) != 0) { ubcore_log_warn("failed to unbind tp\n"); @@ -1215,9 +1270,14 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, struct ubcore_tp_node *tp_node; struct ubcore_tp *new_tp; + if (dev == NULL || remote_eid == NULL || advice == NULL || udata == NULL) { + ubcore_log_err("Invalid parameter.\n"); + return -EINVAL; + } + /* Must call driver->create_tp with udata if we are advising jetty */ tp_node = ubcore_hash_table_lookup(advice->meta.ht, advice->meta.hash, &advice->meta.key); - if (tp_node != NULL && !tp_node->tp->flag.bs.target) + if (tp_node != NULL && tp_node->tp != NULL && !tp_node->tp->flag.bs.target) return 0; ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RM, &tp_param); @@ -1258,6 +1318,11 @@ int ubcore_unadvise_tp(struct ubcore_device *dev, struct ubcore_tp_advice *advic { struct ubcore_vtp_param tp_param; + if (dev == NULL || advice == NULL) { + ubcore_log_err("Invalid parameter.\n"); + return -EINVAL; + } + ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RM, &tp_param); return ubcore_send_del_tp_req(dev, &tp_param); } @@ -1461,9 +1526,10 @@ void ubcore_restore_tp(struct ubcore_device *dev, struct ubcore_tp *tp) * Do not send retore tp req from target to inititor, * Do not restore UM TP, as it is only visable by the driver */ - if (dev->transport_type != UBCORE_TRANSPORT_IB || tp->flag.bs.target || + if (!ubcore_have_tp_ops(dev) || tp == NULL || + dev->transport_type != UBCORE_TRANSPORT_IB || tp->flag.bs.target || tp->priv == NULL || tp->trans_mode == UBCORE_TP_UM || - tp->state != UBCORE_TP_STATE_ERR || !ubcore_have_tp_ops(dev)) + tp->state != UBCORE_TP_STATE_ERR) return; req_msg = ubcore_get_restore_tp_req(tp); @@ -1499,7 +1565,7 @@ void ubcore_restore_tp(struct ubcore_device *dev, struct ubcore_tp *tp) } EXPORT_SYMBOL(ubcore_restore_tp); -static struct ubcore_nlmsg *ubcore_get_tp_error_req(struct ubcore_tp *tp) +static struct ubcore_nlmsg *ubcore_get_tp_error_req(struct ubcore_device *dev, struct ubcore_tp *tp) { uint32_t payload_len = (uint32_t)sizeof(struct ubcore_tp_error_req); struct ubcore_tp_error_req *error_req; @@ -1528,6 +1594,8 @@ static struct ubcore_nlmsg *ubcore_get_tp_error_req(struct ubcore_tp *tp) error_req->local_jetty_id = tp->local_jetty.id; error_req->peer_jetty_id = tp->peer_jetty.id; } + (void)memcpy(error_req->tpf_dev_name, dev->dev_name, + UBCORE_MAX_DEV_NAME); return req; } @@ -1549,7 +1617,7 @@ void ubcore_report_tp_error(struct ubcore_device *dev, struct ubcore_tp *tp) } } - req_msg = ubcore_get_tp_error_req(tp); + req_msg = ubcore_get_tp_error_req(dev, tp); if (req_msg == NULL) { ubcore_log_err("Failed to get tp error req"); return; @@ -1564,7 +1632,8 @@ void ubcore_report_tp_error(struct ubcore_device *dev, struct ubcore_tp *tp) kfree(req_msg); } -static struct ubcore_nlmsg *ubcore_get_tp_suspend_req(struct ubcore_tp *tp) +static struct ubcore_nlmsg *ubcore_get_tp_suspend_req(struct ubcore_device *dev, + struct ubcore_tp *tp) { uint32_t payload_len = (uint32_t)sizeof(struct ubcore_tp_suspend_req); struct ubcore_tp_suspend_req *suspend_req; @@ -1584,6 +1653,8 @@ static struct ubcore_nlmsg *ubcore_get_tp_suspend_req(struct ubcore_tp *tp) suspend_req->sip_idx = tp->local_net_addr_idx; ubcore_log_info("report tp suspend: data_udp_start: %hu, ack_udp_start: %hu", tp->data_udp_start, tp->ack_udp_start); + (void)memcpy(suspend_req->tpf_dev_name, dev->dev_name, + UBCORE_MAX_DEV_NAME); return req; } @@ -1593,7 +1664,7 @@ void ubcore_report_tp_suspend(struct ubcore_device *dev, struct ubcore_tp *tp) struct ubcore_nlmsg *req_msg; int ret; - req_msg = ubcore_get_tp_suspend_req(tp); + req_msg = ubcore_get_tp_suspend_req(dev, tp); if (req_msg == NULL) { ubcore_log_err("Failed to get tp suspend req"); return; @@ -1651,7 +1722,8 @@ static struct ubcore_tp *ubcore_restore_bound_target_tp(struct ubcore_device *de static struct ubcore_tp *ubcore_handle_restore_tp(struct ubcore_device *dev, struct ubcore_nl_restore_tp_req *restore) { - if (dev->transport_type != UBCORE_TRANSPORT_IB || restore->trans_mode == UBCORE_TP_UM || + if (dev->transport_type != UBCORE_TRANSPORT_IB || + restore == NULL || restore->trans_mode == UBCORE_TP_UM || restore->ta.ta_type == UBCORE_TA_NONE || restore->ta.ta_type >= UBCORE_TA_VIRT) return NULL; @@ -1663,18 +1735,18 @@ static struct ubcore_tp *ubcore_handle_restore_tp(struct ubcore_device *dev, struct ubcore_nlmsg *ubcore_handle_restore_tp_req(struct ubcore_nlmsg *req) { - struct ubcore_nl_restore_tp_req *restore = - (struct ubcore_nl_restore_tp_req *)(void *)req->payload; + struct ubcore_nl_restore_tp_req *restore; struct ubcore_device *dev; struct ubcore_tp *tp; - if (req->payload_len != sizeof(struct ubcore_nl_restore_tp_req)) { + if (req == NULL || req->payload_len != sizeof(struct ubcore_nl_restore_tp_req)) { ubcore_log_err("Invalid restore req"); return NULL; } + restore = (struct ubcore_nl_restore_tp_req *)(void *)req->payload; dev = ubcore_find_device(&req->dst_eid, req->transport_type); - if (dev == NULL || !ubcore_have_tp_ops(dev)) { + if (!ubcore_have_tp_ops(dev)) { if (dev != NULL) ubcore_put_device(dev); ubcore_log_err("Failed to find device or device ops invalid"); diff --git a/drivers/ub/urma/ubcore/ubcore_tp.h b/drivers/ub/urma/ubcore/ubcore_tp.h index 450ee00f1477..a8b77a848298 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.h +++ b/drivers/ub/urma/ubcore/ubcore_tp.h @@ -38,8 +38,8 @@ struct ubcore_tp_advice { static inline bool ubcore_have_tp_ops(struct ubcore_device *dev) { - return (dev != NULL && dev->ops->create_tp != NULL && dev->ops->modify_tp != NULL && - dev->ops->destroy_tp != NULL); + return (dev != NULL && dev->ops != NULL && dev->ops->create_tp != NULL && + dev->ops->modify_tp != NULL && dev->ops->destroy_tp != NULL); } /* alpha */ diff --git a/drivers/ub/urma/ubcore/ubcore_tpg.c b/drivers/ub/urma/ubcore/ubcore_tpg.c index 4e446b4ad5ea..539150bc93ca 100644 --- a/drivers/ub/urma/ubcore/ubcore_tpg.c +++ b/drivers/ub/urma/ubcore/ubcore_tpg.c @@ -135,6 +135,10 @@ int ubcore_create_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg, /* add tp to tpg */ for (i = 0; i < tp_cnt; i++) { + if (tp[i] == NULL) { + ubcore_log_warn("create multi tp, buf tp is null_ptr"); + continue; + } ubcore_store_tp_init_cfg(tpg, tp[i], dev, &cfg[i]); tpg->tp_list[i] = tp[i]; } @@ -160,7 +164,7 @@ uint32_t ubcore_destroy_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *t if (ret != (int)tp_cnt) ubcore_log_err("Failed to destroy multi tp %d", ret); - for (i = 0; i < ret; i++) + for (i = 0; (i < ret) && (i < UBCORE_MAX_TP_CNT_IN_GRP); i++) tpg->tp_list[i] = NULL; return (ret > 0 ? (uint32_t)ret : 0); @@ -177,9 +181,9 @@ uint32_t ubcore_modify_tp_in_tpg(struct ubcore_device *dev, struct ubcore_tpg *t ret = dev->ops->modify_multi_tp(tpg->tpg_cfg.tp_cnt, tpg->tp_list, attr, mask, failed_tp); if (ret != (int)tpg->tpg_cfg.tp_cnt) - ubcore_log_err("Failed to modify multi tp %d", ret); + ubcore_log_err("Failed to modify multi tp %d and tpgn %u ", ret, tpg->tpgn); - for (i = 0; i < ret; i++) + for (i = 0; (i < ret && i < UBCORE_MAX_TP_CNT_IN_GRP); i++) ubcore_modify_tp_attr(tpg->tp_list[i], &attr[i], mask[i]); return (ret > 0 ? (uint32_t)ret : 0); diff --git a/drivers/ub/urma/ubcore/ubcore_umem.c b/drivers/ub/urma/ubcore/ubcore_umem.c index c2ec7ad67617..06decb95de97 100644 --- a/drivers/ub/urma/ubcore/ubcore_umem.c +++ b/drivers/ub/urma/ubcore/ubcore_umem.c @@ -133,7 +133,7 @@ static int umem_verify_input(struct ubcore_device *ub_dev, uint64_t va, uint64_t { if (ub_dev == NULL || ((va + len) < va) || PAGE_ALIGN(va + len) < (va + len)) { - ubcore_log_err("Invalid parameter, va: %llx, len: %llx.\n", va, len); + ubcore_log_err("Invalid parameter, va or len is invalid.\n"); return -EINVAL; } if (flag.bs.non_pin == 1) { @@ -182,7 +182,7 @@ static struct ubcore_umem *ubcore_get_target_umem(struct ubcore_device *dev, uin int ret = 0; umem = kzalloc(sizeof(*umem), GFP_KERNEL); - if (umem == 0) { + if (umem == NULL) { ret = -ENOMEM; goto out; } @@ -237,7 +237,7 @@ struct ubcore_umem *ubcore_umem_get(struct ubcore_device *dev, uint64_t va, return ERR_PTR(ret); page_list = (struct page **)__get_free_page(GFP_KERNEL); - if (page_list == 0) + if (page_list == NULL) return ERR_PTR(-ENOMEM); return ubcore_get_target_umem(dev, va, len, flag, page_list); @@ -248,8 +248,16 @@ void ubcore_umem_release(struct ubcore_umem *umem) { uint64_t npages; - if (IS_ERR_OR_NULL(umem)) + if (IS_ERR_OR_NULL(umem) || umem->ub_dev == NULL || umem->owning_mm == NULL) { + ubcore_log_err("Invalid parameter.\n"); return; + } + + if (((umem->va + umem->length) < umem->va) || + PAGE_ALIGN(umem->va + umem->length) < (umem->va + umem->length)) { + ubcore_log_err("Invalid parameter, va or len is invalid.\n"); + return; + } npages = umem_cal_npages(umem->va, umem->length); dma_unmap_sg(umem->ub_dev->dma_dev, umem->sg_head.sgl, (int)umem->nmap, DMA_BIDIRECTIONAL); diff --git a/drivers/ub/urma/ubcore/ubcore_utp.c b/drivers/ub/urma/ubcore/ubcore_utp.c index 478fed8ce25d..362155d21165 100644 --- a/drivers/ub/urma/ubcore/ubcore_utp.c +++ b/drivers/ub/urma/ubcore/ubcore_utp.c @@ -28,7 +28,8 @@ static int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, { struct ubcore_device_status st = { 0 }; - if (port_num >= dev->attr.port_cnt || dev->ops->query_device_status == NULL) { + if (port_num >= dev->attr.port_cnt || dev->ops == NULL || + dev->ops->query_device_status == NULL || port_num >= UBCORE_MAX_PORT_CNT) { ubcore_log_err("Invalid parameter"); return -1; } diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c index 81ddd627db73..db3c5967f888 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c @@ -98,7 +98,7 @@ static struct ubcore_tpg *ubcore_create_tpg_and_multi_tp(struct ubcore_device *d struct ubcore_tpg *tpg; int ret = 0; - if (tpg_cfg->tp_cnt > UBCORE_MAX_TP_CNT_IN_GRP || + if (tpg_cfg->tp_cnt > UBCORE_MAX_TP_CNT_IN_GRP || tpg_cfg->tp_cnt == 0 || (tpg_cfg->trans_mode == UBCORE_TP_RC && tpg_cfg->tp_cnt != RC_TP_CNT)) return ERR_PTR(-EINVAL); @@ -139,19 +139,23 @@ static int ubcore_para_ta(struct ubcore_device *dev, struct ubcore_tp_advice *ad switch (ta_data->ta_type) { case UBCORE_TA_JFS_TJFR: jfs = ubcore_find_jfs(dev, ta_data->jetty_id.id); - if (jfs != NULL) { - meta->ht = ubcore_get_tptable(jfs->tptable); - advice->ta.jfs = jfs; - advice->ta.tjetty_id = ta_data->tjetty_id; + if (jfs == NULL) { + ubcore_log_err("Failed to find jfs by jetty id %u", ta_data->jetty_id.id); + return -1; } + meta->ht = ubcore_get_tptable(jfs->tptable); + advice->ta.jfs = jfs; + advice->ta.tjetty_id = ta_data->tjetty_id; break; case UBCORE_TA_JETTY_TJETTY: jetty = ubcore_find_jetty(dev, ta_data->jetty_id.id); - if (jetty != NULL) { - meta->ht = ubcore_get_tptable(jetty->tptable); - advice->ta.jetty = jetty; - advice->ta.tjetty_id = ta_data->tjetty_id; + if (jetty == NULL) { + ubcore_log_err("Failed to find jetty by jetty id %u", ta_data->jetty_id.id); + return -1; } + meta->ht = ubcore_get_tptable(jetty->tptable); + advice->ta.jetty = jetty; + advice->ta.tjetty_id = ta_data->tjetty_id; break; case UBCORE_TA_NONE: case UBCORE_TA_VIRT: @@ -168,7 +172,8 @@ static int ubcore_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, { struct ubcore_device_status st = { 0 }; - if (port_num >= dev->attr.port_cnt || dev->ops->query_device_status == NULL) { + if (port_num >= dev->attr.port_cnt || dev->ops == NULL || + dev->ops->query_device_status == NULL) { ubcore_log_err("Invalid parameter"); return -1; } @@ -241,7 +246,6 @@ static struct ubcore_tp_node *ubcore_get_tp_node(struct ubcore_device *dev, static int ubcore_cmd_create_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_create_tpg *arg) { struct ubcore_tp_advice advice = { 0 }; - struct ubcore_tp_cfg tp_cfg = { 0 }; struct ubcore_tp_node *tp_node = NULL; struct ubcore_device *dev = NULL; int ret = 0; @@ -257,7 +261,6 @@ static int ubcore_cmd_create_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_cr ubcore_log_err("tp table is already released"); goto put_device; } - ubcore_set_tp_cfg_with_cmd(&tp_cfg, &arg->in.tp_cfg[0]); tp_node = ubcore_hash_table_lookup(advice.meta.ht, advice.meta.hash, &advice.meta.key); if (!tp_node) goto put_tptable; @@ -305,6 +308,9 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) goto free_arg; } + if (ubcore_get_active_mtu(dev, 0, &arg->local_mtu) != 0) + goto put_device; + tpg = ubcore_create_tpg_and_multi_tp(dev, &arg->in.tpg_cfg, arg->in.tp_cfg); if (IS_ERR_OR_NULL(tpg)) { ret = -EPERM; @@ -318,7 +324,7 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_tpg)); - if (ret) + if (ret != 0) goto destroy_tpg; else goto put_device; @@ -781,6 +787,28 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, return -1; } +static int ubcore_process_ub_mtu( + struct ubcore_cmd_create_target_tpg *arg, struct ubcore_device *dev) +{ + enum ubcore_mtu active_mtu; + uint32_t i; + int ret; + + ret = ubcore_get_active_mtu(dev, 0, &active_mtu); + if (ret != 0 && (arg->local_mtu == 0 || arg->peer_mtu == 0)) + return ret; + + if (arg->local_mtu == 0) + arg->local_mtu = active_mtu; + else if (active_mtu > 0) + arg->local_mtu = min(arg->local_mtu, active_mtu); + + for (i = 0; i < arg->in.tpg_cfg.tp_cnt; i++) + arg->in.rtr_attr[i].mtu = min(arg->local_mtu, arg->peer_mtu); + + return 0; +} + static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) { struct ubcore_tp *failed_tp[UBCORE_MAX_TP_CNT_IN_GRP]; @@ -810,6 +838,10 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) goto free_arg; } + ret = ubcore_process_ub_mtu(arg, dev); + if (ret != 0) + goto put_device; + tpg = ubcore_create_tpg_and_multi_tp(dev, &arg->in.tpg_cfg, arg->in.tp_cfg); if (IS_ERR_OR_NULL(tpg)) { ret = -EPERM; @@ -970,7 +1002,7 @@ static int ubcore_cmd_destroy_vtp(struct ubcore_cmd_hdr *hdr) goto put_device; } - ret = ubcore_unmap_vtp(vtp); + ret = ubcore_check_and_unmap_vtp(vtp, arg.in.role); put_device: ubcore_put_device(dev); @@ -1134,15 +1166,12 @@ static int ubcore_cmd_set_upi(struct ubcore_cmd_hdr *hdr) continue; if (pattern3_upi == UCBORE_INVALID_UPI) { cfg.upi = arg.in.upi; - (void)ubcore_add_ueid( - dev, (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); } else { cfg.upi = pattern3_upi; - (void)ubcore_delete_ueid( - dev, (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); cfg.upi = arg.in.upi; - (void)ubcore_add_ueid( - dev, (uint16_t)UBCORE_NON_VIRTUALIZATION_FE_IDX, &cfg); + (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); } } (void)ubcore_add_upi_list(dev, arg.in.upi); @@ -1265,6 +1294,12 @@ static int ubcore_cmd_set_vport_cfg(struct ubcore_cmd_hdr *hdr) return 0; } + if (!dev->attr.tp_maintainer) { + ubcore_log_err("vport should config in tpf, dev_name:%s ", dev->dev_name); + ubcore_put_device(dev); + return -ENXIO; + } + /* check whethre the tp in tpg configed is exceeded the device cap */ if (arg.in.vport_cfg.tp_cnt > dev->attr.dev_cap.max_tp_in_tpg) { ubcore_log_err("configed tp_cnt:%u is exceeded the devce cap:%u", @@ -1311,7 +1346,7 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) } ubcore_log_info("get tpf device name %s", tpf_dev->dev_name); - (void)strcpy(arg.out.target_tpf_name, tpf_dev->dev_name); + (void)memcpy(arg.out.target_tpf_name, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); ubcore_put_device(tpf_dev); if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, @@ -1483,7 +1518,7 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) ubcore_set_vtp2ctp_cfg(&vtp_cfg, &arg->in.vtp, ctp); } - vtp = ubcore_map_vtp(dev, &vtp_cfg); + vtp = ubcore_check_and_map_vtp(dev, &vtp_cfg, arg->in.role); if (vtp == NULL) { ret = -EPERM; goto put_device; @@ -1498,7 +1533,7 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) goto put_device; unmap_vtp: - (void)ubcore_unmap_vtp(vtp); + (void)ubcore_check_and_unmap_vtp(vtp, arg->in.role); put_device: ubcore_put_device(dev); free_arg: @@ -2002,7 +2037,7 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) tpg = ubcore_find_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; - ubcore_log_err("Failed to find tpg"); + ubcore_log_err("Failed to find tpg %u", arg.in.tpgn); goto put_device; } @@ -2013,11 +2048,21 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) continue; } - if (tp->state != UBCORE_TP_STATE_RESET && ubcore_change_tp_to_err(dev, tp) != 0) - ubcore_log_warn("Failed to change tp to error in tpg %u", arg.in.tpgn); + if (tp->state == UBCORE_TP_STATE_RESET) { + ubcore_log_info("TP:%u already in RESET", tp->tpn); + continue; + } + + if (ubcore_change_tp_to_err(dev, tp) != 0) { + ubcore_log_warn("Failed to change tp:%u, to error in tpg %u", + tp->tpn, arg.in.tpgn); + continue; + } + arg.out.tp_error_cnt++; } - ubcore_log_info("Success to finish cmd change tpg to error"); + ubcore_log_info("Success to finish change tpg to error, tp err cnt:%u, tpgn %u", + arg.out.tp_error_cnt, arg.in.tpgn); if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct ubcore_cmd_change_tpg_to_error)) != 0) @@ -2120,6 +2165,12 @@ static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) ubcore_log_err("fail to find tpf device"); goto put_device; } + if (arg->in.cfg_cnt > UBCORE_MAX_VTP_CFG_CNT) { + ret = -ENODEV; + ubcore_log_err("arg cfg_cnt %u is err, range in [0, %d].\n", + arg->in.cfg_cnt, UBCORE_MAX_VTP_CFG_CNT); + goto put_device; + } for (i = 0; i < arg->in.cfg_cnt; i++) { ret = ubcore_init_modify_vtp(dev, &arg->in.vtp[i], &vtp_param, @@ -2191,12 +2242,6 @@ static int ubcore_cmd_opt_update_eid(struct ubcore_cmd_hdr *hdr) if (dev == NULL) return -1; - if (!dev->attr.virtualization && dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) { - ubcore_put_device(dev); - ubcore_log_err("pattern1 does not support static mode\n"); - return -1; - } - cfg.eid = arg.in.eid; cfg.eid_index = arg.in.eid_index; cfg.upi = arg.in.upi; @@ -2246,6 +2291,222 @@ static int ubcore_cmd_opt_query_fe_idx(struct ubcore_cmd_hdr *hdr) return ret; } +static int ubcore_cmd_get_vtp_table_cnt(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_get_vtp_table_cnt arg; + struct ubcore_device **dev_list = NULL; + uint32_t dev_cnt, i = 0; + int ret; + + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_get_vtp_table_cnt)); + if (ret != 0) + return ret; + + arg.out.vtp_cnt = 0; + dev_list = ubcore_get_all_tpf_device(UBCORE_TRANSPORT_UB, &dev_cnt); + + for (i = 0; i < dev_cnt; ++i) { + arg.out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_RM_VTP]); + arg.out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_UM_VTP]); + } + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + sizeof(struct ubcore_cmd_get_vtp_table_cnt)); + + if (dev_list != NULL) { + for (i = 0; i < dev_cnt; ++i) + if (dev_list[i] != NULL) + ubcore_put_device(dev_list[i]); + + kfree(dev_list); + } + return ret; +} + +static void ubcore_assign_single_out_vtp_table(struct ubcore_vtp *vtp, + struct ubcore_restored_vtp_entry *out_entry, const char *dev_name) +{ + uint32_t dev_tpn_idx = 0; + + if (vtp == NULL) + return; + + out_entry->fe_idx = vtp->cfg.fe_idx; + out_entry->vtpn = vtp->cfg.vtpn; + out_entry->local_jetty = vtp->cfg.local_jetty; + out_entry->local_eid = vtp->cfg.local_eid; + out_entry->peer_eid = vtp->cfg.peer_eid; + out_entry->peer_jetty = vtp->cfg.peer_jetty; + out_entry->trans_mode = vtp->cfg.trans_mode; + out_entry->role = vtp->role; + + if (vtp->cfg.trans_mode == UBCORE_TP_RM || vtp->cfg.trans_mode == UBCORE_TP_RC) { + if (vtp->cfg.tp == NULL) + return; + out_entry->local_net_addr_idx = vtp->cfg.tp->local_net_addr_idx; + if (vtp->cfg.tpg == NULL || vtp->cfg.tpg->tp_list == NULL) { + ubcore_log_err("tpg is null or tpg->tp_list is null"); + return; + } + + out_entry->tpgn = vtp->cfg.tpg->tpgn; + out_entry->tp_cnt = vtp->cfg.tpg->tpg_cfg.tp_cnt; + for (dev_tpn_idx = 0; dev_tpn_idx < out_entry->tp_cnt; dev_tpn_idx++) + out_entry->tpn[dev_tpn_idx] = vtp->cfg.tpg->tp_list[dev_tpn_idx]->tpn; + } else { + if (vtp->cfg.utp == NULL) { + ubcore_log_err("utp is null"); + return; + } + out_entry->local_net_addr_idx = vtp->cfg.utp->utp_cfg.local_net_addr_idx; + out_entry->utp_idx = vtp->cfg.utp->utpn; + } + (void)strcpy(out_entry->dev_name, dev_name); +} + +static void ubcore_get_dev_vtp_table(struct ubcore_hash_table *dev_ht, const char *dev_name, + uint32_t *out_entry_idx, struct ubcore_cmd_restored_vtp_entry *arg) +{ + uint32_t dev_vtp_idx, dev_vtp_cnt = 0; + struct ubcore_vtp **e = NULL; + + e = ubcore_get_all_vtp(dev_ht, &dev_vtp_cnt); + for (dev_vtp_idx = 0; dev_vtp_idx < dev_vtp_cnt; dev_vtp_idx++, (*out_entry_idx)++) + ubcore_assign_single_out_vtp_table(e[dev_vtp_idx], + &arg->out.entry[*out_entry_idx], dev_name); + + if (e != NULL) + kfree(e); +} + +static int ubcore_cmd_restore_vtp_table(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_restored_vtp_entry *arg; + struct ubcore_device **dev_list = NULL; + uint32_t dev_cnt, i = 0, out_idx = 0; + int ret; + + arg = kcalloc(1, hdr->args_len, GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; + + ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, hdr->args_len); + if (ret != 0) + return ret; + + arg->out.vtp_cnt = 0; + dev_list = ubcore_get_all_tpf_device(UBCORE_TRANSPORT_UB, &dev_cnt); + if (dev_cnt == 0) { + ubcore_log_info("dev count is 0\n"); + goto free_arg; + } + + for (i = 0; i < dev_cnt; ++i) { + arg->out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_RM_VTP]); + arg->out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_UM_VTP]); + } + if (arg->out.vtp_cnt != arg->in.vtp_cnt) { + ubcore_log_warn("input vtp_cnt: %u does not match current vtp_cnt: %u\n", + arg->out.vtp_cnt, arg->in.vtp_cnt); + ret = -1; + goto free_arg; + } + + for (i = 0; i < dev_cnt; ++i) { + ubcore_get_dev_vtp_table(&dev_list[i]->ht[UBCORE_HT_RM_VTP], + dev_list[i]->dev_name, &out_idx, arg); + ubcore_get_dev_vtp_table(&dev_list[i]->ht[UBCORE_HT_UM_VTP], + dev_list[i]->dev_name, &out_idx, arg); + } + + if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, hdr->args_len) != 0) + ret = -EPERM; + + for (i = 0; i < dev_cnt; ++i) + ubcore_put_device(dev_list[i]); + + if (dev_list != NULL) + kfree(dev_list); + +free_arg: + kfree(arg); + return ret; +} + +// target vtp is pseudo. +static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_map_target_vtp *arg; + struct ubcore_vtp_cfg vtp_cfg; + struct ubcore_vtp *vtp = NULL; + struct ubcore_device *dev; + struct ubcore_tpg *tpg; + struct ubcore_utp *utp; + struct ubcore_ctp *ctp; + int ret; + + arg = kzalloc(sizeof(struct ubcore_cmd_map_target_vtp), GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; + + ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_map_target_vtp)); + if (ret != 0) + goto free_arg; + + dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); + if (dev == NULL) { + ret = -ENODEV; + goto free_arg; + } + + if (arg->in.vtp.flag.bs.clan_tp == 0) { + /* deal with trans domain -G */ + if (arg->in.vtp.trans_mode != UBCORE_TP_UM) { + /* deal with RM first */ + tpg = ubcore_find_tpg(dev, arg->in.vtp.tpgn); + if (tpg == NULL) { + ret = -EINVAL; + ubcore_log_err("Failed to find tpg"); + goto put_device; + } + ubcore_set_vtp2tpg_cfg(&vtp_cfg, &arg->in.vtp, tpg); + } else { + /* deal with UM */ + utp = ubcore_find_utp(dev, arg->in.vtp.utpn); + if (utp == NULL) { + ret = -EINVAL; + ubcore_log_err("Failed to find utp"); + goto put_device; + } + ubcore_set_vtp2utp_cfg(&vtp_cfg, &arg->in.vtp, utp); + } + } else { + /* deal with trans domain -C */ + ctp = ubcore_find_ctp(dev, arg->in.vtp.ctpn); + if (ctp == NULL) { + ret = -EINVAL; + ubcore_log_err("Failed to find ctp"); + goto put_device; + } + ubcore_set_vtp2ctp_cfg(&vtp_cfg, &arg->in.vtp, ctp); + } + + vtp = ubcore_check_and_map_target_vtp(dev, &vtp_cfg); + if (vtp == NULL) { + ret = -EPERM; + goto put_device; + } + vtp->role = (vtp->role != arg->in.role ? UBCORE_VTP_DUPLEX : vtp->role); + +put_device: + ubcore_put_device(dev); +free_arg: + kfree(arg); + return ret; +} + typedef int (*ubcore_uvs_cmd_handler)(struct ubcore_cmd_hdr *hdr); static ubcore_uvs_cmd_handler g_ubcore_uvs_cmd_handlers[] = { @@ -2284,6 +2545,9 @@ static ubcore_uvs_cmd_handler g_ubcore_uvs_cmd_handlers[] = { [UBCORE_CMD_DEALLOC_EID] = ubcore_cmd_opt_update_eid, [UBCORE_CMD_QUERY_FE_IDX] = ubcore_cmd_opt_query_fe_idx, [UBCORE_CMD_CONFIG_DSCP_VL] = ubcore_cmd_opt_config_dscp_vl, + [UBCORE_CMD_GET_VTP_TABLE_CNT] = ubcore_cmd_get_vtp_table_cnt, + [UBCORE_CMD_RESTORE_TABLE] = ubcore_cmd_restore_vtp_table, + [UBCORE_CMD_MAP_TARGET_VTP] = ubcore_cmd_map_target_vtp, }; int ubcore_uvs_cmd_parse(struct ubcore_cmd_hdr *hdr) diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h index c3d7426fc72c..741d7ba2e65a 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h @@ -74,6 +74,9 @@ enum ubcore_uvs_cmd { UBCORE_CMD_DEALLOC_EID, UBCORE_CMD_QUERY_FE_IDX, UBCORE_CMD_CONFIG_DSCP_VL, + UBCORE_CMD_GET_VTP_TABLE_CNT, + UBCORE_CMD_RESTORE_TABLE, + UBCORE_CMD_MAP_TARGET_VTP, UBCORE_CMD_LAST }; @@ -238,11 +241,20 @@ struct ubcore_cmd_modify_target_tpg { struct ubcore_ta_data ta_data; }; +struct ubcore_cmd_map_target_vtp { + struct { + struct ubcore_cmd_tpf tpf; + struct ubcore_cmd_vtp_cfg vtp; + uint32_t role; + } in; +}; + struct ubcore_cmd_destroy_vtp { struct { struct ubcore_cmd_tpf tpf; enum ubcore_transport_mode mode; uint32_t local_jetty; + uint32_t role; /* key start */ union ubcore_eid local_eid; union ubcore_eid peer_eid; @@ -275,6 +287,7 @@ struct ubcore_cmd_map_vtp { struct ubcore_cmd_tpf tpf; /* create vtp */ struct ubcore_cmd_vtp_cfg vtp; + uint32_t role; } in; struct { uint32_t vtpn; @@ -437,6 +450,47 @@ struct ubcore_cmd_change_tpg_to_error { uint32_t tpgn; struct ubcore_cmd_tpf tpf; } in; + + struct { + uint32_t tp_error_cnt; + } out; +}; + +struct ubcore_cmd_get_vtp_table_cnt { + struct { + uint32_t vtp_cnt; + } out; +}; + +struct ubcore_restored_vtp_entry { + uint16_t fe_idx; + uint32_t vtpn; + uint32_t local_jetty; + uint32_t peer_jetty; + uint32_t local_net_addr_idx; + union ubcore_eid local_eid; + union ubcore_eid peer_eid; + enum ubcore_transport_mode trans_mode; + union { + uint32_t tpgn; + uint32_t utp_idx; + uint32_t ctp_idx; + }; + char dev_name[UBCORE_MAX_DEV_NAME]; + bool target; + uint32_t tp_cnt; + uint32_t tpn[UBCORE_MAX_TP_CNT_IN_GRP]; + uint32_t role; +}; + +struct ubcore_cmd_restored_vtp_entry { + struct { + uint32_t vtp_cnt; + } in; + struct { + uint32_t vtp_cnt; + struct ubcore_restored_vtp_entry entry[0]; + } out; }; int ubcore_uvs_cmd_parse(struct ubcore_cmd_hdr *hdr); diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.c b/drivers/ub/urma/ubcore/ubcore_vtp.c index 387676a8214a..30f2feb02509 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.c +++ b/drivers/ub/urma/ubcore/ubcore_vtp.c @@ -59,6 +59,8 @@ static int ubcore_send_create_vtp_req(struct ubcore_device *dev, int ret; req = kzalloc(sizeof(struct ubcore_req) + data_len, GFP_KERNEL); + if (req == NULL) + return -ENOMEM; req->opcode = UBCORE_MSG_CREATE_VTP; req->len = data_len; @@ -106,6 +108,8 @@ static int ubcore_send_del_vtp_req(struct ubcore_vtpn *vtpn) int ret; req = kzalloc(sizeof(struct ubcore_req) + data_len, GFP_KERNEL); + if (req == NULL) + return -ENOMEM; req->opcode = UBCORE_MSG_DESTROY_VTP; req->len = data_len; @@ -167,7 +171,7 @@ static int ubcore_free_vtpn(struct ubcore_vtpn *vtpn) vtpn->vtpn, atomic_read(&vtpn->use_cnt)); return 0; } - atomic_set(&vtpn->state, (int)UBCORE_VTPS_DELETING); + atomic_set(&vtpn->state, (int)UBCORE_VTPS_DELETED); return dev->ops->free_vtpn(vtpn); } @@ -184,17 +188,17 @@ static int ubcore_find_add_vtpn(struct ubcore_device *dev, } *exist_vtpn = ubcore_hash_table_lookup_nolock(ht, - ubcore_get_vtpn_hash(&new_vtpn->local_eid), &new_vtpn->local_eid); + ubcore_get_vtpn_hash(&new_vtpn->trans_mode), &new_vtpn->trans_mode); if (*exist_vtpn != NULL) return -EEXIST; ubcore_hash_table_add_nolock(ht, &new_vtpn->hnode, - ubcore_get_vtpn_hash(&new_vtpn->local_eid)); + ubcore_get_vtpn_hash(&new_vtpn->trans_mode)); return 0; } -static struct ubcore_vtpn *ubcore_connect_rm_vtp(struct ubcore_device *dev, +static struct ubcore_vtpn *ubcore_connect_rm_um_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *param) { struct ubcore_vtpn *exist_vtpn; @@ -207,8 +211,8 @@ static struct ubcore_vtpn *ubcore_connect_rm_vtp(struct ubcore_device *dev, /* reuse */ spin_lock(&ht->lock); - old_vtpn = ubcore_hash_table_lookup_nolock(ht, ubcore_get_vtpn_hash(¶m->local_eid), - ¶m->local_eid); + old_vtpn = ubcore_hash_table_lookup_nolock(ht, ubcore_get_vtpn_hash(¶m->trans_mode), + ¶m->trans_mode); if (old_vtpn != NULL && atomic_read(&old_vtpn->state) == (int)UBCORE_VTPS_READY) { atomic_inc(&old_vtpn->use_cnt); ubcore_log_info("reuse vtpn, with vtpn id = %u, use cnt = %d", @@ -221,6 +225,11 @@ static struct ubcore_vtpn *ubcore_connect_rm_vtp(struct ubcore_device *dev, return NULL; } + if (old_vtpn != NULL) + ubcore_log_warn("found existed vtpn state = %u and use_cnt = %u", + (uint32_t)atomic_read(&old_vtpn->state), + (uint32_t)atomic_read(&old_vtpn->use_cnt)); + new_vtpn = ubcore_alloc_vtpn(dev, param); if (new_vtpn == NULL) { ubcore_log_err("failed to alloc vtpn!"); @@ -241,7 +250,8 @@ static struct ubcore_vtpn *ubcore_connect_rm_vtp(struct ubcore_device *dev, if (atomic_read(&exist_vtpn->state) == (int)UBCORE_VTPS_READY) { atomic_inc(&exist_vtpn->use_cnt); - ubcore_log_info("success to reuse the vtpn, it is ready"); + ubcore_log_info("success to reuse the vtpn %u, it is ready, reuse cnt %d", + exist_vtpn->vtpn, atomic_read(&exist_vtpn->use_cnt)); } else { exist_vtpn = NULL; ubcore_log_err("failed to reuse the vtpn, it is not ready"); @@ -250,6 +260,7 @@ static struct ubcore_vtpn *ubcore_connect_rm_vtp(struct ubcore_device *dev, spin_unlock(&ht->lock); return exist_vtpn; } + /* TODO: port_idx use 0, for now tp_cnt = 1 */ if (ubcore_check_port_state(dev, 0) != 0 || ubcore_send_create_vtp_req(dev, param, new_vtpn) != 0) { @@ -259,8 +270,8 @@ static struct ubcore_vtpn *ubcore_connect_rm_vtp(struct ubcore_device *dev, spin_unlock(&ht->lock); return NULL; } - spin_unlock(&ht->lock); + return new_vtpn; } @@ -274,8 +285,8 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, return NULL; } - if (param->trans_mode == UBCORE_TP_RM) - return ubcore_connect_rm_vtp(dev, param); + if (param->trans_mode == UBCORE_TP_RM || param->trans_mode == UBCORE_TP_UM) + return ubcore_connect_rm_um_vtp(dev, param); vtpn = ubcore_alloc_vtpn(dev, param); if (vtpn == NULL) @@ -289,7 +300,7 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, return vtpn; } -static int ubcore_disconnect_rm_vtp(struct ubcore_vtpn *vtpn) +static int ubcore_disconnect_rm_um_vtp(struct ubcore_vtpn *vtpn) { struct ubcore_device *dev = vtpn->ub_dev; int ret; @@ -303,10 +314,17 @@ static int ubcore_disconnect_rm_vtp(struct ubcore_vtpn *vtpn) return 0; } + if (atomic_read(&vtpn->state) != UBCORE_VTPS_READY) { + ubcore_log_err("vtpn state is not in ready state, it is in %d state", + atomic_read(&vtpn->state)); + return -1; + } + atomic_set(&vtpn->state, (int)UBCORE_VTPS_DELETING); + ret = ubcore_send_del_vtp_req(vtpn); if (ret != 0) { - atomic_inc(&vtpn->use_cnt); ubcore_log_err("failed to send del vtp req"); + atomic_set(&vtpn->state, (int)UBCORE_VTPS_READY); return ret; } @@ -315,7 +333,7 @@ static int ubcore_disconnect_rm_vtp(struct ubcore_vtpn *vtpn) ret = ubcore_free_vtpn(vtpn); if (ret != 0) { ubcore_hash_table_add(&vtpn->ub_dev->ht[UBCORE_HT_VTPN], &vtpn->hnode, - ubcore_get_vtpn_hash(&vtpn->local_eid)); + ubcore_get_vtpn_hash(&vtpn->trans_mode)); ubcore_log_err("failed to free vtp"); /* TODO roll back, start connect_vtp process again */ return ret; @@ -333,8 +351,8 @@ int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn) return -1; } - if (vtpn->trans_mode == UBCORE_TP_RM) - return ubcore_disconnect_rm_vtp(vtpn); + if (vtpn->trans_mode == UBCORE_TP_RM || vtpn->trans_mode == UBCORE_TP_UM) + return ubcore_disconnect_rm_um_vtp(vtpn); ret = ubcore_send_del_vtp_req(vtpn); if (ret != 0) { @@ -446,7 +464,10 @@ int ubcore_unmap_vtp(struct ubcore_vtp *vtp) ubcore_remove_vtp(dev, cfg.trans_mode, vtp); - ret = dev->ops->destroy_vtp(vtp); + if (vtp->cfg.vtpn == UINT_MAX) + kfree(vtp); + else + ret = dev->ops->destroy_vtp(vtp); if (ret != 0) { (void)ubcore_find_add_vtp(dev, cfg.trans_mode, vtp); ubcore_log_err("Failed to destroy vtp"); @@ -465,6 +486,64 @@ int ubcore_unmap_vtp(struct ubcore_vtp *vtp) return ret; } +int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role) +{ + struct ubcore_device *dev = NULL; + struct ubcore_vtp *new_vtp = NULL; + struct ubcore_vtp_cfg cfg; + int ret = 0; + + if (vtp == NULL || vtp->ub_dev == NULL || vtp->ub_dev->ops == NULL || + vtp->ub_dev->ops->destroy_vtp == NULL) + return -EINVAL; + + dev = vtp->ub_dev; + + if (vtp->role != UBCORE_VTP_DUPLEX) + return ubcore_unmap_vtp(vtp); + + cfg = vtp->cfg; + + if (role == UBCORE_VTP_INITIATOR) { + // delete original vtp, create pseudo vtp + new_vtp = kcalloc(1, sizeof(struct ubcore_vtp), GFP_KERNEL); + if (new_vtp == NULL) + return -ENOMEM; + + new_vtp->ub_dev = dev; + new_vtp->role = UBCORE_VTP_TARGET; + (void)memcpy(&new_vtp->cfg, &vtp->cfg, sizeof(struct ubcore_vtp_cfg)); + + ubcore_remove_vtp(dev, cfg.trans_mode, vtp); + ret = dev->ops->destroy_vtp(vtp); + if (ret != 0) { + (void)ubcore_find_add_vtp(dev, cfg.trans_mode, vtp); + kfree(new_vtp); + ubcore_log_err("Failed to destroy vtp"); + return ret; + } + + ret = ubcore_find_add_vtp(dev, new_vtp->cfg.trans_mode, new_vtp); + if (ret != 0) { + kfree(new_vtp); + if (cfg.flag.bs.clan_tp) { + atomic_dec(&cfg.ctp->use_cnt); + } else { + if (cfg.trans_mode != UBCORE_TP_UM) + atomic_dec(&cfg.tpg->use_cnt); + else + atomic_dec(&cfg.utp->use_cnt); + } + ubcore_log_err("Failed to add new vtp to the vtp table"); + return -1; + } + } else { + vtp->role = UBCORE_VTP_INITIATOR; + } + + return ret; +} + struct ubcore_vtp *ubcore_find_vtp(struct ubcore_device *dev, enum ubcore_transport_mode mode, union ubcore_eid *local_eid, union ubcore_eid *peer_eid) { @@ -493,6 +572,12 @@ struct ubcore_vtp *ubcore_find_vtp(struct ubcore_device *dev, void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, struct ubcore_tjetty_cfg *cfg, struct ubcore_vtp_param *vtp_param) { + if (cfg->eid_index >= dev->eid_table.eid_cnt) { + ubcore_log_err("invalid param, eid_index[%u] >= eid_cnt[%u]", + cfg->eid_index, dev->eid_table.eid_cnt); + return; + } + vtp_param->trans_mode = cfg->trans_mode; /* * RM/UM VTP for userspace app: get local eid from ucontext @@ -521,6 +606,12 @@ int ubcore_config_function_migrate_state(struct ubcore_device *dev, uint16_t fe_ return ret; } + if (dev == NULL || dev->ops == NULL || dev->ops->config_function_migrate_state == NULL) { + ret = -EINVAL; + ubcore_log_err("invalid param"); + return ret; + } + ret = dev->ops->config_function_migrate_state(dev, fe_idx, cnt, cfg, state); if (ret < 0) ubcore_log_err("Fail to config function migrate state"); @@ -534,6 +625,12 @@ int ubcore_modify_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *vtp_pa struct ubcore_vtp *vtp; int ret; + if (dev == NULL || dev->ops == NULL || dev->ops->modify_vtp == NULL) { + ret = -EINVAL; + ubcore_log_err("invalid param"); + return ret; + } + vtp = ubcore_find_vtp(dev, vtp_param->trans_mode, &vtp_param->local_eid, &vtp_param->peer_eid); if (vtp == NULL) { @@ -549,3 +646,148 @@ int ubcore_modify_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *vtp_pa return 0; } + +struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg, + uint32_t role) +{ + uint32_t vtp_role = role; + struct ubcore_vtp *vtp; + int ret; + + if (dev->ops == NULL || dev->ops->create_vtp == NULL) + return NULL; + + vtp = ubcore_find_vtp(dev, cfg->trans_mode, &cfg->local_eid, &cfg->peer_eid); + if (vtp != NULL) { + ubcore_log_info("vtp already exists"); + if (vtp->cfg.vtpn == UINT_MAX) { // only this may happen + vtp_role = (role == vtp->role) ? role : UBCORE_VTP_DUPLEX; + // delete original vtp + ubcore_log_info("vtpn is UINT_MAX, delete old one"); + ubcore_remove_vtp(dev, cfg->trans_mode, vtp); + kfree(vtp); + } else { // this should never happen + if (cfg->vtpn != UINT_MAX) { + ubcore_log_warn("origin vtpn is not UINT_MAX, input vtpn is not UINT_MAX"); + return vtp; + } + ubcore_log_warn("origin vtpn is not UINT_MAX, input vtpn is UINT_MAX"); + return NULL; + } + } + + vtp = dev->ops->create_vtp(dev, cfg, NULL); + if (vtp == NULL) { + ubcore_log_err("Failed to create vtp"); + return NULL; + } + + vtp->ub_dev = dev; + vtp->role = vtp_role; + + ret = ubcore_find_add_vtp(dev, cfg->trans_mode, vtp); + if (ret != 0) { + (void)dev->ops->destroy_vtp(vtp); + vtp = NULL; + ubcore_log_err("Failed to add vtp to the vtp table"); + return vtp; + } + + if (cfg->flag.bs.clan_tp) { + atomic_inc(&cfg->ctp->use_cnt); + } else { + if (cfg->trans_mode != UBCORE_TP_UM) + atomic_inc(&cfg->tpg->use_cnt); + else + atomic_inc(&cfg->utp->use_cnt); + } + + return vtp; +} + +struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, + struct ubcore_vtp_cfg *cfg) +{ + struct ubcore_vtp *vtp = NULL; + int ret; + + vtp = ubcore_find_vtp(dev, cfg->trans_mode, &cfg->local_eid, &cfg->peer_eid); + if (vtp != NULL) + return vtp; + + vtp = kcalloc(1, sizeof(struct ubcore_vtp), GFP_KERNEL); + if (vtp == NULL) + return NULL; + + vtp->ub_dev = dev; + (void)memcpy(&vtp->cfg, cfg, sizeof(struct ubcore_vtp_cfg)); + + ret = ubcore_find_add_vtp(dev, cfg->trans_mode, vtp); + if (ret != 0) { + kfree(vtp); + vtp = NULL; + ubcore_log_err("Failed to add vtp to the vtp table"); + return vtp; + } + + if (cfg->flag.bs.clan_tp) { + atomic_inc(&cfg->ctp->use_cnt); + } else { + if (cfg->trans_mode != UBCORE_TP_UM) + atomic_inc(&cfg->tpg->use_cnt); + else + atomic_inc(&cfg->utp->use_cnt); + } + + return vtp; +} + +uint32_t ubcore_get_all_vtp_cnt(struct ubcore_hash_table *ht) +{ + struct ubcore_vtp *vtp; + uint32_t cnt = 0; + uint32_t i = 0; + + spin_lock(&ht->lock); + if (ht->head == NULL) { + spin_unlock(&ht->lock); + return cnt; + } + + for (; i < ht->p.size; i++) { + hlist_for_each_entry(vtp, &ht->head[i], hnode) { + ++cnt; + } + } + + spin_unlock(&ht->lock); + return cnt; +} + +struct ubcore_vtp **ubcore_get_all_vtp(struct ubcore_hash_table *ht, + uint32_t *dev_vtp_cnt) +{ + struct ubcore_vtp **vtp_entry; + struct ubcore_vtp *vtp; + uint32_t i = 0, j = 0; + + *dev_vtp_cnt = ubcore_get_all_vtp_cnt(ht); + vtp_entry = kcalloc(1, (*dev_vtp_cnt) * (uint32_t)sizeof(struct ubcore_vtp *), GFP_KERNEL); + if (vtp_entry == NULL) + return NULL; + + spin_lock(&ht->lock); + if (ht->head == NULL) { + spin_unlock(&ht->lock); + return NULL; + } + + for (; i < ht->p.size; i++) { + hlist_for_each_entry(vtp, &ht->head[i], hnode) { + vtp_entry[j++] = vtp; + } + } + + spin_unlock(&ht->lock); + return vtp_entry; +} diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.h b/drivers/ub/urma/ubcore/ubcore_vtp.h index a6e0254d0001..dd05c282cdaa 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.h +++ b/drivers/ub/urma/ubcore/ubcore_vtp.h @@ -27,6 +27,10 @@ #include "ubcore_netlink.h" #include "ubcore_tp.h" +#define UBCORE_VTP_TARGET 1 +#define UBCORE_VTP_INITIATOR 0 +#define UBCORE_VTP_DUPLEX 2 + struct ubcore_vtp_param { enum ubcore_transport_mode trans_mode; /* RM vtpn key start */ @@ -99,7 +103,12 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn); /* map vtp to tpg, utp .... */ struct ubcore_vtp *ubcore_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg); +struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg, + uint32_t role); +struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, + struct ubcore_vtp_cfg *cfg); int ubcore_unmap_vtp(struct ubcore_vtp *vtp); +int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role); /* find mapped vtp */ struct ubcore_vtp *ubcore_find_vtp(struct ubcore_device *dev, enum ubcore_transport_mode mode, union ubcore_eid *local_eid, union ubcore_eid *peer_eid); @@ -111,4 +120,10 @@ int ubcore_config_function_migrate_state(struct ubcore_device *dev, uint16_t fe_ uint32_t cnt, struct ubcore_ueid_cfg *cfg, enum ubcore_mig_state state); int ubcore_modify_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *vtp_param, struct ubcore_vtp_attr *vattr, union ubcore_vtp_attr_mask *vattr_mask); + +uint32_t ubcore_get_all_vtp_cnt(struct ubcore_hash_table *ht); +/* returned list should be freed by caller */ +struct ubcore_vtp **ubcore_get_all_vtp(struct ubcore_hash_table *ht, + uint32_t *dev_vtp_cnt); + #endif diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.c b/drivers/ub/urma/ubcore/ubcore_workqueue.c new file mode 100644 index 000000000000..001bdb2af5bc --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: Ubcore workqueue + * Author:Zhangjiayu + * Create: 2024-1-27 + * Note: + * History: 2024-1-27: Create file + */ + +#include "ubcore_log.h" +#include "ubcore_workqueue.h" + +static struct workqueue_struct *g_ubcore_workqueues[(int)UBCORE_QUEUE_TYPE_NUM]; +const char UBCORE_QUEUE_NAMES[(int)UBCORE_QUEUE_TYPE_NUM][UBCORE_QUEUE_NAME_LEN] = { + {"ubcore-device-wq"}, {"ubcore-sip-wq"}, {"ubcore-bond-wq"}}; + +static bool check_queue_type_valid(int queue_type) +{ + return (queue_type >= (int)UBCORE_DISPATCH_EVENT_WQ) && + (queue_type < (int)UBCORE_QUEUE_TYPE_NUM); +} + +void ubcore_flush_workqueue(int queue_type) +{ + if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] == NULL) { + ubcore_log_err("queue_type %d out of range or workqueue is NULL\n", queue_type); + return; + } + + flush_workqueue(g_ubcore_workqueues[queue_type]); +} + +int ubcore_alloc_workqueue(int queue_type) +{ + if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] != NULL) { + ubcore_log_err("queue_type %d out of range or workqueue already exist\n", + queue_type); + return -EINVAL; + } + g_ubcore_workqueues[queue_type] = + alloc_workqueue("%s", 0, 0, UBCORE_QUEUE_NAMES[queue_type]); + if (g_ubcore_workqueues[queue_type] == NULL) { + ubcore_log_err("Failed to alloc workqueue, queue type %d\n", queue_type); + return -ENOMEM; + } + return 0; +} + +int ubcore_queue_work(int queue_type, struct work_struct *work) +{ + if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] == NULL) { + ubcore_log_err("queue_type %d out of range or workqueue is NULL\n", queue_type); + return -EINVAL; + } + return queue_work(g_ubcore_workqueues[queue_type], work) ? 0 : -1; +} + +int ubcore_destroy_workqueue(int queue_type) +{ + if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] == NULL) { + ubcore_log_err("queue_type %d out of range or workqueue is NULL\n", queue_type); + return -EINVAL; + } + destroy_workqueue(g_ubcore_workqueues[queue_type]); + g_ubcore_workqueues[queue_type] = NULL; + return 0; +} diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.h b/drivers/ub/urma/ubcore/ubcore_workqueue.h new file mode 100644 index 000000000000..b1487796bc57 --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: Ubcore workqueue + * Author: Zhang Jiayu + * Create: 2024-1-27 + * Note: + * History: 2024-1-27: Create file + */ + +#ifndef UBCORE_WORKQUEUE_H +#define UBCORE_WORKQUEUE_H + +#include +#include + +#define UBCORE_QUEUE_NAME_LEN 20 + +enum ubcore_queue_type { + UBCORE_DISPATCH_EVENT_WQ = 0, + UBCORE_SIP_NOTIFY_WQ, + UBCORE_BOND_EVENT_WQ, + UBCORE_QUEUE_TYPE_NUM +}; + +void ubcore_flush_workqueue(int queue_type); + +int ubcore_alloc_workqueue(int queue_type); + +int ubcore_queue_work(int queue_type, struct work_struct *work); + +int ubcore_destroy_workqueue(int queue_type); + +#endif diff --git a/drivers/ub/urma/uburma/Makefile b/drivers/ub/urma/uburma/Makefile index ad16b9596f03..1340fab0aa48 100644 --- a/drivers/ub/urma/uburma/Makefile +++ b/drivers/ub/urma/uburma/Makefile @@ -6,9 +6,8 @@ uburma-objs := uburma_main.o \ uburma_dev_ops.o \ uburma_cmd.o \ - uburma_cdev_file.o \ uburma_event.o \ uburma_uobj.o \ - uburma_netlink.o + uburma_log.o obj-$(CONFIG_UB_URMA) += uburma.o diff --git a/drivers/ub/urma/uburma/uburma_cdev_file.c b/drivers/ub/urma/uburma/uburma_cdev_file.c deleted file mode 100644 index 58b60aa32aa0..000000000000 --- a/drivers/ub/urma/uburma/uburma_cdev_file.c +++ /dev/null @@ -1,1107 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * Description: uburma cdev file - * Author: Qian Guoxin - * Create: 2022-08-16 - * Note: - * History: 2022-08-16: Create file - */ - -#include -#include -#include - -#include -#include - -#include "uburma_log.h" -#include "uburma_types.h" -#include "uburma_cdev_file.h" - -#define UBURMA_MAX_DEV_NAME 64 -#define UBURMA_MAX_VALUE_LEN 24 - -/* callback information */ -typedef ssize_t (*uburma_show_attr_cb)(struct ubcore_device *ubc_dev, - char *buf); -typedef ssize_t (*uburma_store_attr_cb)(struct ubcore_device *ubc_dev, - const char *buf, size_t len); -typedef ssize_t (*uburma_show_port_attr_cb)(struct ubcore_device *ubc_dev, - char *buf, uint8_t port_num); -typedef ssize_t (*uburma_show_fe_attr_cb)(struct ubcore_device *ubc_dev, - char *buf, uint16_t fe_num); -typedef ssize_t (*uburma_store_fe_attr_cb)(struct ubcore_device *ubc_dev, - const char *buf, size_t len, uint16_t fe_num); -typedef ssize_t (*uburma_show_eid_attr_cb)(struct ubcore_device *ubc_dev, - char *buf, uint16_t idx, struct net *net); - -static inline struct uburma_device *get_uburma_device(struct uburma_logic_device *ldev) -{ - return ldev == NULL ? NULL : ldev->ubu_dev; -} - -static ssize_t uburma_show_dev_attr(struct device *dev, struct device_attribute *attr, - char *buf, uburma_show_attr_cb show_cb) -{ - struct uburma_logic_device *ldev = dev_get_drvdata(dev); - struct uburma_device *ubu_dev = get_uburma_device(ldev); - struct ubcore_device *ubc_dev; - ssize_t ret = -ENODEV; - int srcu_idx; - - if (!ldev || !ubu_dev || !buf) { - uburma_log_err("Invalid argument.\n"); - return -EINVAL; - } - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (ubc_dev) - ret = show_cb(ubc_dev, buf); - - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -static ssize_t uburma_store_dev_attr(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len, uburma_store_attr_cb store_cb) -{ - struct uburma_logic_device *ldev = dev_get_drvdata(dev); - struct uburma_device *ubu_dev = get_uburma_device(ldev); - struct ubcore_device *ubc_dev; - ssize_t ret = -ENODEV; - int srcu_idx; - - if (!ldev || !ubu_dev || !buf) { - uburma_log_err("Invalid argument.\n"); - return -EINVAL; - } - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (ubc_dev) - ret = store_cb(ubc_dev, buf, len); - - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -/* interface for exporting device attributes */ -static ssize_t ubdev_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBCORE_MAX_DEV_NAME, "%s\n", ubc_dev->dev_name); -} - -static ssize_t ubdev_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, ubdev_show_cb); -} - -static DEVICE_ATTR_RO(ubdev); - -static ssize_t guid_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT "\n", - EID_ARGS(ubc_dev->attr.guid)); -} - -static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, guid_show_cb); -} - -static DEVICE_ATTR_RO(guid); - -static ssize_t max_upi_cnt_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_upi_cnt); -} - -static ssize_t max_upi_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_upi_cnt_show_cb); -} - -static DEVICE_ATTR_RO(max_upi_cnt); - -static ssize_t uburma_query_upi(struct ubcore_device *ubc_dev, char *buf, uint16_t fe_idx) -{ - struct ubcore_res_key key = { 0 }; - struct ubcore_res_val val = { 0 }; - uint32_t upi; - uint32_t i; - ssize_t ret; - - key.type = UBCORE_RES_KEY_UPI; - key.key = (uint32_t)fe_idx; - - val.len = (uint32_t)sizeof(uint32_t) * UBCORE_MAX_UPI_CNT; - val.addr = (uint64_t)kcalloc(1, val.len, GFP_KERNEL); - if (val.addr == 0) { - uburma_log_err("kcalloc fe%hu failed.\n", fe_idx); - return -ENOMEM; - } - - if (ubcore_query_resource(ubc_dev, &key, &val) != 0) { - uburma_log_err("query fe%hu resource failed.\n", fe_idx); - kfree((void *)val.addr); - return -EPERM; - } - -#define UBURMA_UPI_STR_LEN (9) /* 2^20 <= 8bit, add 1 bit space */ - for (i = 0; i < (val.len / sizeof(upi)); i++) { - upi = *((uint32_t *)val.addr + i); - ret = snprintf(buf + (UBURMA_UPI_STR_LEN * i), UBURMA_UPI_STR_LEN + 1, "%8u ", upi); - if (ret <= 0) { - uburma_log_err("snprintf for fe%hu upi failed %ld.\n", fe_idx, ret); - kfree((void *)val.addr); - return ret; - } - } - - buf[(UBURMA_UPI_STR_LEN * i) - 1] = '\n'; - - kfree((void *)val.addr); - return (ssize_t)(UBURMA_UPI_STR_LEN * i); -} - -static int uburma_parse_upi_str(const char *buf, size_t len, uint16_t *idx, uint32_t *upi) -{ - int ret; - - ret = sscanf(buf, "%hu=%u", idx, upi); - if (ret <= 1) // ret must be equal to 2 - return -1; - - return 0; -} - -static ssize_t uburma_set_upi(struct ubcore_device *ubc_dev, const char *buf, - size_t len, uint16_t fe_idx) -{ - ssize_t ret = -ENODEV; - uint16_t idx; - uint32_t upi; - - ret = uburma_parse_upi_str(buf, len, &idx, &upi); - if (ret != 0) { - uburma_log_err("parse fe%hu upi str:%s failed %ld.\n", fe_idx, buf, ret); - return -EINVAL; - } - - if (ubcore_set_upi(ubc_dev, fe_idx, idx, upi) != 0) { - uburma_log_err("set fe%hu idx:%hu upi:%u failed.\n", fe_idx, idx, upi); - return -EPERM; - } - return (ssize_t)len; // len is required for success return. -} - -static ssize_t upi_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return uburma_query_upi(ubc_dev, buf, UBCORE_OWN_FE_IDX); -} - -static ssize_t upi_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, upi_show_cb); -} - -static ssize_t upi_store_cb(struct ubcore_device *ubc_dev, const char *buf, size_t len) -{ - return uburma_set_upi(ubc_dev, buf, len, UBCORE_OWN_FE_IDX); -} - -static ssize_t upi_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) -{ - return uburma_store_dev_attr(dev, attr, buf, len, upi_store_cb); -} - -static DEVICE_ATTR_RW(upi); - -static ssize_t feature_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "0x%x\n", ubc_dev->attr.dev_cap.feature.value); -} - -static ssize_t feature_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, feature_show_cb); -} - -static DEVICE_ATTR_RO(feature); - -static ssize_t max_jfc_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfc); -} - -static ssize_t max_jfc_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfc_show_cb); -} - -static DEVICE_ATTR_RO(max_jfc); - -static ssize_t max_jfs_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfs); -} - -static ssize_t max_jfs_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfs_show_cb); -} - -static DEVICE_ATTR_RO(max_jfs); - -static ssize_t max_jfr_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfr); -} - -static ssize_t max_jfr_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfr_show_cb); -} - -static DEVICE_ATTR_RO(max_jfr); - -static ssize_t max_jetty_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jetty); -} - -static ssize_t max_jetty_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jetty_show_cb); -} - -static DEVICE_ATTR_RO(max_jetty); - -static ssize_t show_max_jetty_grp_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jetty_grp); -} -static ssize_t max_jetty_grp_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_max_jetty_grp_cb); -} -static DEVICE_ATTR_RO(max_jetty_grp); - -static ssize_t show_max_jetty_in_jetty_grp_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", - ubc_dev->attr.dev_cap.max_jetty_in_jetty_grp); -} -static ssize_t max_jetty_in_jetty_grp_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_max_jetty_in_jetty_grp_cb); -} -static DEVICE_ATTR_RO(max_jetty_in_jetty_grp); - -static ssize_t max_jfc_depth_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfc_depth); -} - -static ssize_t max_jfc_depth_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfc_depth_show_cb); -} - -static DEVICE_ATTR_RO(max_jfc_depth); - -static ssize_t max_jfs_depth_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfs_depth); -} - -static ssize_t max_jfs_depth_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfs_depth_show_cb); -} - -static DEVICE_ATTR_RO(max_jfs_depth); - -static ssize_t max_jfr_depth_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfr_depth); -} - -static ssize_t max_jfr_depth_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfr_depth_show_cb); -} - -static DEVICE_ATTR_RO(max_jfr_depth); - -static ssize_t show_max_jfs_inline_size_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", - ubc_dev->attr.dev_cap.max_jfs_inline_size); -} - -static ssize_t max_jfs_inline_size_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_max_jfs_inline_size_cb); -} - -static DEVICE_ATTR_RO(max_jfs_inline_size); - -static ssize_t max_jfs_sge_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfs_sge); -} - -static ssize_t max_jfs_sge_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfs_sge_show_cb); -} - -static DEVICE_ATTR_RO(max_jfs_sge); - -static ssize_t max_jfs_rsge_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfs_rsge); -} - -static ssize_t max_jfs_rsge_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfs_rsge_show_cb); -} - -static DEVICE_ATTR_RO(max_jfs_rsge); - -static ssize_t max_jfr_sge_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_jfr_sge); -} - -static ssize_t max_jfr_sge_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_jfr_sge_show_cb); -} - -static DEVICE_ATTR_RO(max_jfr_sge); - -static ssize_t max_msg_size_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%llu\n", ubc_dev->attr.dev_cap.max_msg_size); -} - -static ssize_t max_msg_size_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_msg_size_show_cb); -} - -static DEVICE_ATTR_RO(max_msg_size); - -static ssize_t show_max_atomic_size_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_atomic_size); -} -static ssize_t max_atomic_size_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_max_atomic_size_cb); -} -static DEVICE_ATTR_RO(max_atomic_size); - -static ssize_t show_atomic_feat_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.atomic_feat.value); -} -static ssize_t atomic_feat_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_atomic_feat_cb); -} -static DEVICE_ATTR_RO(atomic_feat); - -static ssize_t max_rc_outstd_cnt_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%llu\n", ubc_dev->attr.dev_cap.max_rc_outstd_cnt); -} - -static ssize_t max_rc_outstd_cnt_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_rc_outstd_cnt_show_cb); -} - -static DEVICE_ATTR_RO(max_rc_outstd_cnt); - -static ssize_t trans_mode_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.trans_mode); -} - -static ssize_t trans_mode_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, trans_mode_show_cb); -} - -static DEVICE_ATTR_RO(trans_mode); - -static ssize_t congestion_ctrl_alg_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%u\n", ubc_dev->attr.dev_cap.congestion_ctrl_alg); -} - -static ssize_t congestion_ctrl_alg_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, congestion_ctrl_alg_show_cb); -} - -static ssize_t congestion_ctrl_alg_store_cb(struct ubcore_device *ubc_dev, const char *buf, - size_t len) -{ - uint16_t value; - int ret; - - ret = kstrtou16(buf, 0, &value); - if (ret != 0) - return -EINVAL; - - ubc_dev->attr.dev_cap.congestion_ctrl_alg = value; - return (ssize_t)len; -} - -static ssize_t congestion_ctrl_alg_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) -{ - return uburma_store_dev_attr(dev, attr, buf, len, congestion_ctrl_alg_store_cb); -} - -static DEVICE_ATTR_RW(congestion_ctrl_alg); // 0644 - -static ssize_t ceq_cnt_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.ceq_cnt); -} - -static ssize_t ceq_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, ceq_cnt_show_cb); -} - -static DEVICE_ATTR_RO(ceq_cnt); - -static ssize_t utp_cnt_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.utp_cnt); -} - -static ssize_t utp_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, utp_cnt_show_cb); -} - -static DEVICE_ATTR_RO(utp_cnt); - -static ssize_t max_tp_in_tpg_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", - ubc_dev->attr.dev_cap.max_tp_in_tpg); -} - -static ssize_t max_tp_in_tpg_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_tp_in_tpg_show_cb); -} - -static DEVICE_ATTR_RO(max_tp_in_tpg); - -static ssize_t port_count_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.port_cnt); -} - -static ssize_t port_count_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, port_count_show_cb); -} - -static DEVICE_ATTR_RO(port_count); - -static ssize_t virtualization_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%s\n", ubc_dev->attr.virtualization ? "true" : "false"); -} -static ssize_t virtualization_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, virtualization_show_cb); -} -static DEVICE_ATTR_RO(virtualization); - -static ssize_t show_fe_cnt_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN - 1, "%u\n", ubc_dev->attr.dev_cap.max_fe_cnt); -} -static ssize_t fe_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_fe_cnt_cb); -} -static DEVICE_ATTR_RO(fe_cnt); - -static ssize_t show_dynamic_eid_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%d\n", ubc_dev->dynamic_eid); -} -static ssize_t dynamic_eid_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, show_dynamic_eid_cb); -} -static DEVICE_ATTR_RO(dynamic_eid); - -static ssize_t max_eid_cnt_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%u\n", ubc_dev->attr.dev_cap.max_eid_cnt); -} - -static ssize_t max_eid_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, max_eid_cnt_show_cb); -} - -static DEVICE_ATTR_RO(max_eid_cnt); - -static ssize_t transport_type_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, "%d\n", (int)ubc_dev->transport_type); -} - -static ssize_t transport_type_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, transport_type_show_cb); -} - -static DEVICE_ATTR_RO(transport_type); - -static ssize_t driver_name_show_cb(struct ubcore_device *ubc_dev, char *buf) -{ - if (ubc_dev->ops == NULL) - return -EINVAL; - - return snprintf(buf, UBCORE_MAX_DRIVER_NAME, "%s\n", ubc_dev->ops->driver_name); -} - -static ssize_t driver_name_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - return uburma_show_dev_attr(dev, attr, buf, driver_name_show_cb); -} - -static DEVICE_ATTR_RO(driver_name); - -static struct attribute *uburma_dev_attrs[] = { - &dev_attr_ubdev.attr, - &dev_attr_guid.attr, - &dev_attr_max_upi_cnt.attr, - &dev_attr_upi.attr, - &dev_attr_feature.attr, - &dev_attr_max_jfc.attr, - &dev_attr_max_jfs.attr, - &dev_attr_max_jfr.attr, - &dev_attr_max_jetty.attr, - &dev_attr_max_jetty_grp.attr, - &dev_attr_max_jetty_in_jetty_grp.attr, - &dev_attr_max_jfc_depth.attr, - &dev_attr_max_jfs_depth.attr, - &dev_attr_max_jfr_depth.attr, - &dev_attr_max_jfs_inline_size.attr, - &dev_attr_max_jfs_sge.attr, - &dev_attr_max_jfs_rsge.attr, - &dev_attr_max_jfr_sge.attr, - &dev_attr_max_msg_size.attr, - &dev_attr_max_atomic_size.attr, - &dev_attr_atomic_feat.attr, - &dev_attr_max_rc_outstd_cnt.attr, - &dev_attr_trans_mode.attr, - &dev_attr_congestion_ctrl_alg.attr, - &dev_attr_ceq_cnt.attr, - &dev_attr_utp_cnt.attr, - &dev_attr_max_tp_in_tpg.attr, - &dev_attr_port_count.attr, - &dev_attr_fe_cnt.attr, - &dev_attr_max_eid_cnt.attr, - &dev_attr_dynamic_eid.attr, - &dev_attr_virtualization.attr, - &dev_attr_transport_type.attr, - &dev_attr_driver_name.attr, - NULL, -}; - -static const struct attribute_group uburma_dev_attr_group = { - .attrs = uburma_dev_attrs, -}; - -static ssize_t uburma_show_port_attr(struct uburma_port *p, struct uburma_port_attribute *attr, - char *buf, uburma_show_port_attr_cb show_cb) -{ - struct uburma_device *ubu_dev = p->ubu_dev; - struct ubcore_device *ubc_dev; - ssize_t ret = -ENODEV; - int srcu_idx; - - if (!ubu_dev || !buf) { - uburma_log_err("Invalid argument.\n"); - return -EINVAL; - } - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (ubc_dev == NULL) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return -ENODEV; - } - - ret = show_cb(ubc_dev, buf, p->port_num); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -static ssize_t max_mtu_show_cb(struct ubcore_device *ubc_dev, char *buf, uint8_t port_num) -{ - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%d\n", (int)ubc_dev->attr.port_attr[port_num].max_mtu); -} - -static ssize_t max_mtu_show(struct uburma_port *p, struct uburma_port_attribute *attr, char *buf) -{ - return uburma_show_port_attr(p, attr, buf, max_mtu_show_cb); -} - -static PORT_ATTR_RO(max_mtu); - -static ssize_t state_show_cb(struct ubcore_device *ubc_dev, char *buf, uint8_t port_num) -{ - struct ubcore_device_status status; - - if (ubcore_query_device_status(ubc_dev, &status) != 0) { - uburma_log_err("query device status for state failed.\n"); - return -EPERM; - } - - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%u\n", (uint32_t)status.port_status[port_num].state); -} - -static ssize_t state_show(struct uburma_port *p, struct uburma_port_attribute *attr, char *buf) -{ - return uburma_show_port_attr(p, attr, buf, state_show_cb); -} - -static PORT_ATTR_RO(state); - -static ssize_t active_speed_show_cb(struct ubcore_device *ubc_dev, char *buf, - uint8_t port_num) -{ - struct ubcore_device_status status; - - if (ubcore_query_device_status(ubc_dev, &status) != 0) { - uburma_log_err("query device status for active speed failed.\n"); - return -EPERM; - } - - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%u\n", status.port_status[port_num].active_speed); -} - -static ssize_t active_speed_show(struct uburma_port *p, struct uburma_port_attribute *attr, - char *buf) -{ - return uburma_show_port_attr(p, attr, buf, active_speed_show_cb); -} - -static PORT_ATTR_RO(active_speed); - -static ssize_t active_width_show_cb(struct ubcore_device *ubc_dev, char *buf, - uint8_t port_num) -{ - struct ubcore_device_status status; - - if (ubcore_query_device_status(ubc_dev, &status) != 0) { - uburma_log_err("query device status for active width failed.\n"); - return -EPERM; - } - - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%u\n", status.port_status[port_num].active_width); -} - -static ssize_t active_width_show(struct uburma_port *p, struct uburma_port_attribute *attr, - char *buf) -{ - return uburma_show_port_attr(p, attr, buf, active_width_show_cb); -} - -static PORT_ATTR_RO(active_width); - -static ssize_t active_mtu_show_cb(struct ubcore_device *ubc_dev, char *buf, uint8_t port_num) -{ - struct ubcore_device_status status; - - if (ubcore_query_device_status(ubc_dev, &status) != 0) { - uburma_log_err("query device status for active mtu failed.\n"); - return -EPERM; - } - - return snprintf(buf, UBURMA_MAX_VALUE_LEN, - "%u\n", (uint32_t)status.port_status[port_num].active_mtu); -} - -static ssize_t active_mtu_show(struct uburma_port *p, struct uburma_port_attribute *attr, - char *buf) -{ - return uburma_show_port_attr(p, attr, buf, active_mtu_show_cb); -} - -static PORT_ATTR_RO(active_mtu); - -static struct attribute *uburma_port_attrs[] = { - &port_attr_max_mtu.attr, &port_attr_state.attr, &port_attr_active_speed.attr, - &port_attr_active_width.attr, &port_attr_active_mtu.attr, NULL, -}; - -static ssize_t uburma_port_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct uburma_port_attribute *port_attr = - container_of(attr, struct uburma_port_attribute, attr); - struct uburma_port *p = container_of(kobj, struct uburma_port, kobj); - - if (!port_attr->show) - return -EIO; - - return port_attr->show(p, port_attr, buf); -} - -static ssize_t uburma_port_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct uburma_port_attribute *port_attr = - container_of(attr, struct uburma_port_attribute, attr); - struct uburma_port *p = container_of(kobj, struct uburma_port, kobj); - - if (!port_attr->store) - return -EIO; - - return port_attr->store(p, port_attr, buf, count); -} - -static const struct sysfs_ops uburma_port_sysfs_ops = { .show = uburma_port_attr_show, - .store = uburma_port_attr_store }; - -static void uburma_port_release(struct kobject *kobj) -{ -} - -// ATTRIBUTE_GROUPS defined in 3.11, but must be consistent with kobj_type->default_groups -ATTRIBUTE_GROUPS(uburma_port); - -static struct kobj_type uburma_port_type = { .release = uburma_port_release, - .sysfs_ops = &uburma_port_sysfs_ops, - .default_groups = uburma_port_groups -}; - -static ssize_t uburma_show_fe_attr(struct uburma_fe *fe, struct uburma_fe_attribute *attr, - char *buf, uburma_show_fe_attr_cb show_cb) -{ - struct uburma_device *ubu_dev = fe->ubu_dev; - struct ubcore_device *ubc_dev; - int srcu_idx; - ssize_t ret; - - if (!ubu_dev) { - uburma_log_err("Invalid argument in show_fe_attr.\n"); - return -EINVAL; - } - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (ubc_dev == NULL) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return -ENODEV; - } - - ret = show_cb(ubc_dev, buf, fe->fe_idx); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -static ssize_t uburma_store_fe_attr(struct uburma_fe *fe, struct uburma_fe_attribute *attr, - const char *buf, size_t len, uburma_store_fe_attr_cb store_cb) -{ - struct uburma_device *ubu_dev = fe->ubu_dev; - struct ubcore_device *ubc_dev; - int srcu_idx; - ssize_t ret; - - if (!ubu_dev) { - uburma_log_err("Invalid argument in store_fe_attr.\n"); - return -EINVAL; - } - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (ubc_dev == NULL) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return -ENODEV; - } - - ret = store_cb(ubc_dev, buf, len, fe->fe_idx); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -static ssize_t fe_upi_show_cb(struct ubcore_device *ubc_dev, char *buf, uint16_t fe_idx) -{ - return uburma_query_upi(ubc_dev, buf, fe_idx); -} - -static ssize_t fe_upi_show(struct uburma_fe *fe, struct uburma_fe_attribute *attr, char *buf) -{ - return uburma_show_fe_attr(fe, attr, buf, fe_upi_show_cb); -} - -static ssize_t fe_upi_store_cb(struct ubcore_device *ubc_dev, const char *buf, - size_t len, uint16_t fe_idx) -{ - if (ubc_dev == NULL || buf == NULL) - return -EINVAL; - - return uburma_set_upi(ubc_dev, buf, len, fe_idx); -} - -static ssize_t fe_upi_store(struct uburma_fe *fe, struct uburma_fe_attribute *attr, - const char *buf, size_t len) -{ - return uburma_store_fe_attr(fe, attr, buf, len, fe_upi_store_cb); -} - -static FE_ATTR(upi, 0644, fe_upi_show, fe_upi_store); - -static struct attribute *uburma_fe_attrs[] = { - &fe_attr_upi.attr, - NULL, -}; - -static ssize_t uburma_fe_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct uburma_fe_attribute *fe_attr = container_of(attr, struct uburma_fe_attribute, attr); - struct uburma_fe *fe = container_of(kobj, struct uburma_fe, kobj); - - if (!fe_attr->show) - return -EIO; - - return fe_attr->show(fe, fe_attr, buf); -} - -static ssize_t uburma_fe_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct uburma_fe_attribute *fe_attr = container_of(attr, struct uburma_fe_attribute, attr); - struct uburma_fe *fe = container_of(kobj, struct uburma_fe, kobj); - - if (!fe_attr->store) - return -EIO; - return fe_attr->store(fe, fe_attr, buf, count); -} - -static const struct sysfs_ops uburma_fe_sysfs_ops = { - .show = uburma_fe_attr_show, - .store = uburma_fe_attr_store -}; - -static void uburma_fe_release(struct kobject *kobj) -{ -} - -// ATTRIBUTE_GROUPS defined in 3.11, but must be consistent with kobj_type->default_groups -ATTRIBUTE_GROUPS(uburma_fe); - -static struct kobj_type uburma_fe_type = { - .release = uburma_fe_release, - .sysfs_ops = &uburma_fe_sysfs_ops, - .default_groups = uburma_fe_groups -}; - -static ssize_t uburma_show_eid_attr(struct uburma_eid *eid, struct uburma_eid_attribute *attr, - char *buf, uburma_show_eid_attr_cb show_cb) -{ - struct uburma_logic_device *ldev = eid->ldev; - struct uburma_device *ubu_dev = get_uburma_device(ldev); - struct ubcore_device *ubc_dev; - int srcu_idx; - ssize_t ret; - - if (!ldev || !ubu_dev) { - uburma_log_err("Invalid argument in show_fe_attr.\n"); - return -EINVAL; - } - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (ubc_dev == NULL) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return -ENODEV; - } - - ret = show_cb(ubc_dev, buf, eid->eid_idx, read_pnet(&ldev->net)); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -static ssize_t show_eid_cb(struct ubcore_device *ubc_dev, char *buf, uint16_t idx, struct net *net) -{ - union ubcore_eid eid; - - if (net_eq(ubc_dev->eid_table.eid_entries[idx].net, net)) { - return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", - EID_ARGS(ubc_dev->eid_table.eid_entries[idx].eid)); - } else { - memset(&eid, 0, sizeof(union ubcore_eid)); - return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", - EID_ARGS(eid)); - } -} - -static ssize_t eid_show(struct uburma_eid *eid, struct uburma_eid_attribute *attr, char *buf) -{ - return uburma_show_eid_attr(eid, attr, buf, show_eid_cb); -} - -static EID_ATTR_RO(eid); - -static struct attribute *uburma_eid_attrs[] = { - &eid_attr_eid.attr, - NULL, -}; - -static ssize_t uburma_eid_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct uburma_eid_attribute *eid_attr = - container_of(attr, struct uburma_eid_attribute, attr); - struct uburma_eid *eid = container_of(kobj, struct uburma_eid, kobj); - - if (!eid_attr->show) - return -EIO; - - return eid_attr->show(eid, eid_attr, buf); -} - -static ssize_t uburma_eid_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct uburma_eid_attribute *eid_attr = - container_of(attr, struct uburma_eid_attribute, attr); - struct uburma_eid *eid = container_of(kobj, struct uburma_eid, kobj); - - if (!eid_attr->store) - return -EIO; - return eid_attr->store(eid, eid_attr, buf, count); -} - -static const struct sysfs_ops uburma_eid_sysfs_ops = { - .show = uburma_eid_attr_show, - .store = uburma_eid_attr_store -}; - -static void uburma_eid_release(struct kobject *kobj) -{ -} - -// ATTRIBUTE_GROUPS defined in 3.11, but must be consistent with kobj_type->default_groups -ATTRIBUTE_GROUPS(uburma_eid); - -static struct kobj_type uburma_eid_type = { - .release = uburma_eid_release, - .sysfs_ops = &uburma_eid_sysfs_ops, - .default_groups = uburma_eid_groups -}; - -int uburma_create_port_attr_files(struct uburma_logic_device *ldev, - struct uburma_device *ubu_dev, uint8_t port_num) -{ - struct uburma_port *p; - - p = &ldev->port[port_num]; - p->ubu_dev = ubu_dev; - p->port_num = port_num; - - return kobject_init_and_add(&p->kobj, &uburma_port_type, &ldev->dev->kobj, - "port%hhu", port_num); -} - -int uburma_create_fe_attr_files(struct uburma_logic_device *ldev, - struct uburma_device *ubu_dev, uint16_t fe_num) -{ - struct uburma_fe *fe; - - fe = &ldev->fe[fe_num]; - fe->ubu_dev = ubu_dev; - fe->fe_idx = fe_num; - - return kobject_init_and_add(&fe->kobj, &uburma_fe_type, &ldev->dev->kobj, - "fe%hu", fe_num); -} - -int uburma_create_eid_attr_files(struct uburma_logic_device *ldev, uint32_t eid_num) -{ - struct uburma_eid *eid; - - eid = &ldev->eid[eid_num]; - eid->ldev = ldev; - eid->eid_idx = eid_num; - - return kobject_init_and_add(&eid->kobj, &uburma_eid_type, &ldev->dev->kobj, - "eid%u", eid_num); -} - -int uburma_create_dev_attr_files(struct uburma_logic_device *ldev) -{ - int ret; - - ret = sysfs_create_group(&ldev->dev->kobj, &uburma_dev_attr_group); - if (ret != 0) { - uburma_log_err("sysfs create group failed, ret:%d.\n", ret); - return -1; - } - - return 0; -} - -void uburma_remove_port_attr_files(struct uburma_logic_device *ldev, uint8_t port_num) -{ - kobject_put(&ldev->port[port_num].kobj); -} - -void uburma_remove_fe_attr_files(struct uburma_logic_device *ldev, uint16_t fe_num) -{ - kobject_put(&ldev->fe[fe_num].kobj); -} - -void uburma_remove_eid_attr_files(struct uburma_logic_device *ldev, uint32_t eid_num) -{ - kobject_put(&ldev->eid[eid_num].kobj); -} - -void uburma_remove_dev_attr_files(struct uburma_logic_device *ldev) -{ - sysfs_remove_group(&ldev->dev->kobj, &uburma_dev_attr_group); -} diff --git a/drivers/ub/urma/uburma/uburma_cdev_file.h b/drivers/ub/urma/uburma/uburma_cdev_file.h deleted file mode 100644 index f2ee96bf2fb7..000000000000 --- a/drivers/ub/urma/uburma/uburma_cdev_file.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * Description: uburma device file ops file - * Author: Qian Guoxin - * Create: 2022-8-16 - * Note: - * History: 2022-8-16: Create file - */ - -#ifndef UBURMA_CDEV_FILE_H -#define UBURMA_CDEV_FILE_H - -#include "uburma_types.h" - -struct uburma_port_attribute { - struct attribute attr; - ssize_t (*show)(struct uburma_port *p, struct uburma_port_attribute *attr, char *buf); - ssize_t (*store)(struct uburma_port *p, struct uburma_port_attribute *attr, - const char *buf, size_t count); -}; - -#define PORT_ATTR(_name, _mode, _show, _store) \ - struct uburma_port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store) - -#define PORT_ATTR_RO(_name) struct uburma_port_attribute port_attr_##_name = __ATTR_RO(_name) - -struct uburma_fe_attribute { - struct attribute attr; - ssize_t (*show)(struct uburma_fe *fe, struct uburma_fe_attribute *attr, char *buf); - ssize_t (*store)(struct uburma_fe *fe, struct uburma_fe_attribute *attr, - const char *buf, size_t count); -}; - -#define FE_ATTR(_name, _mode, _show, _store) \ -struct uburma_fe_attribute fe_attr_##_name = __ATTR(_name, _mode, _show, _store) - -#define FE_ATTR_RO(_name) \ -struct uburma_fe_attribute fe_attr_##_name = __ATTR_RO(_name) - -struct uburma_eid_attribute { - struct attribute attr; - ssize_t (*show)(struct uburma_eid *eid, struct uburma_eid_attribute *attr, char *buf); - ssize_t (*store)(struct uburma_eid *eid, struct uburma_eid_attribute *attr, - const char *buf, size_t count); -}; - -#define EID_ATTR(_name, _mode, _show, _store) \ -struct uburma_eid_attribute eid_attr_##_name = __ATTR(_name, _mode, _show, _store) - -#define EID_ATTR_RO(_name) \ -struct uburma_eid_attribute eid_attr_##_name = __ATTR_RO(_name) - -int uburma_create_port_attr_files(struct uburma_logic_device *ldev, - struct uburma_device *ubu_dev, uint8_t port_num); -int uburma_create_fe_attr_files(struct uburma_logic_device *ldev, - struct uburma_device *ubu_dev, uint16_t fe_num); -int uburma_create_eid_attr_files(struct uburma_logic_device *ldev, uint32_t eid_num); -int uburma_create_dev_attr_files(struct uburma_logic_device *ldev); - -void uburma_remove_port_attr_files(struct uburma_logic_device *ldev, uint8_t port_num); -void uburma_remove_fe_attr_files(struct uburma_logic_device *ldev, uint16_t fe_num); -void uburma_remove_eid_attr_files(struct uburma_logic_device *ldev, uint32_t eid_num); -void uburma_remove_dev_attr_files(struct uburma_logic_device *ldev); - -#endif /* UBURMA_CDEV_FILE_H */ diff --git a/drivers/ub/urma/uburma/uburma_cmd.c b/drivers/ub/urma/uburma/uburma_cmd.c index 39e45ef11453..1d875f76e5e9 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.c +++ b/drivers/ub/urma/uburma/uburma_cmd.c @@ -173,7 +173,8 @@ static int uburma_cmd_alloc_token_id(struct ubcore_device *ubc_dev, struct uburm if (ret != 0) goto err_free_token_id; - return uobj_alloc_commit(uobj); + uobj_alloc_commit(uobj); + return 0; err_free_token_id: (void)ubcore_free_token_id(token_id); @@ -229,7 +230,7 @@ static int uburma_cmd_register_seg(struct ubcore_device *ubc_dev, struct uburma_ return ret; token_id_uobj = uobj_get_read(UOBJ_CLASS_TOKEN, (int)arg.in.token_id_handle, file); - if (!IS_ERR(token_id_uobj)) + if (!IS_ERR_OR_NULL(token_id_uobj)) cfg.token_id = (struct ubcore_token_id *)token_id_uobj->object; uburma_fill_attr(&cfg, &arg); @@ -410,7 +411,7 @@ static int uburma_cmd_create_jfs(struct ubcore_device *ubc_dev, cfg.jfs_context = jfs_uobj; jfc_uobj = uobj_get_read(UOBJ_CLASS_JFC, arg.in.jfc_handle, file); - if (IS_ERR(jfc_uobj)) { + if (IS_ERR_OR_NULL(jfc_uobj)) { uburma_log_err("failed to find jfc, jfc_handle:%llu.\n", arg.in.jfc_handle); ret = -EINVAL; goto err_alloc_abort; @@ -689,7 +690,7 @@ static int uburma_cmd_create_jfr(struct ubcore_device *ubc_dev, cfg.jfr_context = jfr_uobj; jfc_uobj = uobj_get_read(UOBJ_CLASS_JFC, arg.in.jfc_handle, file); - if (IS_ERR(jfc_uobj)) { + if (IS_ERR_OR_NULL(jfc_uobj)) { uburma_log_err("failed to find jfc, jfc_handle:%llu.\n", arg.in.jfc_handle); ret = -EINVAL; goto err_alloc_abort; @@ -1080,7 +1081,7 @@ static int uburma_cmd_create_jetty(struct ubcore_device *ubc_dev, cfg.eid_index = file->ucontext->eid_index; send_jfc_uobj = uobj_get_read(UOBJ_CLASS_JFC, arg.in.send_jfc_handle, file); recv_jfc_uobj = uobj_get_read(UOBJ_CLASS_JFC, arg.in.recv_jfc_handle, file); - if (IS_ERR(send_jfc_uobj) || IS_ERR(recv_jfc_uobj)) { + if (IS_ERR_OR_NULL(send_jfc_uobj) || IS_ERR_OR_NULL(recv_jfc_uobj)) { uburma_log_err("failed to find send %llu or recv jfc %llu.\n", arg.in.send_jfc_handle, arg.in.recv_jfc_handle); ret = -EINVAL; @@ -1090,7 +1091,7 @@ static int uburma_cmd_create_jetty(struct ubcore_device *ubc_dev, cfg.recv_jfc = recv_jfc_uobj->object; if (arg.in.jfr_handle != 0) { jfr_uobj = uobj_get_read(UOBJ_CLASS_JFR, arg.in.jfr_handle, file); - if (IS_ERR(jfr_uobj)) { + if (IS_ERR_OR_NULL(jfr_uobj)) { uburma_log_err("failed to find jfr, jfr_handle:%llu.\n", arg.in.jfr_handle); ret = -EINVAL; goto err_put; @@ -1100,7 +1101,7 @@ static int uburma_cmd_create_jetty(struct ubcore_device *ubc_dev, } if (arg.in.is_jetty_grp != 0) { jetty_grp_uobj = uobj_get_read(UOBJ_CLASS_JETTY_GRP, arg.in.jetty_grp_handle, file); - if (IS_ERR(jetty_grp_uobj)) { + if (IS_ERR_OR_NULL(jetty_grp_uobj)) { uburma_log_err("failed to find jetty_grp, jetty_grp_handle:%llu.\n", arg.in.jetty_grp_handle); ret = -EINVAL; @@ -1488,13 +1489,13 @@ static int uburma_get_jetty_tjetty_objs(struct uburma_file *file, uint64_t jetty uint64_t tjetty_handle, struct uburma_uobj **jetty_uobj, struct uburma_uobj **tjetty_uobj) { *jetty_uobj = uobj_get_read(UOBJ_CLASS_JETTY, jetty_handle, file); - if (IS_ERR(*jetty_uobj)) { + if (IS_ERR_OR_NULL(*jetty_uobj)) { uburma_log_err("failed to find jetty with handle %llu", jetty_handle); return -EINVAL; } *tjetty_uobj = uobj_get_read(UOBJ_CLASS_TARGET_JETTY, tjetty_handle, file); - if (IS_ERR(*tjetty_uobj)) { + if (IS_ERR_OR_NULL(*tjetty_uobj)) { uobj_put_read(*jetty_uobj); uburma_log_err("failed to find target jetty with handle %llu", tjetty_handle); return -EINVAL; @@ -1514,13 +1515,13 @@ static int uburma_get_jfs_tjfr_objs(struct uburma_file *file, uint64_t jetty_han struct uburma_uobj **tjetty_uobj) { *jetty_uobj = uobj_get_read(UOBJ_CLASS_JFS, jetty_handle, file); - if (IS_ERR(*jetty_uobj)) { + if (IS_ERR_OR_NULL(*jetty_uobj)) { uburma_log_err("failed to find jfs with handle %llu", jetty_handle); return -EINVAL; } *tjetty_uobj = uobj_get_read(UOBJ_CLASS_TARGET_JFR, tjetty_handle, file); - if (IS_ERR(*tjetty_uobj)) { + if (IS_ERR_OR_NULL(*tjetty_uobj)) { uobj_put_read(*jetty_uobj); uburma_log_err("failed to find target jfr with handle %llu", tjetty_handle); return -EINVAL; @@ -1770,7 +1771,7 @@ static int uburma_cmd_create_jetty_grp(struct ubcore_device *ubc_dev, if (ret != 0) goto err_put_jfae; - (void)uobj_alloc_commit(&jetty_grp_uobj->uobj); + uobj_alloc_commit(&jetty_grp_uobj->uobj); return ret; err_put_jfae: @@ -1929,6 +1930,11 @@ long uburma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int srcu_idx; long ret; + if (ubu_dev == NULL || file == NULL) { + uburma_log_err("invalid param"); + return -EINVAL; + } + uburma_cmd_inc(ubu_dev); srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); diff --git a/drivers/ub/urma/uburma/uburma_dev_ops.c b/drivers/ub/urma/uburma/uburma_dev_ops.c index 0f2655e774d2..b25d62bfaac4 100644 --- a/drivers/ub/urma/uburma/uburma_dev_ops.c +++ b/drivers/ub/urma/uburma/uburma_dev_ops.c @@ -29,7 +29,6 @@ #include "uburma_types.h" #include "uburma_uobj.h" #include "uburma_cmd.h" -#include "uburma_main.h" int uburma_mmap(struct file *filp, struct vm_area_struct *vma) { @@ -39,7 +38,7 @@ int uburma_mmap(struct file *filp, struct vm_area_struct *vma) int srcu_idx; int ret; - if (file == NULL || file->ucontext == NULL) { + if (file == NULL || file->ucontext == NULL || file->ubu_dev == NULL) { uburma_log_err("can not find ucontext.\n"); return -EINVAL; } @@ -103,12 +102,6 @@ int uburma_open(struct inode *inode, struct file *filp) goto err; } - if (!uburma_dev_accessible_by_ns(ubu_dev, current->nsproxy->net_ns)) { - ret = EPERM; - uburma_log_err("urma device is not accessible by current ns.\n"); - goto err; - } - file = kzalloc(sizeof(struct uburma_file), GFP_KERNEL); if (!file) { ret = -ENOMEM; diff --git a/drivers/ub/urma/uburma/uburma_event.c b/drivers/ub/urma/uburma/uburma_event.c index 8078a37bd72f..3ea0a0b0510e 100644 --- a/drivers/ub/urma/uburma/uburma_event.c +++ b/drivers/ub/urma/uburma/uburma_event.c @@ -52,7 +52,7 @@ struct uburma_jfce_uobj *uburma_get_jfce_uobj(int fd, struct uburma_file *ufile) return ERR_PTR(-ENOENT); uobj = uobj_get_read(UOBJ_CLASS_JFCE, fd, ufile); - if (IS_ERR(uobj)) { + if (IS_ERR_OR_NULL(uobj)) { uburma_log_err("get jfce uobj fail with fd %d\n", fd); return (void *)uobj; } diff --git a/drivers/ub/urma/uburma/uburma_log.c b/drivers/ub/urma/uburma/uburma_log.c new file mode 100644 index 000000000000..3cf0a693974c --- /dev/null +++ b/drivers/ub/urma/uburma/uburma_log.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: uburma log file + * Author: Qian Guoxin + * Create: 2024-2-5 + * Note: + * History: 2024-2-5: Create file + */ + +#include +#include "uburma_log.h" + +uint32_t g_uburma_log_level = UBURMA_LOG_LEVEL_INFO; diff --git a/drivers/ub/urma/uburma/uburma_log.h b/drivers/ub/urma/uburma/uburma_log.h index c59f5de35eb8..fd009089f412 100644 --- a/drivers/ub/urma/uburma/uburma_log.h +++ b/drivers/ub/urma/uburma/uburma_log.h @@ -21,17 +21,46 @@ #ifndef UBURMA_LOG_H #define UBURMA_LOG_H +#include +#include + +enum uburma_log_level { + UBURMA_LOG_LEVEL_EMERG = 0, + UBURMA_LOG_LEVEL_ALERT = 1, + UBURMA_LOG_LEVEL_CRIT = 2, + UBURMA_LOG_LEVEL_ERR = 3, + UBURMA_LOG_LEVEL_WARNING = 4, + UBURMA_LOG_LEVEL_NOTICE = 5, + UBURMA_LOG_LEVEL_INFO = 6, + UBURMA_LOG_LEVEL_DEBUG = 7, + UBURMA_LOG_LEVEL_MAX = 8, +}; + /* add log head info, "LogTag_UBURMA|function|[line]| */ #define UBURMA_LOG_TAG "LogTag_UBURMA" #define uburma_log(l, format, args...) \ - ((void)pr_##l("%s|%s:[%d]|" format, UBURMA_LOG_TAG, __func__, __LINE__, ##args)) + pr_##l("%s|%s:[%d]|" format, UBURMA_LOG_TAG, __func__, __LINE__, ##args) + +extern uint32_t g_uburma_log_level; -#define uburma_log_info(...) uburma_log(info, __VA_ARGS__) +#define uburma_log_info(...) do { \ + if (g_uburma_log_level >= UBURMA_LOG_LEVEL_INFO) \ + uburma_log(info, __VA_ARGS__); \ +} while (0) -#define uburma_log_err(...) uburma_log(err, __VA_ARGS__) +#define uburma_log_err(...) do { \ + if (g_uburma_log_level >= UBURMA_LOG_LEVEL_ERR) \ + uburma_log(err, __VA_ARGS__); \ +} while (0) -#define uburma_log_warn(...) uburma_log(warn, __VA_ARGS__) +#define uburma_log_warn(...) do { \ + if (g_uburma_log_level >= UBURMA_LOG_LEVEL_WARNING) \ + uburma_log(warn, __VA_ARGS__); \ +} while (0) -#define uburma_log_debug(...) uburma_log(debug, __VA_ARGS__) +#define uburma_log_debug(...) do { \ + if (g_uburma_log_level >= UBURMA_LOG_LEVEL_DEBUG) \ + uburma_log(debug, __VA_ARGS__); \ +} while (0) #endif /* UBURMA_LOG_H */ diff --git a/drivers/ub/urma/uburma/uburma_main.c b/drivers/ub/urma/uburma/uburma_main.c index 4db1f10d837f..f1fc26490e6b 100644 --- a/drivers/ub/urma/uburma/uburma_main.c +++ b/drivers/ub/urma/uburma/uburma_main.c @@ -34,10 +34,13 @@ #include "uburma_log.h" #include "uburma_types.h" #include "uburma_file_ops.h" -#include "uburma_cdev_file.h" #include "uburma_uobj.h" #include "uburma_cmd.h" -#include "uburma_netlink.h" + +#define UBURMA_LOG_FILE_PERMISSION (0644) + +module_param(g_uburma_log_level, uint, UBURMA_LOG_FILE_PERMISSION); +MODULE_PARM_DESC(g_uburma_log_level, " 3: ERR, 4: WARNING, 6: INFO, 7: DEBUG"); #define UBURMA_MAX_DEVICE 1024 #define UBURMA_DYNAMIC_MINOR_NUM UBURMA_MAX_DEVICE @@ -47,33 +50,6 @@ static DECLARE_BITMAP(g_dev_bitmap, UBURMA_MAX_DEVICE); static dev_t g_dynamic_uburma_dev; -static bool g_shared_ns = true; - -static const void *uburma_net_namespace(struct device *dev) -{ - struct uburma_logic_device *ldev = dev_get_drvdata(dev); - struct uburma_device *ubu_dev; - struct ubcore_device *ubc_dev; - - if (ldev == NULL || ldev->ubu_dev == NULL || ldev->ubu_dev->ubc_dev == NULL) { - uburma_log_info("init net %p", ldev); - return &init_net; - } - - ubu_dev = ldev->ubu_dev; - ubc_dev = ubu_dev->ubc_dev; - - if (ubc_dev->transport_type == UBCORE_TRANSPORT_UB) { - return read_pnet(&ldev->net); - } else if (ubc_dev->transport_type == UBCORE_TRANSPORT_IP) { - if (ubc_dev->netdev) - return dev_net(ubc_dev->netdev); - else - return &init_net; - } else { /* URMA IB device not support namespace yet */ - return &init_net; - } -} static char *uburma_devnode(struct device *dev, umode_t *mode) { @@ -86,8 +62,6 @@ static char *uburma_devnode(struct device *dev, umode_t *mode) static struct class g_uburma_class = { .name = UBURMA_MODULE_NAME, .devnode = uburma_devnode, - .ns_type = &net_ns_type_operations, - .namespace = uburma_net_namespace }; static const struct file_operations g_uburma_fops = { @@ -101,18 +75,6 @@ static const struct file_operations g_uburma_fops = { .compat_ioctl = uburma_ioctl, }; -static LIST_HEAD(g_uburma_device_list); -static DECLARE_RWSEM(g_uburma_device_rwsem); - -static unsigned int g_uburma_net_id; -static LIST_HEAD(g_uburma_net_list); -static DEFINE_SPINLOCK(g_uburma_net_lock); -static DECLARE_RWSEM(g_uburma_net_rwsem); - -struct uburma_net { - possible_net_t net; - struct list_head node; -}; static int uburma_add_device(struct ubcore_device *ubc_dev); static void uburma_remove_device(struct ubcore_device *ubc_dev, void *client_ctx); @@ -149,264 +111,23 @@ static int uburma_get_devt(dev_t *devt) return 0; } -static int uburma_create_eid_table(struct uburma_logic_device *ldev, struct ubcore_device *ubc_dev) -{ - struct uburma_eid *eid_list; - - eid_list = kcalloc( - 1, ubc_dev->attr.dev_cap.max_eid_cnt * sizeof(struct uburma_eid), GFP_ATOMIC); - if (eid_list == NULL) - return -ENOMEM; - - ldev->eid = eid_list; - return 0; -} - -static void uburma_destroy_eid_table(struct uburma_logic_device *ldev) -{ - if (ldev->eid != NULL) { - kfree(ldev->eid); - ldev->eid = NULL; - } -} - -static int uburma_fill_logic_device_attr(struct uburma_logic_device *ldev, - struct uburma_device *ubu_dev, struct ubcore_device *ubc_dev) -{ - uint32_t e1, e2; /* eid */ - uint16_t f1, f2; /* fe */ - uint8_t p1, p2; /* port */ - - if (uburma_create_dev_attr_files(ldev) != 0) { - uburma_log_err("failed to fill attributes, device:%s.\n", ubc_dev->dev_name); - return -EPERM; - } - - /* create /sys/class/uburma/dev_name>/port* */ - for (p1 = 0; p1 < ubc_dev->attr.port_cnt; p1++) { - if (uburma_create_port_attr_files(ldev, ubu_dev, p1) != 0) - goto err_port_attr; - } - - /* create /sys/class/uburma/dev_name>/fe* */ - for (f1 = 0; f1 < ubc_dev->attr.dev_cap.max_fe_cnt; f1++) { - if (uburma_create_fe_attr_files(ldev, ubu_dev, f1) != 0) - goto err_fe_attr; - } - - /* create /sys/class/uburma/dev_name>/eid* */ - if (uburma_create_eid_table(ldev, ubc_dev) != 0) - goto err_fe_attr; - - for (e1 = 0; e1 < ubc_dev->attr.dev_cap.max_eid_cnt; e1++) { - if (uburma_create_eid_attr_files(ldev, e1) != 0) - goto err_eid_attr; - } - return 0; - -err_eid_attr: - for (e2 = 0; e2 < e1; e2++) - uburma_remove_eid_attr_files(ldev, e2); - - uburma_destroy_eid_table(ldev); -err_fe_attr: - for (f2 = 0; f2 < f1; f2++) - uburma_remove_fe_attr_files(ldev, f2); -err_port_attr: - for (p2 = 0; p2 < p1; p2++) - uburma_remove_port_attr_files(ldev, p2); - - uburma_remove_dev_attr_files(ldev); - return -EPERM; -} - - -static void uburma_unfill_logic_device_attr(struct uburma_logic_device *ldev, - struct ubcore_device *ubc_dev) -{ - uint32_t e; - uint16_t f; - uint8_t p; - - for (e = 0; e < ubc_dev->attr.dev_cap.max_eid_cnt; e++) - uburma_remove_eid_attr_files(ldev, e); - - uburma_destroy_eid_table(ldev); - - for (f = 0; f < ubc_dev->attr.dev_cap.max_fe_cnt; f++) - uburma_remove_fe_attr_files(ldev, f); - - for (p = 0; p < ubc_dev->attr.port_cnt; p++) - uburma_remove_port_attr_files(ldev, p); - - uburma_remove_dev_attr_files(ldev); -} - -static int uburma_device_create(struct uburma_logic_device *ldev, - struct uburma_device *ubu_dev, struct ubcore_device *ubc_dev, struct net *net) +static int uburma_device_create(struct uburma_device *ubu_dev, struct ubcore_device *ubc_dev) { /* create /sys/class/uburma/dev_name> */ - write_pnet(&ldev->net, net); - ldev->ubu_dev = ubu_dev; - - /* Two devices have same char device devt will cause duplicate file name - * error in sysfs_create_link, although they are in different namespaces - */ - if (net_eq(net, &init_net)) - ldev->dev = device_create(&g_uburma_class, ubc_dev->dev.parent, - ubu_dev->cdev.dev, ldev, "%s", ubc_dev->dev_name); - else - ldev->dev = device_create(&g_uburma_class, ubc_dev->dev.parent, - MKDEV(0, 0), ldev, "%s", ubc_dev->dev_name); - if (IS_ERR(ldev->dev)) { + ubu_dev->dev = device_create(&g_uburma_class, ubc_dev->dev.parent, + ubu_dev->cdev.dev, ubu_dev, "%s", ubc_dev->dev_name); + if (IS_ERR(ubu_dev->dev)) { uburma_log_err("device create failed, device:%s.\n", ubc_dev->dev_name); return -ENOMEM; } - if (uburma_fill_logic_device_attr(ldev, ubu_dev, ubc_dev) != 0) { - device_unregister(ldev->dev); - ldev->dev = NULL; - uburma_log_err("failed to fill attributes, device:%s.\n", ubc_dev->dev_name); - return -EPERM; - } - return 0; } -static void uburma_device_destroy(struct uburma_logic_device *ldev, struct ubcore_device *ubc_dev) +static void uburma_device_destroy(struct uburma_device *ubu_dev) { - uburma_unfill_logic_device_attr(ldev, ubc_dev); - device_unregister(ldev->dev); - ldev->dev = NULL; -} - -static void uburma_remove_one_logic_device(struct uburma_device *ubu_dev, struct net *net) -{ - struct uburma_logic_device *ldev, *tmp; - struct ubcore_device *ubc_dev; - int srcu_idx; - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (!ubc_dev) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return; - } - - if (ubc_dev->transport_type != UBCORE_TRANSPORT_UB) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return; - } - - mutex_lock(&ubu_dev->ldev_mutex); - list_for_each_entry_safe(ldev, tmp, &ubu_dev->ldev_list, node) { - if (net_eq(read_pnet(&ldev->net), net)) { - uburma_device_destroy(ldev, ubc_dev); - list_del(&ldev->node); - kfree(ldev); - break; - } - } - mutex_unlock(&ubu_dev->ldev_mutex); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); -} - -static void uburma_remove_logic_devices(struct uburma_device *ubu_dev, - struct ubcore_device *ubc_dev) -{ - struct uburma_logic_device *ldev, *tmp; - - if (ubc_dev->transport_type != UBCORE_TRANSPORT_UB) - return; - - mutex_lock(&ubu_dev->ldev_mutex); - list_for_each_entry_safe(ldev, tmp, &ubu_dev->ldev_list, node) { - uburma_device_destroy(ldev, ubc_dev); - list_del(&ldev->node); - kfree(ldev); - } - mutex_unlock(&ubu_dev->ldev_mutex); -} - -static int uburma_create_one_logic_device(struct uburma_device *ubu_dev, - struct ubcore_device *ubc_dev, struct net *net) -{ - struct uburma_logic_device *ldev; - int ret; - - mutex_lock(&ubu_dev->ldev_mutex); - list_for_each_entry(ldev, &ubu_dev->ldev_list, node) { - if (net_eq(read_pnet(&ubu_dev->ldev.net), net)) { - mutex_unlock(&ubu_dev->ldev_mutex); - return 0; - } - } - - ldev = kzalloc(sizeof(struct uburma_logic_device), GFP_KERNEL); - if (ldev == NULL) { - mutex_unlock(&ubu_dev->ldev_mutex); - return -ENOMEM; - } - - ret = uburma_device_create(ldev, ubu_dev, ubc_dev, net); - if (ret) { - kfree(ldev); - mutex_unlock(&ubu_dev->ldev_mutex); - uburma_log_err("add device failed %s in net %u", ubc_dev->dev_name, net->ns.inum); - return ret; - } - - list_add_tail(&ldev->node, &ubu_dev->ldev_list); - mutex_unlock(&ubu_dev->ldev_mutex); - uburma_log_info("add device %s in net %u", ubc_dev->dev_name, net->ns.inum); - return 0; -} - -static int uburma_add_one_logic_device(struct uburma_device *ubu_dev, struct net *net) -{ - struct ubcore_device *ubc_dev; - int srcu_idx; - int ret; - - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (!ubc_dev) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return 0; - } - - if (ubc_dev->transport_type != UBCORE_TRANSPORT_UB) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return 0; - } - - ret = uburma_create_one_logic_device(ubu_dev, ubc_dev, net); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return ret; -} - -static int uburma_copy_logic_devices(struct uburma_device *ubu_dev, struct ubcore_device *ubc_dev) -{ - struct uburma_net *unet; - int ret = 0; - - if (ubc_dev->transport_type != UBCORE_TRANSPORT_UB) - return 0; - - down_read(&g_uburma_net_rwsem); - list_for_each_entry(unet, &g_uburma_net_list, node) { - if (net_eq(read_pnet(&unet->net), read_pnet(&ubu_dev->ldev.net))) - continue; - ret = uburma_create_one_logic_device(ubu_dev, ubc_dev, read_pnet(&unet->net)); - if (ret != 0) - break; - } - up_read(&g_uburma_net_rwsem); - - if (ret) - uburma_remove_logic_devices(ubu_dev, ubc_dev); - - return ret; + device_destroy(&g_uburma_class, ubu_dev->cdev.dev); + ubu_dev->dev = NULL; } static int uburma_cdev_create(struct uburma_device *ubu_dev, struct ubcore_device *ubc_dev) @@ -429,19 +150,13 @@ static int uburma_cdev_create(struct uburma_device *ubu_dev, struct ubcore_devic if (cdev_add(&ubu_dev->cdev, base, 1)) goto free_bit; - if (uburma_device_create(&ubu_dev->ldev, ubu_dev, ubc_dev, &init_net) != 0) { + if (uburma_device_create(ubu_dev, ubc_dev) != 0) { uburma_log_err("device create failed, device:%s.\n", ubc_dev->dev_name); goto del_cdev; } - if (uburma_copy_logic_devices(ubu_dev, ubc_dev) != 0) { - uburma_log_err("copy logic device failed, device:%s.\n", ubc_dev->dev_name); - goto destroy_device; - } return 0; -destroy_device: - uburma_device_destroy(&ubu_dev->ldev, ubc_dev); del_cdev: cdev_del(&ubu_dev->cdev); free_bit: @@ -449,19 +164,6 @@ static int uburma_cdev_create(struct uburma_device *ubu_dev, struct ubcore_devic return -EPERM; } -static void uburma_list_add_device(struct uburma_device *ubu_dev) -{ - down_write(&g_uburma_device_rwsem); - list_add_tail(&ubu_dev->node, &g_uburma_device_list); - up_write(&g_uburma_device_rwsem); -} - -static void uburma_list_remove_device(struct uburma_device *ubu_dev) -{ - down_write(&g_uburma_device_rwsem); - list_del_init(&ubu_dev->node); - up_write(&g_uburma_device_rwsem); -} static int uburma_add_device(struct ubcore_device *ubc_dev) { @@ -489,9 +191,6 @@ static int uburma_add_device(struct ubcore_device *ubc_dev) mutex_init(&ubu_dev->lists_mutex); INIT_LIST_HEAD(&ubu_dev->uburma_file_list); - mutex_init(&ubu_dev->ldev_mutex); - INIT_LIST_HEAD(&ubu_dev->ldev_list); - rcu_assign_pointer(ubu_dev->ubc_dev, ubc_dev); if (uburma_cdev_create(ubu_dev, ubc_dev) != 0) { @@ -500,7 +199,6 @@ static int uburma_add_device(struct ubcore_device *ubc_dev) } ubcore_set_client_ctx_data(ubc_dev, &g_urma_client, ubu_dev); - uburma_list_add_device(ubu_dev); return 0; err: @@ -508,7 +206,6 @@ static int uburma_add_device(struct ubcore_device *ubc_dev) complete(&ubu_dev->comp); wait_for_completion(&ubu_dev->comp); - mutex_destroy(&ubu_dev->ldev_mutex); mutex_destroy(&ubu_dev->lists_mutex); kfree(ubu_dev); return -EPERM; @@ -553,9 +250,7 @@ static void uburma_remove_device(struct ubcore_device *ubc_dev, void *client_ctx if (ubu_dev == NULL) return; - uburma_list_remove_device(ubu_dev); - uburma_remove_logic_devices(ubu_dev, ubc_dev); - uburma_device_destroy(&ubu_dev->ldev, ubc_dev); + uburma_device_destroy(ubu_dev); cdev_del(&ubu_dev->cdev); clear_bit(ubu_dev->devnum, g_dev_bitmap); @@ -604,10 +299,6 @@ static int uburma_class_create(void) goto out_chrdev; } - /* - * to do class_create_file - */ - return 0; out_chrdev: unregister_chrdev_region(g_dynamic_uburma_dev, UBURMA_DYNAMIC_MINOR_NUM); @@ -621,217 +312,6 @@ static void uburma_class_destroy(void) unregister_chrdev_region(g_dynamic_uburma_dev, UBURMA_DYNAMIC_MINOR_NUM); } -static int remove_logic_devices(struct uburma_device *ubu_dev) -{ - struct ubcore_device *ubc_dev; - int srcu_idx; - - /* Get ubcore device and remove copied logic device */ - srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); - ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); - if (!ubc_dev) { - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return -EIO; - } - uburma_remove_logic_devices(ubu_dev, ubc_dev); - srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); - return 0; -} - -bool uburma_dev_accessible_by_ns(struct uburma_device *ubu_dev, struct net *net) -{ - return (g_shared_ns || net_eq(net, read_pnet(&ubu_dev->ldev.net))); -} - -static int uburma_modify_dev_ns(struct uburma_device *ubu_dev, struct net *net) -{ - struct net *cur; - int ret; - - cur = read_pnet(&ubu_dev->ldev.net); - if (net_eq(net, cur)) - return 0; - - write_pnet(&ubu_dev->ldev.net, net); - kobject_uevent(&ubu_dev->ldev.dev->kobj, KOBJ_REMOVE); - ret = device_rename(ubu_dev->ldev.dev, dev_name(ubu_dev->ldev.dev)); - if (ret) { - write_pnet(&ubu_dev->ldev.net, cur); - uburma_log_err("Failed to rename device in the new ns.\n"); - } - kobject_uevent(&ubu_dev->ldev.dev->kobj, KOBJ_ADD); - return ret; -} - -int uburma_set_dev_ns(char *device_name, int ns_fd) -{ - struct uburma_device *ubu_dev = NULL, *tmp; - struct net *net; - int ret = 0; - - if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { - uburma_log_err("current user does not have net admin capability"); - return -EPERM; - } - - if (g_shared_ns) { - uburma_log_err("Can not set device to ns under shared ns mode.\n"); - return -EPERM; - } - - net = get_net_ns_by_fd(ns_fd); - if (IS_ERR(net)) { - uburma_log_err("Failed to get ns by fd.\n"); - return PTR_ERR(net); - } - - /* Find uburma device by name */ - down_read(&g_uburma_device_rwsem); - list_for_each_entry(tmp, &g_uburma_device_list, node) { - if (strcmp(dev_name(tmp->ldev.dev), device_name) == 0) { - ubu_dev = tmp; - break; - } - } - if (ubu_dev == NULL) { - ret = -EINVAL; - uburma_log_err("Failed to find device.\n"); - goto out; - } - - /* Do not modify ns if some user process opened the device */ - if (atomic_read(&ubu_dev->refcnt) > 1) { - ret = -EBUSY; - uburma_log_err("Can not set device ns if it is in use.\n"); - goto out; - } - - ret = remove_logic_devices(ubu_dev); - if (ret) { - uburma_log_err("Failed to remove logic devices.\n"); - goto out; - } - - /* Put device in the new ns */ - ret = uburma_modify_dev_ns(ubu_dev, net); - -out: - up_read(&g_uburma_device_rwsem); - put_net(net); - return ret; -} - -int uburma_set_ns_mode(bool shared) -{ - unsigned long flags; - - if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { - uburma_log_err("current user does not have net admin capability"); - return -EPERM; - } - - down_write(&g_uburma_net_rwsem); - if (g_shared_ns == shared) { - up_write(&g_uburma_net_rwsem); - return 0; - } - spin_lock_irqsave(&g_uburma_net_lock, flags); - if (!list_empty(&g_uburma_net_list)) { - spin_unlock_irqrestore(&g_uburma_net_lock, flags); - up_write(&g_uburma_net_rwsem); - uburma_log_err("Failed to modify ns mode with existing ns"); - return -EPERM; - } - g_shared_ns = shared; - spin_unlock_irqrestore(&g_uburma_net_lock, flags); - up_write(&g_uburma_net_rwsem); - return 0; -} - -static void uburma_net_exit(struct net *net) -{ - struct uburma_net *unet = net_generic(net, g_uburma_net_id); - struct uburma_device *ubu_dev; - unsigned long flags; - - if (unet == NULL) - return; - - uburma_log_info("net exit %u", net->ns.inum); - down_write(&g_uburma_net_rwsem); - spin_lock_irqsave(&g_uburma_net_lock, flags); - if (list_empty(&unet->node)) { - spin_unlock_irqrestore(&g_uburma_net_lock, flags); - up_write(&g_uburma_net_rwsem); - return; - } - list_del_init(&unet->node); - spin_unlock_irqrestore(&g_uburma_net_lock, flags); - up_write(&g_uburma_net_rwsem); - - if (!g_shared_ns) { - down_read(&g_uburma_device_rwsem); - list_for_each_entry(ubu_dev, &g_uburma_device_list, node) { - (void)uburma_modify_dev_ns(ubu_dev, &init_net); - } - up_read(&g_uburma_device_rwsem); - return; - } - - down_read(&g_uburma_device_rwsem); - list_for_each_entry(ubu_dev, &g_uburma_device_list, node) { - uburma_remove_one_logic_device(ubu_dev, net); - } - up_read(&g_uburma_device_rwsem); -} - -static int uburma_net_init(struct net *net) -{ - struct uburma_net *unet = net_generic(net, g_uburma_net_id); - struct uburma_device *ubu_dev; - unsigned long flags; - int ret = 0; - - if (unet == NULL) - return 0; - - uburma_log_info("net init %u", net->ns.inum); - write_pnet(&unet->net, net); - if (net_eq(net, &init_net)) { - INIT_LIST_HEAD(&unet->node); - return 0; - } - - spin_lock_irqsave(&g_uburma_net_lock, flags); - list_add_tail(&unet->node, &g_uburma_net_list); - spin_unlock_irqrestore(&g_uburma_net_lock, flags); - - if (!g_shared_ns) - return 0; - - down_read(&g_uburma_device_rwsem); - list_for_each_entry(ubu_dev, &g_uburma_device_list, node) { - down_read(&g_uburma_net_rwsem); - ret = uburma_add_one_logic_device(ubu_dev, net); - up_read(&g_uburma_net_rwsem); - if (ret) - break; - } - up_read(&g_uburma_device_rwsem); - if (ret) - uburma_net_exit(net); - - /* return ret will cause error starting a container */ - return 0; -} - -static struct pernet_operations g_uburma_net_ops = { - .init = uburma_net_init, - .exit = uburma_net_exit, - .id = &g_uburma_net_id, - .size = sizeof(struct uburma_net) -}; - static int __init uburma_init(void) { int ret; @@ -843,23 +323,13 @@ static int __init uburma_init(void) } uburma_register_client(); - uburma_netlink_init(); - ret = register_pernet_device(&g_uburma_net_ops); - if (ret != 0) { - uburma_unregister_client(); - uburma_class_destroy(); - uburma_log_err("register_pernet_device failed"); - return ret; - } uburma_log_info("uburma module init success.\n"); return 0; } static void __exit uburma_exit(void) { - unregister_pernet_device(&g_uburma_net_ops); - uburma_netlink_exit(); uburma_unregister_client(); uburma_class_destroy(); uburma_log_info("uburma module exits.\n"); diff --git a/drivers/ub/urma/uburma/uburma_netlink.c b/drivers/ub/urma/uburma/uburma_netlink.c deleted file mode 100644 index 21811c3d5125..000000000000 --- a/drivers/ub/urma/uburma/uburma_netlink.c +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * Description: uburma netlink implementation - * Author: Yan Fangfang - * Create: 2023-12-06 - * Note: - * History: 2023-12-06: create file - */ - -#include -#include -#include -#include -#include "uburma_log.h" -#include "uburma_main.h" -#include "uburma_netlink.h" - -#define UBURMA_NL_TYPE 25 /* same with urma admin netlink type */ - -static struct sock *g_uburma_nl_sock; - -static int uburma_nl_reply(struct nlmsghdr *req, struct uburma_nl_resp *resp, uint32_t pid) -{ - struct sk_buff *nl_skb; - struct nlmsghdr *nlh; - int ret; - - nl_skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct uburma_nl_resp)), GFP_ATOMIC); - if (nl_skb == NULL) { - uburma_log_err("failed to alloc.\n"); - return -1; - } - - nlh = nlmsg_put(nl_skb, pid, req->nlmsg_seq, req->nlmsg_type, - sizeof(struct uburma_nl_resp), 0); - if (nlh == NULL) { - nlmsg_free(nl_skb); - uburma_log_err("Failed to nlmsg put.\n"); - return -1; - } - - memcpy(nlmsg_data(nlh), resp, sizeof(struct uburma_nl_resp)); - ret = netlink_unicast(g_uburma_nl_sock, nl_skb, pid, 0); - return ret < 0 ? ret : 0; -} - -static void uburma_nl_handle_set_ns_mode(struct nlmsghdr *nlh, uint32_t pid) -{ - struct uburma_nl_set_ns_mode *msg = nlmsg_data(nlh); - bool ns_mode = (msg->ns_mode == 0 ? false : true); - struct uburma_nl_resp resp = {0}; - - if (nlmsg_len(nlh) < sizeof(struct uburma_nl_set_ns_mode)) { - resp.ret = -1; - (void)uburma_nl_reply(nlh, &resp, pid); - uburma_log_err("Invalid nl msg received"); - return; - } - resp.ret = uburma_set_ns_mode(ns_mode); - (void)uburma_nl_reply(nlh, &resp, pid); -} - -static void uburma_nl_handle_set_dev_ns(struct nlmsghdr *nlh, uint32_t pid) -{ - struct uburma_nl_set_dev_ns *msg = nlmsg_data(nlh); - struct uburma_nl_resp resp = {0}; - - if (nlmsg_len(nlh) < sizeof(struct uburma_nl_set_dev_ns)) { - resp.ret = -1; - (void)uburma_nl_reply(nlh, &resp, pid); - uburma_log_err("Invalid nl msg received"); - return; - } - resp.ret = uburma_set_dev_ns(msg->dev_name, msg->ns_fd); - (void)uburma_nl_reply(nlh, &resp, pid); -} - -static void uburma_nl_cb_func(struct sk_buff *skb) -{ - struct nlmsghdr *nlh; - uint32_t pid; /* portid */ - - nlh = nlmsg_hdr(skb); - if (skb->len < nlh->nlmsg_len) { - uburma_log_err("Invalid nl msg received"); - return; - } - - pid = NETLINK_CB(skb).portid; - switch (nlh->nlmsg_type) { - case UBURMA_NL_SET_NS_MODE: - uburma_nl_handle_set_ns_mode(nlh, pid); - break; - case UBURMA_NL_SET_DEV_NS: - uburma_nl_handle_set_dev_ns(nlh, pid); - break; - default: - uburma_log_err("Unexpected nl msg type: %d received\n", nlh->nlmsg_type); - break; - } -} - -int uburma_netlink_init(void) -{ - struct netlink_kernel_cfg cfg = {0}; - - cfg.input = uburma_nl_cb_func; - g_uburma_nl_sock = (struct sock *)netlink_kernel_create(&init_net, UBURMA_NL_TYPE, &cfg); - if (g_uburma_nl_sock == NULL) { - uburma_log_err("Netlink_kernel_create error.\n"); - return -1; - } - return 0; -} - -void uburma_netlink_exit(void) -{ - if (g_uburma_nl_sock != NULL) { - netlink_kernel_release(g_uburma_nl_sock); - g_uburma_nl_sock = NULL; - } -} diff --git a/drivers/ub/urma/uburma/uburma_types.h b/drivers/ub/urma/uburma/uburma_types.h index 9426378cd6bc..486df78ca8ee 100644 --- a/drivers/ub/urma/uburma/uburma_types.h +++ b/drivers/ub/urma/uburma/uburma_types.h @@ -21,8 +21,6 @@ #ifndef UBURMA_TYPES_H #define UBURMA_TYPES_H -#include -#include #include #include #include @@ -61,34 +59,6 @@ struct uburma_file { int is_closed; }; -struct uburma_port { - struct kobject kobj; - struct uburma_device *ubu_dev; - uint8_t port_num; -}; - -struct uburma_fe { - struct kobject kobj; - struct uburma_device *ubu_dev; - uint16_t fe_idx; -}; - -struct uburma_eid { - struct kobject kobj; - struct uburma_logic_device *ldev; - uint32_t eid_idx; -}; - -struct uburma_logic_device { - struct device *dev; - struct uburma_port port[UBCORE_MAX_PORT_CNT]; - struct uburma_fe fe[UBCORE_MAX_FE_CNT]; - struct uburma_eid *eid; - struct list_head node; /* add to ldev list */ - possible_net_t net; - struct uburma_device *ubu_dev; -}; - struct uburma_device { atomic_t refcnt; struct completion comp; /* When refcnt becomes 0, it will wake up */ @@ -96,15 +66,12 @@ struct uburma_device { struct completion cmddone; /* When cmdcnt becomes 0, cmddone will wake up */ unsigned int devnum; struct cdev cdev; - struct uburma_logic_device ldev; + struct device *dev; struct ubcore_device *__rcu ubc_dev; struct srcu_struct ubc_dev_srcu; /* protect ubc_dev */ struct kobject kobj; /* when equal to 0 , free uburma_device. */ struct mutex lists_mutex; /* protect lists */ struct list_head uburma_file_list; - struct list_head node; /* add to uburma_device_list */ - struct mutex ldev_mutex; - struct list_head ldev_list; }; #endif /* UBURMA_TYPES_H */ diff --git a/drivers/ub/urma/uburma/uburma_uobj.c b/drivers/ub/urma/uburma/uburma_uobj.c index 6c2325a38d25..53db41018d0f 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.c +++ b/drivers/ub/urma/uburma/uburma_uobj.c @@ -54,7 +54,7 @@ struct uburma_uobj *uobj_alloc_begin(const struct uobj_type *type, struct uburma return uobj; } -int uobj_alloc_commit(struct uburma_uobj *uobj) +void uobj_alloc_commit(struct uburma_uobj *uobj) { /* relase write lock */ atomic_set(&uobj->rcnt, 0); @@ -67,7 +67,6 @@ int uobj_alloc_commit(struct uburma_uobj *uobj) uobj->type->type_class->alloc_commit(uobj); up_read(&uobj->ufile->cleanup_rwsem); - return 0; } void uobj_alloc_abort(struct uburma_uobj *uobj) diff --git a/drivers/ub/urma/uburma/uburma_uobj.h b/drivers/ub/urma/uburma/uburma_uobj.h index f4f7617ae223..919fc024fbdf 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.h +++ b/drivers/ub/urma/uburma/uburma_uobj.h @@ -154,7 +154,7 @@ extern const struct uobj_type_class uobj_fd_type_class; /* uobj base ops */ struct uburma_uobj *uobj_alloc_begin(const struct uobj_type *type, struct uburma_file *ufile); -int uobj_alloc_commit(struct uburma_uobj *uobj); +void uobj_alloc_commit(struct uburma_uobj *uobj); void uobj_alloc_abort(struct uburma_uobj *uobj); struct uburma_uobj *uobj_lookup_get(const struct uobj_type *type, struct uburma_file *ufile, int id, enum uobj_access flag); diff --git a/include/urma/ubcore_types.h b/include/urma/ubcore_types.h index ce2150c313ff..7a56c6e6fcef 100644 --- a/include/urma/ubcore_types.h +++ b/include/urma/ubcore_types.h @@ -41,6 +41,7 @@ #define UBCORE_GET_VERSION(a, b) (((a) << 16) + ((b) > 65535 ? 65535 : (b))) #define UBCORE_API_VERSION ((0 << 16) + 9) // Current Version: 0.9 +#define UBCORE_MAX_JETTY_IN_JETTY_GRP 16U #define UBCORE_MAX_PORT_CNT 16 #define UBCORE_MAX_FE_CNT 1024 #define UBCORE_MAX_DEV_NAME 64 @@ -53,6 +54,8 @@ #define UBCORE_EID_STR_LEN (39) #define UBCORE_DEVID_SIZE (16) #define UBCORE_GUID_SIZE (16) +#define UBCORE_MAX_MSG 4096 +#define UBCORE_MAX_EID_CNT 1024 #define EID_FMT \ "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x" @@ -937,12 +940,12 @@ struct ubcore_vtpn { uint32_t vtpn; /* driver fills */ struct ubcore_device *ub_dev; /* ubcore private, inaccessible to driver */ - enum ubcore_transport_mode trans_mode; /* vtpn key start */ + enum ubcore_transport_mode trans_mode; union ubcore_eid local_eid; union ubcore_eid peer_eid; /* vtpn key end */ - uint32_t eid_index; + uint32_t eid_index; /* next of vtpn key. if modifed, should update VTPN_KEY_SIZE */ uint32_t local_jetty; uint32_t peer_jetty; atomic_t state; @@ -982,6 +985,7 @@ struct ubcore_vtp { struct ubcore_device *ub_dev; struct ubcore_vtp_cfg cfg; /* driver fills */ struct hlist_node hnode; /* driver inaccessible */ + uint32_t role; /* current side is initiator, target or duplex */ }; struct ubcore_vtp_attr { @@ -1625,16 +1629,6 @@ struct ubcore_ops { char driver_name[UBCORE_MAX_DRIVER_NAME]; /* user space driver name */ uint32_t abi_version; /* abi version of kernel driver */ - /** - * set upi - * @param[in] dev: the ub device handle; - * @param[in] fe_idx: fe_idx; - * @param[in] idx: idx of upi in fe; - * @param[in] upi: upi of fe to set - * @return: 0 on success, other value on error - */ - int (*set_upi)(struct ubcore_device *dev, uint16_t fe_idx, uint16_t idx, uint32_t upi); - /** * add a function entity id (eid) to ub device (for uvs) * @param[in] dev: the ubcore_device handle; @@ -2338,6 +2332,27 @@ struct ubcore_sip_table { DECLARE_BITMAP(index_bitmap, UBCORE_MAX_SIP); }; +struct ubcore_port_kobj { + struct kobject kobj; + struct ubcore_device *dev; + uint8_t port_id; +}; + +struct ubcore_eid_kobj { + struct kobject kobj; + struct ubcore_logic_device *ldev; + uint32_t eid_idx; +}; + +struct ubcore_logic_device { + struct device *dev; + struct ubcore_port_kobj port[UBCORE_MAX_PORT_CNT]; + struct ubcore_eid_kobj *eid; + struct list_head node; /* add to ldev list */ + possible_net_t net; + struct ubcore_device *ub_dev; +}; + struct ubcore_device { struct list_head list_node; /* add to device list */ @@ -2356,14 +2371,13 @@ struct ubcore_device { struct ubcore_device_cfg cfg; /* port management */ - struct kobject *ports_parent; /* kobject parent of the ports in the port list */ - struct list_head port_list; /* add to port list */ + struct list_head port_list; /* For ubcore client */ - spinlock_t client_ctx_lock; + struct rw_semaphore client_ctx_rwsem; struct list_head client_ctx_list; struct list_head event_handler_list; - spinlock_t event_handler_lock; + struct rw_semaphore event_handler_rwsem; struct ubcore_hash_table ht[UBCORE_HT_NUM]; /* to be replaced with uobj */ /* protect from unregister device */ @@ -2373,13 +2387,11 @@ struct ubcore_device { struct ubcore_eid_table eid_table; struct ubcore_cg_device cg_device; struct ubcore_sip_table sip_table; -}; -struct ubcore_port { - struct kobject kobj; /* add to port list */ - struct ubcore_device *ub_dev; - uint32_t port_id; - struct ubcore_net_addr net_addr; + /* logic device list and mutex */ + struct ubcore_logic_device ldev; + struct mutex ldev_mutex; + struct list_head ldev_list; }; struct ubcore_client { diff --git a/include/urma/ubcore_uapi.h b/include/urma/ubcore_uapi.h index 80453b666166..26feb893b55f 100644 --- a/include/urma/ubcore_uapi.h +++ b/include/urma/ubcore_uapi.h @@ -43,15 +43,7 @@ struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_ * not by other kernel modules */ void ubcore_free_ucontext(struct ubcore_device *dev, struct ubcore_ucontext *ucontext); -/** - * set upi - * @param[in] dev: the ubcore_device handle; - * @param[in] fe_idx: fe_idx; - * @param[in] idx: idx of upi in fe; - * @param[in] upi: upi of fe to set - * @return: 0 on success, other value on error - */ -int ubcore_set_upi(struct ubcore_device *dev, uint16_t fe_idx, uint16_t idx, uint32_t upi); + /** * add a function entity id (eid) to ub device (for uvs) * @param[in] dev: the ubcore_device handle; diff --git a/include/urma/uboib_user_ctl.h b/include/urma/uboib_user_ctl.h deleted file mode 100644 index 9dab55b2a2e0..000000000000 --- a/include/urma/uboib_user_ctl.h +++ /dev/null @@ -1,116 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * Description: UBOIB user control header file - * Author: Wu Yuyan - * Create: 2024-01-13 - * Note: - * History: 2024-01-13 Create File - */ - -#ifndef UBOIB_USER_CTL_H -#define UBOIB_USER_CTL_H - -#include - -/* add user_ctrl for ums */ -enum uboib_user_control_opcode { - UBOIB_USER_CTL_SYNC_SG = 0x30, - UBOIB_USER_CTL_GET_MAC, - UBOIB_USER_CTL_GET_GID, - UBOIB_USER_CTL_PUT_GID, - UBOIB_USER_CTL_QUERY_DEV_ATTR, - UBOIB_USER_CTL_READ_PNET -}; - -/* Refer to UBOIB_USER_CTL_SYNC_SG */ -struct uboib_user_ctl_sync_sg_in { - struct ubcore_target_seg *ub_tseg; - int data_direction; -}; - -/* Refer to UBOIB_USER_CTL_GET_MAC */ -struct uboib_user_ctl_get_mac_in { - uint8_t port; -}; - -struct uboib_user_ctl_get_mac_out { - uint8_t mac[UBCORE_MAC_BYTES]; - int ret; -}; - -/* Refer to UBOIB_USER_CTL_GET_GID */ -struct uboib_user_ctl_get_gid_in { - uint8_t port; - int gid_idx; -}; - -struct uboib_user_ctl_gid_attr { - int gid_type; - int roce_v1_type; - int roce_v2_type; - uint16_t index; - uint8_t gid[UBCORE_EID_SIZE]; -}; - -struct uboib_user_ctl_get_gid_out { - uint32_t core_cap_flags; - const struct net_device *ndev; - struct uboib_user_ctl_gid_attr gid_attr; - int ret; -}; - -/* Refer to UBOIB_USER_CTL_PUT_GID */ -struct uboib_user_ctl_put_gid_in { - uint8_t port; - int gid_idx; -}; - -/* Refer to UBOIB_USER_CTL_QUERY_DEV_ATTR */ -enum uboib_user_ctl_query_dev_mask { - UBOIB_QUERY_GID_TBL_LEN = 0x1, - UBOIB_QUERY_NET_DEV = 0x1 << 1, - UBOIB_QUERY_NET_NS = 0x1 << 2 -}; - -struct uboib_user_ctl_query_dev_attr_in { - uint32_t mask; - uint8_t port; - struct net *net; -}; - -struct uboib_user_ctl_port_attr { - bool is_valid; - int gid_tbl_len; - struct net_device *ndev; -}; - -#define UBOIB_USER_CTL_MAX_PORTS 2 -struct uboib_user_ctl_dev_attr { - bool is_accessed_from_ns; - struct uboib_user_ctl_port_attr port_attr[UBOIB_USER_CTL_MAX_PORTS]; -}; - -struct uboib_user_ctl_query_dev_attr_out { - struct uboib_user_ctl_dev_attr dev_attr; - int ret; -}; - -/* Refer to UBOIB_USER_CTL_READ_PNET */ -struct uboib_user_ctl_read_pnet_out { - struct net *net; -}; - -int uboib_user_ctl(struct ubcore_device *dev, struct ubcore_user_ctl *user_ctl); - -#endif -- Gitee From 013280dfab06d20e73de842e8d2fc2a200055455 Mon Sep 17 00:00:00 2001 From: WenChen Date: Fri, 17 May 2024 17:10:17 +0800 Subject: [PATCH 2/6] urma: upload kernel patch for 20240224_rain driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I91DSN CVE: NA -------------------------------- Upload kernel patch for 20240224_rain, detailed fixes are as follows: 1. cp tpsa_ini.c to daemon 2. Supporting multi io_thread 3. Too many kernel state logs are abnormal 4. ub_dstring support longer strings 5. Deletion of redundant jfs/jetty mutex 6. Put eid in the dev ns in exclusive mode Fixes: 329bf7f33128 ("ubcore: fix the bug of tp negotiation concurrency") Signed-off-by: WenChen Signed-off-by: Weibo Zhao --- drivers/ub/urma/ubcore/ubcore_cdev_file.c | 8 +- drivers/ub/urma/ubcore/ubcore_cgroup.c | 5 + drivers/ub/urma/ubcore/ubcore_device.c | 128 +++++-- drivers/ub/urma/ubcore/ubcore_device.h | 2 +- drivers/ub/urma/ubcore/ubcore_genl_admin.c | 6 +- drivers/ub/urma/ubcore/ubcore_hash_table.c | 38 +++ drivers/ub/urma/ubcore/ubcore_hash_table.h | 3 + drivers/ub/urma/ubcore/ubcore_jetty.c | 2 +- drivers/ub/urma/ubcore/ubcore_log.h | 10 +- drivers/ub/urma/ubcore/ubcore_main.c | 23 +- drivers/ub/urma/ubcore/ubcore_msg.c | 5 + drivers/ub/urma/ubcore/ubcore_msg.h | 1 + drivers/ub/urma/ubcore/ubcore_netdev.c | 12 +- drivers/ub/urma/ubcore/ubcore_netlink.c | 2 +- drivers/ub/urma/ubcore/ubcore_priv.h | 7 +- drivers/ub/urma/ubcore/ubcore_tp.c | 5 +- drivers/ub/urma/ubcore/ubcore_utp.c | 4 +- drivers/ub/urma/ubcore/ubcore_uvs_cmd.c | 29 +- drivers/ub/urma/ubcore/ubcore_vtp.c | 371 +++++++++++---------- drivers/ub/urma/ubcore/ubcore_vtp.h | 7 +- drivers/ub/urma/uburma/uburma_cmd.c | 1 + drivers/ub/urma/uburma/uburma_cmd.h | 1 + include/urma/ubcore_opcode.h | 4 +- include/urma/ubcore_types.h | 29 +- 24 files changed, 438 insertions(+), 265 deletions(-) diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.c b/drivers/ub/urma/ubcore/ubcore_cdev_file.c index 5f8815f585ca..aa16e14c0880 100644 --- a/drivers/ub/urma/ubcore/ubcore_cdev_file.c +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.c @@ -707,7 +707,7 @@ static ssize_t ubcore_show_eid_attr(struct ubcore_eid_kobj *eid, struct ubcore_e struct ubcore_device *dev = get_ubcore_device(ldev); if (!ldev || !dev) { - ubcore_log_err("Invalid argument in show_fe_attr.\n"); + ubcore_log_err("Invalid argument in show_eid_attr.\n"); return -EINVAL; } @@ -716,11 +716,13 @@ static ssize_t ubcore_show_eid_attr(struct ubcore_eid_kobj *eid, struct ubcore_e static ssize_t show_eid_cb(struct ubcore_device *dev, char *buf, uint16_t idx, struct net *net) { + struct ubcore_eid_entry *e; union ubcore_eid eid; - if (net_eq(dev->eid_table.eid_entries[idx].net, net)) { + e = &dev->eid_table.eid_entries[idx]; + if (e->valid && net_eq(e->net, net)) { return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", - EID_ARGS(dev->eid_table.eid_entries[idx].eid)); + EID_ARGS(e->eid)); } else { memset(&eid, 0, sizeof(union ubcore_eid)); return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", diff --git a/drivers/ub/urma/ubcore/ubcore_cgroup.c b/drivers/ub/urma/ubcore/ubcore_cgroup.c index f5cac5c2fa44..12c602c50ee9 100644 --- a/drivers/ub/urma/ubcore/ubcore_cgroup.c +++ b/drivers/ub/urma/ubcore/ubcore_cgroup.c @@ -31,6 +31,11 @@ static inline bool ubcore_is_use_cg(struct ubcore_device *dev) void ubcore_cgroup_reg_dev(struct ubcore_device *dev) { + if (dev == NULL) { + ubcore_log_err("dev is null"); + return; + } + dev->cg_device.dev.name = dev->dev_name; if (!ubcore_is_use_cg(dev)) return; diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index bed9d45c0e5f..ebd430e6e973 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -147,6 +147,11 @@ static struct ubcore_client_ctx *ubcore_lookup_client_context(struct ubcore_devi struct ubcore_client_ctx *found_ctx = NULL; struct ubcore_client_ctx *ctx, *tmp; + if (dev == NULL || client == NULL) { + ubcore_log_err("dev is null"); + return NULL; + } + down_read(&dev->client_ctx_rwsem); list_for_each_entry_safe(ctx, tmp, &dev->client_ctx_list, list_node) { if (ctx->client == client) { @@ -217,6 +222,11 @@ int ubcore_register_client(struct ubcore_client *new_client) { struct ubcore_device *dev; + if (new_client == NULL) { + ubcore_log_err("new_client is null"); + return -1; + } + mutex_lock(&g_device_mutex); list_for_each_entry(dev, &g_device_list, list_node) { @@ -240,6 +250,11 @@ void ubcore_unregister_client(struct ubcore_client *rm_client) struct ubcore_client_ctx *found_ctx = NULL; struct ubcore_device *dev; + if (rm_client == NULL) { + ubcore_log_err("rm_client is null"); + return; + } + mutex_lock(&g_device_mutex); down_write(&g_clients_rwsem); @@ -419,7 +434,7 @@ void ubcore_put_devices(struct ubcore_device **devices, uint32_t cnt) void ubcore_get_device(struct ubcore_device *dev) { if (IS_ERR_OR_NULL(dev)) { - ubcore_log_err("Invalid parameter"); + ubcore_log_err("Invalid parameter\n"); return; } @@ -429,7 +444,7 @@ void ubcore_get_device(struct ubcore_device *dev) void ubcore_put_device(struct ubcore_device *dev) { if (IS_ERR_OR_NULL(dev)) { - ubcore_log_err("Invalid parameter"); + ubcore_log_err("Invalid parameter\n"); return; } @@ -440,7 +455,7 @@ void ubcore_put_device(struct ubcore_device *dev) struct ubcore_device *ubcore_find_tpf_device_legacy(void) { if (g_tpf == NULL) - ubcore_log_err("tpf is not registered yet"); + ubcore_log_err("tpf is not registered yet\n"); ubcore_get_device(g_tpf); return g_tpf; @@ -564,48 +579,61 @@ int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg) static struct ubcore_ht_param g_ht_params[] = { [UBCORE_HT_JFS] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfs, hnode), - offsetof(struct ubcore_jfs, id), sizeof(uint32_t), NULL, NULL}, + offsetof(struct ubcore_jfs, id), sizeof(uint32_t), NULL, NULL, NULL}, [UBCORE_HT_JFR] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfr, hnode), - offsetof(struct ubcore_jfr, id), sizeof(uint32_t), NULL, NULL }, + offsetof(struct ubcore_jfr, id), sizeof(uint32_t), NULL, NULL, NULL}, [UBCORE_HT_JFC] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfc, hnode), - offsetof(struct ubcore_jfc, id), sizeof(uint32_t), NULL, NULL }, + offsetof(struct ubcore_jfc, id), sizeof(uint32_t), NULL, NULL, NULL}, [UBCORE_HT_JETTY] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jetty, hnode), - offsetof(struct ubcore_jetty, id), sizeof(uint32_t), NULL, NULL }, + offsetof(struct ubcore_jetty, id), + sizeof(uint32_t), NULL, NULL, NULL}, [UBCORE_HT_TP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tp_node, hnode), - offsetof(struct ubcore_tp_node, key), sizeof(struct ubcore_tp_key), NULL, NULL}, + offsetof(struct ubcore_tp_node, key), + sizeof(struct ubcore_tp_key), NULL, NULL, NULL}, [UBCORE_HT_TPG] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tpg, hnode), - offsetof(struct ubcore_tpg, tpgn), sizeof(uint32_t), NULL, NULL}, + offsetof(struct ubcore_tpg, tpgn), sizeof(uint32_t), NULL, NULL, NULL}, /* key: seid + deid */ [UBCORE_HT_RM_VTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtp, hnode), offsetof(struct ubcore_vtp, cfg) + offsetof(struct ubcore_vtp_cfg, local_eid), - sizeof(union ubcore_eid) * 2, NULL, NULL}, + sizeof(union ubcore_eid) * 2, NULL, NULL, NULL}, /* key: deid + djetty */ [UBCORE_HT_RC_VTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtp, hnode), offsetof(struct ubcore_vtp, cfg) + offsetof(struct ubcore_vtp_cfg, peer_eid), - sizeof(union ubcore_eid) + sizeof(uint32_t), NULL, NULL}, + sizeof(union ubcore_eid) + sizeof(uint32_t), NULL, NULL, NULL}, /* key: seid + deid */ [UBCORE_HT_UM_VTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtp, hnode), offsetof(struct ubcore_vtp, cfg) + offsetof(struct ubcore_vtp_cfg, local_eid), - sizeof(union ubcore_eid) * 2, NULL, NULL}, + sizeof(union ubcore_eid) * 2, NULL, NULL, NULL}, /* key: src_eid + des_eid */ - [UBCORE_HT_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), - offsetof(struct ubcore_vtpn, trans_mode), VTPN_KEY_SIZE, NULL, NULL}, + [UBCORE_HT_RM_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), + offsetof(struct ubcore_vtpn, local_eid), 2 * sizeof(union ubcore_eid), NULL, NULL, + ubcore_vtpn_get}, + + /* key: src_eid + des_eid + src_jetty + des_jetty */ + [UBCORE_HT_RC_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), + offsetof(struct ubcore_vtpn, local_eid), + 2 * sizeof(union ubcore_eid) + 2 * sizeof(uint32_t), NULL, NULL, ubcore_vtpn_get}, + + /* key: src_eid + des_eid */ + [UBCORE_HT_UM_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), + offsetof(struct ubcore_vtpn, local_eid), 2 * sizeof(union ubcore_eid), NULL, NULL, + ubcore_vtpn_get}, /* key: utp idx */ [UBCORE_HT_UTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_utp, hnode), - offsetof(struct ubcore_utp, utpn), sizeof(uint32_t), NULL, NULL}, + offsetof(struct ubcore_utp, utpn), sizeof(uint32_t), NULL, NULL, NULL}, /* key: ctp idx */ [UBCORE_HT_CTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_ctp, hnode), - offsetof(struct ubcore_ctp, ctpn), sizeof(uint32_t), NULL, NULL}, + offsetof(struct ubcore_ctp, ctpn), sizeof(uint32_t), NULL, NULL, NULL}, }; static int ubcore_alloc_hash_tables(struct ubcore_device *dev) @@ -1451,9 +1479,9 @@ static bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index) return net_eq(net, current->nsproxy->net_ns); } -bool ubcore_dev_accessible(struct ubcore_device *dev) +bool ubcore_dev_accessible(struct ubcore_device *dev, struct net *net) { - return (g_shared_ns || net_eq(current->nsproxy->net_ns, read_pnet(&dev->ldev.net))); + return (g_shared_ns || net_eq(net, read_pnet(&dev->ldev.net))); } struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_t eid_index, @@ -1469,7 +1497,8 @@ struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_ return NULL; } - if (!ubcore_dev_accessible(dev) || !ubcore_eid_accessible(dev, eid_index)) { + if (!ubcore_dev_accessible(dev, current->nsproxy->net_ns) || + !ubcore_eid_accessible(dev, eid_index)) { ubcore_log_err("eid is not accessible by current ns.\n"); return NULL; } @@ -1544,8 +1573,7 @@ int ubcore_add_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ue ret = op_dev->ops->add_ueid(op_dev, fe_idx, cfg); if (ret != 0) { - ubcore_log_err( - "failed to add ueid, fe_idx:%hu, eid:"EID_FMT", upi:%u, eid_idx:%u, ret:%d", + ubcore_log_err("failed to add ueid, ret:%d\n", fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); goto put_dev; } @@ -1573,8 +1601,7 @@ int ubcore_delete_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore ret = op_dev->ops->delete_ueid(op_dev, fe_idx, cfg); if (ret != 0) { - ubcore_log_err( - "failed to add ueid, fe_idx:%hu, eid:"EID_FMT", upi:%u, eid_idx:%u, ret:%d", + ubcore_log_err("failed to add ueid, ret:%d\n", fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); goto put_dev; } @@ -1918,7 +1945,43 @@ struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(struct ubcore_net_addr *addr return target; } -static int ubcore_modify_dev_ns(struct ubcore_device *dev, struct net *net) +static void ubcore_modify_eid_ns(struct ubcore_device *dev, struct net *net) +{ + struct ubcore_eid_entry *e; + uint32_t i; + + if (dev->eid_table.eid_entries == NULL) + return; + + spin_lock(&dev->eid_table.lock); + for (i = 0; i < dev->eid_table.eid_cnt; i++) { + e = &dev->eid_table.eid_entries[i]; + if (e->valid && !net_eq(e->net, net)) + e->net = net; + } + spin_unlock(&dev->eid_table.lock); +} + +static void ubcore_invalidate_eid_ns(struct ubcore_device *dev, struct net *net) +{ + struct ubcore_eid_entry *e; + uint32_t i; + + if (dev->eid_table.eid_entries == NULL) + return; + + spin_lock(&dev->eid_table.lock); + for (i = 0; i < dev->eid_table.eid_cnt; i++) { + e = &dev->eid_table.eid_entries[i]; + if (e->valid && net_eq(e->net, net)) { + e->net = &init_net; + e->valid = false; + } + } + spin_unlock(&dev->eid_table.lock); +} + +static int ubcore_modify_dev_ns(struct ubcore_device *dev, struct net *net, bool exit) { struct net *cur; int ret; @@ -1934,7 +1997,15 @@ static int ubcore_modify_dev_ns(struct ubcore_device *dev, struct net *net) if (ret) { write_pnet(&dev->ldev.net, cur); ubcore_log_err("Failed to rename device in the new ns.\n"); + goto out; } + + if (exit) + ubcore_invalidate_eid_ns(dev, cur); + else + ubcore_modify_eid_ns(dev, net); + +out: ubcore_clients_add(dev); kobject_uevent(&dev->ldev.dev->kobj, KOBJ_ADD); return ret; @@ -1970,14 +2041,14 @@ int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd) break; } } - if (dev == NULL) { + if (dev == NULL || dev->transport_type != UBCORE_TRANSPORT_UB) { ret = -EINVAL; ubcore_log_err("Failed to find device.\n"); goto out; } /* Put device in the new ns */ - ret = ubcore_modify_dev_ns(dev, net); + ret = ubcore_modify_dev_ns(dev, net, false); out: mutex_unlock(&g_device_mutex); @@ -2036,7 +2107,9 @@ void ubcore_net_exit(struct net *net) if (!g_shared_ns) { mutex_lock(&g_device_mutex); list_for_each_entry(dev, &g_device_list, list_node) { - (void)ubcore_modify_dev_ns(dev, &init_net); + if (dev->transport_type != UBCORE_TRANSPORT_UB) + continue; + (void)ubcore_modify_dev_ns(dev, &init_net, true); } mutex_unlock(&g_device_mutex); } else { @@ -2045,6 +2118,7 @@ void ubcore_net_exit(struct net *net) if (dev->transport_type != UBCORE_TRANSPORT_UB) continue; ubcore_remove_one_logic_device(dev, net); + ubcore_invalidate_eid_ns(dev, net); } mutex_unlock(&g_device_mutex); } diff --git a/drivers/ub/urma/ubcore/ubcore_device.h b/drivers/ub/urma/ubcore/ubcore_device.h index fd37e509c78b..395eef63fef8 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.h +++ b/drivers/ub/urma/ubcore/ubcore_device.h @@ -27,5 +27,5 @@ int ubcore_class_register(struct class **ubcore_class); void ubcore_class_unregister(struct class *ubcore_class); int ubcore_set_ns_mode(bool shared); int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd); - +bool ubcore_dev_accessible(struct ubcore_device *dev, struct net *net); #endif // UBCORE_DEVICE_H diff --git a/drivers/ub/urma/ubcore/ubcore_genl_admin.c b/drivers/ub/urma/ubcore/ubcore_genl_admin.c index 2f867d428aab..a3f3ba9bfa68 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl_admin.c +++ b/drivers/ub/urma/ubcore/ubcore_genl_admin.c @@ -246,11 +246,13 @@ static int ubcore_update_ueid(struct genl_info *info, enum ubcore_msg_opcode op) if (arg.in.ns_fd >= 0) { net = get_net_ns_by_fd(arg.in.ns_fd); - if (IS_ERR(net)) { + if (IS_ERR(net) || !ubcore_dev_accessible(dev, net)) { ubcore_put_device(dev); - ubcore_log_err("Failed to get ns by fd.\n"); + ubcore_log_err("invalid net ns.\n"); return (int)PTR_ERR(net); } + } else if (op == UBCORE_MSG_ALLOC_EID) { + net = read_pnet(&dev->ldev.net); } if (ubcore_msg_discover_eid(dev, arg.in.eid_index, op, net) != 0) diff --git a/drivers/ub/urma/ubcore/ubcore_hash_table.c b/drivers/ub/urma/ubcore/ubcore_hash_table.c index 12f6f335f1ce..bd493dd4a9a9 100644 --- a/drivers/ub/urma/ubcore/ubcore_hash_table.c +++ b/drivers/ub/urma/ubcore/ubcore_hash_table.c @@ -110,6 +110,44 @@ void ubcore_hash_table_remove(struct ubcore_hash_table *ht, struct hlist_node *h spin_unlock(&ht->lock); } +void *ubcore_hash_table_lookup_nolock_get(struct ubcore_hash_table *ht, uint32_t hash, + const void *key) +{ + struct hlist_node *pos = NULL; + void *obj = NULL; + + hlist_for_each(pos, &ht->head[hash % ht->p.size]) { + obj = ubcore_ht_obj(ht, pos); + if (ht->p.cmp_f != NULL && ht->p.cmp_f(obj, key) == 0) { + break; + } else if (ht->p.key_size > 0 && + memcmp(ubcore_ht_key(ht, pos), key, ht->p.key_size) == 0) { + break; + } + obj = NULL; + } + if (ht->p.get_f != NULL && obj != NULL) + ht->p.get_f(obj); + + return obj; +} + +void *ubcore_hash_table_lookup_get(struct ubcore_hash_table *ht, uint32_t hash, const void *key) +{ + void *obj = NULL; + + spin_lock(&ht->lock); + if (ht->head == NULL) { + spin_unlock(&ht->lock); + return NULL; + } + obj = ubcore_hash_table_lookup_nolock_get(ht, hash, key); + + spin_unlock(&ht->lock); + return obj; +} + + void *ubcore_hash_table_lookup_nolock(struct ubcore_hash_table *ht, uint32_t hash, const void *key) { struct hlist_node *pos = NULL; diff --git a/drivers/ub/urma/ubcore/ubcore_hash_table.h b/drivers/ub/urma/ubcore/ubcore_hash_table.h index d885068c10d5..4de04ddadbae 100644 --- a/drivers/ub/urma/ubcore/ubcore_hash_table.h +++ b/drivers/ub/urma/ubcore/ubcore_hash_table.h @@ -47,6 +47,9 @@ void ubcore_hash_table_remove_nolock(struct ubcore_hash_table *ht, struct hlist_ void *ubcore_hash_table_lookup(struct ubcore_hash_table *ht, uint32_t hash, const void *key); void *ubcore_hash_table_lookup_nolock(struct ubcore_hash_table *ht, uint32_t hash, const void *key); +void *ubcore_hash_table_lookup_get(struct ubcore_hash_table *ht, uint32_t hash, const void *key); +void *ubcore_hash_table_lookup_nolock_get(struct ubcore_hash_table *ht, uint32_t hash, + const void *key); void *ubcore_hash_table_find_remove(struct ubcore_hash_table *ht, uint32_t hash, const void *key); /* Do not insert a new entry if an old entry with the same key exists */ int ubcore_hash_table_find_add(struct ubcore_hash_table *ht, struct hlist_node *hnode, diff --git a/drivers/ub/urma/ubcore/ubcore_jetty.c b/drivers/ub/urma/ubcore/ubcore_jetty.c index 6cb7b410d350..62d08bb15ac2 100644 --- a/drivers/ub/urma/ubcore/ubcore_jetty.c +++ b/drivers/ub/urma/ubcore/ubcore_jetty.c @@ -946,7 +946,7 @@ struct ubcore_tjetty *ubcore_import_jetty(struct ubcore_device *dev, struct ubcore_tjetty *tjetty; if (!ubcore_have_tp_ops(dev) || dev->ops->import_jetty == NULL || - dev->ops->unimport_jfr == NULL || cfg == NULL || + dev->ops->unimport_jetty == NULL || cfg == NULL || dev->attr.dev_cap.max_eid_cnt < cfg->eid_index) return NULL; diff --git a/drivers/ub/urma/ubcore/ubcore_log.h b/drivers/ub/urma/ubcore/ubcore_log.h index 921663651df1..17f9fddac5cb 100644 --- a/drivers/ub/urma/ubcore/ubcore_log.h +++ b/drivers/ub/urma/ubcore/ubcore_log.h @@ -38,24 +38,28 @@ enum ubcore_log_level { /* add log head info, "LogTag_UBCORE|function|[line]| */ #define UBCORE_LOG_TAG "LogTag_UBCORE" +/* only use debug log */ #define ubcore_log(l, format, args...) \ pr_##l("%s|%s:[%d]|" format, UBCORE_LOG_TAG, __func__, __LINE__, ##args) +/* use default log, info/warn/err */ +#define ubcore_default_log(l, format, args...) \ + ((void)pr_##l("%s|%s:[%d]|" format, UBCORE_LOG_TAG, __func__, __LINE__, ##args)) extern uint32_t g_ubcore_log_level; #define ubcore_log_info(...) do { \ if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_INFO) \ - ubcore_log(info, __VA_ARGS__); \ + ubcore_default_log(info, __VA_ARGS__); \ } while (0) #define ubcore_log_err(...) do { \ if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_ERR) \ - ubcore_log(err, __VA_ARGS__); \ + ubcore_default_log(err, __VA_ARGS__); \ } while (0) #define ubcore_log_warn(...) do { \ if (g_ubcore_log_level >= UBCORE_LOG_LEVEL_WARNING) \ - ubcore_log(warn, __VA_ARGS__); \ + ubcore_default_log(warn, __VA_ARGS__); \ } while (0) #define ubcore_log_debug(...) do { \ diff --git a/drivers/ub/urma/ubcore/ubcore_main.c b/drivers/ub/urma/ubcore/ubcore_main.c index 9b0a806a41ec..dc08b66ca18a 100644 --- a/drivers/ub/urma/ubcore/ubcore_main.c +++ b/drivers/ub/urma/ubcore/ubcore_main.c @@ -114,13 +114,9 @@ int ubcore_open(struct inode *i_node, struct file *filp) } static void ubcore_update_pattern1_eid(struct ubcore_device *dev, - union ubcore_eid *eid, bool is_add) + union ubcore_eid *eid, uint32_t eid_idx, bool is_add) { struct ubcore_ueid_cfg cfg; - uint32_t eid_idx = 0; - - if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) - return; cfg.eid = *eid; cfg.eid_index = eid_idx; @@ -132,14 +128,10 @@ static void ubcore_update_pattern1_eid(struct ubcore_device *dev, } static void ubcore_update_pattern3_eid(struct ubcore_device *dev, - union ubcore_eid *eid, bool is_add) + union ubcore_eid *eid, uint32_t eid_idx, bool is_add) { uint32_t pattern3_upi = 0; struct ubcore_ueid_cfg cfg; - uint32_t eid_idx = 0; - - if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) - return; if (dev->attr.virtualization || ubcore_find_upi_with_dev_name(dev->dev_name, &pattern3_upi) == NULL) @@ -447,20 +439,23 @@ static void ubcore_update_eid(struct ubcore_device *dev, struct ubcore_net_addr *netaddr, bool is_add) { union ubcore_eid *eid; + uint32_t eid_idx = 0; if (dev->transport_type <= UBCORE_TRANSPORT_INVALID || dev->transport_type >= UBCORE_TRANSPORT_MAX) return; if (!dev->dynamic_eid) { - ubcore_log_err("static mode does not allow modify of eid"); + ubcore_log_err("static mode does not allow modify of eid\n"); return; } eid = (union ubcore_eid *)(void *)&netaddr->net_addr; + if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) + return; if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) - ubcore_update_pattern1_eid(dev, eid, is_add); + ubcore_update_pattern1_eid(dev, eid, eid_idx, is_add); else - ubcore_update_pattern3_eid(dev, eid, is_add); + ubcore_update_pattern3_eid(dev, eid, eid_idx, is_add); } static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long event, @@ -530,7 +525,7 @@ static int ubcore_ipv6_notifier_call(struct notifier_block *nb, return NOTIFY_DONE; netdev = ifa->idev->dev; - ubcore_log_info("Get a ipv6 event %s from netdev %s%s ip %pI6c prefixlen %u", + ubcore_log_info("Get a ipv6 event %s from netdev %s%s ip %pI6c prefixlen %u\n", netdev_cmd_to_name(event), netdev_name(netdev), netdev_reg_state(netdev), &ifa->addr, ifa->prefix_len); diff --git a/drivers/ub/urma/ubcore/ubcore_msg.c b/drivers/ub/urma/ubcore/ubcore_msg.c index 478a557c7693..3e1dfcf41aaa 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.c +++ b/drivers/ub/urma/ubcore/ubcore_msg.c @@ -271,6 +271,11 @@ int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req) return -EINVAL; } + if (strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) == UBCORE_MAX_DEV_NAME) { + ubcore_log_err("Invalid dev_name.\n!"); + return -EINVAL; + } + if (req->req.opcode >= UBCORE_MSG_STOP_PROC_VTP_MSG) { handle_req = ubcore_migrate_req(dev, req); if (handle_req == NULL) { diff --git a/drivers/ub/urma/ubcore/ubcore_msg.h b/drivers/ub/urma/ubcore/ubcore_msg.h index 108de96ed7a9..9dddc78dbaad 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.h +++ b/drivers/ub/urma/ubcore/ubcore_msg.h @@ -24,6 +24,7 @@ #include enum ubcore_msg_resp_status { + UBCORE_MSG_RESP_LIMIT_RATE = -4, UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND = -3, UBCORE_MSG_RESP_IN_PROGRESS = -2, UBCORE_MSG_RESP_FAIL = -1, diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.c b/drivers/ub/urma/ubcore/ubcore_netdev.c index 2ed0c02e91d4..0a53bf9e114b 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.c +++ b/drivers/ub/urma/ubcore/ubcore_netdev.c @@ -143,8 +143,14 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, UBCORE_MAX_PORT_CNT); sip_req->prefix_len = sip_info->prefix_len; sip_req->mtu = sip_info->mtu; - (void)memcpy(sip_req->netdev_name, - sip_info->netdev_name, UBCORE_MAX_DEV_NAME); + + if (strnlen(sip_info->netdev_name, UBCORE_MAX_DEV_NAME) == UBCORE_MAX_DEV_NAME) { + ubcore_log_err("sip_info->netdev_name len is invalid"); + kfree(req_msg); + return -1; + } + + (void)memcpy(sip_req->netdev_name, sip_info->netdev_name, UBCORE_MAX_DEV_NAME); resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { @@ -325,7 +331,7 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, new_node->port_list[0] = (uint8_t)port_id; new_node->valid_list[0] = true; new_node->port_cnt = 1; - (void)strcpy(new_node->dev_name, dev->dev_name); + (void)memcpy(new_node->dev_name, dev->dev_name, sizeof(char) * UBCORE_MAX_DEV_NAME); down_write(&g_port_list_lock); list_add_tail(&new_node->node, &dev->port_list); up_write(&g_port_list_lock); diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.c b/drivers/ub/urma/ubcore/ubcore_netlink.c index 214778b339c9..b9aa123d051e 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.c +++ b/drivers/ub/urma/ubcore/ubcore_netlink.c @@ -136,7 +136,7 @@ static void ubcore_nl_handle_tp_resp(struct nlmsghdr *nlh) resp = ubcore_get_nlmsg_data(nlh); if (resp == NULL) { - ubcore_log_err("Failed to calloc and copy response"); + ubcore_log_err("Failed to calloc and copy response.\n"); return; } s = ubcore_find_nl_session(resp->nlmsg_seq); diff --git a/drivers/ub/urma/ubcore/ubcore_priv.h b/drivers/ub/urma/ubcore/ubcore_priv.h index fe44501355c5..a9bbd4147add 100644 --- a/drivers/ub/urma/ubcore/ubcore_priv.h +++ b/drivers/ub/urma/ubcore/ubcore_priv.h @@ -154,12 +154,9 @@ static inline uint32_t ubcore_get_rc_vtp_hash(union ubcore_eid *peer_eid) return jhash(peer_eid, sizeof(union ubcore_eid) + sizeof(uint32_t), 0); } -#define VTPN_KEY_SIZE (offsetof(struct ubcore_vtpn, eid_index) - \ - offsetof(struct ubcore_vtpn, trans_mode)) - -static inline uint32_t ubcore_get_vtpn_hash(enum ubcore_transport_mode *key_addr) +static inline uint32_t ubcore_get_vtpn_hash(struct ubcore_hash_table *ht, void *key_addr) { - return jhash(key_addr, VTPN_KEY_SIZE, 0); + return jhash(key_addr, ht->p.key_size, 0); } static inline bool ubcore_jfs_need_advise(struct ubcore_jfs *jfs) diff --git a/drivers/ub/urma/ubcore/ubcore_tp.c b/drivers/ub/urma/ubcore/ubcore_tp.c index 78c88cfaf2bd..e4b412f09947 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.c +++ b/drivers/ub/urma/ubcore/ubcore_tp.c @@ -1187,7 +1187,7 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, struct ubcore_tp *new_tp = NULL; struct ubcore_tp_cfg tp_cfg = { 0 }; - if (jetty == NULL || tjetty == NULL || advice == NULL || udata == NULL) { + if (jetty == NULL || tjetty == NULL || advice == NULL) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } @@ -1262,6 +1262,7 @@ int ubcore_unbind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, } EXPORT_SYMBOL(ubcore_unbind_tp); +/* udata may be empty because the data may come from the user space or kernel space. */ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, struct ubcore_tp_advice *advice, struct ubcore_udata *udata) { @@ -1270,7 +1271,7 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, struct ubcore_tp_node *tp_node; struct ubcore_tp *new_tp; - if (dev == NULL || remote_eid == NULL || advice == NULL || udata == NULL) { + if (dev == NULL || remote_eid == NULL || advice == NULL) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } diff --git a/drivers/ub/urma/ubcore/ubcore_utp.c b/drivers/ub/urma/ubcore/ubcore_utp.c index 362155d21165..8be3ac5eb9f0 100644 --- a/drivers/ub/urma/ubcore/ubcore_utp.c +++ b/drivers/ub/urma/ubcore/ubcore_utp.c @@ -34,7 +34,7 @@ static int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, return -1; } if (dev->ops->query_device_status(dev, &st) != 0) { - ubcore_log_err("Failed to query query_device_status for port %d", port_num); + ubcore_log_err("Failed to query query_device_status for port %hhu", port_num); return -1; } if (st.port_status[port_num].state != UBCORE_PORT_ACTIVE) { @@ -64,7 +64,7 @@ struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_ut ubcore_log_info("Global cfg not config, device mtu is %d", (int32_t)cfg->mtu); } - ubcore_log_info("Utp mtu config to %u", (int32_t)cfg->mtu); + ubcore_log_info("Utp mtu config to %u", (uint32_t)cfg->mtu); utp = dev->ops->create_utp(dev, cfg, NULL); if (utp == NULL) { diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c index db3c5967f888..b4e324ef71e1 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c @@ -60,8 +60,14 @@ static int ubcore_uvs_cmd_channel_init(struct ubcore_cmd_hdr *hdr) static void ubcore_set_tp_cfg_with_cmd(struct ubcore_tp_cfg *cfg, struct ubcore_cmd_tp_cfg *cmd) { cfg->flag = cmd->flag; - cfg->local_jetty = cmd->local_jetty; - cfg->peer_jetty = cmd->peer_jetty; + if (cmd->trans_mode == UBCORE_TP_RM) { + cfg->local_eid = cmd->local_eid; + cfg->peer_eid = cmd->peer_eid; + } else { + cfg->local_jetty = cmd->local_jetty; + cfg->peer_jetty = cmd->peer_jetty; + } + cfg->trans_mode = cmd->trans_mode; cfg->retry_num = cmd->retry_num; cfg->retry_factor = cmd->retry_factor; @@ -609,9 +615,10 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) goto to_user; } -to_user: ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_modify_tpg)); + +to_user: if (ret) ubcore_log_warn("ubcore cmd modify tpg to user failed"); if (rts_attr != NULL) @@ -1051,8 +1058,10 @@ static int ubcore_eidtbl_add_entry(struct ubcore_device *dev, union ubcore_eid * for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { if (memcmp(dev->eid_table.eid_entries[i].eid.raw, eid->raw, UBCORE_EID_SIZE) == 0) { ubcore_log_warn("eid already exists\n"); - break; + return 0; } + } + for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { if (dev->eid_table.eid_entries[i].valid == false) { dev->eid_table.eid_entries[i].eid = *eid; dev->eid_table.eid_entries[i].valid = true; @@ -1064,7 +1073,7 @@ static int ubcore_eidtbl_add_entry(struct ubcore_device *dev, union ubcore_eid * } } if (i == dev->attr.dev_cap.max_eid_cnt) { - ubcore_log_err("eid table is full"); + ubcore_log_err("eid table is full\n"); return -1; } return 0; @@ -1566,8 +1575,10 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) } utp = ubcore_create_utp(dev, &arg->in.utp_cfg); - if (utp == NULL) + if (utp == NULL) { + ret = -EPERM; goto put_device; + } ubcore_set_vtp2utp_cfg(&vtp_cfg, &arg->in.vtp, utp); vtp = ubcore_map_vtp(dev, &vtp_cfg); @@ -1621,8 +1632,10 @@ static int ubcore_cmd_only_create_utp(struct ubcore_cmd_hdr *hdr) } utp = ubcore_create_utp(dev, &arg->in.utp_cfg); - if (utp == NULL) + if (utp == NULL) { + ret = -EPERM; goto put_device; + } /* fill output */ arg->out.idx = utp->utpn; @@ -2493,7 +2506,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) ubcore_set_vtp2ctp_cfg(&vtp_cfg, &arg->in.vtp, ctp); } - vtp = ubcore_check_and_map_target_vtp(dev, &vtp_cfg); + vtp = ubcore_check_and_map_target_vtp(dev, &vtp_cfg, arg->in.role); if (vtp == NULL) { ret = -EPERM; goto put_device; diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.c b/drivers/ub/urma/ubcore/ubcore_vtp.c index 30f2feb02509..10f6a29033bf 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.c +++ b/drivers/ub/urma/ubcore/ubcore_vtp.c @@ -33,19 +33,25 @@ static int ubcore_handle_create_vtp_resp(struct ubcore_device *dev, struct ubcore_create_vtp_resp *vtp_resp = (struct ubcore_create_vtp_resp *)resp->data; struct ubcore_vtpn *vtpn = (struct ubcore_vtpn *)user_arg; - if (vtp_resp->ret == UBCORE_MSG_RESP_FAIL) { - ubcore_log_err("failed to create vtp: response error"); + switch (vtp_resp->ret) { + case UBCORE_MSG_RESP_FAIL: + ubcore_log_err("failed to create vtp: response error.\n"); return -1; - } else if (vtp_resp->ret == UBCORE_MSG_RESP_IN_PROGRESS) { - ubcore_log_err("failed: try to create vtp which is being created. Try again later"); + case UBCORE_MSG_RESP_IN_PROGRESS: + ubcore_log_err("failed to create vtp: response error.\n"); + return -1; + case UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND: + ubcore_log_err("failed: rc jetty already bind by other jetty.\n"); return -1; - } else if (vtp_resp->ret == UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND) { - ubcore_log_err("failed: rc jetty already bind by other jetty"); + case UBCORE_MSG_RESP_LIMIT_RATE: + ubcore_log_err("failed: the current link setup speed has reached the maximum value.\n"); return -1; + case UBCORE_MSG_RESP_SUCCESS: + default: + break; } /* tpf may return a new vtpn */ vtpn->vtpn = vtp_resp->vtpn; - atomic_set(&vtpn->state, (int)UBCORE_VTPS_READY); return 0; } @@ -86,7 +92,6 @@ static int ubcore_handle_del_vtp_resp(struct ubcore_device *dev, struct ubcore_resp *resp, void *user_arg) { struct ubcore_destroy_vtp_resp *vtp_resp = (struct ubcore_destroy_vtp_resp *)resp->data; - struct ubcore_vtpn *vtpn = (struct ubcore_vtpn *)user_arg; if (vtp_resp->ret == UBCORE_MSG_RESP_FAIL) { ubcore_log_err("failed to destroy vtp: response error"); @@ -95,7 +100,7 @@ static int ubcore_handle_del_vtp_resp(struct ubcore_device *dev, ubcore_log_err("failed: try to del vtp which is being created. Try again later"); return -1; } - atomic_set(&vtpn->state, (int)UBCORE_VTPS_DELETED); + return 0; } @@ -146,17 +151,39 @@ static struct ubcore_vtpn *ubcore_alloc_vtpn(struct ubcore_device *dev, } vtpn->ub_dev = dev; - atomic_set(&vtpn->use_cnt, 1); - atomic_set(&vtpn->state, (int)UBCORE_VTPS_CREATING); + atomic_set(&vtpn->use_cnt, 0); + kref_init(&vtpn->ref_cnt); + init_completion(&vtpn->comp); vtpn->trans_mode = param->trans_mode; vtpn->local_eid = param->local_eid; vtpn->peer_eid = param->peer_eid; vtpn->eid_index = param->eid_index; vtpn->local_jetty = param->local_jetty; vtpn->peer_jetty = param->peer_jetty; + vtpn->state = UBCORE_VTPS_RESET; + mutex_init(&vtpn->state_lock); return vtpn; } +static void ubcore_vtpn_kref_release(struct kref *ref_cnt) +{ + struct ubcore_vtpn *vtpn = container_of(ref_cnt, struct ubcore_vtpn, ref_cnt); + + complete(&vtpn->comp); +} + +static void ubcore_vtpn_kref_put(struct ubcore_vtpn *vtpn) +{ + (void)kref_put(&vtpn->ref_cnt, ubcore_vtpn_kref_release); +} + +void ubcore_vtpn_get(void *obj) +{ + struct ubcore_vtpn *vtpn = obj; + + kref_get(&vtpn->ref_cnt); +} + static int ubcore_free_vtpn(struct ubcore_vtpn *vtpn) { struct ubcore_device *dev = vtpn->ub_dev; @@ -166,204 +193,198 @@ static int ubcore_free_vtpn(struct ubcore_vtpn *vtpn) return -EINVAL; } - if (atomic_dec_return(&vtpn->use_cnt) > 0) { + if (atomic_read(&vtpn->use_cnt) > 0) { ubcore_log_info("vtpn in use, vtpn id = %u, vtpn use_cnt = %d", vtpn->vtpn, atomic_read(&vtpn->use_cnt)); return 0; } - atomic_set(&vtpn->state, (int)UBCORE_VTPS_DELETED); - + ubcore_vtpn_kref_put(vtpn); + wait_for_completion(&vtpn->comp); + mutex_destroy(&vtpn->state_lock); return dev->ops->free_vtpn(vtpn); } -static int ubcore_find_add_vtpn(struct ubcore_device *dev, - struct ubcore_vtpn *new_vtpn, struct ubcore_vtpn **exist_vtpn) +static struct ubcore_hash_table *ubcore_get_vtpn_ht(struct ubcore_device *dev, + enum ubcore_transport_mode trans_mode) { - struct ubcore_hash_table *ht; - - ht = &dev->ht[UBCORE_HT_VTPN]; - if (ht->head == NULL) { - ubcore_log_err("hash table's head equals NULL"); - return -EINVAL; - } + if (trans_mode == UBCORE_TP_RM) + return &dev->ht[UBCORE_HT_RM_VTPN]; - *exist_vtpn = ubcore_hash_table_lookup_nolock(ht, - ubcore_get_vtpn_hash(&new_vtpn->trans_mode), &new_vtpn->trans_mode); - if (*exist_vtpn != NULL) - return -EEXIST; + if (trans_mode == UBCORE_TP_RC) + return &dev->ht[UBCORE_HT_RC_VTPN]; - ubcore_hash_table_add_nolock(ht, &new_vtpn->hnode, - ubcore_get_vtpn_hash(&new_vtpn->trans_mode)); + if (trans_mode == UBCORE_TP_UM) + return &dev->ht[UBCORE_HT_UM_VTPN]; - return 0; + return NULL; } -static struct ubcore_vtpn *ubcore_connect_rm_um_vtp(struct ubcore_device *dev, +static struct ubcore_vtpn *ubcore_find_vtpn(struct ubcore_device *dev, struct ubcore_vtp_param *param) { - struct ubcore_vtpn *exist_vtpn; struct ubcore_hash_table *ht; - struct ubcore_vtpn *new_vtpn; - struct ubcore_vtpn *old_vtpn; - int ret; - - ht = &dev->ht[UBCORE_HT_VTPN]; - /* reuse */ + uint32_t hash; - spin_lock(&ht->lock); - old_vtpn = ubcore_hash_table_lookup_nolock(ht, ubcore_get_vtpn_hash(¶m->trans_mode), - ¶m->trans_mode); - if (old_vtpn != NULL && atomic_read(&old_vtpn->state) == (int)UBCORE_VTPS_READY) { - atomic_inc(&old_vtpn->use_cnt); - ubcore_log_info("reuse vtpn, with vtpn id = %u, use cnt = %d", - old_vtpn->vtpn, atomic_read(&old_vtpn->use_cnt)); - spin_unlock(&ht->lock); - return old_vtpn; - } else if (old_vtpn != NULL && atomic_read(&old_vtpn->state) == (int)UBCORE_VTPS_CREATING) { - ubcore_log_info("vtpn is already in the list but its creation hasn't completed yet"); - spin_unlock(&ht->lock); + ht = ubcore_get_vtpn_ht(dev, param->trans_mode); + if (ht == NULL) return NULL; - } - if (old_vtpn != NULL) - ubcore_log_warn("found existed vtpn state = %u and use_cnt = %u", - (uint32_t)atomic_read(&old_vtpn->state), - (uint32_t)atomic_read(&old_vtpn->use_cnt)); + hash = ubcore_get_vtpn_hash(ht, ¶m->local_eid); + return ubcore_hash_table_lookup_get(ht, hash, ¶m->local_eid); +} - new_vtpn = ubcore_alloc_vtpn(dev, param); - if (new_vtpn == NULL) { - ubcore_log_err("failed to alloc vtpn!"); - spin_unlock(&ht->lock); - return NULL; - } +static int ubcore_find_add_vtpn(struct ubcore_device *dev, + struct ubcore_vtpn *new_vtpn, struct ubcore_vtpn **exist_vtpn) +{ + struct ubcore_hash_table *ht; + uint32_t hash; - /* Conncurrency: only one thread can add vtpn to table successfully */ - ret = ubcore_find_add_vtpn(dev, new_vtpn, &exist_vtpn); - if (ret == -EINVAL) { - (void)ubcore_free_vtpn(new_vtpn); - new_vtpn = NULL; - spin_unlock(&ht->lock); - return NULL; - } else if (ret == -EEXIST) { - (void)ubcore_free_vtpn(new_vtpn); - new_vtpn = NULL; - - if (atomic_read(&exist_vtpn->state) == (int)UBCORE_VTPS_READY) { - atomic_inc(&exist_vtpn->use_cnt); - ubcore_log_info("success to reuse the vtpn %u, it is ready, reuse cnt %d", - exist_vtpn->vtpn, atomic_read(&exist_vtpn->use_cnt)); - } else { - exist_vtpn = NULL; - ubcore_log_err("failed to reuse the vtpn, it is not ready"); - } + ht = ubcore_get_vtpn_ht(dev, new_vtpn->trans_mode); + if (ht == NULL || ht->head == NULL) { + ubcore_log_err("hash table's head equals NULL"); + return -EINVAL; + } + hash = ubcore_get_vtpn_hash(ht, &new_vtpn->local_eid); + spin_lock(&ht->lock); + *exist_vtpn = ubcore_hash_table_lookup_nolock_get(ht, hash, &new_vtpn->local_eid); + if (*exist_vtpn != NULL) { spin_unlock(&ht->lock); - return exist_vtpn; + return -EEXIST; } + ubcore_hash_table_add_nolock(ht, &new_vtpn->hnode, hash); + ubcore_vtpn_kref_put(new_vtpn); + spin_unlock(&ht->lock); + return 0; +} - /* TODO: port_idx use 0, for now tp_cnt = 1 */ - if (ubcore_check_port_state(dev, 0) != 0 || - ubcore_send_create_vtp_req(dev, param, new_vtpn) != 0) { - ubcore_hash_table_remove_nolock(ht, &new_vtpn->hnode); - (void)ubcore_free_vtpn(new_vtpn); - ubcore_log_err("failed to send create vtp req"); - spin_unlock(&ht->lock); +void ubcore_hash_table_rmv_vtpn(struct ubcore_device *dev, struct ubcore_vtpn *vtpn) +{ + struct ubcore_hash_table *ht; + + ht = ubcore_get_vtpn_ht(dev, vtpn->trans_mode); + if (ht == NULL) + return; + ubcore_hash_table_remove(ht, &vtpn->hnode); +} + +static struct ubcore_vtpn *ubcore_reuse_vtpn(struct ubcore_device *dev, struct ubcore_vtpn *vtpn) +{ + mutex_lock(&vtpn->state_lock); + if (vtpn->state == UBCORE_VTPS_READY) { + atomic_inc(&vtpn->use_cnt); + mutex_unlock(&vtpn->state_lock); + ubcore_log_info("Success to reuse vtpn:%u", vtpn->vtpn); + ubcore_vtpn_kref_put(vtpn); + return vtpn; + } + + if (vtpn->state == UBCORE_VTPS_RESET) { + mutex_unlock(&vtpn->state_lock); + ubcore_log_warn("failed to reuse vtpn:%u, use_cnt:%d", + vtpn->vtpn, atomic_read(&vtpn->use_cnt)); + ubcore_vtpn_kref_put(vtpn); return NULL; } - spin_unlock(&ht->lock); - return new_vtpn; + mutex_unlock(&vtpn->state_lock); + ubcore_log_err("Unknown states, vtpn:%u, state:%d", + vtpn->vtpn, (int)vtpn->state); + ubcore_vtpn_kref_put(vtpn); + return NULL; } struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *param) { + struct ubcore_vtpn *exist_vtpn = NULL; struct ubcore_vtpn *vtpn; + int ret; if (dev == NULL || param == NULL) { ubcore_log_err("Invalid param"); return NULL; } - if (param->trans_mode == UBCORE_TP_RM || param->trans_mode == UBCORE_TP_UM) - return ubcore_connect_rm_um_vtp(dev, param); + if (ubcore_check_port_state(dev, 0) != 0) { + ubcore_log_err("Check port status Failed"); + return NULL; + } + + // 1. try to reuse vtpn + vtpn = ubcore_find_vtpn(dev, param); + if (vtpn != NULL) + return ubcore_reuse_vtpn(dev, vtpn); + // 2. alloc new vtpn vtpn = ubcore_alloc_vtpn(dev, param); - if (vtpn == NULL) + if (vtpn == NULL) { + ubcore_log_err("failed to alloc vtpn!"); return NULL; + } + + // 3. add vtpn to hashtable + ret = ubcore_find_add_vtpn(dev, vtpn, &exist_vtpn); + if (ret == -EEXIST && exist_vtpn != NULL) { + exist_vtpn = ubcore_reuse_vtpn(dev, exist_vtpn); // reuse immediately + (void)ubcore_free_vtpn(vtpn); + return exist_vtpn; + } else if (ret != 0) { + (void)ubcore_free_vtpn(vtpn); + return NULL; + } - if (ubcore_check_port_state(dev, 0) != 0 || ubcore_send_create_vtp_req(dev, param, vtpn)) { + // 4. Send connecting msg + mutex_lock(&vtpn->state_lock); + ret = ubcore_send_create_vtp_req(dev, param, vtpn); + if (ret == 0) { + atomic_inc(&vtpn->use_cnt); + vtpn->state = UBCORE_VTPS_READY; + } + mutex_unlock(&vtpn->state_lock); + + // 5. failed roll back + if (ret != 0) { + ubcore_log_err("failed to send create vtp req, vtpn:%u", vtpn->vtpn); + ubcore_hash_table_rmv_vtpn(dev, vtpn); (void)ubcore_free_vtpn(vtpn); - ubcore_log_err("failed to send create vtp req"); return NULL; } + + ubcore_log_info("connect vtpn:%u", vtpn->vtpn); return vtpn; } -static int ubcore_disconnect_rm_um_vtp(struct ubcore_vtpn *vtpn) +int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn) { - struct ubcore_device *dev = vtpn->ub_dev; - int ret; + struct ubcore_device *dev; + int ret = 0; - if (vtpn->ub_dev == NULL) + if (vtpn == NULL || vtpn->ub_dev == NULL) return -EINVAL; + dev = vtpn->ub_dev; if (atomic_dec_return(&vtpn->use_cnt) > 0) { ubcore_log_info("vtpn in use, vtpn id = %u, vtpn use_cnt = %d", vtpn->vtpn, atomic_read(&vtpn->use_cnt)); return 0; } - if (atomic_read(&vtpn->state) != UBCORE_VTPS_READY) { - ubcore_log_err("vtpn state is not in ready state, it is in %d state", - atomic_read(&vtpn->state)); - return -1; - } - atomic_set(&vtpn->state, (int)UBCORE_VTPS_DELETING); - - ret = ubcore_send_del_vtp_req(vtpn); - if (ret != 0) { - ubcore_log_err("failed to send del vtp req"); - atomic_set(&vtpn->state, (int)UBCORE_VTPS_READY); - return ret; - } - - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_VTPN], &vtpn->hnode); - - ret = ubcore_free_vtpn(vtpn); - if (ret != 0) { - ubcore_hash_table_add(&vtpn->ub_dev->ht[UBCORE_HT_VTPN], &vtpn->hnode, - ubcore_get_vtpn_hash(&vtpn->trans_mode)); - ubcore_log_err("failed to free vtp"); - /* TODO roll back, start connect_vtp process again */ - return ret; - } - - return 0; -} - -int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn) -{ - int ret; - - if (vtpn == NULL) { - ubcore_log_err("vtp has been deleted\n"); - return -1; + mutex_lock(&vtpn->state_lock); + if (atomic_read(&vtpn->use_cnt) > 0) { + mutex_unlock(&vtpn->state_lock); + return 0; } - - if (vtpn->trans_mode == UBCORE_TP_RM || vtpn->trans_mode == UBCORE_TP_UM) - return ubcore_disconnect_rm_um_vtp(vtpn); - - ret = ubcore_send_del_vtp_req(vtpn); - if (ret != 0) { - ubcore_log_err("failed to send del vtp req"); - return ret; + if (vtpn->state == UBCORE_VTPS_READY) { + ret = ubcore_send_del_vtp_req(vtpn); + vtpn->state = UBCORE_VTPS_RESET; } + mutex_unlock(&vtpn->state_lock); - ret = ubcore_free_vtpn(vtpn); - if (ret != 0) { - ubcore_log_err("failed to free vtp"); - return ret; + ubcore_log_info("disconnect vtpn:%u, ret:%d", vtpn->vtpn, ret); + if (atomic_read(&vtpn->use_cnt) == 0) { + ubcore_hash_table_rmv_vtpn(dev, vtpn); + (void)ubcore_free_vtpn(vtpn); } return 0; @@ -464,23 +485,24 @@ int ubcore_unmap_vtp(struct ubcore_vtp *vtp) ubcore_remove_vtp(dev, cfg.trans_mode, vtp); - if (vtp->cfg.vtpn == UINT_MAX) + if (vtp->cfg.vtpn == UINT_MAX) { kfree(vtp); - else + } else { ret = dev->ops->destroy_vtp(vtp); - if (ret != 0) { - (void)ubcore_find_add_vtp(dev, cfg.trans_mode, vtp); - ubcore_log_err("Failed to destroy vtp"); - return ret; - } + if (ret != 0) { + (void)ubcore_find_add_vtp(dev, cfg.trans_mode, vtp); + ubcore_log_err("Failed to destroy vtp"); + return ret; + } - if (cfg.flag.bs.clan_tp) { - atomic_dec(&cfg.ctp->use_cnt); - } else { - if (cfg.trans_mode != UBCORE_TP_UM) - atomic_dec(&cfg.tpg->use_cnt); - else - atomic_dec(&cfg.utp->use_cnt); + if (cfg.flag.bs.clan_tp) { + atomic_dec(&cfg.ctp->use_cnt); + } else { + if (cfg.trans_mode != UBCORE_TP_UM) + atomic_dec(&cfg.tpg->use_cnt); + else + atomic_dec(&cfg.utp->use_cnt); + } } return ret; @@ -513,6 +535,7 @@ int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role) new_vtp->ub_dev = dev; new_vtp->role = UBCORE_VTP_TARGET; (void)memcpy(&new_vtp->cfg, &vtp->cfg, sizeof(struct ubcore_vtp_cfg)); + new_vtp->cfg.vtpn = UINT_MAX; ubcore_remove_vtp(dev, cfg.trans_mode, vtp); ret = dev->ops->destroy_vtp(vtp); @@ -523,17 +546,17 @@ int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role) return ret; } + if (cfg.flag.bs.clan_tp) { + atomic_dec(&cfg.ctp->use_cnt); + } else { + if (cfg.trans_mode != UBCORE_TP_UM) + atomic_dec(&cfg.tpg->use_cnt); + else + atomic_dec(&cfg.utp->use_cnt); + } ret = ubcore_find_add_vtp(dev, new_vtp->cfg.trans_mode, new_vtp); if (ret != 0) { kfree(new_vtp); - if (cfg.flag.bs.clan_tp) { - atomic_dec(&cfg.ctp->use_cnt); - } else { - if (cfg.trans_mode != UBCORE_TP_UM) - atomic_dec(&cfg.tpg->use_cnt); - else - atomic_dec(&cfg.utp->use_cnt); - } ubcore_log_err("Failed to add new vtp to the vtp table"); return -1; } @@ -706,7 +729,7 @@ struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ub } struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, - struct ubcore_vtp_cfg *cfg) + struct ubcore_vtp_cfg *cfg, uint32_t role) { struct ubcore_vtp *vtp = NULL; int ret; @@ -721,6 +744,7 @@ struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, vtp->ub_dev = dev; (void)memcpy(&vtp->cfg, cfg, sizeof(struct ubcore_vtp_cfg)); + vtp->role = role; ret = ubcore_find_add_vtp(dev, cfg->trans_mode, vtp); if (ret != 0) { @@ -730,15 +754,6 @@ struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, return vtp; } - if (cfg->flag.bs.clan_tp) { - atomic_inc(&cfg->ctp->use_cnt); - } else { - if (cfg->trans_mode != UBCORE_TP_UM) - atomic_inc(&cfg->tpg->use_cnt); - else - atomic_inc(&cfg->utp->use_cnt); - } - return vtp; } diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.h b/drivers/ub/urma/ubcore/ubcore_vtp.h index dd05c282cdaa..947068153341 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.h +++ b/drivers/ub/urma/ubcore/ubcore_vtp.h @@ -33,12 +33,12 @@ struct ubcore_vtp_param { enum ubcore_transport_mode trans_mode; - /* RM vtpn key start */ + /* vtpn key start */ union ubcore_eid local_eid; union ubcore_eid peer_eid; - /* RM vtpn key end */ uint32_t local_jetty; uint32_t peer_jetty; + /* vtpn key end */ uint32_t eid_index; /* for alpha */ struct ubcore_ta ta; @@ -106,7 +106,7 @@ struct ubcore_vtp *ubcore_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_c struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg, uint32_t role); struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, - struct ubcore_vtp_cfg *cfg); + struct ubcore_vtp_cfg *cfg, uint32_t role); int ubcore_unmap_vtp(struct ubcore_vtp *vtp); int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role); /* find mapped vtp */ @@ -126,4 +126,5 @@ uint32_t ubcore_get_all_vtp_cnt(struct ubcore_hash_table *ht); struct ubcore_vtp **ubcore_get_all_vtp(struct ubcore_hash_table *ht, uint32_t *dev_vtp_cnt); +void ubcore_vtpn_get(void *obj); #endif diff --git a/drivers/ub/urma/uburma/uburma_cmd.c b/drivers/ub/urma/uburma/uburma_cmd.c index 1d875f76e5e9..5912f5a99187 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.c +++ b/drivers/ub/urma/uburma/uburma_cmd.c @@ -1737,6 +1737,7 @@ static int uburma_cmd_create_jetty_grp(struct ubcore_device *ubc_dev, cfg.token_value.token = arg.in.token; cfg.id = arg.in.id; cfg.policy = (enum ubcore_jetty_grp_policy)arg.in.policy; + cfg.flag.value = arg.in.flag; cfg.eid_index = file->ucontext->eid_index; fill_udata(&udata, file->ucontext, &arg.udata); diff --git a/drivers/ub/urma/uburma/uburma_cmd.h b/drivers/ub/urma/uburma/uburma_cmd.h index 998c5acdfab0..903354c8e731 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.h +++ b/drivers/ub/urma/uburma/uburma_cmd.h @@ -501,6 +501,7 @@ struct uburma_cmd_create_jetty_grp { uint32_t token; uint32_t id; uint32_t policy; + uint32_t flag; uint64_t urma_jetty_grp; /* urma jetty group pointer */ } in; struct { diff --git a/include/urma/ubcore_opcode.h b/include/urma/ubcore_opcode.h index 85e3490ef67b..31c2048a1f45 100644 --- a/include/urma/ubcore_opcode.h +++ b/include/urma/ubcore_opcode.h @@ -102,7 +102,9 @@ enum ubcore_cr_status { // completion record status UBCORE_CR_FLUSH_ERR, UBCORE_CR_WR_SUSPEND_DONE, UBCORE_CR_WR_FLUSH_ERR_DONE, - UBCORE_CR_WR_UNHANDLED + UBCORE_CR_WR_UNHANDLED, + UBCORE_CR_LOC_DATA_POISON, + UBCORE_CR_REM_DATA_POISON }; /* Must be consistent with urma_cr_opcode_t */ diff --git a/include/urma/ubcore_types.h b/include/urma/ubcore_types.h index 7a56c6e6fcef..b816c553d4e7 100644 --- a/include/urma/ubcore_types.h +++ b/include/urma/ubcore_types.h @@ -22,6 +22,7 @@ #ifndef UBCORE_TYPES_H #define UBCORE_TYPES_H +#include #include #include #include @@ -153,6 +154,7 @@ struct ubcore_ht_param { uint32_t key_size; int (*cmp_f)(void *obj, const void *key); void (*free_f)(void *obj); + void (*get_f)(void *obj); }; struct ubcore_hash_table { @@ -274,13 +276,13 @@ union ubcore_import_seg_flag { union ubcore_reg_seg_flag { struct { - uint32_t token_policy : 3; + uint32_t token_policy : 3; uint32_t cacheable : 1; uint32_t dsva : 1; uint32_t access : 6; uint32_t non_pin : 1; uint32_t user_iova : 1; - uint32_t token_id_valid : 1; + uint32_t token_id_valid : 1; uint32_t reserved : 18; } bs; uint32_t value; @@ -817,6 +819,7 @@ struct ubcore_tp { union ubcore_tp_flag flag; /* indicate initiator or target, etc */ uint32_t local_net_addr_idx; struct ubcore_net_addr peer_net_addr; + /* only for RC START */ union { union ubcore_eid local_eid; struct ubcore_jetty_id local_jetty; @@ -825,6 +828,7 @@ struct ubcore_tp { union ubcore_eid peer_eid; struct ubcore_jetty_id peer_jetty; }; + /* only for RC END */ enum ubcore_transport_mode trans_mode; enum ubcore_tp_state state; uint32_t rx_psn; @@ -930,27 +934,28 @@ struct ubcore_ctp { }; enum ubcore_vtp_state { - UBCORE_VTPS_CREATING = 0, - UBCORE_VTPS_READY, - UBCORE_VTPS_DELETING, - UBCORE_VTPS_DELETED + UBCORE_VTPS_RESET = 0, + UBCORE_VTPS_READY = 1 }; struct ubcore_vtpn { uint32_t vtpn; /* driver fills */ struct ubcore_device *ub_dev; /* ubcore private, inaccessible to driver */ - /* vtpn key start */ enum ubcore_transport_mode trans_mode; + /* vtpn key start */ union ubcore_eid local_eid; union ubcore_eid peer_eid; - /* vtpn key end */ - uint32_t eid_index; /* next of vtpn key. if modifed, should update VTPN_KEY_SIZE */ uint32_t local_jetty; uint32_t peer_jetty; - atomic_t state; + /* vtpn key end */ + uint32_t eid_index; + struct mutex state_lock; + enum ubcore_vtp_state state; /* protect by state_lock */ struct hlist_node hnode; atomic_t use_cnt; + struct kref ref_cnt; + struct completion comp; }; union ubcore_vtp_cfg_flag { @@ -2307,7 +2312,9 @@ enum ubcore_hash_table_type { UBCORE_HT_RM_VTP, /* rm vtp table */ UBCORE_HT_RC_VTP, /* rc vtp table */ UBCORE_HT_UM_VTP, /* um vtp table */ - UBCORE_HT_VTPN, /* vtpn table */ + UBCORE_HT_RM_VTPN, /* rm vtpn table */ + UBCORE_HT_RC_VTPN, /* rc vtpn table */ + UBCORE_HT_UM_VTPN, /* um vtpn table */ UBCORE_HT_UTP, /* utp table */ UBCORE_HT_CTP, /* ctp table */ UBCORE_HT_NUM -- Gitee From 6d14be01fcb032c478cd4669b32526fda0393195 Mon Sep 17 00:00:00 2001 From: WenChen Date: Fri, 17 May 2024 18:39:40 +0800 Subject: [PATCH 3/6] urma: upload kernel patch for 20240318_happy_birthday driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I91DSN CVE: NA -------------------------------- Upload kernel patch for 20240318_happy_birthday, detailed fixes are as follows: 1. Modify urma_tjetty_cfg_t and urma_tjfr_cfg_t. 2. Rmv delete ctx, use close fd 3. Fix mutex lock competition long-term blocking 4. Rearrange order of function call of uobj_fd_alloc_commit 5. Add uvs_admin query_res 6. Fix perftest bug Fixes: 329bf7f33128 ("ubcore: fix the bug of tp negotiation concurrency") Signed-off-by: WenChen Signed-off-by: Jie Lei Signed-off-by: Weibo Zhao --- drivers/ub/hw/hns3/hns3_udma_dfx.c | 620 +++++++------- drivers/ub/hw/hns3/hns3_udma_jetty.c | 2 +- drivers/ub/hw/hns3/hns3_udma_jfr.c | 2 +- drivers/ub/hw/hns3/hns3_udma_jfs.c | 3 +- drivers/ub/urma/ubcore/ubcore_cdev_file.c | 192 ++--- drivers/ub/urma/ubcore/ubcore_cdev_file.h | 13 - drivers/ub/urma/ubcore/ubcore_cmd.h | 26 +- drivers/ub/urma/ubcore/ubcore_ctp.c | 62 +- drivers/ub/urma/ubcore/ubcore_ctp.h | 4 + drivers/ub/urma/ubcore/ubcore_device.c | 673 ++++++++++----- drivers/ub/urma/ubcore/ubcore_device.h | 7 +- drivers/ub/urma/ubcore/ubcore_genl.c | 67 +- drivers/ub/urma/ubcore/ubcore_genl_admin.c | 652 +++++++-------- drivers/ub/urma/ubcore/ubcore_genl_admin.h | 9 +- drivers/ub/urma/ubcore/ubcore_genl_define.h | 8 + drivers/ub/urma/ubcore/ubcore_hash_table.c | 4 +- drivers/ub/urma/ubcore/ubcore_jetty.c | 282 ++++--- drivers/ub/urma/ubcore/ubcore_main.c | 214 ++--- drivers/ub/urma/ubcore/ubcore_msg.c | 97 ++- drivers/ub/urma/ubcore/ubcore_msg.h | 28 +- drivers/ub/urma/ubcore/ubcore_netdev.c | 154 ++-- drivers/ub/urma/ubcore/ubcore_netdev.h | 10 +- drivers/ub/urma/ubcore/ubcore_netlink.c | 423 ++++++---- drivers/ub/urma/ubcore/ubcore_netlink.h | 87 +- drivers/ub/urma/ubcore/ubcore_priv.h | 21 +- drivers/ub/urma/ubcore/ubcore_segment.c | 31 +- drivers/ub/urma/ubcore/ubcore_tp.c | 598 +++----------- drivers/ub/urma/ubcore/ubcore_tp.h | 4 +- drivers/ub/urma/ubcore/ubcore_tp_table.c | 31 +- drivers/ub/urma/ubcore/ubcore_tp_table.h | 2 - drivers/ub/urma/ubcore/ubcore_tpg.c | 218 ++++- drivers/ub/urma/ubcore/ubcore_tpg.h | 10 + drivers/ub/urma/ubcore/ubcore_umem.c | 14 +- drivers/ub/urma/ubcore/ubcore_utp.c | 76 +- drivers/ub/urma/ubcore/ubcore_utp.h | 6 + drivers/ub/urma/ubcore/ubcore_uvs_cmd.c | 858 +++++++++++++------- drivers/ub/urma/ubcore/ubcore_uvs_cmd.h | 82 +- drivers/ub/urma/ubcore/ubcore_vtp.c | 307 ++++--- drivers/ub/urma/ubcore/ubcore_vtp.h | 18 +- drivers/ub/urma/ubcore/ubcore_workqueue.c | 3 +- drivers/ub/urma/uburma/uburma_cmd.c | 107 +-- drivers/ub/urma/uburma/uburma_cmd.h | 2 +- drivers/ub/urma/uburma/uburma_event.c | 43 +- drivers/ub/urma/uburma/uburma_uobj.c | 9 +- drivers/ub/urma/uburma/uburma_uobj.h | 3 + include/urma/ubcore_api.h | 22 +- include/urma/ubcore_jetty.h | 35 + include/urma/ubcore_types.h | 168 ++-- include/urma/ubcore_uapi.h | 11 +- 49 files changed, 3547 insertions(+), 2771 deletions(-) create mode 100644 include/urma/ubcore_jetty.h diff --git a/drivers/ub/hw/hns3/hns3_udma_dfx.c b/drivers/ub/hw/hns3/hns3_udma_dfx.c index f89226edf544..d240f43a7332 100644 --- a/drivers/ub/hw/hns3/hns3_udma_dfx.c +++ b/drivers/ub/hw/hns3/hns3_udma_dfx.c @@ -358,6 +358,280 @@ int udma_find_dfx_dev(struct udma_dev *udma_dev, int *num) return -EINVAL; } +static int udma_query_res_tp_list(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) +{ + struct ubcore_res_list_val *res_list = (struct ubcore_res_list_val *)val->addr; + struct tpn_list *tpn_now; + uint32_t *tp_list; + uint32_t tpn_cnt; + int ret; + int i; + + res_list->cnt = 0; + + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; + + spin_lock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); + tpn_cnt = g_udma_dfx_list[i].dfx->tpn_cnt; + if (tpn_cnt == 0) { + spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return 0; + } + + tp_list = vmalloc(sizeof(*tp_list) * tpn_cnt); + if (!tp_list) { + spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return -ENOMEM; + } + + list_for_each_entry(tpn_now, + &g_udma_dfx_list[i].dfx->tpn_list->node, node) { + tp_list[res_list->cnt] = tpn_now->tpn; + res_list->cnt++; + } + spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + + res_list->list = tp_list; + + return 0; +} + +static int udma_query_res_jfs_list(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) +{ + struct ubcore_res_list_val *res_list = (struct ubcore_res_list_val *)val->addr; + struct jfs_list *jfs_now; + uint32_t *jfs_list; + uint32_t jfs_cnt; + int ret; + int i; + + res_list->cnt = 0; + + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; + + spin_lock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); + jfs_cnt = g_udma_dfx_list[i].dfx->jfs_cnt; + if (jfs_cnt == 0) { + spin_unlock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return 0; + } + + jfs_list = vmalloc(sizeof(*jfs_list) * jfs_cnt); + if (!jfs_list) { + spin_unlock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return -ENOMEM; + } + + list_for_each_entry(jfs_now, + &g_udma_dfx_list[i].dfx->jfs_list->node, node) { + jfs_list[res_list->cnt] = jfs_now->jfs_id; + res_list->cnt++; + } + spin_unlock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + + res_list->list = jfs_list; + + return 0; +} + +static int udma_query_res_jfr_list(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) +{ + struct ubcore_res_list_val *res_list = (struct ubcore_res_list_val *)val->addr; + struct jfr_list *jfr_now; + uint32_t *jfr_list; + uint32_t jfr_cnt; + int ret; + int i; + + res_list->cnt = 0; + + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; + + spin_lock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); + jfr_cnt = g_udma_dfx_list[i].dfx->jfr_cnt; + if (jfr_cnt == 0) { + spin_unlock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return 0; + } + + jfr_list = vmalloc(sizeof(*jfr_list) * jfr_cnt); + if (!jfr_list) { + spin_unlock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return -ENOMEM; + } + + list_for_each_entry(jfr_now, + &g_udma_dfx_list[i].dfx->jfr_list->node, node) { + jfr_list[res_list->cnt] = jfr_now->jfr_id; + res_list->cnt++; + } + spin_unlock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + + res_list->list = jfr_list; + + return 0; +} + +static int udma_query_res_jetty_list(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) +{ + struct ubcore_res_list_val *res_list = (struct ubcore_res_list_val *)val->addr; + struct jetty_list *jetty_now; + uint32_t *jetty_list; + uint32_t jetty_cnt; + int ret; + int i; + + res_list->cnt = 0; + + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; + + spin_lock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); + jetty_cnt = g_udma_dfx_list[i].dfx->jetty_cnt; + if (jetty_cnt == 0) { + spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return 0; + } + + jetty_list = vmalloc(sizeof(*jetty_list) * jetty_cnt); + if (!jetty_list) { + spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return -ENOMEM; + } + + list_for_each_entry(jetty_now, + &g_udma_dfx_list[i].dfx->jetty_list->node, node) { + jetty_list[res_list->cnt] = jetty_now->jetty_id; + res_list->cnt++; + } + spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + + res_list->list = jetty_list; + + return 0; +} + +static int udma_query_res_jfc_list(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) +{ + struct ubcore_res_list_val *res_list = (struct ubcore_res_list_val *)val->addr; + struct jfc_list *jfc_now; + uint32_t *jfc_list; + uint32_t jfc_cnt; + int ret; + int i; + + res_list->cnt = 0; + + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; + + spin_lock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); + jfc_cnt = g_udma_dfx_list[i].dfx->jfc_cnt; + if (jfc_cnt == 0) { + spin_unlock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return 0; + } + + jfc_list = vmalloc(sizeof(*jfc_list) * jfc_cnt); + if (!jfc_list) { + spin_unlock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return -ENOMEM; + } + + list_for_each_entry(jfc_now, + &g_udma_dfx_list[i].dfx->jfc_list->node, node) { + jfc_list[res_list->cnt] = jfc_now->jfc_id; + res_list->cnt++; + } + spin_unlock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + + res_list->list = jfc_list; + + return 0; +} + +static int udma_query_res_seg_list(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) +{ + struct ubcore_res_seg_val *res_list = (struct ubcore_res_seg_val *)val->addr; + struct ubcore_seg_info *seg_list; + struct seg_list *seg_now; + uint32_t seg_cnt; + int ret; + int i; + + res_list->seg_cnt = 0; + + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; + + spin_lock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); + seg_cnt = g_udma_dfx_list[i].dfx->seg_cnt; + if (seg_cnt == 0) { + spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return 0; + } + + seg_list = vmalloc(sizeof(*seg_list) * seg_cnt); + if (!seg_list) { + spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + return -ENOMEM; + } + + list_for_each_entry(seg_now, + &g_udma_dfx_list[i].dfx->seg_list->node, node) { + memcpy(&seg_list[res_list->seg_cnt].ubva.eid, &seg_now->eid, + sizeof(union ubcore_eid)); + seg_list[res_list->seg_cnt].ubva.va = seg_now->iova; + seg_list[res_list->seg_cnt].len = seg_now->len; + seg_list[res_list->seg_cnt].token_id = seg_now->key_id; + res_list->seg_cnt++; + } + spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); + + res_list->seg_list = seg_list; + + return 0; +} + static enum ubcore_tp_state to_ubcore_tp_state(enum udma_qp_state state) { switch (state) { @@ -382,6 +656,9 @@ static int udma_query_res_tp(struct udma_dev *udma_dev, struct udma_qp_context qp_context; int ret; + if (key->key_cnt == 0) + return udma_query_res_tp_list(udma_dev, key, val); + ret = udma_dfx_query_context(udma_dev, key->key, &qp_context, sizeof(qp_context), UDMA_CMD_QUERY_QPC); if (ret) { @@ -415,6 +692,9 @@ static int udma_query_res_jfs(struct udma_dev *udma_dev, int ret; int i; + if (key->key_cnt == 0) + return udma_query_res_jfs_list(udma_dev, key, val); + ret = udma_find_dfx_dev(udma_dev, &i); if (ret) return ret; @@ -450,6 +730,9 @@ static int udma_query_res_jfr(struct udma_dev *udma_dev, int ret; int i; + if (key->key_cnt == 0) + return udma_query_res_jfr_list(udma_dev, key, val); + ret = udma_find_dfx_dev(udma_dev, &i); if (ret) return ret; @@ -494,6 +777,9 @@ static int udma_query_res_jetty(struct udma_dev *udma_dev, int ret; int i; + if (key->key_cnt == 0) + return udma_query_res_jetty_list(udma_dev, key, val); + ret = udma_find_dfx_dev(udma_dev, &i); if (ret) return ret; @@ -527,6 +813,9 @@ static int udma_query_res_jfc(struct udma_dev *udma_dev, struct udma_jfc_context jfc_context; int ret; + if (key->key_cnt == 0) + return udma_query_res_jfc_list(udma_dev, key, val); + ret = udma_dfx_query_context(udma_dev, key->key, &jfc_context, sizeof(jfc_context), UDMA_CMD_QUERY_CQC); if (ret) { @@ -553,6 +842,9 @@ static int udma_query_res_seg(struct udma_dev *udma_dev, struct ubcore_res_key * union ubcore_eid eid; int ret, i; + if (key->key_cnt == 0) + return udma_query_res_seg_list(udma_dev, key, val); + mpt_index = key_to_hw_index(key->key) & (udma_dev->caps.num_mtpts - 1); ret = udma_dfx_query_context(udma_dev, mpt_index, &mpt_entry, sizeof(mpt_entry), UDMA_CMD_QUERY_MPT); @@ -598,319 +890,67 @@ static int udma_query_res_seg(struct udma_dev *udma_dev, struct ubcore_res_key * return 0; } -static int udma_query_res_dev_tp(struct udma_dev *udma_dev, +static int udma_query_res_dev_ta(struct udma_dev *udma_dev, struct ubcore_res_key *key, - struct ubcore_res_val *val, int i) + struct ubcore_res_val *val) { - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - struct tpn_list *tpn_now; - uint32_t *tp_list; - uint32_t tpn_cnt; - - dev->tp_cnt = 0; - if (!g_udma_dfx_list[i].dfx) { - dev_err(udma_dev->dev, "query res_dev_tp failed!\n"); - return -EINVAL; - } - - spin_lock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); - tpn_cnt = g_udma_dfx_list[i].dfx->tpn_cnt; - if (tpn_cnt == 0) { - spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); - return 0; - } - - tp_list = vmalloc(sizeof(*tp_list) * tpn_cnt); - if (!tp_list) { - spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); - return -ENOMEM; - } - - list_for_each_entry(tpn_now, - &g_udma_dfx_list[i].dfx->tpn_list->node, node) { - tp_list[dev->tp_cnt] = tpn_now->tpn; - dev->tp_cnt++; - } - spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); - - dev->tp_list = tp_list; - - return 0; -} + struct ubcore_res_dev_ta_val *res_ta = (struct ubcore_res_dev_ta_val *)val->addr; + int ret; + int i; -static int udma_query_res_dev_jfs(struct udma_dev *udma_dev, - struct ubcore_res_key *key, - struct ubcore_res_val *val, int i) -{ - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - struct jfs_list *jfs_now; - uint32_t *jfs_list; - uint32_t jfs_cnt; + ret = udma_find_dfx_dev(udma_dev, &i); + if (ret) + return ret; - dev->jfs_cnt = 0; - if (!g_udma_dfx_list[i].dfx) { - dev_err(udma_dev->dev, "query res_dev_jfs failed!\n"); - return -EINVAL; - } + spin_lock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); + res_ta->seg_cnt = g_udma_dfx_list[i].dfx->seg_cnt; + spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); spin_lock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); - jfs_cnt = g_udma_dfx_list[i].dfx->jfs_cnt; - if (jfs_cnt == 0) { - spin_unlock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); - return 0; - } - - jfs_list = vmalloc(sizeof(*jfs_list) * jfs_cnt); - if (!jfs_list) { - spin_unlock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); - return -ENOMEM; - } - - list_for_each_entry(jfs_now, - &g_udma_dfx_list[i].dfx->jfs_list->node, node) { - jfs_list[dev->jfs_cnt] = jfs_now->jfs_id; - dev->jfs_cnt++; - } + res_ta->jfs_cnt = g_udma_dfx_list[i].dfx->jfs_cnt; spin_unlock(&g_udma_dfx_list[i].dfx->jfs_list->node_lock); - dev->jfs_list = jfs_list; - - return 0; -} - -static int udma_query_res_dev_jfr(struct udma_dev *udma_dev, - struct ubcore_res_key *key, - struct ubcore_res_val *val, int i) -{ - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - struct jfr_list *jfr_now; - uint32_t *jfr_list; - uint32_t jfr_cnt; - - dev->jfr_cnt = 0; - if (!g_udma_dfx_list[i].dfx) { - dev_err(udma_dev->dev, "query res_dev_jfr failed!\n"); - return -EINVAL; - } - spin_lock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); - jfr_cnt = g_udma_dfx_list[i].dfx->jfr_cnt; - if (jfr_cnt == 0) { - spin_unlock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); - return 0; - } - - jfr_list = vmalloc(sizeof(*jfr_list) * jfr_cnt); - if (!jfr_list) { - spin_unlock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); - return -ENOMEM; - } - - list_for_each_entry(jfr_now, - &g_udma_dfx_list[i].dfx->jfr_list->node, node) { - jfr_list[dev->jfr_cnt] = jfr_now->jfr_id; - dev->jfr_cnt++; - } + res_ta->jfr_cnt = g_udma_dfx_list[i].dfx->jfr_cnt; spin_unlock(&g_udma_dfx_list[i].dfx->jfr_list->node_lock); - dev->jfr_list = jfr_list; - - return 0; -} - -static int udma_query_res_dev_jetty(struct udma_dev *udma_dev, - struct ubcore_res_key *key, - struct ubcore_res_val *val, int i) -{ - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - struct jetty_list *jetty_now; - uint32_t *jetty_list; - uint32_t jetty_cnt; - - dev->jetty_cnt = 0; - if (!g_udma_dfx_list[i].dfx) { - dev_err(udma_dev->dev, "query res_dev_jetty failed!\n"); - return -EINVAL; - } - - spin_lock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); - jetty_cnt = g_udma_dfx_list[i].dfx->jetty_cnt; - if (jetty_cnt == 0) { - spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); - return 0; - } - - jetty_list = vmalloc(sizeof(*jetty_list) * jetty_cnt); - if (!jetty_list) { - spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); - return -ENOMEM; - } - - list_for_each_entry(jetty_now, - &g_udma_dfx_list[i].dfx->jetty_list->node, node) { - jetty_list[dev->jetty_cnt] = jetty_now->jetty_id; - dev->jetty_cnt++; - } - spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); - - dev->jetty_list = jetty_list; - - return 0; -} - -static int udma_query_res_dev_jfc(struct udma_dev *udma_dev, - struct ubcore_res_key *key, - struct ubcore_res_val *val, int i) -{ - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - struct jfc_list *jfc_now; - uint32_t *jfc_list; - uint32_t jfc_cnt; - - dev->jfc_cnt = 0; - if (!g_udma_dfx_list[i].dfx) { - dev_err(udma_dev->dev, "query res_dev_jfc failed!\n"); - return -EINVAL; - } - spin_lock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); - jfc_cnt = g_udma_dfx_list[i].dfx->jfc_cnt; - if (jfc_cnt == 0) { - spin_unlock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); - return 0; - } - - jfc_list = vmalloc(sizeof(*jfc_list) * jfc_cnt); - if (!jfc_list) { - spin_unlock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); - return -ENOMEM; - } - - list_for_each_entry(jfc_now, - &g_udma_dfx_list[i].dfx->jfc_list->node, node) { - jfc_list[dev->jfc_cnt] = jfc_now->jfc_id; - dev->jfc_cnt++; - } + res_ta->jfc_cnt = g_udma_dfx_list[i].dfx->jfc_cnt; spin_unlock(&g_udma_dfx_list[i].dfx->jfc_list->node_lock); - dev->jfc_list = jfc_list; - - return 0; -} - -static int udma_query_res_dev_seg(struct udma_dev *udma_dev, - struct ubcore_res_key *key, - struct ubcore_res_val *val, int i) -{ - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - struct ubcore_seg_info *seg_list; - struct seg_list *seg_now; - uint32_t seg_cnt; - - dev->seg_cnt = 0; - if (!g_udma_dfx_list[i].dfx) { - dev_err(udma_dev->dev, "query res_dev_seg failed!\n"); - return -EINVAL; - } - - spin_lock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); - seg_cnt = g_udma_dfx_list[i].dfx->seg_cnt; - if (seg_cnt == 0) { - spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); - return 0; - } - - seg_list = vmalloc(sizeof(*seg_list) * seg_cnt); - if (!seg_list) { - spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); - return -ENOMEM; - } + spin_lock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); + res_ta->jetty_cnt = g_udma_dfx_list[i].dfx->jetty_cnt; + spin_unlock(&g_udma_dfx_list[i].dfx->jetty_list->node_lock); - list_for_each_entry(seg_now, - &g_udma_dfx_list[i].dfx->seg_list->node, node) { - memcpy(&seg_list[dev->seg_cnt].ubva.eid, &seg_now->eid, - sizeof(union ubcore_eid)); - seg_list[dev->seg_cnt].ubva.va = seg_now->iova; - seg_list[dev->seg_cnt].len = seg_now->len; - seg_list[dev->seg_cnt].token_id = seg_now->key_id; - dev->seg_cnt++; - } - spin_unlock(&g_udma_dfx_list[i].dfx->seg_list->node_lock); + read_unlock(&g_udma_dfx_list[i].rwlock); - dev->seg_list = seg_list; + res_ta->jetty_group_cnt = 0; + res_ta->rc_cnt = 0; return 0; } -static int udma_query_res_dev(struct udma_dev *udma_dev, - struct ubcore_res_key *key, - struct ubcore_res_val *val) +static int udma_query_res_dev_tp(struct udma_dev *udma_dev, + struct ubcore_res_key *key, + struct ubcore_res_val *val) { - struct ubcore_res_dev_val *dev = (struct ubcore_res_dev_val *)val->addr; - int ret, i; - - if (val->len < sizeof(struct ubcore_res_dev_val)) { - dev_err(udma_dev->dev, "failed to check len, type: %u, val->len: %u.\n", - (uint32_t)key->type, val->len); - val->len = sizeof(struct ubcore_res_dev_val); - return -EINVAL; - } + struct ubcore_res_dev_tp_val *res_tp = (struct ubcore_res_dev_tp_val *)val->addr; + int ret; + int i; ret = udma_find_dfx_dev(udma_dev, &i); if (ret) return ret; - ret = udma_query_res_dev_tp(udma_dev, key, val, i); - if (ret) - goto err_query_res; - - ret = udma_query_res_dev_jfs(udma_dev, key, val, i); - if (ret) - goto err_query_res; - - ret = udma_query_res_dev_jfr(udma_dev, key, val, i); - if (ret) - goto err_query_res; - - ret = udma_query_res_dev_jetty(udma_dev, key, val, i); - if (ret) - goto err_query_res; - - ret = udma_query_res_dev_jfc(udma_dev, key, val, i); - if (ret) - goto err_query_res; - - ret = udma_query_res_dev_seg(udma_dev, key, val, i); - if (ret) - goto err_query_res; - - dev->tpg_cnt = 0; - dev->utp_cnt = 0; - dev->vtp_cnt = 0; - dev->jetty_group_cnt = 0; - dev->rc_cnt = 0; + spin_lock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); + res_tp->tp_cnt = g_udma_dfx_list[i].dfx->tpn_cnt; + spin_unlock(&g_udma_dfx_list[i].dfx->tpn_list->node_lock); -err_query_res: read_unlock(&g_udma_dfx_list[i].rwlock); - return ret; -} - -static int udma_check_key_type(struct udma_dev *udma_dev, - struct ubcore_res_key *key) -{ - bool ret; - - ret = key->type < UBCORE_RES_KEY_UPI || - key->type > UBCORE_RES_KEY_URMA_DEV || - key->type == UBCORE_RES_KEY_UPI || - key->type == UBCORE_RES_KEY_TPG || - key->type == UBCORE_RES_KEY_UTP || - key->type == UBCORE_RES_KEY_JETTY_GROUP; - if (ret) { - dev_err(udma_dev->dev, "key type: %u invalid.\n", (uint32_t)key->type); - return -EINVAL; - } + res_tp->vtp_cnt = 0; + res_tp->tpg_cnt = 0; + res_tp->utp_cnt = 0; return 0; } @@ -919,11 +959,6 @@ int udma_query_res(struct ubcore_device *dev, struct ubcore_res_key *key, struct ubcore_res_val *val) { struct udma_dev *udma_dev = to_udma_dev(dev); - int ret; - - ret = udma_check_key_type(udma_dev, key); - if (ret) - return ret; switch (key->type) { case UBCORE_RES_KEY_TP: @@ -938,9 +973,12 @@ int udma_query_res(struct ubcore_device *dev, return udma_query_res_jfc(udma_dev, key, val); case UBCORE_RES_KEY_SEG: return udma_query_res_seg(udma_dev, key, val); - case UBCORE_RES_KEY_URMA_DEV: - return udma_query_res_dev(udma_dev, key, val); + case UBCORE_RES_KEY_DEV_TA: + return udma_query_res_dev_ta(udma_dev, key, val); + case UBCORE_RES_KEY_DEV_TP: + return udma_query_res_dev_tp(udma_dev, key, val); default: + dev_err(udma_dev->dev, "key type: %u invalid.\n", (uint32_t)key->type); return -EINVAL; } diff --git a/drivers/ub/hw/hns3/hns3_udma_jetty.c b/drivers/ub/hw/hns3/hns3_udma_jetty.c index d08c0be6922f..1cf3d454389c 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jetty.c +++ b/drivers/ub/hw/hns3/hns3_udma_jetty.c @@ -300,7 +300,7 @@ static int alloc_common_jetty_id(struct udma_dev *udma_dev, struct udma_jetty *j free_common_qpn(udma_dev, jetty->jetty_id); return ret; } - jetty->ubcore_jetty.id = jetty->jetty_id; + jetty->ubcore_jetty.jetty_id.id = jetty->jetty_id; return ret; } diff --git a/drivers/ub/hw/hns3/hns3_udma_jfr.c b/drivers/ub/hw/hns3/hns3_udma_jfr.c index d2cd484be683..6535c4d0a6ff 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jfr.c +++ b/drivers/ub/hw/hns3/hns3_udma_jfr.c @@ -369,7 +369,7 @@ static int alloc_jfrc(struct udma_dev *dev, struct udma_jfr *jfr) } jfr->srqn = (uint32_t)id; - jfr->ubcore_jfr.id = jfr->jfrn; + jfr->ubcore_jfr.jfr_id.id = jfr->jfrn; ret = udma_table_get(dev, &jfr_table->table, jfr->srqn); if (ret) { diff --git a/drivers/ub/hw/hns3/hns3_udma_jfs.c b/drivers/ub/hw/hns3/hns3_udma_jfs.c index 66874e998248..840ef5f025d9 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jfs.c +++ b/drivers/ub/hw/hns3/hns3_udma_jfs.c @@ -178,8 +178,7 @@ static int alloc_jfs_id(struct udma_dev *udma_dev, struct udma_jfs *jfs) dev_err(udma_dev->dev, "failed to store JFS, ret = %d.\n", ret); goto store_err; } - - jfs->ubcore_jfs.id = jfs->jfs_id; + jfs->ubcore_jfs.jfs_id.id = jfs->jfs_id; return ret; store_err: diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.c b/drivers/ub/urma/ubcore/ubcore_cdev_file.c index aa16e14c0880..3da675553aed 100644 --- a/drivers/ub/urma/ubcore/ubcore_cdev_file.c +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.c @@ -37,8 +37,6 @@ typedef ssize_t (*ubcore_store_attr_cb)(struct ubcore_device *dev, const char *buf, size_t len); typedef ssize_t (*ubcore_show_port_attr_cb)(struct ubcore_device *dev, char *buf, uint8_t port_id); -typedef ssize_t (*ubcore_show_eid_attr_cb)(struct ubcore_device *dev, - char *buf, uint16_t idx, struct net *net); static inline struct ubcore_device *get_ubcore_device(struct ubcore_logic_device *ldev) { @@ -383,7 +381,8 @@ static DEVICE_ATTR_RO(ceq_cnt); static ssize_t utp_cnt_show_cb(struct ubcore_device *dev, char *buf) { - return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.utp_cnt); + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", + dev->attr.dev_cap.max_utp_cnt); } static ssize_t utp_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -487,6 +486,50 @@ static ssize_t driver_name_show(struct device *dev, struct device_attribute *att static DEVICE_ATTR_RO(driver_name); +/* One eid line has upto 51 bytes with the format: + * "4294967295 0000:0000:0000:0000:0000:ffff:7f00:0001\n" + * sysfs buf size is PAGESIZE, upto 80 eid lines are supported in the sysfs + */ +#define UBCORE_MAX_EID_LINE 51 + +static ssize_t eid_show_cb(struct ubcore_device *dev, char *buf, struct net *net) +{ + struct ubcore_eid_entry *e; + ssize_t len = 0; + uint32_t i; + + if (dev->eid_table.eid_entries == NULL) + return -EINVAL; + + spin_lock(&dev->eid_table.lock); + for (i = 0; i < dev->eid_table.eid_cnt; i++) { + e = &dev->eid_table.eid_entries[i]; + if (!e->valid || !net_eq(e->net, net)) + continue; + len += snprintf(buf + len, UBCORE_MAX_EID_LINE, + "%u "EID_FMT"\n", i, EID_ARGS(e->eid)); + if (len >= (ssize_t)(PAGE_SIZE - UBCORE_MAX_EID_LINE)) + break; + } + spin_unlock(&dev->eid_table.lock); + return len; +} + +static ssize_t eid_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ubcore_logic_device *ldev = dev_get_drvdata(dev); + struct ubcore_device *ub_dev = get_ubcore_device(ldev); + + if (!ldev || !ub_dev || !buf) { + ubcore_log_err("Invalid argument.\n"); + return -EINVAL; + } + + return eid_show_cb(ub_dev, buf, read_pnet(&ldev->net)); +} +static DEVICE_ATTR_RO(eid); + + static struct attribute *ubcore_dev_attrs[] = { &dev_attr_ubdev.attr, &dev_attr_guid.attr, @@ -521,6 +564,7 @@ static struct attribute *ubcore_dev_attrs[] = { &dev_attr_virtualization.attr, &dev_attr_transport_type.attr, &dev_attr_driver_name.attr, + &dev_attr_eid.attr, NULL, }; @@ -700,101 +744,6 @@ int ubcore_create_port_attr_files(struct ubcore_logic_device *ldev, "port%hhu", port_id); } -static ssize_t ubcore_show_eid_attr(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, - char *buf, ubcore_show_eid_attr_cb show_cb) -{ - struct ubcore_logic_device *ldev = eid->ldev; - struct ubcore_device *dev = get_ubcore_device(ldev); - - if (!ldev || !dev) { - ubcore_log_err("Invalid argument in show_eid_attr.\n"); - return -EINVAL; - } - - return show_cb(dev, buf, eid->eid_idx, read_pnet(&ldev->net)); -} - -static ssize_t show_eid_cb(struct ubcore_device *dev, char *buf, uint16_t idx, struct net *net) -{ - struct ubcore_eid_entry *e; - union ubcore_eid eid; - - e = &dev->eid_table.eid_entries[idx]; - if (e->valid && net_eq(e->net, net)) { - return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", - EID_ARGS(e->eid)); - } else { - memset(&eid, 0, sizeof(union ubcore_eid)); - return snprintf(buf, (UBCORE_EID_STR_LEN + 1) + 1, EID_FMT"\n", - EID_ARGS(eid)); - } -} - -static ssize_t eid_show(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, char *buf) -{ - return ubcore_show_eid_attr(eid, attr, buf, show_eid_cb); -} - -static EID_ATTR_RO(eid); - -static struct attribute *ubcore_eid_attrs[] = { - &eid_attr_eid.attr, - NULL, -}; - -static ssize_t ubcore_eid_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct ubcore_eid_attribute *eid_attr = - container_of(attr, struct ubcore_eid_attribute, attr); - struct ubcore_eid_kobj *eid = container_of(kobj, struct ubcore_eid_kobj, kobj); - - if (!eid_attr->show) - return -EIO; - - return eid_attr->show(eid, eid_attr, buf); -} - -static ssize_t ubcore_eid_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct ubcore_eid_attribute *eid_attr = - container_of(attr, struct ubcore_eid_attribute, attr); - struct ubcore_eid_kobj *eid = container_of(kobj, struct ubcore_eid_kobj, kobj); - - if (!eid_attr->store) - return -EIO; - return eid_attr->store(eid, eid_attr, buf, count); -} - -static const struct sysfs_ops ubcore_eid_sysfs_ops = { - .show = ubcore_eid_attr_show, - .store = ubcore_eid_attr_store -}; - -static void ubcore_eid_release(struct kobject *kobj) -{ -} - -// ATTRIBUTE_GROUPS defined in 3.11, but must be consistent with kobj_type->default_groups -ATTRIBUTE_GROUPS(ubcore_eid); - -static struct kobj_type ubcore_eid_type = { - .release = ubcore_eid_release, - .sysfs_ops = &ubcore_eid_sysfs_ops, - .default_groups = ubcore_eid_groups -}; - -int ubcore_create_eid_attr_files(struct ubcore_logic_device *ldev, uint32_t eid_num) -{ - struct ubcore_eid_kobj *eid; - - eid = &ldev->eid[eid_num]; - eid->ldev = ldev; - eid->eid_idx = eid_num; - - return kobject_init_and_add(&eid->kobj, &ubcore_eid_type, &ldev->dev->kobj, - "eid%u", eid_num); -} int ubcore_create_dev_attr_files(struct ubcore_logic_device *ldev) { @@ -814,41 +763,14 @@ void ubcore_remove_port_attr_files(struct ubcore_logic_device *ldev, uint8_t por kobject_put(&ldev->port[port_id].kobj); } -void ubcore_remove_eid_attr_files(struct ubcore_logic_device *ldev, uint32_t eid_num) -{ - kobject_put(&ldev->eid[eid_num].kobj); -} - void ubcore_remove_dev_attr_files(struct ubcore_logic_device *ldev) { sysfs_remove_group(&ldev->dev->kobj, &ubcore_dev_attr_group); } -static int ubcore_create_eid_table(struct ubcore_logic_device *ldev, struct ubcore_device *dev) -{ - struct ubcore_eid_kobj *eid_list; - - eid_list = kcalloc( - 1, dev->attr.dev_cap.max_eid_cnt * sizeof(struct ubcore_eid_kobj), GFP_ATOMIC); - if (eid_list == NULL) - return -ENOMEM; - - ldev->eid = eid_list; - return 0; -} - -static void ubcore_destroy_eid_table(struct ubcore_logic_device *ldev) -{ - if (ldev->eid != NULL) { - kfree(ldev->eid); - ldev->eid = NULL; - } -} - int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, struct ubcore_device *dev) { - uint32_t e1, e2; /* eid */ uint8_t p1, p2; /* port */ if (ubcore_create_dev_attr_files(ldev) != 0) { @@ -862,22 +784,8 @@ int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, goto err_port_attr; } - /* create /sys/class/ubcore/dev_name>/eid* */ - if (ubcore_create_eid_table(ldev, dev) != 0) - goto err_port_attr; - - for (e1 = 0; e1 < dev->attr.dev_cap.max_eid_cnt; e1++) { - if (ubcore_create_eid_attr_files(ldev, e1) != 0) - goto err_eid_attr; - } return 0; -err_eid_attr: - for (e2 = 0; e2 < e1; e2++) - ubcore_remove_eid_attr_files(ldev, e2); - - ubcore_destroy_eid_table(ldev); - err_port_attr: for (p2 = 0; p2 < p1; p2++) ubcore_remove_port_attr_files(ldev, p2); @@ -889,14 +797,8 @@ int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, void ubcore_unfill_logic_device_attr(struct ubcore_logic_device *ldev, struct ubcore_device *dev) { - uint32_t e; uint8_t p; - for (e = 0; e < dev->attr.dev_cap.max_eid_cnt; e++) - ubcore_remove_eid_attr_files(ldev, e); - - ubcore_destroy_eid_table(ldev); - for (p = 0; p < dev->attr.port_cnt; p++) ubcore_remove_port_attr_files(ldev, p); diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.h b/drivers/ub/urma/ubcore/ubcore_cdev_file.h index eaa63c659d12..dd51450f92cc 100644 --- a/drivers/ub/urma/ubcore/ubcore_cdev_file.h +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.h @@ -35,19 +35,6 @@ struct ubcore_port_attribute { #define PORT_ATTR_RO(_name) struct ubcore_port_attribute port_attr_##_name = __ATTR_RO(_name) -struct ubcore_eid_attribute { - struct attribute attr; - ssize_t (*show)(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, char *buf); - ssize_t (*store)(struct ubcore_eid_kobj *eid, struct ubcore_eid_attribute *attr, - const char *buf, size_t count); -}; - -#define EID_ATTR(_name, _mode, _show, _store) \ -struct ubcore_eid_attribute eid_attr_##_name = __ATTR(_name, _mode, _show, _store) - -#define EID_ATTR_RO(_name) \ -struct ubcore_eid_attribute eid_attr_##_name = __ATTR_RO(_name) - int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, struct ubcore_device *dev); void ubcore_unfill_logic_device_attr(struct ubcore_logic_device *ldev, diff --git a/drivers/ub/urma/ubcore/ubcore_cmd.h b/drivers/ub/urma/ubcore/ubcore_cmd.h index 24d3f44d3b0f..d8ebd5d7e132 100644 --- a/drivers/ub/urma/ubcore/ubcore_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_cmd.h @@ -35,8 +35,6 @@ struct ubcore_cmd_hdr { #define UBCORE_CMD_MAGIC 'C' #define UBCORE_CMD _IOWR(UBCORE_CMD_MAGIC, 1, struct ubcore_cmd_hdr) #define UBCORE_MAX_CMD_SIZE 8192 -#define UBCORE_CMD_EID_SIZE 16 -#define UBCORE_CMD_DEV_MAX 64 /* only for ubcore device ioctl */ enum ubcore_cmd { @@ -48,6 +46,26 @@ enum ubcore_cmd { UBCORE_CMD_SET_EID_MODE, UBCORE_CMD_SET_NS_MODE, UBCORE_CMD_SET_DEV_NS, + UBCORE_CMD_SET_GENL_PID, + UBCORE_CMD_UVS_INIT_RES, + /* alpha netlink ops begin: */ + UBCORE_CMD_QUERY_TP_REQ, + UBCORE_CMD_QUERY_TP_RESP, + UBCORE_CMD_RESTORE_TP_REQ, + UBCORE_CMD_RESTORE_TP_RESP, + /* alpha netlink ops end: */ + UBCORE_CMD_FE2TPF_REQ, + UBCORE_CMD_TPF2FE_RESP, + UBCORE_CMD_ADD_SIP_REQ, + UBCORE_CMD_ADD_SIP_RESP, + UBCORE_CMD_DEL_SIP_REQ, + UBCORE_CMD_DEL_SIP_RESP, + UBCORE_CMD_TP_ERROR_REQ, + UBCORE_CMD_TP_SUSPEND_REQ, + UBCORE_CMD_MIGRATE_VTP_SWITCH, + UBCORE_CMD_MIGRATE_VTP_ROLLBACK, + UBCORE_CMD_UPDATE_TPF_DEV_INFO_REQ, + UBCORE_CMD_UPDATE_TPF_DEV_INFO_RESP, UBCORE_CMD_MAX }; @@ -96,7 +114,7 @@ struct ubcore_cmd_show_utp { struct ubcore_cmd_update_ueid { struct { - char dev_name[UBCORE_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; uint32_t eid_index; int ns_fd; } in; @@ -104,7 +122,7 @@ struct ubcore_cmd_update_ueid { struct ubcore_cmd_set_eid_mode { struct { - char dev_name[UBCORE_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; bool eid_mode; } in; }; diff --git a/drivers/ub/urma/ubcore/ubcore_ctp.c b/drivers/ub/urma/ubcore/ubcore_ctp.c index 28075c212c30..1540baa6bba8 100644 --- a/drivers/ub/urma/ubcore/ubcore_ctp.c +++ b/drivers/ub/urma/ubcore/ubcore_ctp.c @@ -38,7 +38,9 @@ struct ubcore_ctp *ubcore_create_ctp(struct ubcore_device *dev, struct ubcore_ct } ctp->ub_dev = dev; ctp->ctp_cfg = *cfg; - atomic_set(&ctp->use_cnt, 1); + atomic_set(&ctp->use_cnt, 0); + kref_init(&ctp->ref_cnt); + init_completion(&ctp->comp); ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_CTP], &ctp->hnode, ctp->ctpn); if (ret != 0) { @@ -52,6 +54,25 @@ struct ubcore_ctp *ubcore_create_ctp(struct ubcore_device *dev, struct ubcore_ct return ctp; } +static void ubcore_ctp_kref_release(struct kref *ref_cnt) +{ + struct ubcore_ctp *ctp = container_of(ref_cnt, struct ubcore_ctp, ref_cnt); + + complete(&ctp->comp); +} + +void ubcore_ctp_kref_put(struct ubcore_ctp *ctp) +{ + (void)kref_put(&ctp->ref_cnt, ubcore_ctp_kref_release); +} + +void ubcore_ctp_get(void *obj) +{ + struct ubcore_ctp *ctp = obj; + + kref_get(&ctp->ref_cnt); +} + int ubcore_destroy_ctp(struct ubcore_ctp *ctp) { struct ubcore_device *dev = ctp->ub_dev; @@ -61,13 +82,8 @@ int ubcore_destroy_ctp(struct ubcore_ctp *ctp) if (dev == NULL || dev->ops == NULL || dev->ops->destroy_ctp == NULL) return -EINVAL; - if (atomic_dec_return(&ctp->use_cnt) > 0) { - ubcore_log_err("ctp in use"); - return -EBUSY; - } - - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_CTP], &ctp->hnode); - + ubcore_ctp_kref_put(ctp); + wait_for_completion(&ctp->comp); ret = dev->ops->destroy_ctp(ctp); if (ret != 0) { (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_CTP], &ctp->hnode, ctp->ctpn); @@ -84,3 +100,33 @@ struct ubcore_ctp *ubcore_find_ctp(struct ubcore_device *dev, uint32_t idx) { return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_CTP], idx, &idx); } + +struct ubcore_ctp *ubcore_find_get_ctp(struct ubcore_device *dev, uint32_t idx) +{ + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_CTP], idx, &idx); +} + +struct ubcore_ctp *ubcore_find_remove_ctp(struct ubcore_device *dev, uint32_t idx) +{ + struct ubcore_ctp *ctp; + + spin_lock(&dev->ht[UBCORE_HT_CTP].lock); + if (&dev->ht[UBCORE_HT_CTP].head == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_CTP].lock); + return NULL; + } + ctp = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_CTP], idx, &idx); + if (ctp == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_CTP].lock); + return NULL; + } + if (atomic_read(&ctp->use_cnt) > 0) { + spin_unlock(&dev->ht[UBCORE_HT_CTP].lock); + ubcore_log_err("Failed to remove ctp"); + return NULL; + } + ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_CTP], &ctp->hnode); + spin_unlock(&dev->ht[UBCORE_HT_CTP].lock); + + return ctp; +} diff --git a/drivers/ub/urma/ubcore/ubcore_ctp.h b/drivers/ub/urma/ubcore/ubcore_ctp.h index a63cd01f25ae..393455b7014c 100644 --- a/drivers/ub/urma/ubcore/ubcore_ctp.h +++ b/drivers/ub/urma/ubcore/ubcore_ctp.h @@ -25,4 +25,8 @@ struct ubcore_ctp *ubcore_create_ctp(struct ubcore_device *dev, struct ubcore_ctp_cfg *cfg); int ubcore_destroy_ctp(struct ubcore_ctp *ctp); struct ubcore_ctp *ubcore_find_ctp(struct ubcore_device *dev, uint32_t idx); +struct ubcore_ctp *ubcore_find_get_ctp(struct ubcore_device *dev, uint32_t idx); +struct ubcore_ctp *ubcore_find_remove_ctp(struct ubcore_device *dev, uint32_t idx); +void ubcore_ctp_get(void *obj); +void ubcore_ctp_kref_put(struct ubcore_ctp *ctp); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index ebd430e6e973..2121ab9cac9f 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "urma/ubcore_types.h" #include "ubcore_log.h" @@ -42,19 +43,32 @@ #include "ubcore_tp_table.h" #include "ubcore_msg.h" #include "ubcore_netdev.h" +#include "ubcore_utp.h" #include "ubcore_vtp.h" +#include "ubcore_tpg.h" +#include "ubcore_ctp.h" #include "ubcore_netlink.h" #include "ubcore_workqueue.h" #include "ubcore_cdev_file.h" +#include "ubcore_uvs_cmd.h" +#include "ubcore_cmd.h" #include "ubcore_device.h" +#define UBCORE_DEVICE_NAME "ubcore" + +struct ubcore_ctx { + dev_t ubcore_devno; + struct cdev ubcore_cdev; + struct device *ubcore_dev; +}; + static LIST_HEAD(g_client_list); static LIST_HEAD(g_device_list); /* - * g_device_mutex protects writer access by device + * g_device_rwsem protects writer access by device */ -static DEFINE_MUTEX(g_device_mutex); +static DECLARE_RWSEM(g_device_rwsem); /* * g_clients_rwsem protect g_client_list. @@ -71,13 +85,15 @@ static DECLARE_RWSEM(g_ubcore_net_rwsem); static bool g_shared_ns = true; +static struct ubcore_ctx g_ubcore_ctx; + static const void *ubcore_net_namespace(struct device *dev) { struct ubcore_logic_device *ldev = dev_get_drvdata(dev); struct ubcore_device *ubc_dev; if (ldev == NULL || ldev->ub_dev == NULL) { - ubcore_log_info("init net %p", ldev); + ubcore_log_info("init net %pK", ldev); return &init_net; } @@ -121,7 +137,9 @@ void ubcore_set_client_ctx_data(struct ubcore_device *dev, struct ubcore_client { struct ubcore_client_ctx *ctx; - if (dev == NULL || client == NULL) { + if (dev == NULL || client == NULL || client->client_name == NULL || + strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || + strnlen(client->client_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { ubcore_log_err("dev or client is null"); return; } @@ -167,7 +185,9 @@ void *ubcore_get_client_ctx_data(struct ubcore_device *dev, struct ubcore_client { struct ubcore_client_ctx *found_ctx = NULL; - if (dev == NULL || client == NULL) { + if (dev == NULL || client == NULL || client->client_name == NULL || + strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || + strnlen(client->client_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { ubcore_log_err("dev or client is null"); return NULL; } @@ -222,13 +242,18 @@ int ubcore_register_client(struct ubcore_client *new_client) { struct ubcore_device *dev; - if (new_client == NULL) { - ubcore_log_err("new_client is null"); + if (new_client == NULL || new_client->client_name == NULL || + new_client->add == NULL || new_client->remove == NULL) { + ubcore_log_err("Invalid parameter.\n"); return -1; } - mutex_lock(&g_device_mutex); + if (strnlen(new_client->client_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_err("Invalid parameter, client name.\n"); + return -1; + } + down_write(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (create_client_ctx(dev, new_client) != 0) ubcore_log_warn("ubcore device: %s add client:%s context failed.\n", @@ -238,7 +263,7 @@ int ubcore_register_client(struct ubcore_client *new_client) list_add_tail(&new_client->list_node, &g_client_list); up_write(&g_clients_rwsem); - mutex_unlock(&g_device_mutex); + up_write(&g_device_rwsem); ubcore_log_info("ubcore client: %s register success.\n", new_client->client_name); return 0; @@ -250,17 +275,23 @@ void ubcore_unregister_client(struct ubcore_client *rm_client) struct ubcore_client_ctx *found_ctx = NULL; struct ubcore_device *dev; - if (rm_client == NULL) { - ubcore_log_err("rm_client is null"); + if (rm_client == NULL || rm_client->client_name == NULL || + rm_client->add == NULL || rm_client->remove == NULL) { + ubcore_log_err("Invalid parameter"); + return; + } + if (strnlen(rm_client->client_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_err("Invalid parameter, client name.\n"); return; } - mutex_lock(&g_device_mutex); + down_write(&g_device_rwsem); down_write(&g_clients_rwsem); list_del(&rm_client->list_node); up_write(&g_clients_rwsem); + downgrade_write(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { found_ctx = ubcore_lookup_client_context(dev, rm_client); if (found_ctx == NULL) { @@ -276,7 +307,7 @@ void ubcore_unregister_client(struct ubcore_client *rm_client) dev->dev_name, rm_client->client_name); } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); ubcore_log_info("ubcore client: %s unregister success.\n", rm_client->client_name); } EXPORT_SYMBOL(ubcore_unregister_client); @@ -286,7 +317,7 @@ struct ubcore_device *ubcore_find_device(union ubcore_eid *eid, enum ubcore_tran struct ubcore_device *dev, *target = NULL; uint32_t idx; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { for (idx = 0; idx < dev->attr.dev_cap.max_eid_cnt; idx++) { if (memcmp(&dev->eid_table.eid_entries[idx].eid, eid, @@ -299,7 +330,7 @@ struct ubcore_device *ubcore_find_device(union ubcore_eid *eid, enum ubcore_tran if (target != NULL) break; } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return target; } @@ -307,7 +338,7 @@ struct ubcore_device *ubcore_find_device_with_name(const char *dev_name) { struct ubcore_device *dev, *target = NULL; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (strcmp(dev->dev_name, dev_name) == 0) { target = dev; @@ -315,10 +346,21 @@ struct ubcore_device *ubcore_find_device_with_name(const char *dev_name) break; } } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return target; } +bool ubcore_check_dev_is_exist(const char *dev_name) +{ + struct ubcore_device *dev = NULL; + + dev = ubcore_find_device_with_name(dev_name); + if (dev != NULL) + ubcore_put_device(dev); + + return dev != NULL ? true : false; +} + struct ubcore_device *ubcore_find_upi_with_dev_name(const char *dev_name, uint32_t *upi) { struct ubcore_upi_entry *entry = NULL; @@ -379,13 +421,23 @@ void ubcore_destroy_upi_list(struct ubcore_device *dev) mutex_unlock(&g_upi_lock); } -struct ubcore_device **ubcore_get_devices_from_netdev(struct net_device *netdev, uint32_t *cnt) +void ubcore_device_list_lock(void) +{ + down_read(&g_device_rwsem); +} + +void ubcore_device_list_unlock(void) +{ + up_read(&g_device_rwsem); +} + +struct ubcore_device **ubcore_get_devices_from_netdev_nolock(struct net_device *netdev, + uint32_t *cnt) { struct ubcore_device **devices; struct ubcore_device *dev; uint32_t i = 0; - mutex_lock(&g_device_mutex); list_for_each_entry(dev, &g_device_list, list_node) { /* Assume netdev is related to the first and only port */ if (dev->netdev == netdev) @@ -394,14 +446,12 @@ struct ubcore_device **ubcore_get_devices_from_netdev(struct net_device *netdev, if (i == 0) { *cnt = 0; - mutex_unlock(&g_device_mutex); return NULL; } devices = kzalloc(i * sizeof(struct ubcore_device *), GFP_ATOMIC); if (devices == NULL) { *cnt = 0; - mutex_unlock(&g_device_mutex); return NULL; } @@ -414,7 +464,6 @@ struct ubcore_device **ubcore_get_devices_from_netdev(struct net_device *netdev, i++; } } - mutex_unlock(&g_device_mutex); return devices; } @@ -495,12 +544,12 @@ static uint32_t ubcore_get_all_tpf_device_cnt(enum ubcore_transport_type type) struct ubcore_device *dev; uint32_t cnt = 0; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev->attr.tp_maintainer && dev->transport_type == type) ++cnt; } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return cnt; } @@ -511,22 +560,25 @@ struct ubcore_device **ubcore_get_all_tpf_device(enum ubcore_transport_type type int i = 0; *dev_cnt = ubcore_get_all_tpf_device_cnt(type); + if (*dev_cnt == 0) + return NULL; + dev_list = kcalloc(1, (*dev_cnt) * (uint32_t)sizeof(struct ubcore_device *), GFP_KERNEL); if (dev_list == NULL) return NULL; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev->attr.tp_maintainer && dev->transport_type == type) { dev_list[i++] = dev; ubcore_get_device(dev); } } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return dev_list; } -struct ubcore_device *ubcore_find_tpf_device(struct ubcore_net_addr *netaddr, +struct ubcore_device *ubcore_find_tpf_device(union ubcore_net_addr_union *netaddr, enum ubcore_transport_type type) { struct ubcore_device *tpf_dev = NULL; @@ -563,7 +615,7 @@ int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg) } /* Query all existing TPF devices and configure */ - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev->attr.tp_maintainer == false) continue; @@ -573,74 +625,140 @@ int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg) if (ret != 0) ubcore_log_err("dev: %s set failed, ret: %d", dev->dev_name, ret); } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return 0; } +static void ubcore_free_driver_obj(void *obj) +{ + // obj alloced by driver, should not free by ubcore + ubcore_log_err("obj was not free correctly!"); +} + static struct ubcore_ht_param g_ht_params[] = { [UBCORE_HT_JFS] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfs, hnode), - offsetof(struct ubcore_jfs, id), sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_jfs, jfs_id) + offsetof(struct ubcore_jetty_id, id), + sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, [UBCORE_HT_JFR] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfr, hnode), - offsetof(struct ubcore_jfr, id), sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_jfr, jfr_id) + offsetof(struct ubcore_jetty_id, id), + sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, [UBCORE_HT_JFC] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfc, hnode), - offsetof(struct ubcore_jfc, id), sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_jfc, id), sizeof(uint32_t), NULL, + ubcore_free_driver_obj, NULL}, [UBCORE_HT_JETTY] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jetty, hnode), - offsetof(struct ubcore_jetty, id), - sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_jetty, jetty_id) + offsetof(struct ubcore_jetty_id, id), + sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, [UBCORE_HT_TP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tp_node, hnode), - offsetof(struct ubcore_tp_node, key), - sizeof(struct ubcore_tp_key), NULL, NULL, NULL}, + offsetof(struct ubcore_tp_node, key), sizeof(struct ubcore_tp_key), + NULL, NULL, ubcore_tp_get}, [UBCORE_HT_TPG] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tpg, hnode), - offsetof(struct ubcore_tpg, tpgn), sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_tpg, tpgn), sizeof(uint32_t), + NULL, ubcore_free_driver_obj, ubcore_tpg_get}, /* key: seid + deid */ [UBCORE_HT_RM_VTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtp, hnode), offsetof(struct ubcore_vtp, cfg) + offsetof(struct ubcore_vtp_cfg, local_eid), - sizeof(union ubcore_eid) * 2, NULL, NULL, NULL}, + sizeof(union ubcore_eid) * 2, NULL, ubcore_free_driver_obj, ubcore_vtp_get}, /* key: deid + djetty */ [UBCORE_HT_RC_VTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtp, hnode), offsetof(struct ubcore_vtp, cfg) + offsetof(struct ubcore_vtp_cfg, peer_eid), - sizeof(union ubcore_eid) + sizeof(uint32_t), NULL, NULL, NULL}, + sizeof(union ubcore_eid) + sizeof(uint32_t), NULL, ubcore_free_driver_obj, + ubcore_vtp_get}, /* key: seid + deid */ [UBCORE_HT_UM_VTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtp, hnode), offsetof(struct ubcore_vtp, cfg) + offsetof(struct ubcore_vtp_cfg, local_eid), - sizeof(union ubcore_eid) * 2, NULL, NULL, NULL}, + sizeof(union ubcore_eid) * 2, NULL, ubcore_free_driver_obj, ubcore_vtp_get}, /* key: src_eid + des_eid */ [UBCORE_HT_RM_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), - offsetof(struct ubcore_vtpn, local_eid), 2 * sizeof(union ubcore_eid), NULL, NULL, - ubcore_vtpn_get}, + offsetof(struct ubcore_vtpn, local_eid), 2 * sizeof(union ubcore_eid), + NULL, ubcore_free_driver_obj, ubcore_vtpn_get}, /* key: src_eid + des_eid + src_jetty + des_jetty */ [UBCORE_HT_RC_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), offsetof(struct ubcore_vtpn, local_eid), - 2 * sizeof(union ubcore_eid) + 2 * sizeof(uint32_t), NULL, NULL, ubcore_vtpn_get}, + 2 * sizeof(union ubcore_eid) + 2 * sizeof(uint32_t), + NULL, ubcore_free_driver_obj, ubcore_vtpn_get}, /* key: src_eid + des_eid */ [UBCORE_HT_UM_VTPN] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_vtpn, hnode), - offsetof(struct ubcore_vtpn, local_eid), 2 * sizeof(union ubcore_eid), NULL, NULL, - ubcore_vtpn_get}, + offsetof(struct ubcore_vtpn, local_eid), 2 * sizeof(union ubcore_eid), + NULL, ubcore_free_driver_obj, ubcore_vtpn_get}, /* key: utp idx */ [UBCORE_HT_UTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_utp, hnode), - offsetof(struct ubcore_utp, utpn), sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_utp, utpn), sizeof(uint32_t), NULL, + ubcore_free_driver_obj, ubcore_utp_get}, /* key: ctp idx */ [UBCORE_HT_CTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_ctp, hnode), - offsetof(struct ubcore_ctp, ctpn), sizeof(uint32_t), NULL, NULL, NULL}, + offsetof(struct ubcore_ctp, ctpn), sizeof(uint32_t), NULL, + ubcore_free_driver_obj, ubcore_ctp_get}, + + [UBCORE_HT_UB_TP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tp, hnode), + offsetof(struct ubcore_tp, tpn), sizeof(uint32_t), + NULL, ubcore_free_driver_obj, ubcore_tp_get}, }; +static inline void ubcore_set_vtp_hash_table_size(uint32_t vtp_size) +{ + if (vtp_size == 0 || vtp_size > UBCORE_HASH_TABLE_SIZE) + return; + g_ht_params[UBCORE_HT_RM_VTP].size = vtp_size; + g_ht_params[UBCORE_HT_RC_VTP].size = vtp_size; + g_ht_params[UBCORE_HT_UM_VTP].size = vtp_size; +} + +static inline void ubcore_set_vtpn_hash_table_size(uint32_t vtpn_size) +{ + if (vtpn_size == 0 || vtpn_size > UBCORE_HASH_TABLE_SIZE) + return; + g_ht_params[UBCORE_HT_RM_VTPN].size = vtpn_size; + g_ht_params[UBCORE_HT_RC_VTPN].size = vtpn_size; + g_ht_params[UBCORE_HT_UM_VTPN].size = vtpn_size; +} + +static void ubcore_update_hash_tables_size(const struct ubcore_device_cap *cap) +{ + if (cap->max_jfs != 0 && cap->max_jfs < g_ht_params[UBCORE_HT_JFS].size) + g_ht_params[UBCORE_HT_JFS].size = cap->max_jfs; + if (cap->max_jfr != 0 && cap->max_jfr < g_ht_params[UBCORE_HT_JFR].size) + g_ht_params[UBCORE_HT_JFR].size = cap->max_jfr; + if (cap->max_jfc != 0 && cap->max_jfc < g_ht_params[UBCORE_HT_JFC].size) + g_ht_params[UBCORE_HT_JFC].size = cap->max_jfc; + if (cap->max_jetty != 0 && cap->max_jetty < g_ht_params[UBCORE_HT_JETTY].size) + g_ht_params[UBCORE_HT_JETTY].size = cap->max_jetty; + if (cap->max_tp_cnt != 0 && cap->max_tp_cnt < g_ht_params[UBCORE_HT_TP].size) { + g_ht_params[UBCORE_HT_TP].size = cap->max_tp_cnt; + g_ht_params[UBCORE_HT_UB_TP].size = cap->max_tp_cnt; + } + if (cap->max_tpg_cnt != 0 && cap->max_tpg_cnt < g_ht_params[UBCORE_HT_TPG].size) + g_ht_params[UBCORE_HT_TPG].size = cap->max_tpg_cnt; + if (cap->max_vtp_cnt_per_fe < UBCORE_HASH_TABLE_SIZE && + cap->max_fe_cnt < UBCORE_HASH_TABLE_SIZE) + ubcore_set_vtp_hash_table_size((cap->max_vtp_cnt_per_fe * cap->max_fe_cnt)); + ubcore_set_vtpn_hash_table_size(cap->max_vtp_cnt_per_fe); + + if (cap->max_utp_cnt != 0 && cap->max_utp_cnt < g_ht_params[UBCORE_HT_UTP].size) + g_ht_params[UBCORE_HT_UTP].size = cap->max_utp_cnt; + /* ctp size use max_tp_cnt */ + if (cap->max_tp_cnt != 0 && cap->max_tp_cnt < g_ht_params[UBCORE_HT_CTP].size) + g_ht_params[UBCORE_HT_CTP].size = cap->max_tp_cnt; +} + + static int ubcore_alloc_hash_tables(struct ubcore_device *dev) { uint32_t i, j; int ret; + ubcore_update_hash_tables_size(&dev->attr.dev_cap); for (i = 0; i < ARRAY_SIZE(g_ht_params); i++) { ret = ubcore_hash_table_alloc(&dev->ht[i], &g_ht_params[i]); if (ret != 0) { @@ -673,6 +791,12 @@ static int ubcore_create_eidtable(struct ubcore_device *dev) { struct ubcore_eid_entry *entry_list; + if (dev->attr.dev_cap.max_eid_cnt > UBCORE_MAX_EID_CNT) { + ubcore_log_err("Max eid cnt:%u exceeds ubcore_max_eid_cnt!\n", + dev->attr.dev_cap.max_eid_cnt); + return -EINVAL; + } + entry_list = kcalloc(1, dev->attr.dev_cap.max_eid_cnt * sizeof(struct ubcore_eid_entry), GFP_ATOMIC); if (entry_list == NULL) @@ -705,7 +829,7 @@ static int ubcore_send_remove_tpf_dev_info(struct ubcore_device *dev) if (req_msg == NULL) return -ENOMEM; - req_msg->msg_type = UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ; + req_msg->msg_type = UBCORE_CMD_UPDATE_TPF_DEV_INFO_REQ; req_msg->transport_type = dev->transport_type; req_msg->payload_len = sizeof(struct ubcore_update_tpf_dev_info_req); @@ -724,7 +848,7 @@ static int ubcore_send_remove_tpf_dev_info(struct ubcore_device *dev) } resp = (struct ubcore_update_tpf_dev_info_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_UPDATE_TPF_DEV_INFO_RESP || resp == NULL || + if (resp_msg->msg_type != UBCORE_CMD_UPDATE_TPF_DEV_INFO_RESP || resp == NULL || resp->ret != UBCORE_NL_RESP_SUCCESS) { ubcore_log_err("update tpf dev info request is rejected with type %d ret %d", resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); @@ -738,45 +862,43 @@ static int ubcore_send_remove_tpf_dev_info(struct ubcore_device *dev) return ret; } -static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) +struct ubcore_nlmsg *ubcore_new_tpf_dev_msg(struct ubcore_device *dev) { - struct ubcore_nlmsg *resp_msg, *req_msg; - struct ubcore_update_tpf_dev_info_resp *resp; struct ubcore_update_tpf_dev_info_req *data; struct ubcore_cc_entry *cc_entry; struct ubcore_cc_entry *array; + struct ubcore_nlmsg *req_msg; uint32_t cc_entry_cnt; uint32_t cc_len; - int ret; if (dev->ops == NULL || dev->ops->query_cc == NULL) { ubcore_log_err("Invalid parameter!\n"); - return -EINVAL; + return NULL; } cc_entry = dev->ops->query_cc(dev, &cc_entry_cnt); if (cc_entry == NULL) { ubcore_log_err("Failed to query cc entry\n"); - return -EPERM; + return NULL; } if (cc_entry_cnt > UBCORE_CC_IDX_TABLE_SIZE || cc_entry_cnt == 0) { kfree(cc_entry); ubcore_log_err("cc_entry_cnt invalid, %u.\n", cc_entry_cnt); - return -EINVAL; + return NULL; } - cc_len = sizeof(struct ubcore_update_tpf_dev_info_req) + - cc_entry_cnt * sizeof(struct ubcore_cc_entry); + cc_len = (uint32_t)sizeof(struct ubcore_update_tpf_dev_info_req) + + cc_entry_cnt * (uint32_t)sizeof(struct ubcore_cc_entry); req_msg = kcalloc(1, sizeof(struct ubcore_nlmsg) + cc_len, GFP_KERNEL); if (req_msg == NULL) { kfree(cc_entry); - return -ENOMEM; + return NULL; } /* fill msg head */ - req_msg->msg_type = UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ; + req_msg->msg_type = UBCORE_CMD_UPDATE_TPF_DEV_INFO_REQ; req_msg->transport_type = dev->transport_type; req_msg->payload_len = cc_len; @@ -786,19 +908,40 @@ static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) data->cc_entry_cnt = cc_entry_cnt; (void)strcpy(data->dev_name, dev->dev_name); data->opcode = UBCORE_UPDATE_TPF_ADD; + + if (dev->netdev != NULL) { + if (strnlen(dev->netdev->name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_err("Invalid parameter! netdev.\n"); + kfree(req_msg); + kfree(cc_entry); + return NULL; + } + (void)strcpy(data->netdev_name, dev->netdev->name); + } + array = (struct ubcore_cc_entry *)data->data; (void)memcpy(array, cc_entry, sizeof(struct ubcore_cc_entry) * cc_entry_cnt); + kfree(cc_entry); + return req_msg; +} +static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) +{ + struct ubcore_nlmsg *resp_msg, *req_msg; + struct ubcore_update_tpf_dev_info_resp *resp; + int ret; + + req_msg = ubcore_new_tpf_dev_msg(dev); + if (req_msg == NULL) + return -1; resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { ubcore_log_err("Failed to wait query response"); - kfree(cc_entry); kfree(req_msg); return -1; } - resp = (struct ubcore_update_tpf_dev_info_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_UPDATE_TPF_DEV_INFO_RESP || resp == NULL || + if (resp_msg->msg_type != UBCORE_CMD_UPDATE_TPF_DEV_INFO_RESP || resp == NULL || resp->ret != UBCORE_NL_RESP_SUCCESS) { ubcore_log_err("update tpf dev info del request is rejected with type %d ret %d", resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); @@ -807,7 +950,6 @@ static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) ret = 0; } - kfree(cc_entry); kfree(resp_msg); kfree(req_msg); return ret; @@ -818,7 +960,7 @@ int ubcore_query_all_device_tpf_dev_info(void) struct ubcore_device *dev; int ret = 0; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { if (ubcore_query_send_tpf_dev_info(dev) != 0) { @@ -828,7 +970,7 @@ int ubcore_query_all_device_tpf_dev_info(void) } } } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return ret; } @@ -845,14 +987,18 @@ static int ubcore_create_main_device(struct ubcore_device *dev, struct net *net) device_initialize(&dev->dev); dev->dev.class = &g_ubcore_class; dev->dev.release = ubcore_device_release; - dev_set_name(&dev->dev, "%s", dev->dev_name); + /* dev_set_name will alloc mem use put_device to free */ + (void)dev_set_name(&dev->dev, "%s", dev->dev_name); dev_set_drvdata(&dev->dev, ldev); ret = device_add(&dev->dev); - if (ret) + if (ret) { + put_device(&dev->dev); // to free res used by kobj return ret; + } if (ubcore_fill_logic_device_attr(ldev, dev) != 0) { device_del(&dev->dev); + put_device(&dev->dev); ldev->dev = NULL; ubcore_log_err("failed to fill attributes, device:%s.\n", dev->dev_name); return -EPERM; @@ -867,6 +1013,7 @@ static void ubcore_destroy_main_device(struct ubcore_device *dev) ubcore_unfill_logic_device_attr(ldev, dev); device_del(ldev->dev); + put_device(ldev->dev); ldev->dev = NULL; } @@ -882,8 +1029,13 @@ static int init_ubcore_device(struct ubcore_device *dev) if (dev->transport_type == UBCORE_TRANSPORT_UB && g_tpf == NULL && dev->attr.tp_maintainer) g_tpf = dev; - if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) - ubcore_sip_table_init(&dev->sip_table); + if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { + if (ubcore_sip_table_init(&dev->sip_table, + dev->attr.dev_cap.max_netaddr_cnt) != 0) { + ubcore_log_err("Failed init sip table.\n"); + return -1; + } + } INIT_LIST_HEAD(&dev->list_node); init_rwsem(&dev->client_ctx_rwsem); @@ -926,14 +1078,12 @@ static int init_ubcore_device(struct ubcore_device *dev) static void ubcore_remove_uvs_sip_info(struct ubcore_device *dev) { struct ubcore_sip_info *sip_info; - uint32_t max_cnt = 0; uint32_t i; mutex_lock(&dev->sip_table.lock); - max_cnt = ubcore_get_sip_max_cnt(&dev->sip_table); - for (i = 0; i < max_cnt; i++) { - sip_info = dev->sip_table.entry[i]; - if (sip_info == NULL) + for (i = 0; i < dev->sip_table.max_sip_cnt; i++) { + sip_info = &dev->sip_table.entry[i]; + if (!sip_info->is_active) continue; if (ubcore_get_netlink_valid() == true) (void)ubcore_notify_uvs_del_sip(dev, sip_info, i); @@ -1226,13 +1376,122 @@ static int ubcore_copy_logic_devices(struct ubcore_device *dev) return ret; } +static int ubcore_open(struct inode *i_node, struct file *filp) +{ + return 0; +} + +static long ubcore_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct ubcore_cmd_hdr hdr; + int ret; + + if (cmd == UBCORE_UVS_CMD) { + ret = ubcore_copy_from_user(&hdr, (void *)arg, sizeof(struct ubcore_cmd_hdr)); + if ((ret != 0) || (hdr.args_len > UBCORE_MAX_CMD_SIZE)) { + ubcore_log_err("length of ioctl input parameter is out of range.\n"); + return -EINVAL; + } + return ubcore_uvs_cmd_parse(&hdr); + } + + ubcore_log_err("bad ioctl command.\n"); + return -ENOIOCTLCMD; +} + +static int ubcore_close(struct inode *i_node, struct file *filp) +{ + return 0; +} + +static const struct file_operations g_ubcore_ops = { + .owner = THIS_MODULE, + .open = ubcore_open, + .release = ubcore_close, + .unlocked_ioctl = ubcore_ioctl, + .compat_ioctl = ubcore_ioctl, +}; + +static int ubcore_register_sysfs(void) +{ + int ret; + + ret = alloc_chrdev_region(&g_ubcore_ctx.ubcore_devno, 0, 1, UBCORE_DEVICE_NAME); + if (ret != 0) { + ubcore_log_err("alloc chrdev region failed, ret:%d.\n", ret); + return ret; + } + + cdev_init(&g_ubcore_ctx.ubcore_cdev, &g_ubcore_ops); + ret = cdev_add(&g_ubcore_ctx.ubcore_cdev, g_ubcore_ctx.ubcore_devno, 1); + if (ret != 0) { + ubcore_log_err("chrdev add failed, ret:%d.\n", ret); + goto unreg_cdev_region; + } + + /* /dev/ubcore */ + g_ubcore_ctx.ubcore_dev = + device_create(&g_ubcore_class, NULL, g_ubcore_ctx.ubcore_devno, NULL, + UBCORE_DEVICE_NAME); + if (IS_ERR(g_ubcore_ctx.ubcore_dev)) { + ret = (int)PTR_ERR(g_ubcore_ctx.ubcore_dev); + ubcore_log_err("couldn't create device %s, ret:%d.\n", UBCORE_DEVICE_NAME, ret); + goto del_cdev; + } + ubcore_log_info("ubcore device created success.\n"); + return 0; + +del_cdev: + cdev_del(&g_ubcore_ctx.ubcore_cdev); +unreg_cdev_region: + unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); + return ret; +} + +static int ubcore_unregister_sysfs(void) +{ + device_destroy(&g_ubcore_class, g_ubcore_ctx.ubcore_cdev.dev); + cdev_del(&g_ubcore_ctx.ubcore_cdev); + unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); + ubcore_log_info("ubcore device destroyed success.\n"); + return 0; +} + +typedef int (*ubcore_device_handler)(void); + +static int ubcore_device_cdev_proc_withoutlock(ubcore_device_handler cb) +{ + struct ubcore_device *dev; + uint32_t cnt = 0; + int ret = 0; + + list_for_each_entry(dev, &g_device_list, list_node) { + if (dev->attr.tp_maintainer) + ++cnt; + } + if (cnt == 0) + ret = cb(); + + return ret; +} + +static int ubcore_device_cdev_proc(ubcore_device_handler cb) +{ + int ret = 0; + + down_read(&g_device_rwsem); + ret = ubcore_device_cdev_proc_withoutlock(cb); + up_read(&g_device_rwsem); + return ret; +} + int ubcore_register_device(struct ubcore_device *dev) { struct ubcore_device *find_dev = NULL; int ret; if (dev == NULL || dev->ops == NULL || strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) == 0 || - strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) > UBCORE_MAX_DEV_NAME - 1) { + strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } @@ -1249,8 +1508,20 @@ int ubcore_register_device(struct ubcore_device *dev) return -EINVAL; } + // dev->attr is invalid before init_ubcore_device + if (dev->attr.tp_maintainer) { + ret = ubcore_device_cdev_proc(ubcore_register_sysfs); + if (ret) { + uninit_ubcore_device(dev); + ubcore_log_err("failed to create ubcore char device.\n"); + return -EINVAL; + } + } + ret = ubcore_create_main_device(dev, &init_net); if (ret) { + if (dev->attr.tp_maintainer) + (void)ubcore_device_cdev_proc(ubcore_unregister_sysfs); uninit_ubcore_device(dev); ubcore_log_err("create main device failed.\n"); return ret; @@ -1263,19 +1534,19 @@ int ubcore_register_device(struct ubcore_device *dev) } ubcore_cgroup_reg_dev(dev); - mutex_lock(&g_device_mutex); + down_write(&g_device_rwsem); ubcore_clients_add(dev); ret = ubcore_copy_logic_devices(dev); if (ret) { ubcore_clients_remove(dev); - mutex_unlock(&g_device_mutex); + up_write(&g_device_rwsem); ubcore_log_err("copy logic device failed, device:%s.\n", dev->dev_name); goto err; } list_add_tail(&dev->list_node, &g_device_list); - mutex_unlock(&g_device_mutex); + up_write(&g_device_rwsem); ubcore_log_info("ubcore device: %s register success.\n", dev->dev_name); return 0; @@ -1285,13 +1556,19 @@ int ubcore_register_device(struct ubcore_device *dev) destroy_mdev: ubcore_destroy_main_device(dev); uninit_ubcore_device(dev); + if (dev->attr.tp_maintainer) + (void)ubcore_device_cdev_proc(ubcore_unregister_sysfs); return ret; } EXPORT_SYMBOL(ubcore_register_device); void ubcore_unregister_device(struct ubcore_device *dev) { - mutex_lock(&g_device_mutex); + if (dev == NULL || strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_warn("Invalid input dev is null ptr.\n"); + return; + } + down_write(&g_device_rwsem); /* Remove device from g_device_list */ list_del(&dev->list_node); @@ -1299,6 +1576,7 @@ void ubcore_unregister_device(struct ubcore_device *dev) /* Destroy uburma device, may be scheduled. * This should not be done within a spin_lock_irqsave */ + downgrade_write(&g_device_rwsem); ubcore_clients_remove(dev); ubcore_flush_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); @@ -1309,8 +1587,10 @@ void ubcore_unregister_device(struct ubcore_device *dev) ubcore_remove_logic_devices(dev); ubcore_destroy_main_device(dev); uninit_ubcore_device(dev); + if (dev->attr.tp_maintainer) + (void)ubcore_device_cdev_proc_withoutlock(ubcore_unregister_sysfs); - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); /* Pair with set use_cnt = 1 when init device */ ubcore_put_device(dev); @@ -1454,7 +1734,7 @@ void ubcore_dispatch_async_event(struct ubcore_event *event) } EXPORT_SYMBOL(ubcore_dispatch_async_event); -static bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index) +bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index) { struct net *net; @@ -1491,29 +1771,30 @@ struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_ struct ubcore_cg_object cg_obj; int ret; - if (dev == NULL || dev->ops == NULL || dev->ops->alloc_ucontext == NULL || + if (dev == NULL || strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || + dev->ops == NULL || dev->ops->alloc_ucontext == NULL || eid_index >= UBCORE_MAX_EID_CNT) { ubcore_log_err("Invalid argument.\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (!ubcore_dev_accessible(dev, current->nsproxy->net_ns) || !ubcore_eid_accessible(dev, eid_index)) { ubcore_log_err("eid is not accessible by current ns.\n"); - return NULL; + return ERR_PTR(-EPERM); } ret = ubcore_cgroup_try_charge(&cg_obj, dev, UBCORE_RESOURCE_HCA_HANDLE); if (ret != 0) { ubcore_log_err("cgroup charge fail:%d ,dev_name :%s\n", ret, dev->dev_name); - return NULL; + return ERR_PTR(-EPERM); } ucontext = dev->ops->alloc_ucontext(dev, eid_index, udrv_data); - if (ucontext == NULL) { + if (IS_ERR_OR_NULL(ucontext)) { ubcore_log_err("failed to alloc ucontext.\n"); ubcore_cgroup_uncharge(&cg_obj, dev, UBCORE_RESOURCE_HCA_HANDLE); - return NULL; + return ucontext == NULL ? ERR_PTR(-ENOEXEC) : ucontext; } ucontext->eid_index = eid_index; @@ -1574,7 +1855,7 @@ int ubcore_add_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ue ret = op_dev->ops->add_ueid(op_dev, fe_idx, cfg); if (ret != 0) { ubcore_log_err("failed to add ueid, ret:%d\n", - fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); + fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); goto put_dev; } @@ -1617,7 +1898,8 @@ int ubcore_query_device_attr(struct ubcore_device *dev, struct ubcore_device_att { int ret; - if (dev == NULL || dev->ops == NULL || dev->ops->query_device_attr == NULL) { + if (dev == NULL || attr == NULL || dev->ops == NULL || + dev->ops->query_device_attr == NULL) { ubcore_log_err("Invalid argument.\n"); return -EINVAL; } @@ -1635,7 +1917,8 @@ int ubcore_query_device_status(struct ubcore_device *dev, struct ubcore_device_s { int ret; - if (dev == NULL || dev->ops == NULL || dev->ops->query_device_status == NULL) { + if (dev == NULL || status == NULL || dev->ops == NULL || + dev->ops->query_device_status == NULL) { ubcore_log_err("Invalid argument.\n"); return -EINVAL; } @@ -1655,7 +1938,7 @@ int ubcore_query_resource(struct ubcore_device *dev, struct ubcore_res_key *key, int ret; if (dev == NULL || key == NULL || val == NULL || dev->ops == NULL || - dev->ops->query_res == NULL) { + dev->ops->query_res == NULL) { ubcore_log_err("Invalid argument.\n"); return -EINVAL; } @@ -1730,46 +2013,75 @@ int ubcore_query_stats(struct ubcore_device *dev, struct ubcore_stats_key *key, } EXPORT_SYMBOL(ubcore_query_stats); -static int ubcore_add_device_sip(struct ubcore_device *dev, struct ubcore_sip_info *sip) +static int ubcore_add_device_sip(struct ubcore_sip_info *sip, uint32_t *sip_idx) { + struct ubcore_device *dev; uint32_t index; + int ret = 0; - if (ubcore_lookup_sip_idx(&dev->sip_table, sip, &index) == 0) { - ubcore_log_err("sip already exists\n"); + if (sip == NULL) { + ubcore_log_err("There is an illegal parameter.\n"); return -1; } - index = ubcore_sip_idx_alloc(&dev->sip_table); - if (dev->ops->add_net_addr != NULL && dev->ops->add_net_addr(dev, &sip->addr, index) != 0) { - ubcore_log_err("Failed to set net addr"); - goto free_sip_index; + dev = ubcore_find_tpf_device_by_name(sip->dev_name, UBCORE_TRANSPORT_UB); + if (!dev) { + ubcore_log_err("update sip find no tpf\n"); + return -1; + } + + if (ubcore_lookup_sip_idx(&dev->sip_table, sip, &index) == 0) { + ubcore_log_warn("sip already exists, sip_idx %u\n", index); + ret = -EEXIST; + } else { + index = ubcore_sip_idx_alloc(&dev->sip_table); + + if (dev->ops->add_net_addr != NULL && + dev->ops->add_net_addr(dev, &sip->addr, index) != 0) { + ubcore_log_err("Failed to set net addr"); + goto free_sip_index; + } + /* add net_addr entry, record idx -> netaddr mapping */ + if (ubcore_add_sip_entry(&dev->sip_table, sip, index) != 0) + goto del_net_addr; } - /* add net_addr entry, record idx -> netaddr mapping */ - if (ubcore_add_sip_entry(&dev->sip_table, sip, index) != 0) - goto del_net_addr; /* nodify uvs add sip info */ - if (ubcore_get_netlink_valid() == true && ubcore_notify_uvs_add_sip(dev, sip, index) != 0) - goto del_sip_entry; + if (ubcore_get_netlink_valid() == true) + (void)ubcore_notify_uvs_add_sip(dev, sip, index); - return 0; + *sip_idx = index; + ubcore_put_device(dev); + return ret; -del_sip_entry: - (void)ubcore_del_sip_entry(&dev->sip_table, index); del_net_addr: if (dev->ops->delete_net_addr != NULL) dev->ops->delete_net_addr(dev, index); free_sip_index: (void)ubcore_sip_idx_free(&dev->sip_table, index); + ubcore_put_device(dev); return -1; } -static int ubcore_del_device_sip(struct ubcore_device *dev, struct ubcore_sip_info *sip) +static int ubcore_del_device_sip(struct ubcore_sip_info *sip) { + struct ubcore_device *dev; uint32_t index; + if (sip == NULL) { + ubcore_log_err("There is an illegal parameter.\n"); + return -1; + } + + dev = ubcore_find_tpf_device_by_name(sip->dev_name, UBCORE_TRANSPORT_UB); + if (!dev) { + ubcore_log_err("update sip find no tpf\n"); + return -1; + } + if (ubcore_lookup_sip_idx(&dev->sip_table, sip, &index) != 0) { ubcore_log_err("sip not exists\n"); + ubcore_put_device(dev); return -1; } @@ -1784,6 +2096,7 @@ static int ubcore_del_device_sip(struct ubcore_device *dev, struct ubcore_sip_in goto add_net_addr; (void)ubcore_sip_idx_free(&dev->sip_table, index); + ubcore_put_device(dev); return 0; add_net_addr: @@ -1791,47 +2104,30 @@ static int ubcore_del_device_sip(struct ubcore_device *dev, struct ubcore_sip_in dev->ops->add_net_addr(dev, &sip->addr, index); add_sip_entry: (void)ubcore_add_sip_entry(&dev->sip_table, sip, index); + ubcore_put_device(dev); return -1; } -static int ubcore_update_sip(struct ubcore_sip_info *sip, bool is_add) +int ubcore_add_sip(struct ubcore_sip_info *sip, uint32_t *sip_idx) { - struct ubcore_device *tpf_dev; - - if (sip == NULL) { - ubcore_log_err("There is an illegal parameter.\n"); - return -1; - } - tpf_dev = ubcore_find_tpf_device_by_name(sip->dev_name, UBCORE_TRANSPORT_UB); - if (!tpf_dev) { - ubcore_log_err("update sip find no tpf\n"); - return -1; - } - - if (is_add) { - if (ubcore_add_device_sip(tpf_dev, sip) != 0) { - ubcore_put_device(tpf_dev); - return -1; - } - } else { - if (ubcore_del_device_sip(tpf_dev, sip) != 0) { - ubcore_put_device(tpf_dev); - return -1; - } + if (sip == NULL || sip_idx == NULL || + strnlen(sip->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || + strnlen(sip->netdev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_err("invalid parameter.\n"); + return -EINVAL; } - ubcore_put_device(tpf_dev); - return 0; -} - -int ubcore_add_sip(struct ubcore_sip_info *sip) -{ - return ubcore_update_sip(sip, true); + return ubcore_add_device_sip(sip, sip_idx); } EXPORT_SYMBOL(ubcore_add_sip); int ubcore_delete_sip(struct ubcore_sip_info *sip) { - return ubcore_update_sip(sip, false); + if (sip == NULL || strnlen(sip->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_err("invalid parameter.\n"); + return -EINVAL; + } + + return ubcore_del_device_sip(sip); } EXPORT_SYMBOL(ubcore_delete_sip); @@ -1889,19 +2185,17 @@ void ubcore_sync_sip_table(void) struct ubcore_sip_table *sip_table; struct ubcore_device *dev = NULL; struct ubcore_sip_info *sip; - uint32_t max_cnt; uint32_t i; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev != NULL && dev->attr.tp_maintainer == true) { ubcore_get_device(dev); sip_table = &dev->sip_table; mutex_lock(&sip_table->lock); - max_cnt = ubcore_get_sip_max_cnt(sip_table); - for (i = 0; i < max_cnt; i++) { - sip = sip_table->entry[i]; - if (sip == NULL) + for (i = 0; i < sip_table->max_sip_cnt; i++) { + sip = &sip_table->entry[i]; + if (!sip->is_active) continue; if (ubcore_get_netlink_valid() == true) (void)ubcore_notify_uvs_add_sip(dev, sip, i); @@ -1910,37 +2204,45 @@ void ubcore_sync_sip_table(void) ubcore_put_device(dev); } } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); } -struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(struct ubcore_net_addr *addr) +static int ubcore_lookup_sip_by_addr(struct ubcore_device *dev, + const union ubcore_net_addr_union *addr) +{ + struct ubcore_sip_table *sip_table = NULL; + uint32_t i; + + sip_table = &dev->sip_table; + mutex_lock(&sip_table->lock); + for (i = 0; i < sip_table->max_sip_cnt; i++) { + if (sip_table->entry[i].is_active && + memcmp(addr, &sip_table->entry[i].addr.net_addr, + sizeof(union ubcore_net_addr_union)) == 0) { + mutex_unlock(&sip_table->lock); + return 0; + } + } + mutex_unlock(&sip_table->lock); + + return -1; +} + +struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(union ubcore_net_addr_union *addr) { struct ubcore_device *dev = NULL, *target = NULL; - struct ubcore_sip_table *sip_table; - uint32_t max_cnt; - uint32_t i = 0; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev != NULL && dev->attr.tp_maintainer == true) { - sip_table = &dev->sip_table; - mutex_lock(&sip_table->lock); - max_cnt = ubcore_get_sip_max_cnt(sip_table); - for (i = 0; dev != NULL && i < max_cnt; i++) { - if (sip_table->entry[i] != NULL && - memcmp(addr, &sip_table->entry[i]->addr, - sizeof(struct ubcore_net_addr)) == 0) { - target = dev; - ubcore_get_device(dev); - mutex_unlock(&sip_table->lock); - mutex_unlock(&g_device_mutex); - return target; - }; + if (ubcore_lookup_sip_by_addr(dev, addr) == 0) { + target = dev; + ubcore_get_device(dev); + break; } - mutex_unlock(&sip_table->lock); } } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); return target; } @@ -2034,7 +2336,8 @@ int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd) } /* Find device by name */ - mutex_lock(&g_device_mutex); + /* device_name len checked by genl */ + down_read(&g_device_rwsem); list_for_each_entry(tmp, &g_device_list, list_node) { if (strcmp(dev_name(tmp->ldev.dev), device_name) == 0) { dev = tmp; @@ -2051,7 +2354,7 @@ int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd) ret = ubcore_modify_dev_ns(dev, net, false); out: - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); put_net(net); return ret; } @@ -2104,24 +2407,23 @@ void ubcore_net_exit(struct net *net) spin_unlock_irqrestore(&g_ubcore_net_lock, flags); up_write(&g_ubcore_net_rwsem); + down_read(&g_device_rwsem); if (!g_shared_ns) { - mutex_lock(&g_device_mutex); list_for_each_entry(dev, &g_device_list, list_node) { if (dev->transport_type != UBCORE_TRANSPORT_UB) continue; (void)ubcore_modify_dev_ns(dev, &init_net, true); } - mutex_unlock(&g_device_mutex); } else { - mutex_lock(&g_device_mutex); list_for_each_entry(dev, &g_device_list, list_node) { - if (dev->transport_type != UBCORE_TRANSPORT_UB) + if (dev->transport_type != UBCORE_TRANSPORT_UB || + !net_eq(read_pnet(&dev->ldev.net), net)) continue; ubcore_remove_one_logic_device(dev, net); ubcore_invalidate_eid_ns(dev, net); } - mutex_unlock(&g_device_mutex); } + up_read(&g_device_rwsem); } static int ubcore_net_init(struct net *net) @@ -2148,7 +2450,7 @@ static int ubcore_net_init(struct net *net) if (!g_shared_ns) return 0; - mutex_lock(&g_device_mutex); + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { if (dev->transport_type != UBCORE_TRANSPORT_UB) continue; @@ -2159,7 +2461,7 @@ static int ubcore_net_init(struct net *net) if (ret) break; } - mutex_unlock(&g_device_mutex); + up_read(&g_device_rwsem); if (ret) ubcore_net_exit(net); @@ -2167,6 +2469,15 @@ static int ubcore_net_init(struct net *net) return 0; } +int ubcore_get_max_mtu(struct ubcore_device *dev, uint8_t port_num, enum ubcore_mtu *mtu) +{ + if (port_num >= dev->attr.port_cnt || port_num >= UBCORE_MAX_PORT_CNT) + return -1; + + *mtu = dev->attr.port_attr[port_num].max_mtu; + return 0; +} + static struct pernet_operations g_ubcore_net_ops = { .init = ubcore_net_init, .exit = ubcore_net_exit, @@ -2183,21 +2494,17 @@ void ubcore_unregister_pnet_ops(void) unregister_pernet_device(&g_ubcore_net_ops); } -int ubcore_class_register(struct class **ubcore_class) +int ubcore_class_register(void) { int ret; ret = class_register(&g_ubcore_class); - if (!ret) - *ubcore_class = &g_ubcore_class; - + if (ret) + ubcore_log_err("couldn't create class\n"); return ret; } -void ubcore_class_unregister(struct class *ubcore_class) +void ubcore_class_unregister(void) { - if (ubcore_class != &g_ubcore_class) - return; - class_unregister(&g_ubcore_class); } diff --git a/drivers/ub/urma/ubcore/ubcore_device.h b/drivers/ub/urma/ubcore/ubcore_device.h index 395eef63fef8..59f71ac9fae7 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.h +++ b/drivers/ub/urma/ubcore/ubcore_device.h @@ -23,9 +23,12 @@ int ubcore_register_pnet_ops(void); void ubcore_unregister_pnet_ops(void); -int ubcore_class_register(struct class **ubcore_class); -void ubcore_class_unregister(struct class *ubcore_class); +int ubcore_class_register(void); +void ubcore_class_unregister(void); int ubcore_set_ns_mode(bool shared); int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd); bool ubcore_dev_accessible(struct ubcore_device *dev, struct net *net); +int ubcore_get_max_mtu(struct ubcore_device *dev, uint8_t port_num, enum ubcore_mtu *mtu); +struct ubcore_nlmsg *ubcore_new_tpf_dev_msg(struct ubcore_device *dev); +bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index); #endif // UBCORE_DEVICE_H diff --git a/drivers/ub/urma/ubcore/ubcore_genl.c b/drivers/ub/urma/ubcore/ubcore_genl.c index 245508516ac6..fd10fe8455e2 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl.c +++ b/drivers/ub/urma/ubcore/ubcore_genl.c @@ -31,6 +31,7 @@ #include "ubcore_device.h" #include "ubcore_genl_admin.h" #include "ubcore_genl_define.h" +#include "ubcore_netlink.h" #include "ubcore_genl.h" static const struct nla_policy ubcore_policy[NUM_UBCORE_ATTR] = { @@ -41,6 +42,14 @@ static const struct nla_policy ubcore_policy[NUM_UBCORE_ATTR] = { [UBCORE_ATTR_NS_MODE] = { .type = NLA_U8 }, [UBCORE_ATTR_DEV_NAME] = { .type = NLA_STRING, .len = UBCORE_MAX_DEV_NAME - 1}, [UBCORE_ATTR_NS_FD] = { .type = NLA_U32 }, + [UBCORE_MSG_SEQ] = { .type = NLA_U32 }, + [UBCORE_MSG_TYPE] = { .type = NLA_U32 }, + [UBCORE_TRANSPORT_TYPE] = { .type = NLA_U32 }, + [UBORE_SRC_ID] = { .len = UBCORE_EID_SIZE}, + [UBORE_DST_ID] = { .len = UBCORE_EID_SIZE}, + [UBCORE_PAYLOAD_LEN] = { .type = NLA_U32 }, + [UBCORE_PAYLOAD_DATA] = { .type = NLA_BINARY }, + [UBCORE_UPDATE_EID_RET] = { .type = NLA_S32 } }; static const struct genl_ops ubcore_genl_ops[] = { @@ -68,14 +77,18 @@ static const struct genl_ops ubcore_genl_ops[] = { .cmd = UBCORE_CMD_ADD_EID, .policy = ubcore_policy, .maxattr = ARRAY_SIZE(ubcore_policy) - 1, - .doit = ubcore_add_eid_ops + .start = ubcore_add_eid_start, + .dumpit = ubcore_add_eid_dump, + .done = ubcore_add_eid_done }, { .cmd = UBCORE_CMD_DEL_EID, .policy = ubcore_policy, .maxattr = ARRAY_SIZE(ubcore_policy) - 1, .flags = GENL_ADMIN_PERM, - .doit = ubcore_delete_eid_ops + .start = ubcore_delete_eid_start, + .dumpit = ubcore_delete_eid_dump, + .done = ubcore_delete_eid_done }, { .cmd = UBCORE_CMD_SET_EID_MODE, @@ -87,14 +100,64 @@ static const struct genl_ops ubcore_genl_ops[] = { .cmd = UBCORE_CMD_SET_NS_MODE, .policy = ubcore_policy, .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .flags = GENL_ADMIN_PERM, .doit = ubcore_set_ns_mode_ops }, { .cmd = UBCORE_CMD_SET_DEV_NS, .policy = ubcore_policy, .maxattr = ARRAY_SIZE(ubcore_policy) - 1, + .flags = GENL_ADMIN_PERM, .doit = ubcore_set_dev_ns_ops }, + { + .cmd = UBCORE_CMD_SET_GENL_PID, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .policy = ubcore_policy, + .doit = ubcore_set_genl_pid_ops + }, + { + .cmd = UBCORE_CMD_UVS_INIT_RES, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .start = ubcore_get_uvs_init_res_start, + .dumpit = ubcore_get_uvs_init_res_dump, + .done = ubcore_get_uvs_init_res_done + }, + { + .cmd = UBCORE_CMD_TPF2FE_RESP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_tpf2fe_resp_ops, + }, + { + .cmd = UBCORE_CMD_RESTORE_TP_REQ, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_tp_req_ops, + }, + { + .cmd = UBCORE_CMD_QUERY_TP_RESP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_tp_resp_ops, + }, + { + .cmd = UBCORE_CMD_RESTORE_TP_RESP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_tp_resp_ops, + }, + { + .cmd = UBCORE_CMD_ADD_SIP_RESP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_tp_resp_ops, + }, + { + .cmd = UBCORE_CMD_DEL_SIP_RESP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_tp_resp_ops, + }, + { + .cmd = UBCORE_CMD_UPDATE_TPF_DEV_INFO_RESP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = ubcore_update_tpf_dev_info_resp_ops, + }, }; /* ubcore family definition */ diff --git a/drivers/ub/urma/ubcore/ubcore_genl_admin.c b/drivers/ub/urma/ubcore/ubcore_genl_admin.c index a3f3ba9bfa68..9220afd47b48 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl_admin.c +++ b/drivers/ub/urma/ubcore/ubcore_genl_admin.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "ubcore_genl_define.h" #include "urma/ubcore_api.h" #include "ubcore_msg.h" @@ -35,6 +37,7 @@ #define CB_ARGS_SART_IDX 2 #define CB_ARGS_NEXT_TYPE 3 #define CB_ARGS_BUF_LEN 4 +#define CB_ARGS_KEY_CNT 5 enum { UBCORE_RES_TPG_TP_CNT, @@ -78,6 +81,20 @@ enum { UBCORE_ATTR_RES_LAST }; +static int ubcore_parse_admin_res_cmd(struct netlink_callback *cb, void *dst, uint32_t copy_len) +{ + struct nlattr **attrs = genl_dumpit_info(cb)->attrs; + uint64_t args_addr; + + if (!attrs[UBCORE_HDR_ARGS_LEN] || !attrs[UBCORE_HDR_ARGS_ADDR]) + return -EINVAL; + + args_addr = nla_get_u64(attrs[UBCORE_HDR_ARGS_ADDR]); + + return ubcore_copy_from_user(dst, (void __user *)(uintptr_t)args_addr, + copy_len); +} + static void ubcore_update_pattern1_eid(struct ubcore_device *dev, union ubcore_eid *eid, bool is_add) { @@ -141,6 +158,7 @@ int ubcore_show_utp_ops(struct sk_buff *skb, struct genl_info *info) if (ret != 0) return -EPERM; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", @@ -183,6 +201,7 @@ int ubcore_query_stats_ops(struct sk_buff *skb, struct genl_info *info) if (ret != 0) return ret; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", @@ -207,27 +226,20 @@ int ubcore_query_stats_ops(struct sk_buff *skb, struct genl_info *info) sizeof(struct ubcore_cmd_query_stats)); } -static int ubcore_update_ueid(struct genl_info *info, enum ubcore_msg_opcode op) +static int ubcore_update_ueid(struct netlink_callback *cb, enum ubcore_msg_opcode op) { struct ubcore_cmd_update_ueid arg; + struct ubcore_update_eid_ctx *ctx; struct net *net = &init_net; struct ubcore_device *dev; - uint64_t args_addr; int ret = -EINVAL; + struct timespec64 tv; - if (!info->attrs[UBCORE_HDR_ARGS_LEN] || !info->attrs[UBCORE_HDR_ARGS_ADDR]) + ret = ubcore_parse_admin_res_cmd(cb, &arg, sizeof(struct ubcore_cmd_update_ueid)); + if (ret) return ret; - args_addr = nla_get_u64(info->attrs[UBCORE_HDR_ARGS_ADDR]); - if (!ns_capable(current->nsproxy->net_ns->user_ns, CAP_NET_ADMIN)) { - ubcore_log_err("current user does not have net admin capability"); - return -EPERM; - } - - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)args_addr, - sizeof(struct ubcore_cmd_update_ueid)); - if (ret != 0) - return -EPERM; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); @@ -255,23 +267,29 @@ static int ubcore_update_ueid(struct genl_info *info, enum ubcore_msg_opcode op) net = read_pnet(&dev->ldev.net); } - if (ubcore_msg_discover_eid(dev, arg.in.eid_index, op, net) != 0) - ret = -EPERM; + ctx = kcalloc(1, sizeof(struct ubcore_update_eid_ctx), GFP_KERNEL); + if (ctx == NULL) { + ubcore_put_device(dev); + if (arg.in.ns_fd >= 0) + put_net(net); + return -ENOMEM; + } + ret = ubcore_msg_discover_eid(dev, arg.in.eid_index, op, net, ctx); + if (ret != 0) { + ubcore_put_device(dev); + if (arg.in.ns_fd >= 0) + put_net(net); + kfree(ctx); + return -EPERM; + } if (arg.in.ns_fd >= 0) - put_net(net); - ubcore_put_device(dev); - return ret; -} - -int ubcore_delete_eid_ops(struct sk_buff *skb, struct genl_info *info) -{ - return ubcore_update_ueid(info, UBCORE_MSG_DEALLOC_EID); -} - -int ubcore_add_eid_ops(struct sk_buff *skb, struct genl_info *info) -{ - return ubcore_update_ueid(info, UBCORE_MSG_ALLOC_EID); + ctx->net = net; + ctx->dev = dev; + ktime_get_ts64(&tv); + ctx->start_ts = tv.tv_sec; + cb->args[0] = (long)ctx; + return 0; } int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) @@ -291,6 +309,8 @@ int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) sizeof(struct ubcore_cmd_set_eid_mode)); if (ret != 0) return -EPERM; + + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); @@ -307,7 +327,7 @@ int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { if (dev->eid_table.eid_entries[i].valid == true) { eid = dev->eid_table.eid_entries[i].eid; - if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) + if (dev->attr.pattern == (uint8_t)UBCORE_PATTERN_1) ubcore_update_pattern1_eid(dev, &eid, false); else ubcore_update_pattern3_eid(dev, &eid, false); @@ -421,370 +441,97 @@ static void ubcore_fill_res_seg(void *res_buf, struct sk_buff *msg, cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; } -static int ubcore_fill_dev_seg(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) +static int ubcore_fill_res_dev_ta_cnt(void *res_buf, struct sk_buff *msg, + struct netlink_callback *cb) { - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + struct ubcore_res_dev_ta_val *dev_val = res_buf; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_SEG_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_SEG_CNT, dev_val->seg_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_SEG_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_SEG_VAL) - return 0; - - for (; idx < dev_val->seg_cnt; ++idx) { - if (nla_put(msg, UBCORE_RES_DEV_SEG_VAL, sizeof(struct ubcore_seg_info), - dev_val->seg_list + idx)) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->seg_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFS_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_jfs(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JFS_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_JFS_CNT, dev_val->jfs_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFS_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JFS_VAL) - return 0; - - for (; idx < dev_val->jfs_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_JFS_VAL, dev_val->jfs_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->jfs_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFR_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_jfr(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JFR_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_JFR_CNT, dev_val->jfr_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFR_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JFR_VAL) - return 0; - - for (; idx < dev_val->jfr_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_JFR_VAL, dev_val->jfr_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->jfr_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFC_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_jfc(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JFC_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_JFC_CNT, dev_val->jfc_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JFC_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JFC_VAL) - return 0; - - for (; idx < dev_val->jfc_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_JFC_VAL, dev_val->jfc_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->jfc_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JETTY_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_jetty(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JETTY_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_JETTY_CNT, dev_val->jetty_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JETTY_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JETTY_VAL) - return 0; - - for (; idx < dev_val->jetty_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_JETTY_VAL, dev_val->jetty_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - if (idx == dev_val->jetty_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JTGRP_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_jettygrp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_JTGRP_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_JTGRP_CNT, dev_val->jetty_group_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_JTGRP_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_JTGRP_VAL) - return 0; - - for (; idx < dev_val->jetty_group_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_JTGRP_VAL, dev_val->jetty_group_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->jetty_group_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_RC_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_rc(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_RC_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_RC_CNT, dev_val->rc_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_RC_VAL; + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; } - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_RC_VAL) - return 0; - - for (; idx < dev_val->rc_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_RC_VAL, dev_val->rc_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - if (idx == dev_val->rc_cnt) { - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; - } return 0; } -static int ubcore_fill_dev_vtp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) +static int ubcore_fill_res_dev_tp_cnt(void *res_buf, struct sk_buff *msg, + struct netlink_callback *cb) { - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + struct ubcore_res_dev_tp_val *dev_val = res_buf; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_VTP_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_VTP_CNT, dev_val->vtp_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_VTP_VAL) - return 0; - - for (; idx < dev_val->vtp_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_VTP_VAL, dev_val->vtp_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->vtp_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TP_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_tp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_TP_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_TP_CNT, dev_val->tp_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TP_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_TP_VAL) - return 0; - - for (; idx < dev_val->tp_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_TP_VAL, dev_val->tp_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->tp_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TPG_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_tpg(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_TPG_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_TPG_CNT, dev_val->tpg_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_TPG_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_TPG_VAL) - return 0; - - for (; idx < dev_val->tpg_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_TPG_VAL, dev_val->tpg_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->tpg_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_UTP_CNT; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static int ubcore_fill_dev_utp(struct sk_buff *msg, struct ubcore_res_dev_val *dev_val, - struct netlink_callback *cb) -{ - uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; if (cb->args[CB_ARGS_NEXT_TYPE] == UBCORE_RES_DEV_UTP_CNT) { if (nla_put_u32(msg, UBCORE_RES_DEV_UTP_CNT, dev_val->utp_cnt)) return -1; - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_UTP_VAL; - } - - if (cb->args[CB_ARGS_NEXT_TYPE] != UBCORE_RES_DEV_UTP_VAL) - return 0; - - for (; idx < dev_val->utp_cnt; ++idx) { - if (nla_put_u32(msg, UBCORE_RES_DEV_UTP_VAL, dev_val->utp_list[idx])) - return -1; - - cb->args[CB_ARGS_SART_IDX] = idx; - } - - if (idx == dev_val->utp_cnt) { cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; - cb->args[CB_ARGS_SART_IDX] = 0; } - return 0; -} - -static void ubcore_fill_res_dev(void *res_buf, struct sk_buff *msg, struct netlink_callback *cb) -{ - struct ubcore_res_dev_val *dev_val = res_buf; - int ret; - - ret = ubcore_fill_dev_seg(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_jfs(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_jfr(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_jfc(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_jetty(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_jettygrp(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_rc(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_vtp(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_tp(msg, dev_val, cb); - if (ret != 0) - return; - - ret = ubcore_fill_dev_tpg(msg, dev_val, cb); - if (ret != 0) - return; - (void)ubcore_fill_dev_utp(msg, dev_val, cb); + return 0; } static int ubcore_fill_res(uint32_t type, void *res_buf, struct sk_buff *skb, @@ -800,11 +547,11 @@ static int ubcore_fill_res(uint32_t type, void *res_buf, struct sk_buff *skb, case UBCORE_RES_KEY_SEG: ubcore_fill_res_seg(res_buf, skb, cb); break; - case UBCORE_RES_KEY_URMA_DEV: - ubcore_fill_res_dev(res_buf, skb, cb); + case UBCORE_RES_KEY_DEV_TA: + ubcore_fill_res_dev_ta_cnt(res_buf, skb, cb); break; - case UBCORE_RES_KEY_UPI: - ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_UPI_VAL); + case UBCORE_RES_KEY_DEV_TP: + ubcore_fill_res_dev_tp_cnt(res_buf, skb, cb); break; case UBCORE_RES_KEY_VTP: ubcore_fill_res_binary(res_buf, skb, cb, UBCORE_RES_VTP_VAL); @@ -837,12 +584,88 @@ static int ubcore_fill_res(uint32_t type, void *res_buf, struct sk_buff *skb, return 0; } +static void ubcore_put_list_res(void *res_buf, struct sk_buff *msg, struct netlink_callback *cb, + int cnt_type, int val_type) +{ + struct ubcore_res_list_val *reslist = res_buf; + uint32_t idx = (uint32_t)cb->args[CB_ARGS_SART_IDX]; + + if (nla_put_u32(msg, cnt_type, reslist->cnt)) + return; + + for (; idx < reslist->cnt; ++idx) { + if (nla_put_u32(msg, val_type, reslist->list[idx])) + return; + + cb->args[CB_ARGS_SART_IDX] = idx; + } + if (idx == reslist->cnt) + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_ATTR_RES_LAST; +} + +static int ubcore_fill_list_res(uint32_t type, void *res_buf, struct sk_buff *skb, + struct netlink_callback *cb) +{ + switch (type) { + case UBCORE_RES_KEY_JETTY_GROUP: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_JTGRP_JETTY_CNT, UBCORE_RES_JTGRP_JETTY_VAL); + break; + case UBCORE_RES_KEY_SEG: + ubcore_fill_res_seg(res_buf, skb, cb); + break; + case UBCORE_RES_KEY_JFS: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_JFS_CNT, UBCORE_RES_DEV_JFS_VAL); + break; + case UBCORE_RES_KEY_JFR: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_JFR_CNT, UBCORE_RES_DEV_JFR_VAL); + break; + case UBCORE_RES_KEY_JETTY: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_JETTY_CNT, UBCORE_RES_DEV_JETTY_VAL); + break; + case UBCORE_RES_KEY_JFC: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_JFC_CNT, UBCORE_RES_DEV_JFC_VAL); + break; + case UBCORE_RES_KEY_RC: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_RC_CNT, UBCORE_RES_DEV_RC_VAL); + break; + case UBCORE_RES_KEY_TPG: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_TPG_CNT, UBCORE_RES_DEV_TPG_VAL); + break; + case UBCORE_RES_KEY_VTP: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_VTP_CNT, UBCORE_RES_DEV_VTP_VAL); + break; + case UBCORE_RES_KEY_TP: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_TP_CNT, UBCORE_RES_DEV_TP_VAL); + break; + case UBCORE_RES_KEY_UTP: + ubcore_put_list_res(res_buf, skb, cb, + UBCORE_RES_DEV_UTP_CNT, UBCORE_RES_DEV_UTP_VAL); + break; + case UBCORE_RES_KEY_DEV_TA: + ubcore_fill_res_dev_ta_cnt(res_buf, skb, cb); + break; + case UBCORE_RES_KEY_DEV_TP: + ubcore_fill_res_dev_tp_cnt(res_buf, skb, cb); + break; + default: + ubcore_log_err("key type :%u no support.\n", type); + return -1; + } + return 0; +} + static uint32_t ubcore_get_query_res_len(uint32_t type, struct netlink_callback *cb) { switch (type) { - case UBCORE_RES_KEY_UPI: - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_UPI_VAL; - return (uint32_t)sizeof(struct ubcore_res_upi_val); case UBCORE_RES_KEY_VTP: cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_VTP_VAL; return (uint32_t)sizeof(struct ubcore_res_vtp_val); @@ -876,9 +699,41 @@ static uint32_t ubcore_get_query_res_len(uint32_t type, struct netlink_callback case UBCORE_RES_KEY_SEG: cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_SEGVAL_SEG_CNT; return (uint32_t)sizeof(struct ubcore_res_seg_val); - case UBCORE_RES_KEY_URMA_DEV: + case UBCORE_RES_KEY_DEV_TA: cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_SEG_CNT; - return (uint32_t)sizeof(struct ubcore_res_dev_val); + return (uint32_t)sizeof(struct ubcore_res_dev_ta_val); + case UBCORE_RES_KEY_DEV_TP: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_CNT; + return (uint32_t)sizeof(struct ubcore_res_dev_tp_val); + default: + break; + } + return 0; +} + +static uint32_t ubcore_get_list_res_len(uint32_t type, struct netlink_callback *cb) +{ + switch (type) { + case UBCORE_RES_KEY_VTP: + case UBCORE_RES_KEY_TP: + case UBCORE_RES_KEY_TPG: + case UBCORE_RES_KEY_UTP: + case UBCORE_RES_KEY_JFS: + case UBCORE_RES_KEY_JFR: + case UBCORE_RES_KEY_JETTY: + case UBCORE_RES_KEY_JETTY_GROUP: + case UBCORE_RES_KEY_JFC: + case UBCORE_RES_KEY_RC: + return (uint32_t)sizeof(struct ubcore_res_list_val); + case UBCORE_RES_KEY_SEG: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_SEGVAL_SEG_CNT; + return (uint32_t)sizeof(struct ubcore_res_seg_val); + case UBCORE_RES_KEY_DEV_TA: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_SEG_CNT; + return (uint32_t)sizeof(struct ubcore_res_dev_ta_val); + case UBCORE_RES_KEY_DEV_TP: + cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_CNT; + return (uint32_t)sizeof(struct ubcore_res_dev_tp_val); default: break; } @@ -916,20 +771,6 @@ static void *ubcore_query_dev_info(struct ubcore_device *dev, struct ubcore_cmd_ return res_buf; } -static int parse_query_res_cmd(struct netlink_callback *cb, struct ubcore_cmd_query_res *arg) -{ - struct nlattr **attrs = genl_dumpit_info(cb)->attrs; - uint64_t args_addr; - - if (!attrs[UBCORE_HDR_ARGS_LEN] || !attrs[UBCORE_HDR_ARGS_ADDR]) - return -EINVAL; - - args_addr = nla_get_u64(attrs[UBCORE_HDR_ARGS_ADDR]); - - return ubcore_copy_from_user(arg, (void __user *)(uintptr_t)args_addr, - sizeof(struct ubcore_cmd_query_res)); -} - int ubcore_query_res_start(struct netlink_callback *cb) { struct ubcore_cmd_query_res arg = {0}; @@ -938,16 +779,20 @@ int ubcore_query_res_start(struct netlink_callback *cb) uint32_t res_len; void *res_buf; - ret = parse_query_res_cmd(cb, &arg); + ret = ubcore_parse_admin_res_cmd(cb, &arg, sizeof(struct ubcore_cmd_query_res)); if (ret) return ret; - res_len = ubcore_get_query_res_len((uint32_t)arg.in.type, cb); + if (arg.in.key_cnt == 0) + res_len = ubcore_get_list_res_len((uint32_t)arg.in.type, cb); + else + res_len = ubcore_get_query_res_len((uint32_t)arg.in.type, cb); if (res_len == 0) { ubcore_log_err("Failed to check res len, type: %u, res_len: %u.\n", (uint32_t)arg.in.type, res_len); return -EINVAL; } + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("find dev failed, arg_in: %s.\n", arg.in.dev_name); @@ -972,22 +817,51 @@ int ubcore_query_res_start(struct netlink_callback *cb) cb->args[CB_ARGS_CMD_TYPE] = (long)arg.in.type; cb->args[CB_ARGS_SART_IDX] = 0; cb->args[CB_ARGS_BUF_LEN] = res_len; + cb->args[CB_ARGS_KEY_CNT] = arg.in.key_cnt; return 0; } -static void ubcore_free_res_dev_list(struct ubcore_res_dev_val *kernal_addr) +static int ubcore_list_res_done(struct netlink_callback *cb) { - vfree(kernal_addr->seg_list); - vfree(kernal_addr->jfs_list); - vfree(kernal_addr->jfr_list); - vfree(kernal_addr->jfc_list); - vfree(kernal_addr->jetty_list); - vfree(kernal_addr->jetty_group_list); - vfree(kernal_addr->rc_list); - vfree(kernal_addr->vtp_list); - vfree(kernal_addr->tp_list); - vfree(kernal_addr->tpg_list); - vfree(kernal_addr->utp_list); + uint32_t type = (uint32_t)(unsigned long)cb->args[CB_ARGS_CMD_TYPE]; + void *res_buf = (void *)cb->args[CB_ARGS_DEV_BUF]; + struct ubcore_res_seg_val *seg_val; + struct ubcore_res_dev_ta_val *ta_val; + struct ubcore_res_dev_tp_val *tp_val; + struct ubcore_res_list_val *list_val; + + switch (type) { + case UBCORE_RES_KEY_JFS: + case UBCORE_RES_KEY_JFR: + case UBCORE_RES_KEY_JETTY: + case UBCORE_RES_KEY_JFC: + case UBCORE_RES_KEY_RC: + case UBCORE_RES_KEY_JETTY_GROUP: + case UBCORE_RES_KEY_VTP: + case UBCORE_RES_KEY_TP: + case UBCORE_RES_KEY_TPG: + case UBCORE_RES_KEY_UTP: + list_val = res_buf; + vfree(list_val->list); + break; + case UBCORE_RES_KEY_SEG: + seg_val = res_buf; + vfree(seg_val->seg_list); + break; + case UBCORE_RES_KEY_DEV_TA: + ta_val = res_buf; + vfree(ta_val); + break; + case UBCORE_RES_KEY_DEV_TP: + tp_val = res_buf; + vfree(tp_val); + break; + default: + break; + } + kfree(res_buf); + + return 0; } int ubcore_query_res_done(struct netlink_callback *cb) @@ -996,9 +870,11 @@ int ubcore_query_res_done(struct netlink_callback *cb) void *res_buf = (void *)cb->args[CB_ARGS_DEV_BUF]; struct ubcore_res_jetty_group_val *jtgrp_val; struct ubcore_res_seg_val *seg_val; - struct ubcore_res_dev_val *dev_val; struct ubcore_res_tpg_val *tpg_val; + if (cb->args[CB_ARGS_KEY_CNT] == 0) + return ubcore_list_res_done(cb); + switch (type) { case UBCORE_RES_KEY_TPG: tpg_val = res_buf; @@ -1012,10 +888,6 @@ int ubcore_query_res_done(struct netlink_callback *cb) seg_val = res_buf; vfree(seg_val->seg_list); break; - case UBCORE_RES_KEY_URMA_DEV: - dev_val = res_buf; - ubcore_free_res_dev_list(dev_val); - break; default: break; } @@ -1039,7 +911,10 @@ int ubcore_query_res_dump(struct sk_buff *skb, struct netlink_callback *cb) if (!hdr) return 0; - ret = ubcore_fill_res(type, res_buf, skb, cb); + if (cb->args[CB_ARGS_KEY_CNT] == 0) + ret = ubcore_fill_list_res(type, res_buf, skb, cb); + else + ret = ubcore_fill_res(type, res_buf, skb, cb); if (ret < 0) genlmsg_cancel(skb, hdr); else @@ -1047,3 +922,74 @@ int ubcore_query_res_dump(struct sk_buff *skb, struct netlink_callback *cb) return (int)skb->len; } + +static void ubcore_free_eid_ctx(struct ubcore_update_eid_ctx *ctx) +{ + if (ctx->net) + put_net(ctx->net); + if (ctx->dev) + ubcore_put_device(ctx->dev); + kfree(ctx->req_msg); + if (ctx->s) { + kfree(ctx->s->resp); + ubcore_destroy_msg_session(ctx->s); + } + kfree(ctx); + ubcore_log_info("updata eid done"); +} + +static int ubcore_dump_eid_ret(struct sk_buff *skb, struct netlink_callback *cb, + enum ubcore_cmd cmd_type) +{ + struct ubcore_update_eid_ctx *ctx = (struct ubcore_update_eid_ctx *)cb->args[0]; + void *hdr; + int ret; + + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, &ubcore_genl_family, + NLM_F_MULTI, (uint8_t)cmd_type); + if (!hdr) + return -ENOMEM; + ret = ubcore_update_uvs_eid_ret(ctx); + if (nla_put_s32(skb, UBCORE_UPDATE_EID_RET, ret)) + genlmsg_cancel(skb, hdr); + else + genlmsg_end(skb, hdr); + + return ret; +} + +int ubcore_add_eid_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + return ubcore_dump_eid_ret(skb, cb, UBCORE_CMD_ADD_EID); +} + +int ubcore_delete_eid_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + return ubcore_dump_eid_ret(skb, cb, UBCORE_CMD_DEL_EID); +} + +int ubcore_delete_eid_done(struct netlink_callback *cb) +{ + struct ubcore_update_eid_ctx *ctx = (struct ubcore_update_eid_ctx *)cb->args[0]; + + ubcore_free_eid_ctx(ctx); + return 0; +} + +int ubcore_add_eid_done(struct netlink_callback *cb) +{ + struct ubcore_update_eid_ctx *ctx = (struct ubcore_update_eid_ctx *)cb->args[0]; + + ubcore_free_eid_ctx(ctx); + return 0; +} + +int ubcore_delete_eid_start(struct netlink_callback *cb) +{ + return ubcore_update_ueid(cb, UBCORE_MSG_DEALLOC_EID); +} + +int ubcore_add_eid_start(struct netlink_callback *cb) +{ + return ubcore_update_ueid(cb, UBCORE_MSG_ALLOC_EID); +} diff --git a/drivers/ub/urma/ubcore/ubcore_genl_admin.h b/drivers/ub/urma/ubcore/ubcore_genl_admin.h index 84932736e37e..5784929e30fa 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl_admin.h +++ b/drivers/ub/urma/ubcore/ubcore_genl_admin.h @@ -28,11 +28,16 @@ int ubcore_query_stats_ops(struct sk_buff *skb, struct genl_info *info); int ubcore_query_res_start(struct netlink_callback *cb); int ubcore_query_res_dump(struct sk_buff *skb, struct netlink_callback *cb); int ubcore_query_res_done(struct netlink_callback *cb); -int ubcore_add_eid_ops(struct sk_buff *skb, struct genl_info *info); -int ubcore_delete_eid_ops(struct sk_buff *skb, struct genl_info *info); int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info); int ubcore_set_ns_mode_ops(struct sk_buff *skb, struct genl_info *info); int ubcore_set_dev_ns_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_add_eid_start(struct netlink_callback *cb); +int ubcore_add_eid_dump(struct sk_buff *skb, struct netlink_callback *cb); +int ubcore_add_eid_done(struct netlink_callback *cb); +int ubcore_delete_eid_start(struct netlink_callback *cb); +int ubcore_delete_eid_done(struct netlink_callback *cb); +int ubcore_delete_eid_dump(struct sk_buff *skb, struct netlink_callback *cb); + extern struct genl_family ubcore_genl_family; #endif // UBCORE_GENERIC_NETLINK_ADMIN_H diff --git a/drivers/ub/urma/ubcore/ubcore_genl_define.h b/drivers/ub/urma/ubcore/ubcore_genl_define.h index 930518f20d80..ad344eab6c1c 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl_define.h +++ b/drivers/ub/urma/ubcore/ubcore_genl_define.h @@ -33,6 +33,14 @@ enum { UBCORE_ATTR_NS_MODE, UBCORE_ATTR_DEV_NAME, UBCORE_ATTR_NS_FD, + UBCORE_MSG_SEQ, + UBCORE_MSG_TYPE, + UBCORE_TRANSPORT_TYPE, + UBORE_SRC_ID, + UBORE_DST_ID, + UBCORE_PAYLOAD_LEN, + UBCORE_PAYLOAD_DATA, + UBCORE_UPDATE_EID_RET, UBCORE_ATTR_AFTER_LAST, NUM_UBCORE_ATTR = UBCORE_ATTR_AFTER_LAST, UBCORE_ATTR_MAX = UBCORE_ATTR_AFTER_LAST - 1 diff --git a/drivers/ub/urma/ubcore/ubcore_hash_table.c b/drivers/ub/urma/ubcore/ubcore_hash_table.c index bd493dd4a9a9..2c8ffe59f8fb 100644 --- a/drivers/ub/urma/ubcore/ubcore_hash_table.c +++ b/drivers/ub/urma/ubcore/ubcore_hash_table.c @@ -187,12 +187,12 @@ int ubcore_hash_table_find_add(struct ubcore_hash_table *ht, struct hlist_node * spin_lock(&ht->lock); if (ht->head == NULL) { spin_unlock(&ht->lock); - return -1; + return -EINVAL; } /* Old entry with the same key exists */ if (ubcore_hash_table_lookup_nolock(ht, hash, ubcore_ht_key(ht, hnode)) != NULL) { spin_unlock(&ht->lock); - return -1; + return -EEXIST; } ubcore_hash_table_add_nolock(ht, hnode, hash); spin_unlock(&ht->lock); diff --git a/drivers/ub/urma/ubcore/ubcore_jetty.c b/drivers/ub/urma/ubcore/ubcore_jetty.c index 62d08bb15ac2..71bbf694c999 100644 --- a/drivers/ub/urma/ubcore/ubcore_jetty.c +++ b/drivers/ub/urma/ubcore/ubcore_jetty.c @@ -33,6 +33,8 @@ #include "ubcore_tp_table.h" #include "ubcore_vtp.h" #include "ubcore_tpg.h" +#include "ubcore_device.h" +#include "urma/ubcore_jetty.h" struct ubcore_jfc *ubcore_find_jfc(struct ubcore_device *dev, uint32_t jfc_id) { @@ -80,21 +82,22 @@ struct ubcore_jfc *ubcore_create_jfc(struct ubcore_device *dev, struct ubcore_jf struct ubcore_udata *udata) { struct ubcore_jfc *jfc; + int ret; if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jfc == NULL || dev->ops->destroy_jfc == NULL) - return NULL; + return ERR_PTR(-EINVAL); jfc = dev->ops->create_jfc(dev, cfg, udata); - if (jfc == NULL) { + if (IS_ERR_OR_NULL(jfc)) { ubcore_log_err("failed to create jfc.\n"); - return NULL; + return jfc == NULL ? ERR_PTR(-ENOEXEC) : jfc; } if (check_and_fill_jfc_attr(&jfc->jfc_cfg, cfg) != 0) { (void)dev->ops->destroy_jfc(jfc); ubcore_log_err("jfc cfg is not qualified.\n"); - return NULL; + return ERR_PTR(-EINVAL); } jfc->jfce_handler = jfce_handler; jfc->jfae_handler = jfae_handler; @@ -102,10 +105,11 @@ struct ubcore_jfc *ubcore_create_jfc(struct ubcore_device *dev, struct ubcore_jf jfc->uctx = ubcore_get_uctx(udata); atomic_set(&jfc->use_cnt, 0); - if (ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFC], &jfc->hnode, jfc->id) != 0) { + ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFC], &jfc->hnode, jfc->id); + if (ret != 0) { (void)dev->ops->destroy_jfc(jfc); ubcore_log_err("Failed to add jfc.\n"); - return NULL; + return ERR_PTR(ret); } return jfc; } @@ -118,7 +122,7 @@ int ubcore_modify_jfc(struct ubcore_jfc *jfc, struct ubcore_jfc_attr *attr, uint32_t jfc_id; int ret; - if (jfc == NULL || jfc->ub_dev == NULL || jfc->ub_dev->ops == NULL || + if (jfc == NULL || attr == NULL || jfc->ub_dev == NULL || jfc->ub_dev->ops == NULL || jfc->ub_dev->ops->modify_jfc == NULL) return -EINVAL; @@ -215,48 +219,52 @@ struct ubcore_jfs *ubcore_create_jfs(struct ubcore_device *dev, struct ubcore_jf ubcore_event_callback_t jfae_handler, struct ubcore_udata *udata) { struct ubcore_jfs *jfs; + int ret; - if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jfs == NULL || - dev->ops->destroy_jfs == NULL) - return NULL; + if (dev == NULL || dev->ops == NULL || dev->ops->create_jfs == NULL || + dev->ops->destroy_jfs == NULL || cfg == NULL || cfg->jfc == NULL || + !ubcore_eid_accessible(dev, cfg->eid_index)) + return ERR_PTR(-EINVAL); if (((uint16_t)cfg->trans_mode & dev->attr.dev_cap.trans_mode) == 0) { ubcore_log_err("jfs cfg is not supported.\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (check_jfs_cfg(dev, cfg) != 0) - return NULL; + return ERR_PTR(-EINVAL); jfs = dev->ops->create_jfs(dev, cfg, udata); - if (jfs == NULL) { + if (IS_ERR_OR_NULL(jfs)) { ubcore_log_err("failed to create jfs.\n"); - return NULL; + return jfs == NULL ? ERR_PTR(-ENOEXEC) : jfs; } /* Prevent ubcore private data from being modified */ if (check_and_fill_jfs_attr(&jfs->jfs_cfg, cfg) != 0) { (void)dev->ops->destroy_jfs(jfs); ubcore_log_err("jfs cfg is not qualified.\n"); - return NULL; + return ERR_PTR(-EINVAL); } jfs->ub_dev = dev; jfs->uctx = ubcore_get_uctx(udata); jfs->jfae_handler = jfae_handler; + jfs->jfs_id.eid = dev->eid_table.eid_entries[cfg->eid_index].eid; if (ubcore_jfs_need_advise(jfs)) { jfs->tptable = ubcore_create_tptable(); if (jfs->tptable == NULL) { (void)dev->ops->destroy_jfs(jfs); ubcore_log_err("Failed to create tp table in the jfs.\n"); - return NULL; + return ERR_PTR(-ENOMEM); } } atomic_set(&jfs->use_cnt, 0); - if (ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFS], &jfs->hnode, jfs->id) != 0) { + ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFS], &jfs->hnode, jfs->jfs_id.id); + if (ret != 0) { ubcore_destroy_tptable(&jfs->tptable); (void)dev->ops->destroy_jfs(jfs); ubcore_log_err("Failed to add jfs.\n"); - return NULL; + return ERR_PTR(ret); } atomic_inc(&cfg->jfc->use_cnt); @@ -271,11 +279,11 @@ int ubcore_modify_jfs(struct ubcore_jfs *jfs, struct ubcore_jfs_attr *attr, uint32_t jfs_id; int ret; - if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops == NULL || + if (jfs == NULL || attr == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops == NULL || jfs->ub_dev->ops->modify_jfs == NULL) return -EINVAL; - jfs_id = jfs->id; + jfs_id = jfs->jfs_id.id; dev = jfs->ub_dev; ret = dev->ops->modify_jfs(jfs, attr, udata); if (ret != 0) @@ -292,11 +300,11 @@ int ubcore_query_jfs(struct ubcore_jfs *jfs, struct ubcore_jfs_cfg *cfg, uint32_t jfs_id; int ret; - if (jfs == NULL || jfs->ub_dev == NULL || jfs->ub_dev->ops == NULL - || jfs->ub_dev->ops->query_jfs == NULL) + if (jfs == NULL || cfg == NULL || attr == NULL || jfs->ub_dev == NULL + || jfs->ub_dev->ops == NULL || jfs->ub_dev->ops->query_jfs == NULL) return -EINVAL; - jfs_id = jfs->id; + jfs_id = jfs->jfs_id.id; dev = jfs->ub_dev; ret = dev->ops->query_jfs(jfs, cfg, attr); if (ret != 0) @@ -318,7 +326,7 @@ int ubcore_delete_jfs(struct ubcore_jfs *jfs) return -EINVAL; jfc = jfs->jfs_cfg.jfc; - jfs_id = jfs->id; + jfs_id = jfs->jfs_id.id; dev = jfs->ub_dev; ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFS], &jfs->hnode); ubcore_destroy_tptable(&jfs->tptable); @@ -335,7 +343,7 @@ int ubcore_delete_jfs(struct ubcore_jfs *jfs) rollback: if (ubcore_jfs_need_advise(jfs)) jfs->tptable = ubcore_create_tptable(); - (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFS], &jfs->hnode, jfs->id); + (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFS], &jfs->hnode, jfs->jfs_id.id); return ret; } EXPORT_SYMBOL(ubcore_delete_jfs); @@ -375,40 +383,44 @@ struct ubcore_jfr *ubcore_create_jfr(struct ubcore_device *dev, struct ubcore_jf ubcore_event_callback_t jfae_handler, struct ubcore_udata *udata) { struct ubcore_jfr *jfr; + int ret; - if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jfr == NULL || - dev->ops->destroy_jfr == NULL) - return NULL; + if (dev == NULL || dev->ops == NULL || dev->ops->create_jfr == NULL || + dev->ops->destroy_jfr == NULL || cfg == NULL || cfg->jfc == NULL || + !ubcore_eid_accessible(dev, cfg->eid_index)) + return ERR_PTR(-EINVAL); jfr = dev->ops->create_jfr(dev, cfg, udata); - if (jfr == NULL) { + if (IS_ERR_OR_NULL(jfr)) { ubcore_log_err("failed to create jfr.\n"); - return NULL; + return jfr == NULL ? ERR_PTR(-ENOEXEC) : jfr; } if (check_and_fill_jfr_attr(&jfr->jfr_cfg, cfg) != 0) { ubcore_log_err("jfr cfg is not qualified.\n"); (void)dev->ops->destroy_jfr(jfr); - return NULL; + return ERR_PTR(-EINVAL); } jfr->ub_dev = dev; jfr->uctx = ubcore_get_uctx(udata); jfr->jfae_handler = jfae_handler; + jfr->jfr_id.eid = dev->eid_table.eid_entries[cfg->eid_index].eid; if (ubcore_jfr_need_advise(jfr)) { jfr->tptable = ubcore_create_tptable(); if (jfr->tptable == NULL) { (void)dev->ops->destroy_jfr(jfr); ubcore_log_err("Failed to create tp table in the jfr.\n"); - return NULL; + return ERR_PTR(-ENOMEM); } } atomic_set(&jfr->use_cnt, 0); - if (ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFR], &jfr->hnode, jfr->id) != 0) { + ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFR], &jfr->hnode, jfr->jfr_id.id); + if (ret != 0) { ubcore_destroy_tptable(&jfr->tptable); (void)dev->ops->destroy_jfr(jfr); ubcore_log_err("Failed to add jfr.\n"); - return NULL; + return ERR_PTR(ret); } atomic_inc(&cfg->jfc->use_cnt); @@ -423,11 +435,11 @@ int ubcore_modify_jfr(struct ubcore_jfr *jfr, struct ubcore_jfr_attr *attr, uint32_t jfr_id; int ret; - if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops == NULL || + if (jfr == NULL || attr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops == NULL || jfr->ub_dev->ops->modify_jfr == NULL) return -EINVAL; - jfr_id = jfr->id; + jfr_id = jfr->jfr_id.id; dev = jfr->ub_dev; ret = dev->ops->modify_jfr(jfr, attr, udata); if (ret != 0) @@ -444,11 +456,11 @@ int ubcore_query_jfr(struct ubcore_jfr *jfr, struct ubcore_jfr_cfg *cfg, uint32_t jfr_id; int ret; - if (jfr == NULL || jfr->ub_dev == NULL || jfr->ub_dev->ops == NULL || - jfr->ub_dev->ops->query_jfr == NULL) + if (jfr == NULL || cfg == NULL || attr == NULL || jfr->ub_dev == NULL || + jfr->ub_dev->ops == NULL || jfr->ub_dev->ops->query_jfr == NULL) return -EINVAL; - jfr_id = jfr->id; + jfr_id = jfr->jfr_id.id; dev = jfr->ub_dev; ret = dev->ops->query_jfr(jfr, cfg, attr); if (ret != 0) @@ -475,7 +487,7 @@ int ubcore_delete_jfr(struct ubcore_jfr *jfr) } jfc = jfr->jfr_cfg.jfc; - jfr_id = jfr->id; + jfr_id = jfr->jfr_id.id; dev = jfr->ub_dev; ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFR], &jfr->hnode); ubcore_destroy_tptable(&jfr->tptable); @@ -492,7 +504,7 @@ int ubcore_delete_jfr(struct ubcore_jfr *jfr) rollback: if (ubcore_jfr_need_advise(jfr)) jfr->tptable = ubcore_create_tptable(); - (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFR], &jfr->hnode, jfr->id); + (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFR], &jfr->hnode, jfr->jfr_id.id); return ret; } EXPORT_SYMBOL(ubcore_delete_jfr); @@ -503,15 +515,17 @@ struct ubcore_tjetty *ubcore_import_jfr(struct ubcore_device *dev, struct ubcore_vtp_param vtp_param; struct ubcore_tjetty *tjfr; - if (!ubcore_have_tp_ops(dev) || dev->ops->import_jetty == NULL || + if (!ubcore_have_tp_ops(dev) || dev->ops->import_jfr == NULL || dev->ops->unimport_jfr == NULL || cfg == NULL || dev->attr.dev_cap.max_eid_cnt < cfg->eid_index) - return NULL; + return ERR_PTR(-EINVAL); tjfr = dev->ops->import_jfr(dev, cfg, udata); - if (tjfr == NULL) { + if (IS_ERR_OR_NULL(tjfr)) { ubcore_log_err("UBEP failed to import jfr, jfr_id:%u.\n", cfg->id.id); - return NULL; + if (tjfr == NULL) + return ERR_PTR(-ENOEXEC); + return tjfr; } tjfr->cfg = *cfg; tjfr->ub_dev = dev; @@ -525,12 +539,14 @@ struct ubcore_tjetty *ubcore_import_jfr(struct ubcore_device *dev, ubcore_set_vtp_param(dev, NULL, cfg, &vtp_param); mutex_lock(&tjfr->lock); tjfr->vtpn = ubcore_connect_vtp(dev, &vtp_param); - if (tjfr->vtpn == NULL) { + if (IS_ERR_OR_NULL(tjfr->vtpn)) { mutex_unlock(&tjfr->lock); mutex_destroy(&tjfr->lock); (void)dev->ops->unimport_jfr(tjfr); ubcore_log_err("Failed to setup tp connection.\n"); - return NULL; + if (tjfr->vtpn == NULL) + return ERR_PTR(-ECONNREFUSED); + return (void *)tjfr->vtpn; } mutex_unlock(&tjfr->lock); } else { @@ -556,7 +572,7 @@ int ubcore_unimport_jfr(struct ubcore_tjetty *tjfr) (tjfr->cfg.trans_mode == UBCORE_TP_RM || tjfr->cfg.trans_mode == UBCORE_TP_UM) && tjfr->vtpn != NULL) { mutex_lock(&tjfr->lock); - ret = ubcore_disconnect_vtp(tjfr->vtpn); + ret = ubcore_disconnect_vtp(tjfr->vtpn, NULL); if (ret != 0) { ubcore_log_err("Failed to disconnect vtp.\n"); mutex_unlock(&tjfr->lock); @@ -739,34 +755,45 @@ static int ubcore_remove_jetty_from_jetty_grp(struct ubcore_jetty *jetty, return -1; } +static int ubcore_jetty_pre_check(struct ubcore_device *dev, struct ubcore_jetty_cfg *cfg) +{ + do { + if (check_jetty_cfg(dev, cfg) != 0) { + ubcore_log_err("failed to check jetty cfg.\n"); + break; + } + + if (check_jetty_cfg_with_jetty_grp(cfg) != 0) { + ubcore_log_err("failed to check jetty cfg.\n"); + break; + } + + if (check_jetty_check_dev_cap(dev, cfg) != 0) { + ubcore_log_err("failed to check jetty cfg.\n"); + break; + } + return 0; + } while (0); + return -EINVAL; +} + struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcore_jetty_cfg *cfg, ubcore_event_callback_t jfae_handler, struct ubcore_udata *udata) { struct ubcore_jetty *jetty; + int ret; if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->create_jetty == NULL || - dev->ops->destroy_jetty == NULL) - return NULL; + dev->ops->destroy_jetty == NULL || !ubcore_eid_accessible(dev, cfg->eid_index)) + return ERR_PTR(-EINVAL); - if (check_jetty_cfg(dev, cfg) != 0) { - ubcore_log_err("failed to check jetty cfg.\n"); - return NULL; - } - - if (check_jetty_cfg_with_jetty_grp(cfg) != 0) { - ubcore_log_err("failed to check jetty cfg.\n"); - return NULL; - } - - if (check_jetty_check_dev_cap(dev, cfg) != 0) { - ubcore_log_err("failed to check jetty cfg.\n"); - return NULL; - } + if (ubcore_jetty_pre_check(dev, cfg) != 0) + return ERR_PTR(-EINVAL); jetty = dev->ops->create_jetty(dev, cfg, udata); - if (jetty == NULL) { + if (IS_ERR_OR_NULL(jetty)) { ubcore_log_err("failed to create jetty.\n"); - return NULL; + return jetty == NULL ? ERR_PTR(-ENOEXEC) : jetty; } jetty->ub_dev = dev; @@ -774,20 +801,24 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor ubcore_add_jetty_to_jetty_grp(jetty, (struct ubcore_jetty_group *)cfg->jetty_grp) != 0) { ubcore_log_err("jetty cfg is not qualified.\n"); + ret = -EPERM; goto destroy_jetty; } if (check_and_fill_jetty_attr(&jetty->jetty_cfg, cfg) != 0) { ubcore_log_err("jetty cfg is not qualified.\n"); + ret = -EINVAL; goto delete_jetty_to_grp; } jetty->uctx = ubcore_get_uctx(udata); jetty->jfae_handler = jfae_handler; + jetty->jetty_id.eid = dev->eid_table.eid_entries[cfg->eid_index].eid; if (ubcore_jetty_need_advise(jetty) || jetty->jetty_cfg.trans_mode == UBCORE_TP_RC) { jetty->tptable = ubcore_create_tptable(); if (jetty->tptable == NULL) { ubcore_log_err("Failed to create tp table in the jetty.\n"); + ret = -ENOMEM; goto delete_jetty_to_grp; } } else { @@ -795,7 +826,9 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor } atomic_set(&jetty->use_cnt, 0); - if (ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode, jetty->id) != 0) { + ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JETTY], + &jetty->hnode, jetty->jetty_id.id); + if (ret != 0) { ubcore_log_err("Failed to add jetty.\n"); goto destroy_tptable; } @@ -814,7 +847,7 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor jetty, (struct ubcore_jetty_group *)cfg->jetty_grp); destroy_jetty: (void)dev->ops->destroy_jetty(jetty); - return NULL; + return ERR_PTR(ret); } EXPORT_SYMBOL(ubcore_create_jetty); @@ -824,12 +857,12 @@ int ubcore_modify_jetty(struct ubcore_jetty *jetty, struct ubcore_jetty_attr *at uint32_t jetty_id; int ret; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || + if (jetty == NULL || attr == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || jetty->ub_dev->ops->modify_jetty == NULL || attr == NULL) return -EINVAL; - jetty_id = jetty->id; + jetty_id = jetty->jetty_id.id; ret = jetty->ub_dev->ops->modify_jetty(jetty, attr, udata); if (ret != 0) @@ -846,11 +879,11 @@ int ubcore_query_jetty(struct ubcore_jetty *jetty, struct ubcore_jetty_cfg *cfg, uint32_t jetty_id; int ret; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || - jetty->ub_dev->ops->query_jetty == NULL) + if (jetty == NULL || cfg == NULL || attr == NULL || jetty->ub_dev == NULL || + jetty->ub_dev->ops == NULL || jetty->ub_dev->ops->query_jetty == NULL) return -EINVAL; - jetty_id = jetty->id; + jetty_id = jetty->jetty_id.id; dev = jetty->ub_dev; ret = dev->ops->query_jetty(jetty, cfg, attr); if (ret != 0) @@ -863,6 +896,7 @@ EXPORT_SYMBOL(ubcore_query_jetty); int ubcore_delete_jetty(struct ubcore_jetty *jetty) { struct ubcore_jetty_group *jetty_grp; + struct ubcore_vtp_param vtp_param; struct ubcore_jfc *send_jfc; struct ubcore_jfc *recv_jfc; struct ubcore_device *dev; @@ -885,14 +919,16 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) send_jfc = jetty->jetty_cfg.send_jfc; recv_jfc = jetty->jetty_cfg.recv_jfc; jfr = jetty->jetty_cfg.jfr; - jetty_id = jetty->id; + jetty_id = jetty->jetty_id.id; dev = jetty->ub_dev; ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode); ubcore_destroy_tptable(&jetty->tptable); if (jetty->ub_dev->transport_type == UBCORE_TRANSPORT_UB && jetty->remote_jetty != NULL) { + vtp_param.sub_trans_mode = jetty->remote_jetty->cfg.flag.bs.sub_trans_mode; + vtp_param.rc_share_tp = jetty->remote_jetty->cfg.flag.bs.rc_share_tp; mutex_lock(&jetty->remote_jetty->lock); - (void)ubcore_disconnect_vtp(jetty->remote_jetty->vtpn); + (void)ubcore_disconnect_vtp(jetty->remote_jetty->vtpn, &vtp_param); jetty->remote_jetty->vtpn = NULL; mutex_unlock(&jetty->remote_jetty->lock); atomic_dec(&jetty->remote_jetty->use_cnt); @@ -922,7 +958,8 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) (void)ubcore_add_jetty_to_jetty_grp(jetty, jetty_grp); if (ubcore_jetty_need_advise(jetty) || jetty->jetty_cfg.trans_mode == UBCORE_TP_RC) jetty->tptable = ubcore_create_tptable(); - (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode, jetty->id); + (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode, + jetty->jetty_id.id); return ret; } EXPORT_SYMBOL(ubcore_delete_jetty); @@ -948,12 +985,12 @@ struct ubcore_tjetty *ubcore_import_jetty(struct ubcore_device *dev, if (!ubcore_have_tp_ops(dev) || dev->ops->import_jetty == NULL || dev->ops->unimport_jetty == NULL || cfg == NULL || dev->attr.dev_cap.max_eid_cnt < cfg->eid_index) - return NULL; + return ERR_PTR(-EINVAL); tjetty = dev->ops->import_jetty(dev, cfg, udata); - if (tjetty == NULL) { + if (IS_ERR_OR_NULL(tjetty)) { ubcore_log_err("UBEP failed to import jetty, jetty_id:%u.\n", cfg->id.id); - return NULL; + return tjetty == NULL ? ERR_PTR(-ENOEXEC) : tjetty; } tjetty->cfg = *cfg; tjetty->ub_dev = dev; @@ -964,16 +1001,20 @@ struct ubcore_tjetty *ubcore_import_jetty(struct ubcore_device *dev, /* create rm tp if the remote eid is not connected */ if (dev->transport_type == UBCORE_TRANSPORT_UB && - (cfg->trans_mode == UBCORE_TP_RM || cfg->trans_mode == UBCORE_TP_UM)) { + (cfg->trans_mode == UBCORE_TP_RM || cfg->trans_mode == UBCORE_TP_UM || + is_create_rc_shared_tp(cfg->trans_mode, cfg->flag.bs.sub_trans_mode, + cfg->flag.bs.rc_share_tp))) { ubcore_set_vtp_param(dev, NULL, cfg, &vtp_param); mutex_lock(&tjetty->lock); tjetty->vtpn = ubcore_connect_vtp(dev, &vtp_param); - if (tjetty->vtpn == NULL) { + if (IS_ERR_OR_NULL(tjetty->vtpn)) { mutex_unlock(&tjetty->lock); mutex_destroy(&tjetty->lock); (void)dev->ops->unimport_jetty(tjetty); ubcore_log_err("Failed to setup tp connection.\n"); - return NULL; + if (tjetty->vtpn == NULL) + return ERR_PTR(-ECONNREFUSED); + return (void *)tjetty->vtpn; } mutex_unlock(&tjetty->lock); } else { @@ -986,6 +1027,7 @@ EXPORT_SYMBOL(ubcore_import_jetty); int ubcore_unimport_jetty(struct ubcore_tjetty *tjetty) { + struct ubcore_vtp_param vtp_param; struct ubcore_device *dev; int ret; @@ -997,10 +1039,15 @@ int ubcore_unimport_jetty(struct ubcore_tjetty *tjetty) if (dev->transport_type == UBCORE_TRANSPORT_UB && (tjetty->cfg.trans_mode == UBCORE_TP_RM || - tjetty->cfg.trans_mode == UBCORE_TP_UM) && + tjetty->cfg.trans_mode == UBCORE_TP_UM || + is_create_rc_shared_tp(tjetty->cfg.trans_mode, + tjetty->cfg.flag.bs.sub_trans_mode, + tjetty->cfg.flag.bs.rc_share_tp)) && tjetty->vtpn != NULL) { + vtp_param.sub_trans_mode = tjetty->cfg.flag.bs.sub_trans_mode; + vtp_param.rc_share_tp = tjetty->cfg.flag.bs.rc_share_tp; mutex_lock(&tjetty->lock); - ret = ubcore_disconnect_vtp(tjetty->vtpn); + ret = ubcore_disconnect_vtp(tjetty->vtpn, &vtp_param); if (ret != 0) { mutex_unlock(&tjetty->lock); ubcore_log_err("Failed to disconnect vtp.\n"); @@ -1213,17 +1260,23 @@ static int ubcore_inner_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tje } atomic_inc(&jetty->use_cnt); - ubcore_set_vtp_param(dev, jetty, &tjetty->cfg, &vtp_param); - mutex_lock(&tjetty->lock); - vtpn = ubcore_connect_vtp(dev, &vtp_param); - if (vtpn == NULL) { + if (!is_create_rc_shared_tp(jetty->jetty_cfg.trans_mode, + jetty->jetty_cfg.flag.bs.sub_trans_mode, + jetty->jetty_cfg.flag.bs.rc_share_tp)) { + ubcore_set_vtp_param(dev, jetty, &tjetty->cfg, &vtp_param); + mutex_lock(&tjetty->lock); + vtpn = ubcore_connect_vtp(dev, &vtp_param); + if (IS_ERR_OR_NULL(vtpn)) { + mutex_unlock(&tjetty->lock); + ubcore_log_err("Failed to setup vtp connection.\n"); + ret = -1; + if (vtpn != NULL) + ret = PTR_ERR(vtpn); + goto unbind; + } + tjetty->vtpn = vtpn; mutex_unlock(&tjetty->lock); - ubcore_log_err("Failed to setup vtp connection.\n"); - ret = -1; - goto unbind; } - tjetty->vtpn = vtpn; - mutex_unlock(&tjetty->lock); } else if (dev->transport_type == UBCORE_TRANSPORT_IB) { ret = ubcore_advice_jetty_tjetty(&advice, jetty, tjetty); if (ret != 0) @@ -1236,7 +1289,7 @@ static int ubcore_inner_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tje return ret; } } - ubcore_log_info("jetty: %u bind tjetty: %u\n", jetty->id, tjetty->cfg.id.id); + ubcore_log_info("jetty: %u bind tjetty: %u\n", jetty->jetty_id.id, tjetty->cfg.id.id); jetty->remote_jetty = tjetty; atomic_inc(&tjetty->use_cnt); return 0; @@ -1264,7 +1317,7 @@ int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, } if (jetty->remote_jetty == tjetty) { ubcore_log_info("bind reentry, jetty: %u bind tjetty: %u\n", - jetty->id, tjetty->cfg.id.id); + jetty->jetty_id.id, tjetty->cfg.id.id); return 0; } if (jetty->remote_jetty != NULL) { @@ -1303,15 +1356,19 @@ int ubcore_unbind_jetty(struct ubcore_jetty *jetty) if (dev->transport_type == UBCORE_TRANSPORT_UB) { if (tjetty->vtpn != NULL) { - mutex_lock(&tjetty->lock); - ret = ubcore_disconnect_vtp(tjetty->vtpn); - if (ret != 0) { + if (!is_create_rc_shared_tp(jetty->jetty_cfg.trans_mode, + jetty->jetty_cfg.flag.bs.sub_trans_mode, + jetty->jetty_cfg.flag.bs.rc_share_tp)) { + mutex_lock(&tjetty->lock); + ret = ubcore_disconnect_vtp(tjetty->vtpn, NULL); + if (ret != 0) { + mutex_unlock(&tjetty->lock); + ubcore_log_err("Failed to disconnect vtp.\n"); + return ret; + } + tjetty->vtpn = NULL; mutex_unlock(&tjetty->lock); - ubcore_log_err("Failed to disconnect vtp.\n"); - return ret; } - tjetty->vtpn = NULL; - mutex_unlock(&tjetty->lock); } } else if (dev->transport_type == UBCORE_TRANSPORT_IB) { ret = ubcore_advice_jetty_tjetty(&advice, jetty, tjetty); @@ -1325,7 +1382,8 @@ int ubcore_unbind_jetty(struct ubcore_jetty *jetty) return ret; } } - ubcore_log_info("jetty: %u unbind tjetty: %u\n", jetty->id, tjetty->cfg.id.id); + + ubcore_log_info("jetty: %u unbind tjetty: %u\n", jetty->jetty_id.id, tjetty->cfg.id.id); /* IB devices don't need to call bind_jetty and unbind_jetty */ if (dev->transport_type == UBCORE_TRANSPORT_UB) { @@ -1367,21 +1425,22 @@ struct ubcore_jetty_group *ubcore_create_jetty_grp(struct ubcore_device *dev, uint32_t max_jetty_in_jetty_grp; uint32_t i; - if (dev == NULL || cfg == NULL || udata == NULL || dev->ops == NULL || - dev->ops->create_jetty_grp == NULL || dev->ops->delete_jetty_grp == NULL) - return NULL; + if (dev == NULL || cfg == NULL || dev->ops == NULL || + dev->ops->create_jetty_grp == NULL || dev->ops->delete_jetty_grp == NULL || + !ubcore_eid_accessible(dev, cfg->eid_index)) + return ERR_PTR(-EINVAL); max_jetty_in_jetty_grp = dev->attr.dev_cap.max_jetty_in_jetty_grp; if (max_jetty_in_jetty_grp == 0 || max_jetty_in_jetty_grp > UBCORE_MAX_JETTY_IN_JETTY_GRP) { ubcore_log_err("max_jetty_in_jetty_grp %u is err, range is 1 to %u.\n", max_jetty_in_jetty_grp, UBCORE_MAX_JETTY_IN_JETTY_GRP); - return NULL; + return ERR_PTR(-EINVAL); } jetty_grp = dev->ops->create_jetty_grp(dev, (struct ubcore_jetty_grp_cfg *)cfg, udata); - if (jetty_grp == NULL) { + if (IS_ERR_OR_NULL(jetty_grp)) { ubcore_log_err("failed to create jetty_grp.\n"); - return NULL; + return jetty_grp == NULL ? ERR_PTR(-ENOEXEC) : jetty_grp; } jetty_grp->jetty = kzalloc( @@ -1389,13 +1448,14 @@ struct ubcore_jetty_group *ubcore_create_jetty_grp(struct ubcore_device *dev, if (jetty_grp->jetty == NULL) { (void)dev->ops->delete_jetty_grp(jetty_grp); ubcore_log_err("Failed to alloc jetty array.\n"); - return NULL; + return ERR_PTR(-ENOMEM); } jetty_grp->ub_dev = dev; jetty_grp->jetty_grp_cfg = *cfg; jetty_grp->jfae_handler = jfae_handler; jetty_grp->uctx = ubcore_get_uctx(udata); + jetty_grp->jetty_grp_id.eid = dev->eid_table.eid_entries[cfg->eid_index].eid; mutex_init(&jetty_grp->lock); jetty_grp->jetty_cnt = 0; for (i = 0; i < dev->attr.dev_cap.max_jetty_in_jetty_grp; i++) @@ -1415,7 +1475,7 @@ int ubcore_delete_jetty_grp(struct ubcore_jetty_group *jetty_grp) jetty_grp->ub_dev->ops->delete_jetty_grp == NULL) return -EINVAL; - jetty_grp_id = jetty_grp->id; + jetty_grp_id = jetty_grp->jetty_grp_id.id; dev = jetty_grp->ub_dev; mutex_lock(&jetty_grp->lock); diff --git a/drivers/ub/urma/ubcore/ubcore_main.c b/drivers/ub/urma/ubcore/ubcore_main.c index dc08b66ca18a..e7b859b11f7b 100644 --- a/drivers/ub/urma/ubcore/ubcore_main.c +++ b/drivers/ub/urma/ubcore/ubcore_main.c @@ -52,25 +52,13 @@ MODULE_PARM_DESC(g_ubcore_log_level, " 3: ERR, 4: WARNING, 6: INFO, 7: DEBUG"); /* ubcore create independent cdev and ioctl channels * to handle public work. */ -#define UBCORE_DEVICE_NAME "ubcore" #define UBCORE_IPV4_MAP_IPV6_PREFIX 0x0000ffff #define UBCORE_LOCAL_SHUNET (0xfe80000000000000ULL) #define SIP_MTU_BITS_BASE_SHIFT 7 - -struct ubcore_ctx { - dev_t ubcore_devno; - struct cdev ubcore_cdev; - struct class *ubcore_class; - struct device *ubcore_dev; -}; - -static struct ubcore_ctx g_ubcore_ctx; - struct ubcore_net_addr_node { struct list_head node; struct ubcore_net_addr addr; - uint32_t prefix_len; }; enum ubcore_bond_op_type { @@ -108,11 +96,6 @@ struct ubcore_notify_uvs_sip_event_work { uint32_t index; }; -int ubcore_open(struct inode *i_node, struct file *filp) -{ - return 0; -} - static void ubcore_update_pattern1_eid(struct ubcore_device *dev, union ubcore_eid *eid, uint32_t eid_idx, bool is_add) { @@ -150,91 +133,6 @@ static void ubcore_update_pattern3_eid(struct ubcore_device *dev, } } -static long ubcore_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct ubcore_cmd_hdr hdr; - int ret; - - if (cmd == UBCORE_UVS_CMD) { - ret = ubcore_copy_from_user(&hdr, (void *)arg, sizeof(struct ubcore_cmd_hdr)); - if ((ret != 0) || (hdr.args_len > UBCORE_MAX_CMD_SIZE)) { - ubcore_log_err("length of ioctl input parameter is out of range.\n"); - return -EINVAL; - } - return ubcore_uvs_cmd_parse(&hdr); - } - - ubcore_log_err("bad ioctl command.\n"); - return -ENOIOCTLCMD; -} - -static int ubcore_close(struct inode *i_node, struct file *filp) -{ - return 0; -} - -static const struct file_operations g_ubcore_ops = { - .owner = THIS_MODULE, - .open = ubcore_open, - .release = ubcore_close, - .unlocked_ioctl = ubcore_ioctl, - .compat_ioctl = ubcore_ioctl, -}; - -static int ubcore_register_sysfs(void) -{ - int ret; - - /* /sys/class/ubus/ubcore */ - ret = ubcore_class_register(&g_ubcore_ctx.ubcore_class); - if (ret) { - ubcore_log_err("couldn't create class\n"); - return ret; - } - - ret = alloc_chrdev_region(&g_ubcore_ctx.ubcore_devno, 0, 1, UBCORE_DEVICE_NAME); - if (ret != 0) { - ubcore_log_err("alloc chrdev region failed, ret:%d.\n", ret); - goto unreg_class; - } - - cdev_init(&g_ubcore_ctx.ubcore_cdev, &g_ubcore_ops); - ret = cdev_add(&g_ubcore_ctx.ubcore_cdev, g_ubcore_ctx.ubcore_devno, 1); - if (ret != 0) { - ubcore_log_err("chrdev add failed, ret:%d.\n", ret); - goto unreg_cdev_region; - } - - /* /dev/ubcore */ - g_ubcore_ctx.ubcore_dev = - device_create(g_ubcore_ctx.ubcore_class, NULL, g_ubcore_ctx.ubcore_devno, NULL, - UBCORE_DEVICE_NAME); - if (IS_ERR(g_ubcore_ctx.ubcore_dev)) { - ret = (int)PTR_ERR(g_ubcore_ctx.ubcore_dev); - ubcore_log_err("couldn't create device %s, ret:%d.\n", UBCORE_DEVICE_NAME, ret); - goto del_cdev; - } - ubcore_log_info("ubcore device created success.\n"); - return 0; - -del_cdev: - cdev_del(&g_ubcore_ctx.ubcore_cdev); -unreg_cdev_region: - unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); -unreg_class: - ubcore_class_unregister(g_ubcore_ctx.ubcore_class); - return ret; -} - -static void ubcore_unregister_sysfs(void) -{ - device_destroy(g_ubcore_ctx.ubcore_class, g_ubcore_ctx.ubcore_cdev.dev); - cdev_del(&g_ubcore_ctx.ubcore_cdev); - unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); - ubcore_class_unregister(g_ubcore_ctx.ubcore_class); - ubcore_log_info("ubcore device destroyed success.\n"); -} - static void ubcore_ipv4_to_netaddr(struct ubcore_net_addr *netaddr, __be32 ipv4) { netaddr->net_addr.in4.reserved1 = 0; @@ -265,17 +163,30 @@ static enum ubcore_mtu sip_get_mtu(uint32_t mtu) return (enum ubcore_mtu)0; } +static enum ubcore_mtu sip_get_mtu_with_ub(uint32_t mtu) +{ + if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_8192)) + return UBCORE_MTU_8192; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_4096)) + return UBCORE_MTU_4096; + else if (mtu >= sip_mtu_enum_to_int(UBCORE_MTU_1024)) + return UBCORE_MTU_1024; + else + return (enum ubcore_mtu)0; +} + static void ubcore_sip_init(struct ubcore_sip_info *sip, struct ubcore_device *tpf_dev, const struct ubcore_net_addr *netaddr, uint8_t *port_list, - uint8_t port_cnt, uint32_t prefix_len, struct net_device *netdev) + uint8_t port_cnt, struct net_device *netdev) { (void)memcpy(sip->dev_name, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); (void)memcpy(&sip->addr, netaddr, sizeof(struct ubcore_net_addr)); if (port_list != NULL) (void)memcpy(sip->port_id, port_list, UBCORE_MAX_PORT_CNT); sip->port_cnt = port_cnt; - sip->prefix_len = prefix_len; - sip->mtu = (uint32_t)sip_get_mtu(netdev->mtu); + sip->mtu = tpf_dev->transport_type == UBCORE_TRANSPORT_UB ? + (uint32_t)sip_get_mtu_with_ub(netdev->mtu) : + (uint32_t)sip_get_mtu(netdev->mtu); (void)memcpy(sip->netdev_name, netdev_name(netdev), UBCORE_MAX_DEV_NAME); } @@ -365,7 +276,7 @@ static int ubcore_notify_uvs_update_sip_manage(struct ubcore_device *tpf_dev, } static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_device *pf_dev, - struct ubcore_net_addr *netaddr, struct net_device *netdev, uint32_t prefix_len, bool async) + struct ubcore_net_addr *netaddr, struct net_device *netdev, bool async) { struct ubcore_sip_info sip = {0}; uint8_t *port_list = NULL; @@ -375,8 +286,7 @@ static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_dev /* get driver set nedev port */ ubcore_find_port_netdev(pf_dev, netdev, &port_list, &port_cnt); - ubcore_sip_init(&sip, tpf_dev, - netaddr, port_list, port_cnt, prefix_len, netdev); + ubcore_sip_init(&sip, tpf_dev, netaddr, port_list, port_cnt, netdev); ret = ubcore_lookup_sip_idx(&tpf_dev->sip_table, &sip, &index); if (ret == 0) { @@ -404,7 +314,7 @@ static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_dev } static void ubcore_delete_net_addr(struct ubcore_device *tpf_dev, struct ubcore_device *pf_dev, - struct ubcore_net_addr *netaddr, struct net_device *netdev, uint32_t prefix_len, bool async) + struct ubcore_net_addr *netaddr, struct net_device *netdev, bool async) { struct ubcore_sip_info sip = {0}; uint8_t *port_list = NULL; @@ -414,7 +324,7 @@ static void ubcore_delete_net_addr(struct ubcore_device *tpf_dev, struct ubcore_ ubcore_find_port_netdev(pf_dev, netdev, &port_list, &port_cnt); ubcore_sip_init(&sip, tpf_dev, - netaddr, port_list, port_cnt, prefix_len, netdev); + netaddr, port_list, port_cnt, netdev); if (ubcore_lookup_sip_idx(&tpf_dev->sip_table, &sip, &index) != 0) return; @@ -452,14 +362,14 @@ static void ubcore_update_eid(struct ubcore_device *dev, eid = (union ubcore_eid *)(void *)&netaddr->net_addr; if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) return; - if (dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_1) + if (dev->attr.pattern == (uint8_t)UBCORE_PATTERN_1) ubcore_update_pattern1_eid(dev, eid, eid_idx, is_add); else ubcore_update_pattern3_eid(dev, eid, eid_idx, is_add); } static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long event, - struct ubcore_net_addr *netaddr, uint32_t prefix_len) + struct ubcore_net_addr *netaddr) { struct net_device *real_netdev; struct ubcore_net_addr real_netaddr; @@ -480,28 +390,27 @@ static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long real_netdev = netdev; real_netaddr = *netaddr; } - - devices = ubcore_get_devices_from_netdev(real_netdev, &num_devices); - if (devices == NULL) + ubcore_device_list_lock(); + devices = ubcore_get_devices_from_netdev_nolock(real_netdev, &num_devices); + if (devices == NULL) { + ubcore_device_list_unlock(); return NOTIFY_DONE; + } for (i = 0; i < num_devices; i++) { dev = devices[i]; if (dev->attr.virtualization) continue; - tpf_dev = ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); switch (event) { case NETDEV_UP: if (tpf_dev) - ubcore_add_net_addr( - tpf_dev, dev, netaddr, netdev, prefix_len, true); + ubcore_add_net_addr(tpf_dev, dev, netaddr, netdev, true); ubcore_update_eid(dev, netaddr, true); break; case NETDEV_DOWN: if (tpf_dev) - ubcore_delete_net_addr( - tpf_dev, dev, netaddr, netdev, prefix_len, true); + ubcore_delete_net_addr(tpf_dev, dev, netaddr, netdev, true); ubcore_update_eid(dev, netaddr, false); break; default: @@ -511,6 +420,7 @@ static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long ubcore_put_device(tpf_dev); } ubcore_put_devices(devices, num_devices); + ubcore_device_list_unlock(); return NOTIFY_OK; } @@ -532,11 +442,12 @@ static int ubcore_ipv6_notifier_call(struct notifier_block *nb, memset(&netaddr, 0, sizeof(struct ubcore_net_addr)); (void)memcpy(&netaddr.net_addr, &ifa->addr, sizeof(struct in6_addr)); (void)ubcore_fill_netaddr_macvlan(&netaddr, netdev, UBCORE_NET_ADDR_TYPE_IPV6); + netaddr.prefix_len = ifa->prefix_len; if (netaddr.net_addr.in6.subnet_prefix == cpu_to_be64(UBCORE_LOCAL_SHUNET)) /* When mtu changes, intercept the ipv6 address up/down that triggers fe80 */ return NOTIFY_DONE; - return ubcore_handle_inetaddr_event(netdev, event, &netaddr, ifa->prefix_len); + return ubcore_handle_inetaddr_event(netdev, event, &netaddr); } static int ubcore_ipv4_notifier_call(struct notifier_block *nb, unsigned long event, void *arg) @@ -556,7 +467,8 @@ static int ubcore_ipv4_notifier_call(struct notifier_block *nb, unsigned long ev memset(&netaddr, 0, sizeof(struct ubcore_net_addr)); ubcore_ipv4_to_netaddr(&netaddr, ifa->ifa_address); (void)ubcore_fill_netaddr_macvlan(&netaddr, netdev, UBCORE_NET_ADDR_TYPE_IPV4); - return ubcore_handle_inetaddr_event(netdev, event, &netaddr, (uint32_t)ifa->ifa_prefixlen); + netaddr.prefix_len = ifa->ifa_prefixlen; + return ubcore_handle_inetaddr_event(netdev, event, &netaddr); } static void ubcore_add_ipv4_entry(struct list_head *list, __be32 ipv4, uint32_t prefix_len, @@ -570,7 +482,7 @@ static void ubcore_add_ipv4_entry(struct list_head *list, __be32 ipv4, uint32_t ubcore_ipv4_to_netaddr(&na_entry->addr, ipv4); (void)ubcore_fill_netaddr_macvlan(&na_entry->addr, netdev, UBCORE_NET_ADDR_TYPE_IPV4); - na_entry->prefix_len = prefix_len; + na_entry->addr.prefix_len = prefix_len; list_add_tail(&na_entry->node, list); } @@ -585,7 +497,7 @@ static void ubcore_add_ipv6_entry(struct list_head *list, struct in6_addr *ipv6, (void)memcpy(&na_entry->addr.net_addr, ipv6, sizeof(struct in6_addr)); (void)ubcore_fill_netaddr_macvlan(&na_entry->addr, netdev, UBCORE_NET_ADDR_TYPE_IPV6); - na_entry->prefix_len = prefix_len; + na_entry->addr.prefix_len = prefix_len; list_add_tail(&na_entry->node, list); } @@ -649,9 +561,9 @@ void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add) if (tpf_dev) is_add == true ? ubcore_add_net_addr(tpf_dev, dev, &na_entry->addr, - netdev, na_entry->prefix_len, false) : + netdev, false) : ubcore_delete_net_addr(tpf_dev, dev, &na_entry->addr, - netdev, na_entry->prefix_len, false); + netdev, false); ubcore_update_eid(dev, &na_entry->addr, is_add); list_del(&na_entry->node); kfree(na_entry); @@ -708,7 +620,6 @@ static void ubcore_change_mtu(struct ubcore_device *dev, struct net_device *netd struct ubcore_device *tpf_dev; struct ubcore_sip_info *new_sip; struct ubcore_sip_info old_sip; - uint32_t max_cnt; uint32_t i; tpf_dev = ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); @@ -716,14 +627,15 @@ static void ubcore_change_mtu(struct ubcore_device *dev, struct net_device *netd return; mutex_lock(&tpf_dev->sip_table.lock); - max_cnt = ubcore_get_sip_max_cnt(&tpf_dev->sip_table); - for (i = 0; i < max_cnt; i++) { - new_sip = ubcore_lookup_sip_info(&tpf_dev->sip_table, i); - if (new_sip == NULL || memcmp(new_sip->netdev_name, netdev_name(netdev), + for (i = 0; i < tpf_dev->sip_table.max_sip_cnt; i++) { + new_sip = &tpf_dev->sip_table.entry[i]; + if (!new_sip->is_active || memcmp(new_sip->netdev_name, netdev_name(netdev), UBCORE_MAX_DEV_NAME) != 0) continue; old_sip = *new_sip; - new_sip->mtu = (uint32_t)sip_get_mtu(netdev->mtu); + new_sip->mtu = tpf_dev->transport_type == UBCORE_TRANSPORT_UB ? + (uint32_t)sip_get_mtu_with_ub(netdev->mtu) : + (uint32_t)sip_get_mtu(netdev->mtu); (void)ubcore_notify_uvs_update_sip_manage( tpf_dev, new_sip, &old_sip, UBCORE_SIP_UPDATE, i, true); } @@ -737,8 +649,8 @@ static void ubcore_do_bond(struct ubcore_bond_event_work *l_bond_event) switch (l_bond_event->bond_op_type) { case UBCORE_BOND_ADD: - ret = l_bond_event->bond_add( - l_bond_event->bond, l_bond_event->slave, &l_bond_event->info_upper); + ret = l_bond_event->bond_add(l_bond_event->bond, + l_bond_event->slave, &l_bond_event->info_upper); if (ret != 0) ubcore_log_err("Failed to bond_add and ret value is %d", ret); break; @@ -949,20 +861,25 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve ubcore_log_info("Get a net event %s from ubcore_dev %s%s", netdev_cmd_to_name(event), netdev_name(netdev), netdev_reg_state(netdev)); - devices = ubcore_get_devices_from_netdev(real_netdev, &num_devices); + ubcore_device_list_lock(); + devices = ubcore_get_devices_from_netdev_nolock(real_netdev, &num_devices); if (devices == NULL) { - if (event != NETDEV_CHANGEUPPER && event != NETDEV_CHANGELOWERSTATE) + if (event != NETDEV_CHANGEUPPER && event != NETDEV_CHANGELOWERSTATE) { + ubcore_device_list_unlock(); return NOTIFY_DONE; + } real_netdev = ubcore_find_master_netdev(event, arg, netdev); if (real_netdev == NULL) { + ubcore_device_list_unlock(); ubcore_log_warn("Can not find master netdev by slave netdev %s", netdev_name(netdev)); return NOTIFY_DONE; } ubcore_log_info("Success to find master netdev %s", netdev_name(real_netdev)); - devices = ubcore_get_devices_from_netdev(real_netdev, &num_devices); + devices = ubcore_get_devices_from_netdev_nolock(real_netdev, &num_devices); if (devices == NULL) { + ubcore_device_list_unlock(); ubcore_log_warn("Can not find devices from master netdev %s", netdev_name(real_netdev)); return NOTIFY_DONE; @@ -976,6 +893,7 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve ubcore_put_devices(devices, num_devices); else kfree(devices); + ubcore_device_list_unlock(); return NOTIFY_OK; } @@ -1049,38 +967,30 @@ static int __init ubcore_init(void) { int ret; - ret = ubcore_register_sysfs(); + ret = ubcore_class_register(); if (ret != 0) return ret; ret = ubcore_genl_init(); if (ret != 0) { (void)pr_err("Failed to ubcore genl init\n"); - ubcore_unregister_sysfs(); - return -1; - } - - if (ubcore_netlink_init() != 0) { - ubcore_genl_exit(); - ubcore_unregister_sysfs(); + ubcore_class_unregister(); return -1; } ret = ubcore_register_notifiers(); if (ret != 0) { pr_err("Failed to register notifiers\n"); - ubcore_netlink_exit(); ubcore_genl_exit(); - ubcore_unregister_sysfs(); + ubcore_class_unregister(); return -1; } ret = ubcore_register_pnet_ops(); if (ret != 0) { ubcore_unregister_notifiers(); - ubcore_netlink_exit(); ubcore_genl_exit(); - ubcore_unregister_sysfs(); + ubcore_class_unregister(); } ret = ubcore_alloc_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); @@ -1088,9 +998,8 @@ static int __init ubcore_init(void) pr_err("Failed to alloc workqueue, ret = %d\n", ret); ubcore_unregister_pnet_ops(); ubcore_unregister_notifiers(); - ubcore_netlink_exit(); ubcore_genl_exit(); - ubcore_unregister_sysfs(); + ubcore_class_unregister(); return ret; } ubcore_log_info("ubcore module init success.\n"); @@ -1101,9 +1010,8 @@ static void __exit ubcore_exit(void) { ubcore_unregister_pnet_ops(); ubcore_unregister_notifiers(); - ubcore_netlink_exit(); ubcore_genl_exit(); - ubcore_unregister_sysfs(); + ubcore_class_unregister(); ubcore_log_info("ubcore module exits.\n"); } diff --git a/drivers/ub/urma/ubcore/ubcore_msg.c b/drivers/ub/urma/ubcore/ubcore_msg.c index 3e1dfcf41aaa..fcea06f0759c 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.c +++ b/drivers/ub/urma/ubcore/ubcore_msg.c @@ -20,14 +20,16 @@ #include #include +#include #include "ubcore_log.h" -#include +#include "urma/ubcore_api.h" #include "ubcore_netlink.h" #include "ubcore_vtp.h" -#include +#include "urma/ubcore_uapi.h" #include "ubcore_priv.h" #include "ubcore_msg.h" +#define MS_PER_SEC 1000 static LIST_HEAD(g_msg_session_list); static DEFINE_SPINLOCK(g_msg_session_lock); static atomic_t g_msg_seq = ATOMIC_INIT(0); @@ -65,7 +67,7 @@ static struct ubcore_msg_session *ubcore_find_msg_session(uint32_t seq) return target; } -static void ubcore_destroy_msg_session(struct ubcore_msg_session *s) +void ubcore_destroy_msg_session(struct ubcore_msg_session *s) { (void)kref_put(&s->kref, ubcore_free_msg_session); } @@ -99,7 +101,7 @@ static struct ubcore_nlmsg *ubcore_get_fe2uvs_nlmsg(struct ubcore_device *dev, return NULL; nlmsg->transport_type = dev->transport_type; - nlmsg->msg_type = UBCORE_NL_FE2TPF_REQ; + nlmsg->msg_type = UBCORE_CMD_FE2TPF_REQ; (void)memcpy(nlmsg->payload, req_host, payload_len); return nlmsg; } @@ -343,8 +345,8 @@ int ubcore_send_resp(struct ubcore_device *dev, struct ubcore_resp_host *resp_ho { int ret; - if (dev == NULL || dev->ops == NULL || dev->ops->send_resp == NULL || resp_host == NULL || - resp_host->resp.len > UBCORE_MAX_MSG) { + if (dev == NULL || dev->ops == NULL || dev->ops->send_resp == NULL || + resp_host == NULL || resp_host->resp.len > UBCORE_MAX_MSG) { ubcore_log_err("Invalid parameter!\n"); return -EINVAL; } @@ -377,7 +379,7 @@ int ubcore_send_fe2tpf_msg(struct ubcore_device *dev, struct ubcore_req *req, ubcore_log_err("Failed to send req, msg_id = %u, opcode = %hu.\n", req->msg_id, (uint16_t)req->opcode); ubcore_destroy_msg_session(s); - return -EIO; + return ret; } leavetime = wait_for_completion_timeout(&s->comp, msecs_to_jiffies(UBCORE_TIMEOUT)); @@ -404,7 +406,8 @@ static int ubcore_msg_discover_eid_cb(struct ubcore_device *dev, struct net *net = (struct net *)msg_ctx; bool is_alloc_eid; - if (dev == NULL || resp == NULL) { + if (dev == NULL || resp == NULL || + resp->len < sizeof(struct ubcore_msg_discover_eid_resp)) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } @@ -423,17 +426,43 @@ static int ubcore_msg_discover_eid_cb(struct ubcore_device *dev, return 0; } +/** + * If you do not need to wait for the response of a message, use ubcore_asyn_send_fe2tpf_msg. + * If you need to wait for a response to a message, use ubcore_send_fe2tpf_msg + */ +struct ubcore_msg_session *ubcore_asyn_send_fe2tpf_msg(struct ubcore_device *dev, + struct ubcore_req *req) +{ + struct ubcore_msg_session *s; + int ret; + + req->msg_id = ubcore_get_msg_seq(); + s = ubcore_create_msg_session(req); + if (s == NULL) { + ubcore_log_err("Failed to create req session!\n"); + return NULL; + } + + ret = ubcore_send_req(dev, req); + if (ret != 0) { + ubcore_log_err("Failed to send req, msg_id = %u, opcode = %hu.\n", + req->msg_id, (uint16_t)req->opcode); + ubcore_destroy_msg_session(s); + return NULL; + } + return s; +} + int ubcore_msg_discover_eid(struct ubcore_device *dev, uint32_t eid_index, - enum ubcore_msg_opcode op, struct net *net) + enum ubcore_msg_opcode op, struct net *net, struct ubcore_update_eid_ctx *ctx) { struct ubcore_msg_discover_eid_req *data; + struct ubcore_msg_session *s; struct ubcore_req *req_msg; uint32_t data_len; - struct ubcore_resp_cb cb; - int ret; - cb.callback = ubcore_msg_discover_eid_cb; - cb.user_arg = net; + ctx->cb.callback = ubcore_msg_discover_eid_cb; + ctx->cb.user_arg = net; data_len = sizeof(struct ubcore_msg_discover_eid_req); req_msg = kcalloc(1, sizeof(struct ubcore_req) + data_len, GFP_KERNEL); if (req_msg == NULL) @@ -443,13 +472,45 @@ int ubcore_msg_discover_eid(struct ubcore_device *dev, uint32_t eid_index, req_msg->opcode = op; data = (struct ubcore_msg_discover_eid_req *)req_msg->data; data->eid_index = eid_index; - data->eid_type = dev->cfg.pattern; + data->eid_type = dev->attr.pattern; data->virtualization = dev->attr.virtualization; (void)memcpy(data->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME); - ret = ubcore_send_fe2tpf_msg(dev, req_msg, &cb); - if (ret != 0) + s = ubcore_asyn_send_fe2tpf_msg(dev, req_msg); + if (s == NULL) { ubcore_log_err("send fe2tpf failed.\n"); - kfree(req_msg); - return ret; + kfree(req_msg); + return -1; + } + ctx->req_msg = req_msg; + ctx->s = s; + return 0; +} + +/** + * if the operation times out or is successful, 0 is returned and reply done to urma_admin. + * if the operation is waiting for the result, 1 is returned and reply dump to urma_admin. + */ +int ubcore_update_uvs_eid_ret(struct ubcore_update_eid_ctx *ctx) +{ + long start_ts = ctx->start_ts; + long leave_time = 0; + struct timespec64 tv; + bool is_done; + + is_done = try_wait_for_completion(&ctx->s->comp); + if (is_done == false) { + ktime_get_ts64(&tv); + leave_time = tv.tv_sec - start_ts; + if (leave_time * MS_PER_SEC < UBCORE_TIMEOUT) + return 1; + + ubcore_log_err("waiting req reply timeout, msg_id = %u, opcode = %hu, leavetime = %ld.\n", + ctx->req_msg->msg_id, (uint16_t)ctx->req_msg->opcode, leave_time); + return 0; + } + ubcore_log_info("waiting req reply success, msg_id = %u, opcode = %hu\n", + ctx->req_msg->msg_id, (uint16_t)ctx->req_msg->opcode); + (void)ctx->cb.callback(ctx->dev, ctx->s->resp, ctx->cb.user_arg); + return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_msg.h b/drivers/ub/urma/ubcore/ubcore_msg.h index 9dddc78dbaad..b85ad3b8e9e2 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.h +++ b/drivers/ub/urma/ubcore/ubcore_msg.h @@ -23,13 +23,12 @@ #include -enum ubcore_msg_resp_status { - UBCORE_MSG_RESP_LIMIT_RATE = -4, - UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND = -3, - UBCORE_MSG_RESP_IN_PROGRESS = -2, - UBCORE_MSG_RESP_FAIL = -1, - UBCORE_MSG_RESP_SUCCESS = 0 -}; +// Must be the same as TPSA_NL_RESP_XXX +#define UBCORE_MSG_RESP_LIMIT_RATE (-EBUSY) +#define UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND (-EEXIST) +#define UBCORE_MSG_RESP_IN_PROGRESS (-EINPROGRESS) +#define UBCORE_MSG_RESP_FAIL (-EPERM) +#define UBCORE_MSG_RESP_SUCCESS 0 typedef int (*ubcore_req_handler)(struct ubcore_device *dev, struct ubcore_req_host *req); typedef int (*ubcore_resp_handler)(struct ubcore_device *dev, @@ -61,7 +60,7 @@ struct ubcore_msg_config_device_req { }; struct ubcore_msg_config_device_resp { - enum ubcore_msg_resp_status ret; + int ret; uint32_t rc_cnt; uint32_t rc_depth; uint32_t slice; /* TA slice size byte */ @@ -96,11 +95,22 @@ struct ubcore_function_mig_resp { enum ubcore_mig_resp_status status; }; +struct ubcore_update_eid_ctx { + struct ubcore_device *dev; + struct ubcore_req *req_msg; + struct ubcore_msg_session *s; + struct net *net; + struct ubcore_resp_cb cb; + long start_ts; +}; + int ubcore_send_req(struct ubcore_device *dev, struct ubcore_req *req); int ubcore_send_resp(struct ubcore_device *dev, struct ubcore_resp_host *resp_host); /* caller should free memory of req after return */ int ubcore_send_fe2tpf_msg(struct ubcore_device *dev, struct ubcore_req *req, struct ubcore_resp_cb *cb); int ubcore_msg_discover_eid(struct ubcore_device *dev, uint32_t eid_index, - enum ubcore_msg_opcode op, struct net *net); + enum ubcore_msg_opcode op, struct net *net, struct ubcore_update_eid_ctx *ctx); +void ubcore_destroy_msg_session(struct ubcore_msg_session *s); +int ubcore_update_uvs_eid_ret(struct ubcore_update_eid_ctx *ctx); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.c b/drivers/ub/urma/ubcore/ubcore_netdev.c index 0a53bf9e114b..49fb10c56124 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.c +++ b/drivers/ub/urma/ubcore/ubcore_netdev.c @@ -37,31 +37,20 @@ struct ubcore_ndev_port { char dev_name[UBCORE_MAX_DEV_NAME]; }; -uint32_t ubcore_get_sip_max_cnt(struct ubcore_sip_table *sip_table) -{ - int i; - - for (i = (int)UBCORE_SIP_TABLE_SIZE - 1; i >= 0; i--) { - if (sip_table->entry[i] != NULL) - break; - } - - return (uint32_t)(i + 1); -} - -struct ubcore_sip_info *ubcore_lookup_sip_info(struct ubcore_sip_table *sip_table, uint32_t idx) +struct ubcore_sip_info *ubcore_lookup_sip_info_without_lock( + struct ubcore_sip_table *sip_table, uint32_t idx) { struct ubcore_sip_info *sip = NULL; - if (idx >= UBCORE_SIP_TABLE_SIZE || sip_table->entry[idx] == NULL) { + if (idx >= sip_table->max_sip_cnt || !sip_table->entry[idx].is_active) { ubcore_log_err("sip node does not exist"); return NULL; } - sip = sip_table->entry[idx]; + sip = &sip_table->entry[idx]; return sip; } -static struct ubcore_nlmsg *ubcore_alloc_sip_req(enum ubcore_nlmsg_type msg_type, +static struct ubcore_nlmsg *ubcore_alloc_sip_req(enum ubcore_cmd msg_type, enum ubcore_transport_type transport_type, uint32_t payload_len, struct ubcore_sip_info *sip_info) { @@ -89,7 +78,7 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, struct ubcore_del_sip_req *sip_req; struct ubcore_del_sip_resp *resp; - req_msg = ubcore_alloc_sip_req(UBCORE_NL_DEL_SIP_REQ, dev->transport_type, + req_msg = ubcore_alloc_sip_req(UBCORE_CMD_DEL_SIP_REQ, dev->transport_type, sizeof(struct ubcore_del_sip_req), sip_info); if (req_msg == NULL) return -ENOMEM; @@ -106,7 +95,7 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, return -1; } resp = (struct ubcore_del_sip_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_DEL_SIP_RESP || + if (resp_msg->msg_type != UBCORE_CMD_DEL_SIP_RESP || resp_msg->payload_len != sizeof(struct ubcore_del_sip_resp) || resp->ret != UBCORE_NL_RESP_SUCCESS) { ubcore_log_err("del sip request is rejected with type %d ret %d", @@ -120,17 +109,16 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, return 0; } -int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, +struct ubcore_nlmsg *ubcore_new_sip_req_msg(struct ubcore_device *dev, struct ubcore_sip_info *sip_info, uint32_t index) { - struct ubcore_nlmsg *req_msg, *resp_msg; struct ubcore_add_sip_req *sip_req; - struct ubcore_add_sip_resp *resp; + struct ubcore_nlmsg *req_msg; - req_msg = ubcore_alloc_sip_req(UBCORE_NL_ADD_SIP_REQ, dev->transport_type, + req_msg = ubcore_alloc_sip_req(UBCORE_CMD_ADD_SIP_REQ, dev->transport_type, sizeof(struct ubcore_add_sip_req), sip_info); if (req_msg == NULL) - return -ENOMEM; + return NULL; sip_req = (struct ubcore_add_sip_req *)(void *)req_msg->payload; (void)memcpy(sip_req->dev_name, sip_info->dev_name, @@ -141,16 +129,27 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, sip_req->port_cnt = sip_info->port_cnt; (void)memcpy(sip_req->port_id, sip_info->port_id, UBCORE_MAX_PORT_CNT); - sip_req->prefix_len = sip_info->prefix_len; sip_req->mtu = sip_info->mtu; if (strnlen(sip_info->netdev_name, UBCORE_MAX_DEV_NAME) == UBCORE_MAX_DEV_NAME) { ubcore_log_err("sip_info->netdev_name len is invalid"); kfree(req_msg); - return -1; + return NULL; } (void)memcpy(sip_req->netdev_name, sip_info->netdev_name, UBCORE_MAX_DEV_NAME); + return req_msg; +} + +int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, + struct ubcore_sip_info *sip_info, uint32_t index) +{ + struct ubcore_nlmsg *req_msg, *resp_msg; + struct ubcore_add_sip_resp *resp; + + req_msg = ubcore_new_sip_req_msg(dev, sip_info, index); + if (req_msg == NULL) + return -ENOMEM; resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { @@ -160,7 +159,7 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, } resp = (struct ubcore_add_sip_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_ADD_SIP_RESP || + if (resp_msg->msg_type != UBCORE_CMD_ADD_SIP_RESP || resp_msg->payload_len != sizeof(struct ubcore_add_sip_resp) || resp->ret != UBCORE_NL_RESP_SUCCESS) { ubcore_log_err("add sip request is rejected with type %d ret %d", @@ -209,8 +208,8 @@ void ubcore_find_port_netdev(struct ubcore_device *dev, *port_list = port_info->port_list; *port_cnt = port_info->port_cnt; up_write(&g_port_list_lock); - ubcore_log_info("Success to fill in port_list with port cnt: %hhu", - *port_cnt); + ubcore_log_info("Success to fill in port_list with port cnt: %hhu and dev_name %s", + *port_cnt, port_info->dev_name); return; } } @@ -262,7 +261,6 @@ static void ubcore_sync_sip_port_list(struct ubcore_device *dev, struct ubcore_sip_info *new_sip; struct ubcore_sip_info old_sip; struct ubcore_device *tpf_dev; - uint32_t max_cnt; uint32_t i; tpf_dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); @@ -270,10 +268,9 @@ static void ubcore_sync_sip_port_list(struct ubcore_device *dev, return; mutex_lock(&tpf_dev->sip_table.lock); - max_cnt = ubcore_get_sip_max_cnt(&tpf_dev->sip_table); - for (i = 0; i < max_cnt; i++) { - new_sip = ubcore_lookup_sip_info(&tpf_dev->sip_table, i); - if (new_sip == NULL) + for (i = 0; i < tpf_dev->sip_table.max_sip_cnt; i++) { + new_sip = &tpf_dev->sip_table.entry[i]; + if (!new_sip->is_active) continue; old_sip = *new_sip; (void)memcpy(new_sip->port_id, port_list, @@ -296,7 +293,9 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, { struct ubcore_ndev_port *port_info, *new_node; - if (dev == NULL || ndev == NULL) { + if (dev == NULL || ndev == NULL || + strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || + strnlen(netdev_name(ndev), UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { ubcore_log_err("invalid input parameter.\n"); return -1; } @@ -331,7 +330,7 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, new_node->port_list[0] = (uint8_t)port_id; new_node->valid_list[0] = true; new_node->port_cnt = 1; - (void)memcpy(new_node->dev_name, dev->dev_name, sizeof(char) * UBCORE_MAX_DEV_NAME); + (void)memcpy(new_node->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME); down_write(&g_port_list_lock); list_add_tail(&new_node->node, &dev->port_list); up_write(&g_port_list_lock); @@ -380,7 +379,9 @@ int ubcore_unset_port_netdev(struct ubcore_device *dev, struct net_device *ndev, { struct ubcore_ndev_port *port_info; - if (dev == NULL || ndev == NULL) { + if (dev == NULL || ndev == NULL || + strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || + strnlen(netdev_name(ndev), UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { ubcore_log_err("invalid input parameter.\n"); return -1; } @@ -420,8 +421,8 @@ void ubcore_put_port_netdev(struct ubcore_device *dev) port_info->port_cnt = 0; (void)memset(port_info->port_list, 0, sizeof(uint8_t) * UBCORE_MAX_PORT_CNT); - ubcore_sync_sip_port_list( - dev, port_info->port_list, port_info->port_cnt); + ubcore_sync_sip_port_list(dev, port_info->port_list, + port_info->port_cnt); } list_del(&port_info->node); kfree(port_info); @@ -431,28 +432,31 @@ void ubcore_put_port_netdev(struct ubcore_device *dev) } EXPORT_SYMBOL(ubcore_put_port_netdev); -void ubcore_sip_table_init(struct ubcore_sip_table *sip_table) +int ubcore_sip_table_init(struct ubcore_sip_table *sip_table, uint32_t size) { - uint32_t i; + uint32_t tmp = UBCORE_MAX_SIP; + if (size != 0 && size < UBCORE_MAX_SIP) { + tmp = size; + ubcore_log_info("sip size init %u complete.\n", tmp); + } else { + ubcore_log_warn("sip size %u err, use default value %u.\n", size, tmp); + } bitmap_zero(sip_table->index_bitmap, UBCORE_MAX_SIP); - for (i = 0; i < UBCORE_SIP_TABLE_SIZE; i++) - sip_table->entry[i] = NULL; + sip_table->entry = kcalloc(tmp, sizeof(struct ubcore_sip_info), GFP_KERNEL); + if (sip_table->entry == NULL) + return -1; + sip_table->max_sip_cnt = tmp; mutex_init(&sip_table->lock); + return 0; } void ubcore_sip_table_uninit(struct ubcore_sip_table *sip_table) { - uint32_t max_cnt; - uint32_t i; - mutex_lock(&sip_table->lock); - max_cnt = ubcore_get_sip_max_cnt(sip_table); - for (i = 0; i < max_cnt; i++) { - if (sip_table->entry[i] != NULL) { - kfree(sip_table->entry[i]); - sip_table->entry[i] = NULL; - } + if (sip_table->entry != NULL) { + kfree(sip_table->entry); + sip_table->entry = NULL; } mutex_unlock(&sip_table->lock); mutex_destroy(&sip_table->lock); @@ -490,19 +494,15 @@ int ubcore_sip_idx_free(struct ubcore_sip_table *sip_table, uint32_t idx) int ubcore_add_sip_entry(struct ubcore_sip_table *sip_table, const struct ubcore_sip_info *sip, uint32_t idx) { - struct ubcore_sip_info *new_sip; - - if (idx >= UBCORE_SIP_TABLE_SIZE || sip_table->entry[idx] != NULL) { + mutex_lock(&sip_table->lock); + if (idx >= sip_table->max_sip_cnt || sip_table->entry[idx].is_active) { + mutex_unlock(&sip_table->lock); ubcore_log_err("Parameters are illegal.\n"); return -EINVAL; } - new_sip = kzalloc(sizeof(struct ubcore_sip_info), GFP_ATOMIC); - if (new_sip == NULL) - return -ENOMEM; - mutex_lock(&sip_table->lock); - (void)memcpy(new_sip, sip, sizeof(struct ubcore_sip_info)); - sip_table->entry[idx] = new_sip; + (void)memcpy(&sip_table->entry[idx], sip, sizeof(struct ubcore_sip_info)); + sip_table->entry[idx].is_active = true; mutex_unlock(&sip_table->lock); ubcore_log_info("tpf_dev_name: %s sip table add entry idx: %d.\n", sip->dev_name, idx); @@ -511,36 +511,48 @@ int ubcore_add_sip_entry(struct ubcore_sip_table *sip_table, const struct ubcore int ubcore_del_sip_entry(struct ubcore_sip_table *sip_table, uint32_t idx) { - if (idx >= UBCORE_SIP_TABLE_SIZE || sip_table->entry[idx] == NULL) { + mutex_lock(&sip_table->lock); + if (idx >= sip_table->max_sip_cnt || !sip_table->entry[idx].is_active) { + mutex_unlock(&sip_table->lock); ubcore_log_err("Parameters are illegal.\n"); return -EINVAL; } ubcore_log_info("tpf_name: %s del sip entry idx: %d.\n", - sip_table->entry[idx]->dev_name, idx); - mutex_lock(&sip_table->lock); - kfree(sip_table->entry[idx]); - sip_table->entry[idx] = NULL; + sip_table->entry[idx].dev_name, idx); + sip_table->entry[idx].is_active = false; mutex_unlock(&sip_table->lock); - return 0; } +static bool ubcore_sip_compare(struct ubcore_sip_info *sip_entry, + struct ubcore_sip_info *del_sip) +{ + if ((memcmp(sip_entry->dev_name, del_sip->dev_name, + sizeof(char) * UBCORE_MAX_DEV_NAME) == 0) && + (memcmp(&sip_entry->addr, &del_sip->addr, + sizeof(struct ubcore_net_addr)) == 0) && + (memcmp(sip_entry->netdev_name, del_sip->netdev_name, + sizeof(struct ubcore_net_addr)) == 0)) + return true; + + return false; +} + int ubcore_lookup_sip_idx(struct ubcore_sip_table *sip_table, struct ubcore_sip_info *sip, uint32_t *idx) { uint32_t i; mutex_lock(&sip_table->lock); - for (i = 0; i < UBCORE_SIP_TABLE_SIZE; i++) { - if (sip_table->entry[i] != NULL && - memcmp(sip_table->entry[i], sip, - sizeof(struct ubcore_sip_info)) == 0) { + for (i = 0; i < sip_table->max_sip_cnt; i++) { + if (sip_table->entry[i].is_active && + ubcore_sip_compare(&sip_table->entry[i], sip)) { *idx = i; break; } } - if (i == UBCORE_SIP_TABLE_SIZE) { + if (i == sip_table->max_sip_cnt) { mutex_unlock(&sip_table->lock); ubcore_log_warn("no available idx found.\n"); return -EINVAL; diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.h b/drivers/ub/urma/ubcore/ubcore_netdev.h index 12f500766ff1..e0eb8534ac77 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.h +++ b/drivers/ub/urma/ubcore/ubcore_netdev.h @@ -27,7 +27,7 @@ int ubcore_check_port_state(struct ubcore_device *dev, uint8_t port_idx); void ubcore_find_port_netdev(struct ubcore_device *dev, struct net_device *ndev, uint8_t **port_list, uint8_t *port_cnt); -void ubcore_sip_table_init(struct ubcore_sip_table *sip_table); +int ubcore_sip_table_init(struct ubcore_sip_table *sip_table, uint32_t size); void ubcore_sip_table_uninit(struct ubcore_sip_table *sip_table); uint32_t ubcore_sip_idx_alloc(struct ubcore_sip_table *sip_table); @@ -38,12 +38,14 @@ int ubcore_add_sip_entry(struct ubcore_sip_table *sip_table, struct ubcore_sip_i int ubcore_del_sip_entry(struct ubcore_sip_table *sip_table, uint32_t idx); int ubcore_lookup_sip_idx(struct ubcore_sip_table *sip_table, struct ubcore_sip_info *sip, uint32_t *idx); -struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(struct ubcore_net_addr *addr); +struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(union ubcore_net_addr_union *addr); int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, const struct ubcore_sip_info *sip, uint32_t index); int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, const struct ubcore_sip_info *sip, uint32_t index); -uint32_t ubcore_get_sip_max_cnt(struct ubcore_sip_table *sip_table); -struct ubcore_sip_info *ubcore_lookup_sip_info(struct ubcore_sip_table *sip_table, uint32_t idx); +struct ubcore_sip_info *ubcore_lookup_sip_info_without_lock( + struct ubcore_sip_table *sip_table, uint32_t idx); +struct ubcore_nlmsg *ubcore_new_sip_req_msg(struct ubcore_device *dev, + struct ubcore_sip_info *sip_info, uint32_t index); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.c b/drivers/ub/urma/ubcore/ubcore_netlink.c index b9aa123d051e..4d7f9e61b320 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.c +++ b/drivers/ub/urma/ubcore/ubcore_netlink.c @@ -26,18 +26,23 @@ #include "ubcore_tp.h" #include "ubcore_vtp.h" #include "ubcore_priv.h" +#include "ubcore_netdev.h" +#include "ubcore_device.h" +#include "ubcore_genl_define.h" #include "ubcore_netlink.h" -#define UBCORE_NL_TYPE 24 /* same with agent netlink type */ #define UBCORE_NL_INVALID_PORT 0 +#define CB_ARGS_DEV_LIST 0 +#define CB_ARGS_DEV_CNT 1 +#define CB_ARGS_DEV_IDX 2 +#define CB_ARGS_SIP_IDX 3 +#define CB_ARGS_INFO_TYPE 4 -static struct sock *nl_sock; static LIST_HEAD(g_nl_session_list); static DEFINE_SPINLOCK(g_nl_session_lock); static atomic_t g_nlmsg_seq; -static uint32_t g_agent_port = UBCORE_NL_INVALID_PORT; /* get agent pid */ - -static int ubcore_nl_unicast(struct ubcore_nlmsg *pbuf, uint32_t len); +static uint32_t g_genl_port = UBCORE_NL_INVALID_PORT; /* get genl pid */ +static struct sock *g_genl_sock; static uint32_t ubcore_get_nlmsg_seq(void) { @@ -97,7 +102,7 @@ static void ubcore_free_nl_session(struct kref *kref) static inline void ubcore_destroy_nl_session(struct ubcore_nl_session *s) { - kref_put(&s->kref, ubcore_free_nl_session); + (void)kref_put(&s->kref, ubcore_free_nl_session); } static struct ubcore_nl_session *ubcore_find_nl_session(uint32_t nlmsg_seq) @@ -117,87 +122,150 @@ static struct ubcore_nl_session *ubcore_find_nl_session(uint32_t nlmsg_seq) return target; } -static struct ubcore_nlmsg *ubcore_get_nlmsg_data(struct nlmsghdr *nlh) +static struct ubcore_nlmsg *ubcore_get_genlmsg_data(struct genl_info *info) { struct ubcore_nlmsg *msg; + uint32_t payload_len = 0; + + if (!info->attrs[UBCORE_MSG_SEQ] || !info->attrs[UBCORE_PAYLOAD_LEN]) + return NULL; - msg = kzalloc(nlmsg_len(nlh), GFP_KERNEL); + payload_len = nla_get_u32(info->attrs[UBCORE_PAYLOAD_LEN]); + msg = kzalloc((size_t)(sizeof(struct ubcore_nlmsg) + payload_len), GFP_KERNEL); if (msg == NULL) return NULL; - (void)memcpy(msg, nlmsg_data(nlh), nlmsg_len(nlh)); + msg->payload_len = payload_len; + msg->nlmsg_seq = nla_get_u32(info->attrs[UBCORE_MSG_SEQ]); + if (info->attrs[UBCORE_MSG_TYPE]) + msg->msg_type = nla_get_u32(info->attrs[UBCORE_MSG_TYPE]); + + if (info->attrs[UBCORE_TRANSPORT_TYPE]) + msg->transport_type = (enum ubcore_transport_type) + nla_get_u32(info->attrs[UBCORE_TRANSPORT_TYPE]); + + if (info->attrs[UBORE_SRC_ID]) + (void)memcpy(&msg->src_eid, + nla_data(info->attrs[UBORE_SRC_ID]), UBCORE_EID_SIZE); + + if (info->attrs[UBORE_DST_ID]) + (void)memcpy(&msg->dst_eid, + nla_data(info->attrs[UBORE_DST_ID]), UBCORE_EID_SIZE); + + if (info->attrs[UBCORE_PAYLOAD_DATA]) { + (void)memcpy(msg->payload, + nla_data(info->attrs[UBCORE_PAYLOAD_DATA]), payload_len); + } + return msg; } -static void ubcore_nl_handle_tp_resp(struct nlmsghdr *nlh) +int ubcore_tp_resp_ops(struct sk_buff *skb, struct genl_info *info) { struct ubcore_nl_session *s; struct ubcore_nlmsg *resp; - resp = ubcore_get_nlmsg_data(nlh); + resp = ubcore_get_genlmsg_data(info); if (resp == NULL) { - ubcore_log_err("Failed to calloc and copy response.\n"); - return; + ubcore_log_err("Failed to calloc and copy response"); + return -1; } s = ubcore_find_nl_session(resp->nlmsg_seq); if (s == NULL) { ubcore_log_err("Failed to find nl session with seq %u", resp->nlmsg_seq); kfree(resp); - return; + return -1; } s->resp = resp; - kref_put(&s->kref, ubcore_free_nl_session); + (void)kref_put(&s->kref, ubcore_free_nl_session); complete(&s->comp); + return 0; } -static void ubcore_nl_handle_tp_req(struct nlmsghdr *nlh) +int ubcore_genl_unicast(struct ubcore_nlmsg *req, uint32_t len) +{ + struct sk_buff *nl_skb; + struct nlmsghdr *nlh; + + if (req == NULL || g_genl_port == UBCORE_NL_INVALID_PORT) { + ubcore_log_err("There are illegal parameters.\n"); + return -1; + } + + /* create sk_buff */ + nl_skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (nl_skb == NULL) { + ubcore_log_err("failed to alloc.\n"); + return -1; + } + /* set genl head */ + nlh = genlmsg_put(nl_skb, g_genl_port, req->nlmsg_seq, &ubcore_genl_family, 0, + (uint8_t)req->msg_type); + if (nlh == NULL) { + ubcore_log_err("Failed to nlmsg put.\n"); + nlmsg_free(nl_skb); + return -1; + } + if (nla_put_u32(nl_skb, UBCORE_MSG_SEQ, req->nlmsg_seq) || + nla_put_u32(nl_skb, UBCORE_MSG_TYPE, (uint32_t)req->msg_type) || + nla_put_u32(nl_skb, UBCORE_TRANSPORT_TYPE, (uint32_t)req->transport_type) || + nla_put_u32(nl_skb, UBCORE_PAYLOAD_LEN, req->payload_len) || + nla_put(nl_skb, UBCORE_PAYLOAD_DATA, (int)req->payload_len, req->payload)) { + nlmsg_free(nl_skb); + return -1; + } + + genlmsg_end(nl_skb, nlh); + ubcore_log_info("send genl msg type %d seq:%u payload_len %u", + (int)req->msg_type, req->nlmsg_seq, req->payload_len); + return nlmsg_unicast(g_genl_sock, nl_skb, g_genl_port); +} + +int ubcore_tp_req_ops(struct sk_buff *skb, struct genl_info *info) { struct ubcore_nlmsg *resp = NULL; struct ubcore_nlmsg *req; - req = ubcore_get_nlmsg_data(nlh); + req = ubcore_get_genlmsg_data(info); if (req == NULL) { ubcore_log_err("Failed to calloc and copy req"); - return; + return -1; } - if (nlh->nlmsg_type == UBCORE_NL_CREATE_TP_REQ) - resp = ubcore_handle_create_tp_req(req); - else if (nlh->nlmsg_type == UBCORE_NL_DESTROY_TP_REQ) - resp = ubcore_handle_destroy_tp_req(req); - else if (nlh->nlmsg_type == UBCORE_NL_RESTORE_TP_REQ) + if (req->msg_type == UBCORE_CMD_RESTORE_TP_REQ) resp = ubcore_handle_restore_tp_req(req); if (resp == NULL) { ubcore_log_err("Failed to handle tp req"); kfree(req); - return; + return -1; } - if (ubcore_nl_unicast(resp, ubcore_nlmsg_len(resp)) != 0) + if (ubcore_genl_unicast(resp, ubcore_nlmsg_len(resp)) != 0) ubcore_log_err("Failed to send response"); kfree(req); kfree(resp); + return 0; } -static void ubcore_nl_handle_tpf2fe_resp(struct nlmsghdr *nlh) +int ubcore_tpf2fe_resp_ops(struct sk_buff *skb, struct genl_info *info) { struct ubcore_nl_session *s; struct ubcore_nlmsg *resp; struct ubcore_device *dev; - resp = ubcore_get_nlmsg_data(nlh); + resp = ubcore_get_genlmsg_data(info); if (resp == NULL) { ubcore_log_err("Failed to calloc and copy response"); - return; + return -1; } s = ubcore_find_nl_session(resp->nlmsg_seq); if (s == NULL) { ubcore_log_err("Failed to find nl session with seq %u", resp->nlmsg_seq); kfree(resp); - return; + return -1; } s->resp = resp; - kref_put(&s->kref, ubcore_free_nl_session); + (void)kref_put(&s->kref, ubcore_free_nl_session); dev = ubcore_find_device_with_name(s->dev_name); if (dev != NULL) { @@ -209,39 +277,29 @@ static void ubcore_nl_handle_tpf2fe_resp(struct nlmsghdr *nlh) kfree(s->req); kfree(s->resp); ubcore_destroy_nl_session(s); + return 0; } -static void ubcore_nl_handle_update_tpf_dev_info_resp(struct nlmsghdr *nlh) +int ubcore_update_tpf_dev_info_resp_ops(struct sk_buff *skb, struct genl_info *info) { struct ubcore_nl_session *s; struct ubcore_nlmsg *resp; - resp = ubcore_get_nlmsg_data(nlh); + resp = ubcore_get_genlmsg_data(info); if (resp == NULL) { ubcore_log_err("Failed to calloc and copy response"); - return; + return -1; } s = ubcore_find_nl_session(resp->nlmsg_seq); if (s == NULL) { ubcore_log_err("Failed to find nl session with seq %u", resp->nlmsg_seq); kfree(resp); - return; + return -1; } s->resp = resp; - kref_put(&s->kref, ubcore_free_nl_session); + (void)kref_put(&s->kref, ubcore_free_nl_session); complete(&s->comp); -} - -static void ubcore_sync_tpf_dev_info(void) -{ - if (ubcore_query_all_device_tpf_dev_info() != 0) - ubcore_log_warn("Failed update tpf dev info after tpsa ready"); -} - -static void ubcore_nl_sync_table(void) -{ - ubcore_sync_tpf_dev_info(); - ubcore_sync_sip_table(); + return 0; } static struct ubcore_nlmsg *ubcore_get_migrate_vtp_req(struct ubcore_vtp *vtp, @@ -257,9 +315,9 @@ static struct ubcore_nlmsg *ubcore_get_migrate_vtp_req(struct ubcore_vtp *vtp, req->transport_type = UBCORE_TRANSPORT_UB; if (event_type == UBCORE_EVENT_MIGRATE_VTP_SWITCH) { - req->msg_type = UBCORE_NL_MIGRATE_VTP_SWITCH; + req->msg_type = UBCORE_CMD_MIGRATE_VTP_SWITCH; } else if (event_type == UBCORE_EVENT_MIGRATE_VTP_ROLLBACK) { - req->msg_type = UBCORE_NL_MIGRATE_VTP_ROLLBACK; + req->msg_type = UBCORE_CMD_MIGRATE_VTP_ROLLBACK; } else { kfree(req); ubcore_log_err("wrong event msg type"); @@ -301,81 +359,6 @@ void ubcore_report_migrate_vtp(struct ubcore_device *dev, struct ubcore_vtp *vtp kfree(req_msg); } -static void ubcore_nl_cb_func(struct sk_buff *skb) -{ - struct nlmsghdr *nlh; - - nlh = nlmsg_hdr(skb); - if (nlmsg_len(nlh) < (int)sizeof(struct ubcore_nlmsg) || skb->len < nlh->nlmsg_len) { - ubcore_log_err("Invalid nl msg received"); - return; - } - - switch (nlh->nlmsg_type) { - case UBCORE_NL_CREATE_TP_REQ: - case UBCORE_NL_DESTROY_TP_REQ: - case UBCORE_NL_RESTORE_TP_REQ: - ubcore_nl_handle_tp_req(nlh); - break; - case UBCORE_NL_CREATE_TP_RESP: - case UBCORE_NL_DESTROY_TP_RESP: - case UBCORE_NL_QUERY_TP_RESP: - case UBCORE_NL_RESTORE_TP_RESP: - case UBCORE_NL_ADD_SIP_RESP: - case UBCORE_NL_DEL_SIP_RESP: - ubcore_nl_handle_tp_resp(nlh); - break; - case UBCORE_NL_SET_AGENT_PID: - g_agent_port = nlh->nlmsg_pid; - ubcore_nl_sync_table(); - break; - case UBCORE_NL_UPDATE_TPF_DEV_INFO_RESP: - ubcore_nl_handle_update_tpf_dev_info_resp(nlh); - break; - case UBCORE_NL_TPF2FE_RESP: - ubcore_nl_handle_tpf2fe_resp(nlh); - break; - case UBCORE_NL_FE2TPF_REQ: - case UBCORE_NL_QUERY_TP_REQ: - case UBCORE_NL_ADD_SIP_REQ: - case UBCORE_NL_DEL_SIP_REQ: - case UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ: - default: - ubcore_log_err("Unexpected nl msg type: %d received\n", nlh->nlmsg_type); - break; - } -} - -static int ubcore_nl_unicast(struct ubcore_nlmsg *pbuf, uint32_t len) -{ - struct sk_buff *nl_skb; - struct nlmsghdr *nlh; - int ret; - - if (pbuf == NULL || g_agent_port == UBCORE_NL_INVALID_PORT) { - ubcore_log_err("There are illegal parameters.\n"); - return -1; - } - - /* create sk_buff */ - nl_skb = nlmsg_new(len, GFP_ATOMIC); - if (nl_skb == NULL) { - ubcore_log_err("failed to alloc.\n"); - return -1; - } - /* set netlink head */ - nlh = nlmsg_put(nl_skb, 0, pbuf->nlmsg_seq, pbuf->msg_type, len, 0); - if (nlh == NULL) { - ubcore_log_err("Failed to nlmsg put.\n"); - nlmsg_free(nl_skb); - return -1; - } - /* copy msg */ - (void)memcpy(nlmsg_data(nlh), pbuf, len); - ret = netlink_unicast(nl_sock, nl_skb, g_agent_port, 0); - return ret < 0 ? ret : 0; -} - struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_device *dev, struct ubcore_nlmsg *req) { unsigned long leavetime; @@ -390,7 +373,7 @@ struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_device *dev, struct ubcor return NULL; } - ret = ubcore_nl_unicast(req, ubcore_nlmsg_len(req)); + ret = ubcore_genl_unicast(req, ubcore_nlmsg_len(req)); if (ret != 0) { ubcore_log_err("Failed to send nl msg %d", ret); ubcore_destroy_nl_session(s); @@ -422,7 +405,7 @@ int ubcore_nl_send_nowait(struct ubcore_device *dev, struct ubcore_nlmsg *req, } s->cb = *cb; - ret = ubcore_nl_unicast(req, ubcore_nlmsg_len(req)); + ret = ubcore_genl_unicast(req, ubcore_nlmsg_len(req)); if (ret != 0) { ubcore_log_err("Failed to send nl msg %d", ret); ubcore_destroy_nl_session(s); @@ -438,7 +421,7 @@ int ubcore_nl_send_nowait_without_cb(struct ubcore_nlmsg *req) req->nlmsg_seq = ubcore_get_nlmsg_seq(); - ret = ubcore_nl_unicast(req, ubcore_nlmsg_len(req)); + ret = ubcore_genl_unicast(req, ubcore_nlmsg_len(req)); if (ret != 0) { ubcore_log_err("Failed to send nl msg %d", ret); return -EIO; @@ -449,55 +432,177 @@ int ubcore_nl_send_nowait_without_cb(struct ubcore_nlmsg *req) bool ubcore_get_netlink_valid(void) { - if (g_agent_port == UBCORE_NL_INVALID_PORT) + if (g_genl_port == UBCORE_NL_INVALID_PORT) ubcore_log_warn("The nelink service is not established well"); - return g_agent_port != UBCORE_NL_INVALID_PORT; + return g_genl_port != UBCORE_NL_INVALID_PORT; } - -static int ubcore_netlink_notify(struct notifier_block *nb, unsigned long event, void *_notify) +static int ubcore_set_genl_nla(struct sk_buff *skb, struct ubcore_nlmsg *req_msg) { - struct netlink_notify *notify = _notify; + if (nla_put_u32(skb, UBCORE_MSG_SEQ, req_msg->nlmsg_seq) || + nla_put_u32(skb, UBCORE_MSG_TYPE, (uint32_t)req_msg->msg_type) || + nla_put_u32(skb, UBCORE_TRANSPORT_TYPE, (uint32_t)req_msg->transport_type) || + nla_put_u32(skb, UBCORE_PAYLOAD_LEN, req_msg->payload_len) || + nla_put(skb, UBCORE_PAYLOAD_DATA, (int)req_msg->payload_len, req_msg->payload)) + return -1; - if (event != NETLINK_URELEASE || notify->protocol != UBCORE_NL_TYPE) - return NOTIFY_DONE; + return 0; +} + +static int ubcore_dump_genl_info(struct sk_buff *skb, struct netlink_callback *cb, + struct ubcore_nlmsg *req_msg) +{ + void *hdr; - ubcore_log_info("netlink release.\n"); - g_agent_port = UBCORE_NL_INVALID_PORT; + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, &ubcore_genl_family, + NLM_F_MULTI, (uint8_t)req_msg->msg_type); + if (!hdr) + return -ENOMEM; - return NOTIFY_OK; + if (ubcore_set_genl_nla(skb, req_msg)) { + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; + } + genlmsg_end(skb, hdr); + return 0; } -static struct notifier_block ubcore_netlink_notifier = { - .notifier_call = ubcore_netlink_notify, -}; +static int ubcore_dev_sip_info(struct sk_buff *skb, struct netlink_callback *cb, + struct ubcore_device *dev) +{ + long i = cb->args[CB_ARGS_SIP_IDX]; + struct ubcore_sip_table *sip_table; + struct ubcore_nlmsg *req_msg; + struct ubcore_sip_info *sip; + uint32_t max_cnt; + int ret; + + sip_table = &dev->sip_table; + mutex_lock(&sip_table->lock); + max_cnt = sip_table->max_sip_cnt; + for (; i < max_cnt; i++) { + sip = &sip_table->entry[i]; + if (!sip->is_active) + continue; + req_msg = ubcore_new_sip_req_msg(dev, sip, (uint32_t)(unsigned long)i); + if (req_msg == NULL) { + ubcore_log_warn("failed to get sip info %s", dev->dev_name); + continue; + } + ret = ubcore_dump_genl_info(skb, cb, req_msg); + kfree(req_msg); + if (ret != 0) { + mutex_unlock(&sip_table->lock); + return -1; + } + cb->args[CB_ARGS_SIP_IDX] = i; + } + mutex_unlock(&sip_table->lock); + + if (i == max_cnt) + cb->args[CB_ARGS_SIP_IDX] = 0; + return 0; +} -int ubcore_netlink_init(void) +static int ubcore_get_sip_info_dump(struct sk_buff *skb, struct netlink_callback *cb) { - /* create netlink socket */ - struct netlink_kernel_cfg cfg = {0}; + struct ubcore_device **dev_list = (struct ubcore_device **)cb->args[CB_ARGS_DEV_LIST]; + long dev_cnt = cb->args[CB_ARGS_DEV_CNT]; + long i = cb->args[CB_ARGS_DEV_IDX]; - cfg.input = ubcore_nl_cb_func; + for (; i < dev_cnt; ++i) { + if (ubcore_dev_sip_info(skb, cb, dev_list[i])) { + --i; + break; + } + } + cb->args[CB_ARGS_DEV_IDX] = i; + return (int)skb->len; +} - nl_sock = (struct sock *)netlink_kernel_create(&init_net, UBCORE_NL_TYPE, &cfg); - if (nl_sock == NULL) { - ubcore_log_err("Netlink_kernel_create error.\n"); - return -1; +static int ubcore_get_tpf_dev_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct ubcore_device **dev_list = (struct ubcore_device **)cb->args[CB_ARGS_DEV_LIST]; + long dev_cnt = cb->args[CB_ARGS_DEV_CNT]; + long i = cb->args[CB_ARGS_DEV_IDX]; + struct ubcore_nlmsg *req_msg; + int ret; + + for (; i < dev_cnt; ++i) { + req_msg = ubcore_new_tpf_dev_msg(dev_list[i]); + if (req_msg == NULL) { + ubcore_log_warn("failed to get tpf dev info %s", dev_list[i]->dev_name); + continue; + } + ret = ubcore_dump_genl_info(skb, cb, req_msg); + kfree(req_msg); + if (ret != 0) { + --i; + break; + } + ubcore_log_info("dump dev :%s success.\n", dev_list[i]->dev_name); } - if (netlink_register_notifier(&ubcore_netlink_notifier) != 0) { - ubcore_log_err("netlink_register_notifier error.\n"); - netlink_kernel_release(nl_sock); - nl_sock = NULL; - return -1; + if (i == dev_cnt) { + cb->args[CB_ARGS_INFO_TYPE] = 1; + cb->args[CB_ARGS_DEV_IDX] = 0; + } else { + cb->args[CB_ARGS_DEV_IDX] = i; } + return (int)skb->len; +} + +int ubcore_get_uvs_init_res_start(struct netlink_callback *cb) +{ + struct ubcore_device **dev_list = NULL; + uint32_t dev_cnt; + + dev_list = ubcore_get_all_tpf_device(UBCORE_TRANSPORT_UB, &dev_cnt); + ubcore_log_info("init_res :%u start.\n", dev_cnt); + + cb->args[CB_ARGS_DEV_LIST] = (long)dev_list; + cb->args[CB_ARGS_DEV_CNT] = dev_cnt; + cb->args[CB_ARGS_DEV_IDX] = 0; + cb->args[CB_ARGS_SIP_IDX] = 0; + cb->args[CB_ARGS_INFO_TYPE] = 0; + cb->args[CB_ARGS_SIP_IDX] = 0; return 0; } -void ubcore_netlink_exit(void) +int ubcore_get_uvs_init_res_dump(struct sk_buff *skb, struct netlink_callback *cb) { - (void)netlink_unregister_notifier(&ubcore_netlink_notifier); - if (nl_sock != NULL) { - netlink_kernel_release(nl_sock); - nl_sock = NULL; - } + long info_type = cb->args[CB_ARGS_INFO_TYPE]; + long dev_cnt = cb->args[CB_ARGS_DEV_CNT]; + int ret; + + if (dev_cnt <= 0) + return 0; + if (info_type == 0) + ret = ubcore_get_tpf_dev_dump(skb, cb); + else + ret = ubcore_get_sip_info_dump(skb, cb); + ubcore_log_info("init_res ret:%d.\n", ret); + return ret; +} + +int ubcore_get_uvs_init_res_done(struct netlink_callback *cb) +{ + struct ubcore_device **dev_list = (struct ubcore_device **)cb->args[CB_ARGS_DEV_LIST]; + long dev_cnt = cb->args[CB_ARGS_DEV_CNT]; + long i; + + for (i = 0; i < dev_cnt; ++i) + if (dev_list[i] != NULL) + ubcore_put_device(dev_list[i]); + + kfree(dev_list); + ubcore_log_info("init_res done.\n"); + return 0; +} + +int ubcore_set_genl_pid_ops(struct sk_buff *skb, struct genl_info *info) +{ + g_genl_port = info->snd_portid; + g_genl_sock = genl_info_net(info)->genl_sock; + ubcore_log_info("set_port :%u success.\n", g_genl_port); + return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.h b/drivers/ub/urma/ubcore/ubcore_netlink.h index 18202ef74f72..5d60867ac3d9 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.h +++ b/drivers/ub/urma/ubcore/ubcore_netlink.h @@ -21,8 +21,10 @@ #ifndef UBCORE_NETLINK_H #define UBCORE_NETLINK_H +#include #include #include +#include "ubcore_cmd.h" enum ubcore_nl_resp_status { UBCORE_NL_RESP_IN_PROGRESS = -2, @@ -30,33 +32,9 @@ enum ubcore_nl_resp_status { UBCORE_NL_RESP_SUCCESS = 0 }; -enum ubcore_nlmsg_type { - UBCORE_NL_CREATE_TP_REQ = NLMSG_MIN_TYPE, /* 0x10 */ - UBCORE_NL_CREATE_TP_RESP, - UBCORE_NL_DESTROY_TP_REQ, - UBCORE_NL_DESTROY_TP_RESP, - UBCORE_NL_QUERY_TP_REQ, - UBCORE_NL_QUERY_TP_RESP, - UBCORE_NL_RESTORE_TP_REQ, - UBCORE_NL_RESTORE_TP_RESP, - UBCORE_NL_SET_AGENT_PID, - UBCORE_NL_FE2TPF_REQ, - UBCORE_NL_TPF2FE_RESP, - UBCORE_NL_ADD_SIP_REQ, - UBCORE_NL_ADD_SIP_RESP, - UBCORE_NL_DEL_SIP_REQ, - UBCORE_NL_DEL_SIP_RESP, - UBCORE_NL_TP_ERROR_REQ, - UBCORE_NL_TP_SUSPEND_REQ, - UBCORE_NL_MIGRATE_VTP_SWITCH, - UBCORE_NL_MIGRATE_VTP_ROLLBACK, - UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ, - UBCORE_NL_UPDATE_TPF_DEV_INFO_RESP, -}; - struct ubcore_nlmsg { uint32_t nlmsg_seq; - enum ubcore_nlmsg_type msg_type; + enum ubcore_cmd msg_type; enum ubcore_transport_type transport_type; union ubcore_eid src_eid; /* todo: delete */ union ubcore_eid dst_eid; /* todo: delete */ @@ -72,50 +50,6 @@ struct ubcore_ta_data { bool is_target; }; -struct ubcore_multipath_tp_cfg { - union ubcore_tp_flag flag; - uint16_t data_rctp_start; - uint16_t ack_rctp_start; - uint16_t data_rmtp_start; - uint16_t ack_rmtp_start; - uint8_t tp_range; - uint16_t congestion_alg; -}; - -struct ubcore_nl_create_tp_req { - uint32_t tpn; - struct ubcore_net_addr local_net_addr; - struct ubcore_net_addr peer_net_addr; - enum ubcore_transport_mode trans_mode; - struct ubcore_multipath_tp_cfg cfg; - uint32_t rx_psn; - enum ubcore_mtu mtu; - struct ubcore_ta_data ta; - uint32_t ext_len; - uint32_t udrv_in_len; - uint8_t ext_udrv[0]; /* struct ubcore_udrv_ext->len + struct ubcore_udrv_priv->in_len */ -}; - -struct ubcore_nl_create_tp_resp { - enum ubcore_nl_resp_status ret; - union ubcore_tp_flag flag; - uint32_t peer_tpn; - uint32_t peer_rx_psn; - enum ubcore_mtu peer_mtu; - uint32_t peer_ext_len; - uint8_t peer_ext[0]; /* struct ubcore_tp_ext->len */ -}; - -struct ubcore_nl_destroy_tp_req { - uint32_t tpn; - uint32_t peer_tpn; - enum ubcore_transport_mode trans_mode; - struct ubcore_ta_data ta; -}; - -struct ubcore_nl_destroy_tp_resp { - enum ubcore_nl_resp_status ret; -}; struct ubcore_nl_query_tp_req { enum ubcore_transport_mode trans_mode; @@ -162,7 +96,6 @@ struct ubcore_nl_session { struct ubcore_add_sip_req { struct ubcore_net_addr netaddr; - uint32_t prefix_len; char dev_name[UBCORE_MAX_DEV_NAME]; uint8_t port_cnt; uint8_t port_id[UBCORE_MAX_PORT_CNT]; @@ -221,6 +154,7 @@ enum ubcore_update_tpf_opcode { struct ubcore_update_tpf_dev_info_req { char dev_name[UBCORE_MAX_DEV_NAME]; + char netdev_name[UBCORE_MAX_DEV_NAME]; union ubcore_device_feat dev_fea; uint32_t cc_entry_cnt; enum ubcore_update_tpf_opcode opcode; @@ -237,9 +171,6 @@ static inline uint32_t ubcore_nlmsg_len(struct ubcore_nlmsg *msg) } bool ubcore_get_netlink_valid(void); -int ubcore_netlink_init(void); -void ubcore_netlink_exit(void); - /* return response msg pointer, caller must release it */ struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_device *dev, struct ubcore_nlmsg *req); @@ -251,5 +182,15 @@ struct ubcore_nlmsg *ubcore_alloc_nlmsg(size_t payload_len, void ubcore_report_migrate_vtp(struct ubcore_device *dev, struct ubcore_vtp *vtp, enum ubcore_event_type event_type); + +int ubcore_get_uvs_init_res_done(struct netlink_callback *cb); +int ubcore_get_uvs_init_res_dump(struct sk_buff *skb, struct netlink_callback *cb); +int ubcore_get_uvs_init_res_start(struct netlink_callback *cb); +extern struct genl_family ubcore_genl_family; +int ubcore_set_genl_pid_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_tpf2fe_resp_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_tp_resp_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_tp_req_ops(struct sk_buff *skb, struct genl_info *info); +int ubcore_update_tpf_dev_info_resp_ops(struct sk_buff *skb, struct genl_info *info); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_priv.h b/drivers/ub/urma/ubcore/ubcore_priv.h index a9bbd4147add..5de967897337 100644 --- a/drivers/ub/urma/ubcore/ubcore_priv.h +++ b/drivers/ub/urma/ubcore/ubcore_priv.h @@ -88,12 +88,26 @@ static inline bool ubcore_check_trans_mode_valid(enum ubcore_transport_mode tran trans_mode == UBCORE_TP_RC || trans_mode == UBCORE_TP_UM; } +/* combine sub_trans_mode and rc_share_tp -> uint16_t? */ +static inline bool is_create_rc_shared_tp(enum ubcore_transport_mode trans_mode, + uint32_t sub_trans_mode, + uint32_t rc_share_tp) +{ + if (trans_mode == UBCORE_TP_RC && + (sub_trans_mode & UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE) && + rc_share_tp == 1) + return true; + + return false; +} + /* Caller must put device */ struct ubcore_device *ubcore_find_device(union ubcore_eid *eid, enum ubcore_transport_type type); struct ubcore_device *ubcore_find_device_with_name(const char *dev_name); +bool ubcore_check_dev_is_exist(const char *dev_name); void ubcore_get_device(struct ubcore_device *dev); void ubcore_put_device(struct ubcore_device *dev); -struct ubcore_device *ubcore_find_tpf_device(struct ubcore_net_addr *netaddr, +struct ubcore_device *ubcore_find_tpf_device(union ubcore_net_addr_union *netaddr, enum ubcore_transport_type type); struct ubcore_device *ubcore_find_tpf_by_dev(struct ubcore_device *dev, enum ubcore_transport_type type); @@ -113,7 +127,10 @@ struct ubcore_device *ubcore_find_upi_with_dev_name(const char *dev_name, uint32 int ubcore_add_upi_list(struct ubcore_device *dev, uint32_t upi); /* Must call ubcore_put_devices to put and release the returned devices */ -struct ubcore_device **ubcore_get_devices_from_netdev(struct net_device *netdev, uint32_t *cnt); +void ubcore_device_list_lock(void); +void ubcore_device_list_unlock(void); +struct ubcore_device **ubcore_get_devices_from_netdev_nolock(struct net_device *netdev, + uint32_t *cnt); void ubcore_put_devices(struct ubcore_device **devices, uint32_t cnt); void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add); void ubcore_update_netaddr(struct ubcore_device *dev, struct net_device *netdev, bool add); diff --git a/drivers/ub/urma/ubcore/ubcore_segment.c b/drivers/ub/urma/ubcore/ubcore_segment.c index 41b9111a43c6..db3db610f128 100644 --- a/drivers/ub/urma/ubcore/ubcore_segment.c +++ b/drivers/ub/urma/ubcore/ubcore_segment.c @@ -33,13 +33,13 @@ struct ubcore_token_id *ubcore_alloc_token_id(struct ubcore_device *dev, if (dev == NULL || dev->ops == NULL || dev->ops->alloc_token_id == NULL || dev->ops->free_token_id == NULL) { ubcore_log_err("invalid parameter.\n"); - return NULL; + return ERR_PTR(-EINVAL); } token_id = dev->ops->alloc_token_id(dev, udata); - if (token_id == NULL) { + if (IS_ERR_OR_NULL(token_id)) { ubcore_log_err("failed to alloc token_id id.\n"); - return NULL; + return token_id == NULL ? ERR_PTR(-ENOEXEC) : token_id; } token_id->ub_dev = dev; token_id->uctx = ubcore_get_uctx(udata); @@ -86,26 +86,27 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, struct ubcore_target_seg *tseg; if (ubcore_check_ops_register_seg(dev, cfg) != 0) - return NULL; + return ERR_PTR(-EINVAL); if (dev->transport_type == UBCORE_TRANSPORT_UB && ((cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_VALID && cfg->token_id == NULL) || (cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_INVALID && cfg->token_id != NULL))) { ubcore_log_err("invalid parameter of token_id.\n"); - return NULL; + return ERR_PTR(-EINVAL); } if ((cfg->flag.bs.access & (UBCORE_ACCESS_REMOTE_WRITE | UBCORE_ACCESS_REMOTE_ATOMIC)) && !(cfg->flag.bs.access & UBCORE_ACCESS_LOCAL_WRITE)) { ubcore_log_err( "Local write must be set when either remote write or remote atomic is declared.\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (cfg->eid_index >= dev->eid_table.eid_cnt) { - ubcore_log_warn("eid_index:%u >= eid_table cnt:%u.\n", + ubcore_log_warn( + "eid_index:%u >= eid_table cnt:%u.\n", cfg->eid_index, dev->eid_table.eid_cnt); - return NULL; + return ERR_PTR(-EINVAL); } if (udata == NULL && cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_INVALID && @@ -115,18 +116,18 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, tmp_cfg = *cfg; if (alloc_token_id == true) { tmp_cfg.token_id = ubcore_alloc_token_id(dev, NULL); - if (tmp_cfg.token_id == NULL) { + if (IS_ERR_OR_NULL(tmp_cfg.token_id)) { ubcore_log_err("alloc token id failed.\n"); - return NULL; + return (void *)tmp_cfg.token_id; } } tseg = dev->ops->register_seg(dev, &tmp_cfg, udata); - if (tseg == NULL) { + if (IS_ERR_OR_NULL(tseg)) { ubcore_log_err("UBEP failed to register segment.\n"); if (alloc_token_id == true) (void)ubcore_free_token_id(tmp_cfg.token_id); - return NULL; + return tseg == NULL ? ERR_PTR(-ENOEXEC) : tseg; } tseg->ub_dev = dev; @@ -189,13 +190,13 @@ struct ubcore_target_seg *ubcore_import_seg(struct ubcore_device *dev, if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->import_seg == NULL || dev->ops->unimport_seg == NULL) { ubcore_log_err("invalid parameter.\n"); - return NULL; + return ERR_PTR(-EINVAL); } tseg = dev->ops->import_seg(dev, cfg, udata); - if (tseg == NULL) { + if (IS_ERR_OR_NULL(tseg)) { ubcore_log_err("UBEP failed to import segment with va\n"); - return NULL; + return tseg == NULL ? ERR_PTR(-ENOEXEC) : tseg; } tseg->ub_dev = dev; tseg->uctx = ubcore_get_uctx(udata); diff --git a/drivers/ub/urma/ubcore/ubcore_tp.c b/drivers/ub/urma/ubcore/ubcore_tp.c index e4b412f09947..f67e1ea83208 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.c +++ b/drivers/ub/urma/ubcore/ubcore_tp.c @@ -31,6 +31,7 @@ #include "ubcore_tp_table.h" #include "ubcore_msg.h" #include "ubcore_vtp.h" +#include "urma/ubcore_jetty.h" #include "ubcore_tp.h" #define UB_PROTOCOL_HEAD_BYTES 313 @@ -87,31 +88,6 @@ enum ubcore_mtu ubcore_get_mtu(int mtu) } EXPORT_SYMBOL(ubcore_get_mtu); -static struct ubcore_nlmsg *ubcore_get_destroy_tp_req(struct ubcore_tp *tp, - const struct ubcore_ta_data *ta) -{ - struct ubcore_nl_destroy_tp_req *destroy; - struct ubcore_nlmsg *req; - - req = ubcore_alloc_nlmsg(sizeof(struct ubcore_nl_destroy_tp_req), &tp->local_eid, - &tp->peer_eid); - if (req == NULL) - return NULL; - - req->msg_type = UBCORE_NL_DESTROY_TP_REQ; - req->transport_type = tp->ub_dev->transport_type; - destroy = (struct ubcore_nl_destroy_tp_req *)req->payload; - destroy->trans_mode = tp->trans_mode; - destroy->tpn = tp->tpn; - destroy->peer_tpn = tp->peer_tpn; - if (ta != NULL) - destroy->ta = *ta; - else - destroy->ta.ta_type = UBCORE_TA_NONE; - - return req; -} - static int ubcore_set_tp_peer_ext(struct ubcore_tp_attr *attr, uint64_t ext_addr, uint32_t ext_len) { @@ -153,7 +129,7 @@ static void ubcore_get_ta_data_from_ta(const struct ubcore_ta *ta, return; ta_data->jetty_id.eid = jfs->ub_dev->eid_table.eid_entries[jfs->jfs_cfg.eid_index].eid; - ta_data->jetty_id.id = jfs->id; + ta_data->jetty_id.id = jfs->jfs_id.id; ta_data->tjetty_id = ta->tjetty_id; break; case UBCORE_TA_JETTY_TJETTY: @@ -162,7 +138,7 @@ static void ubcore_get_ta_data_from_ta(const struct ubcore_ta *ta, return; ta_data->jetty_id.eid = jetty->ub_dev->eid_table.eid_entries[jetty->jetty_cfg.eid_index].eid; - ta_data->jetty_id.id = jetty->id; + ta_data->jetty_id.id = jetty->jetty_id.id; ta_data->tjetty_id = ta->tjetty_id; break; case UBCORE_TA_NONE: @@ -178,6 +154,10 @@ static int ubcore_nl_handle_create_tp_resp_cb(struct ubcore_device *dev, { struct ubcore_create_vtp_resp *vtp_resp; + if (resp == NULL || resp->len < sizeof(struct ubcore_create_vtp_resp)) { + ubcore_log_err("invalid ubcore_create_vtp_resp len"); + return -1; + } vtp_resp = (struct ubcore_create_vtp_resp *)resp->data; if (vtp_resp->ret == UBCORE_MSG_RESP_FAIL) { ubcore_log_err("failed to create vtp: response error"); @@ -192,6 +172,25 @@ static int ubcore_nl_handle_create_tp_resp_cb(struct ubcore_device *dev, return 0; } +static void ubcore_tp_kref_release(struct kref *ref_cnt) +{ + struct ubcore_tp *tp = container_of(ref_cnt, struct ubcore_tp, ref_cnt); + + complete(&tp->comp); +} + +void ubcore_tp_kref_put(struct ubcore_tp *tp) +{ + (void)kref_put(&tp->ref_cnt, ubcore_tp_kref_release); +} + +void ubcore_tp_get(void *obj) +{ + struct ubcore_tp *tp = obj; + + kref_get(&tp->ref_cnt); +} + int ubcore_destroy_tp(struct ubcore_tp *tp) { if (tp == NULL) @@ -242,13 +241,15 @@ struct ubcore_tp *ubcore_create_tp(struct ubcore_device *dev, if (!ubcore_have_tp_ops(dev)) { ubcore_log_err("Invalid parameter"); - return NULL; + return ERR_PTR(-EINVAL); } tp = dev->ops->create_tp(dev, cfg, udata); - if (tp == NULL) { + if (IS_ERR_OR_NULL(tp)) { ubcore_log_err("Failed to create tp towards remote eid %pI6c", &cfg->peer_eid); - return NULL; + if (tp == NULL) + return ERR_PTR(-ENOEXEC); + return tp; } /* The driver may return the old tp pointer */ if (tp->state != UBCORE_TP_STATE_RESET) @@ -264,82 +265,6 @@ struct ubcore_tp *ubcore_create_tp(struct ubcore_device *dev, return tp; } -/* send request to destroy remote peer tp */ -static int ubcore_destroy_peer_tp(struct ubcore_tp *tp, struct ubcore_ta *ta) -{ - struct ubcore_nlmsg *req_msg, *resp_msg; - struct ubcore_nl_destroy_tp_resp *resp; - struct ubcore_ta_data ta_data = { 0 }; - int ret = 0; - - if (tp == NULL) { - ubcore_log_err("Invalid parameter"); - return -1; - } - - if (ta != NULL) - ubcore_get_ta_data_from_ta(ta, tp->ub_dev->transport_type, &ta_data); - - req_msg = ubcore_get_destroy_tp_req(tp, &ta_data); - if (req_msg == NULL) { - ubcore_log_err("Failed to get destroy tp req"); - return -1; - } - - resp_msg = ubcore_nl_send_wait(tp->ub_dev, req_msg); - if (resp_msg == NULL) { - ubcore_log_err("Failed to get destroy tp response"); - kfree(req_msg); - return -1; - } - - resp = (struct ubcore_nl_destroy_tp_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_DESTROY_TP_RESP || resp == NULL || - resp->ret != UBCORE_NL_RESP_SUCCESS) { - ubcore_log_err("Destroy tp request is rejected with type %d ret %d", - resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); - ret = -1; - } - - kfree(resp_msg); - kfree(req_msg); - return ret; -} - -/* Destroy both local tp and remote peer tp */ -static int ubcore_destroy_local_peer_tp(struct ubcore_tp *tp, struct ubcore_ta *ta) -{ - struct ubcore_device *dev = tp->ub_dev; - int ret; - - /* Do not send destroy request to the remote if we are in the VM */ - if (!dev->attr.virtualization) { - ret = ubcore_destroy_peer_tp(tp, ta); - if (ret != 0) { - ubcore_log_err("Failed to destroy peer tp"); - return ret; - } - } - return ubcore_destroy_tp(tp); -} - -/* destroy initiator and peer tp created by ubcore_connect_fe_tp, called by ubcore_destroy_vtp */ -static int ubcore_disconnect_fe_tp(struct ubcore_tp *tp) -{ - struct ubcore_tp_node *tp_node = tp->priv; - struct ubcore_device *dev = tp->ub_dev; - - if (atomic_dec_return(&tp->use_cnt) == 0) { - struct ubcore_ta ta; - - ta.type = UBCORE_TA_VIRT; - - ubcore_remove_tp_node(&dev->ht[UBCORE_HT_TP], tp_node); - return ubcore_destroy_local_peer_tp(tp, &ta); - } - return 0; -} - int ubcore_fill_netaddr_macvlan(struct ubcore_net_addr *netaddr, struct net_device *netdev, enum ubcore_net_addr_type type) { @@ -460,6 +385,7 @@ void ubcore_modify_tp_attr(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, tp->flag.bs.cc_en = attr->flag.bs.cc_en; tp->flag.bs.cc_alg = attr->flag.bs.cc_alg; tp->flag.bs.spray_en = attr->flag.bs.spray_en; + tp->flag.bs.clan = attr->flag.bs.clan; } ubcore_mod_tp_attr_with_mask(tp, attr, peer_tpn, mask); @@ -470,19 +396,10 @@ void ubcore_modify_tp_attr(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, ubcore_mod_tp_attr_with_mask(tp, attr, cc_pattern_idx, mask); ubcore_mod_tp_attr_with_mask(tp, attr, peer_ext, mask); ubcore_mod_tp_attr_with_mask(tp, attr, local_net_addr_idx, mask); + ubcore_mod_tp_attr_with_mask(tp, attr, peer_net_addr, mask); ubcore_mod_tp_attr_with_mask(tp, attr, port_id, mask); } -/* create vtp and connect to a remote vtp peer, called by ubcore_create_vtp */ -static struct ubcore_tp *ubcore_connect_fe_tp(struct ubcore_device *dev, - union ubcore_eid *remote_eid, enum ubcore_transport_mode trans_mode, - struct ubcore_udata *udata) -{ - struct ubcore_tp *tp = NULL; - - return tp; -} - static int ubcore_set_target_peer(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask *mask, struct ubcore_tp_attr *tp_attr, struct ubcore_udata udata) { @@ -500,70 +417,6 @@ static int ubcore_set_target_peer(struct ubcore_tp *tp, struct ubcore_tp_attr *a return ubcore_set_tp_peer_ext(attr, udata.udrv_data->in_addr, udata.udrv_data->in_len); } -static struct ubcore_nlmsg *ubcore_get_destroy_tp_response(enum ubcore_nl_resp_status ret, - struct ubcore_nlmsg *req) -{ - struct ubcore_nl_destroy_tp_resp *destroy_resp; - struct ubcore_nlmsg *resp = NULL; - - resp = ubcore_alloc_nlmsg(sizeof(struct ubcore_nl_destroy_tp_resp), &req->dst_eid, - &req->src_eid); - if (resp == NULL) { - ubcore_log_err("Failed to alloc destroy tp response"); - return NULL; - } - - resp->msg_type = UBCORE_NL_DESTROY_TP_RESP; - resp->nlmsg_seq = req->nlmsg_seq; - resp->transport_type = req->transport_type; - destroy_resp = (struct ubcore_nl_destroy_tp_resp *)resp->payload; - destroy_resp->ret = ret; - - return resp; -} - -static struct ubcore_nlmsg *ubcore_get_create_tp_response(struct ubcore_tp *tp, - struct ubcore_nlmsg *req) -{ - uint32_t payload_len = (uint32_t)sizeof(struct ubcore_nl_create_tp_resp) + - (tp == NULL ? 0 : tp->tp_ext.len); - struct ubcore_nl_create_tp_resp *create_resp; - struct ubcore_nlmsg *resp = NULL; - - if (payload_len < (uint32_t)sizeof(struct ubcore_nl_create_tp_resp)) { - /* If the value overflows, tp must exist */ - ubcore_log_err("tp_ext len %u is err", tp->tp_ext.len); - return NULL; - } - - resp = ubcore_alloc_nlmsg(payload_len, &req->dst_eid, &req->src_eid); - if (resp == NULL) { - ubcore_log_err("Failed to alloc create tp response"); - return NULL; - } - - resp->msg_type = req->msg_type + 1; - resp->nlmsg_seq = req->nlmsg_seq; - resp->transport_type = req->transport_type; - create_resp = (struct ubcore_nl_create_tp_resp *)resp->payload; - if (tp == NULL) { - create_resp->ret = UBCORE_NL_RESP_FAIL; - return resp; - } - - create_resp->ret = UBCORE_NL_RESP_SUCCESS; - create_resp->flag = tp->flag; - create_resp->peer_tpn = tp->tpn; - create_resp->peer_mtu = tp->mtu; - create_resp->peer_rx_psn = tp->rx_psn; - create_resp->peer_ext_len = tp->tp_ext.len; - if (tp->tp_ext.len > 0) - (void)memcpy(create_resp->peer_ext, (void *)tp->tp_ext.addr, - tp->tp_ext.len); - - return resp; -} - static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, enum ubcore_transport_mode trans_mode, struct ubcore_vtp_param *vtp_param) { @@ -581,7 +434,7 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, return; vtp_param->local_eid = jfs->ub_dev->eid_table.eid_entries[jfs->jfs_cfg.eid_index].eid; - vtp_param->local_jetty = jfs->id; + vtp_param->local_jetty = jfs->jfs_id.id; vtp_param->eid_index = jfs->jfs_cfg.eid_index; break; case UBCORE_TA_JETTY_TJETTY: @@ -590,7 +443,7 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, return; vtp_param->local_eid = jetty->ub_dev->eid_table.eid_entries[jetty->jetty_cfg.eid_index].eid; - vtp_param->local_jetty = jetty->id; + vtp_param->local_jetty = jetty->jetty_id.id; vtp_param->eid_index = jetty->jetty_cfg.eid_index; break; case UBCORE_TA_NONE: @@ -605,34 +458,6 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, vtp_param->ta = *ta; } -static struct ubcore_tp *ubcore_create_target_tp(struct ubcore_device *dev, - struct ubcore_nlmsg *req, struct ubcore_ta *ta) -{ - struct ubcore_nl_create_tp_req *create = - (struct ubcore_nl_create_tp_req *)(void *)req->payload; - /* create tp parameters */ - struct ubcore_udrv_priv udrv_data = { - .in_addr = (uint64_t)(create->ext_udrv + create->ext_len), - .in_len = create->udrv_in_len, - .out_addr = 0, - .out_len = 0 - }; - struct ubcore_udata udata = { - .uctx = NULL, - .udrv_data = &udrv_data - }; - struct ubcore_tp_cfg cfg = {0}; - struct ubcore_tp *tp = NULL; - - tp = ubcore_create_tp(dev, &cfg, &udata); - if (tp == NULL) { - ubcore_log_err("Failed to create tp in create target tp.\n"); - return NULL; - } - - return tp; -} - int ubcore_modify_tp(struct ubcore_device *dev, struct ubcore_tp_node *tp_node, struct ubcore_tp_attr *tp_attr, struct ubcore_udata udata) { @@ -685,38 +510,6 @@ int ubcore_modify_tp(struct ubcore_device *dev, struct ubcore_tp_node *tp_node, return ret; } -static struct ubcore_tp *ubcore_accept_target_tp(struct ubcore_device *dev, - struct ubcore_nlmsg *req, - struct ubcore_tp_advice *advice) -{ - struct ubcore_tp_meta *meta = &advice->meta; - struct ubcore_tp *new_tp = NULL; /* new created target tp */ - struct ubcore_tp_node *tp_node; - - tp_node = ubcore_hash_table_lookup(meta->ht, meta->hash, &meta->key); - if (tp_node == NULL) { - new_tp = ubcore_create_target_tp(dev, req, &advice->ta); - if (new_tp == NULL) { - ubcore_log_err("Failed to create target tp towards remote eid %pI6c", - &req->src_eid); - return NULL; - } - tp_node = ubcore_add_tp_node(meta->ht, meta->hash, &meta->key, new_tp, &advice->ta); - if (tp_node == NULL) { - (void)ubcore_destroy_tp(new_tp); - ubcore_log_err( - "Failed to add target tp towards remote eid %pI6c to the tp table", - &req->src_eid); - return NULL; - } - if (tp_node->tp != new_tp) { - (void)ubcore_destroy_tp(new_tp); - new_tp = NULL; - } - } - return tp_node->tp; -} - static int ubcore_parse_ta(struct ubcore_device *dev, struct ubcore_ta_data *ta_data, struct ubcore_tp_advice *advice) { @@ -766,217 +559,6 @@ static int ubcore_parse_ta(struct ubcore_device *dev, struct ubcore_ta_data *ta_ return 0; } -static struct ubcore_tp *ubcore_advise_target_tp(struct ubcore_device *dev, - struct ubcore_nlmsg *req) -{ - struct ubcore_nl_create_tp_req *create = - (struct ubcore_nl_create_tp_req *)(void *)req->payload; - struct ubcore_tp_advice advice; - struct ubcore_tp_meta *meta; - struct ubcore_tp *tp; - - meta = &advice.meta; - if (ubcore_parse_ta(dev, &create->ta, &advice) != 0) { - ubcore_log_err("Failed to parse ta with type %u", (uint32_t)create->ta.ta_type); - return NULL; - } else if (meta->ht == NULL) { - ubcore_log_err("tp table is already released"); - return NULL; - } - - tp = ubcore_accept_target_tp(dev, req, &advice); - /* pair with get_tptable in parse_ta */ - ubcore_put_tptable(meta->ht); - return tp; -} - -static struct ubcore_tp *ubcore_accept_target_vtp(struct ubcore_device *dev, - struct ubcore_nlmsg *req) -{ - struct ubcore_tp_node *tp_node; - struct ubcore_tp *tp = NULL; - - tp = ubcore_create_target_tp(dev, req, NULL); - if (tp == NULL) { - ubcore_log_err("Failed to create tp"); - return NULL; - } - - tp_node = ubcore_add_tp_with_tpn(dev, tp); - if (tp_node == NULL) { - ubcore_log_err("Failed to add tp to the tp table in the device"); - goto destroy_tp; - } - return tp; - -destroy_tp: - (void)ubcore_destroy_tp(tp); - return NULL; -} - -static struct ubcore_tp *ubcore_bind_target_tp(struct ubcore_device *dev, - struct ubcore_nlmsg *req) -{ - return ubcore_advise_target_tp(dev, req); -} - -struct ubcore_nlmsg *ubcore_handle_create_tp_req(struct ubcore_nlmsg *req) -{ - struct ubcore_nl_create_tp_req *create; - struct ubcore_tp *tp = NULL; - struct ubcore_device *dev; - - if (req == NULL) - return NULL; - create = (struct ubcore_nl_create_tp_req *)(void *)req->payload; - if (req->payload_len < sizeof(struct ubcore_nl_create_tp_req)) { - ubcore_log_err("Invalid create req"); - return NULL; - } - - dev = ubcore_find_device(&req->dst_eid, req->transport_type); - if (dev == NULL || !ubcore_have_tp_ops(dev)) { - if (dev != NULL) - ubcore_put_device(dev); - ubcore_log_err("Failed to find device or device ops invalid"); - return ubcore_get_create_tp_response(NULL, req); - } - - if (create->ta.ta_type == UBCORE_TA_VIRT) { - tp = ubcore_accept_target_vtp(dev, req); - } else if (create->trans_mode == UBCORE_TP_RC) { - tp = ubcore_bind_target_tp(dev, req); - } else if (create->trans_mode == UBCORE_TP_RM && - dev->transport_type == UBCORE_TRANSPORT_IB) { - tp = ubcore_advise_target_tp(dev, req); - } - - if (tp == NULL) - ubcore_log_err("Failed to create target tp towards remote eid %pI6c", - &req->src_eid); - - ubcore_put_device(dev); - return ubcore_get_create_tp_response(tp, req); -} -EXPORT_SYMBOL(ubcore_handle_create_tp_req); - -/* destroy target RM tp created by ubcore_advise_target_tp */ -static int ubcore_unadvise_target_tp(struct ubcore_device *dev, - struct ubcore_nl_destroy_tp_req *destroy) -{ - struct ubcore_tp_advice advice; - struct ubcore_tp_meta *meta; - struct ubcore_tp *tp = NULL; - - meta = &advice.meta; - if (ubcore_parse_ta(dev, &destroy->ta, &advice) != 0) { - ubcore_log_err("Failed to parse ta with type %u", (uint32_t)destroy->ta.ta_type); - return -1; - } else if (meta->ht == NULL) { - ubcore_log_warn("tp table is already released"); - return 0; - } - - return ubcore_destroy_tp(tp); -} - -/* destroy target RC tp created by ubcore_bind_target_tp */ -static int ubcore_unbind_target_tp(struct ubcore_device *dev, - struct ubcore_nl_destroy_tp_req *destroy) -{ - return ubcore_unadvise_target_tp(dev, destroy); -} - -struct ubcore_nlmsg *ubcore_handle_destroy_tp_req(struct ubcore_nlmsg *req) -{ - struct ubcore_nl_destroy_tp_req *destroy; - struct ubcore_device *dev; - int ret = -1; - - if (req == NULL) { - ubcore_log_err("Failed to destroy tp req, req is NULL"); - return NULL; - } - - if (req->payload_len != sizeof(struct ubcore_nl_destroy_tp_req)) { - ubcore_log_err("Invalid destroy req"); - return NULL; - } - - dev = ubcore_find_device(&req->dst_eid, req->transport_type); - if (dev == NULL || !ubcore_have_tp_ops(dev)) { - if (dev != NULL) - ubcore_put_device(dev); - ubcore_log_err("Failed to find device or device ops invalid"); - return ubcore_get_destroy_tp_response(UBCORE_NL_RESP_FAIL, req); - } - - destroy = (struct ubcore_nl_destroy_tp_req *)(void *)req->payload; - if (destroy->ta.ta_type == UBCORE_TA_VIRT) { - } else if (destroy->trans_mode == UBCORE_TP_RC) { - ret = ubcore_unbind_target_tp(dev, destroy); - } else if (destroy->trans_mode == UBCORE_TP_RM && - dev->transport_type == UBCORE_TRANSPORT_IB) { - ret = ubcore_unadvise_target_tp(dev, destroy); - } - ubcore_put_device(dev); - return ubcore_get_destroy_tp_response((enum ubcore_nl_resp_status)ret, req); -} -EXPORT_SYMBOL(ubcore_handle_destroy_tp_req); - -struct ubcore_tp *ubcore_create_vtp(struct ubcore_device *dev, union ubcore_eid *remote_eid, - enum ubcore_transport_mode trans_mode, - struct ubcore_udata *udata) -{ - if (!ubcore_have_tp_ops(dev) || dev->attr.virtualization || remote_eid == NULL) { - ubcore_log_err("Invalid parameter"); - return NULL; - } - - switch (dev->transport_type) { - case UBCORE_TRANSPORT_IB: /* alpha */ - if (trans_mode == UBCORE_TP_RM || trans_mode == UBCORE_TP_RC) - return ubcore_connect_fe_tp(dev, remote_eid, trans_mode, udata); - break; - case UBCORE_TRANSPORT_UB: /* beta */ - case UBCORE_TRANSPORT_IP: - case UBCORE_TRANSPORT_INVALID: - case UBCORE_TRANSPORT_MAX: - default: - break; - } - return NULL; -} -EXPORT_SYMBOL(ubcore_create_vtp); - -int ubcore_destroy_vtp(struct ubcore_tp *vtp) -{ - enum ubcore_transport_mode trans_mode; - struct ubcore_device *dev; - - if (vtp == NULL || vtp->ub_dev == NULL || vtp->priv == NULL || - vtp->ub_dev->attr.virtualization) { - ubcore_log_err("Invalid para"); - return -1; - } - dev = vtp->ub_dev; - trans_mode = vtp->trans_mode; - switch (dev->transport_type) { - case UBCORE_TRANSPORT_IB: /* alpha */ - if (trans_mode == UBCORE_TP_RM || trans_mode == UBCORE_TP_RC) - return ubcore_disconnect_fe_tp(vtp); - break; - case UBCORE_TRANSPORT_UB: /* beta */ - case UBCORE_TRANSPORT_IP: - case UBCORE_TRANSPORT_INVALID: - case UBCORE_TRANSPORT_MAX: - default: - break; - } - return -1; -} -EXPORT_SYMBOL(ubcore_destroy_vtp); - static int ubcore_init_create_tp_req(struct ubcore_device *dev, struct ubcore_vtp_param *tp_param, struct ubcore_tp *tp, struct ubcore_udata *udata, struct ubcore_create_vtp_req *data) { @@ -1015,6 +597,10 @@ static int ubcore_send_create_tp_req(struct ubcore_device *dev, struct ubcore_vt uint32_t tp_len; int ret; + /* dev has been unregistered and the message channel has been down */ + if (ubcore_check_dev_is_exist(dev->dev_name) == false) + return -ENONET; + tp_len = tp->tp_ext.len; udata_len = get_udrv_in_len(udata); if ((uint32_t)sizeof(struct ubcore_create_vtp_req) + tp_len > ULONG_MAX - udata_len) @@ -1048,6 +634,11 @@ static int ubcore_handle_del_tp_resp(struct ubcore_device *dev, struct ubcore_re { struct ubcore_destroy_vtp_resp *vtp_resp = (struct ubcore_destroy_vtp_resp *)resp->data; + if (resp == NULL || resp->len < sizeof(struct ubcore_destroy_vtp_resp)) { + ubcore_log_err("invalid ubcore_destroy_vpt_resp len"); + return -1; + } + if (vtp_resp->ret == UBCORE_MSG_RESP_FAIL) { ubcore_log_err("failed to destroy vtp: response error"); return -1; @@ -1065,6 +656,10 @@ static int ubcore_send_del_tp_req(struct ubcore_device *dev, struct ubcore_vtp_p struct ubcore_resp_cb cb; int ret; + /* dev has been unregistered and the message channel has been down */ + if (ubcore_check_dev_is_exist(dev->dev_name) == false) + return -ENONET; + req_msg = kcalloc(1, sizeof(struct ubcore_req) + sizeof(struct ubcore_create_vtp_req), GFP_KERNEL); if (req_msg == NULL) @@ -1105,7 +700,7 @@ static struct ubcore_nlmsg *ubcore_get_query_tp_req(struct ubcore_device *dev, return NULL; req->transport_type = dev->transport_type; - req->msg_type = UBCORE_NL_QUERY_TP_REQ; + req->msg_type = UBCORE_CMD_QUERY_TP_REQ; req->payload_len = payload_len; query = (struct ubcore_nl_query_tp_req *)req->payload; query->trans_mode = trans_mode; @@ -1136,7 +731,7 @@ static int ubcore_query_tp(struct ubcore_device *dev, } resp = (struct ubcore_nl_query_tp_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_NL_QUERY_TP_RESP || resp == NULL || + if (resp_msg->msg_type != UBCORE_CMD_QUERY_TP_RESP || resp == NULL || resp->ret != UBCORE_NL_RESP_SUCCESS) { ret = -1; ubcore_log_err("Query tp request is rejected with type %d ret %d", @@ -1178,20 +773,21 @@ static int ubcore_query_initiator_tp_cfg(struct ubcore_tp_cfg *cfg, struct ubcor return 0; } +/* udata may be empty because the data may come from the user space or kernel space. */ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, struct ubcore_tp_advice *advice, struct ubcore_udata *udata) { - struct ubcore_device *dev = jetty->ub_dev; struct ubcore_vtp_param tp_param = { 0 }; - struct ubcore_tp_node *tp_node; - struct ubcore_tp *new_tp = NULL; struct ubcore_tp_cfg tp_cfg = { 0 }; + struct ubcore_tp *new_tp = NULL; + struct ubcore_tp_node *tp_node; + struct ubcore_device *dev; if (jetty == NULL || tjetty == NULL || advice == NULL) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } - + dev = jetty->ub_dev; mutex_lock(&tjetty->lock); if (tjetty->tp != NULL) { mutex_unlock(&tjetty->lock); @@ -1207,9 +803,9 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, } /* driver gurantee to return the same tp if we have created it as a target */ new_tp = ubcore_create_tp(dev, &tp_cfg, udata); - if (new_tp == NULL) { + if (IS_ERR_OR_NULL(new_tp)) { ubcore_log_err("Failed to create tp"); - return -1; + return PTR_ERR(new_tp); } tp_node = ubcore_add_tp_node(advice->meta.ht, advice->meta.hash, &advice->meta.key, new_tp, &advice->ta); @@ -1223,6 +819,7 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, } if (ubcore_send_create_tp_req(dev, &tp_param, tp_node->tp, udata) != 0) { ubcore_log_err("Failed to send tp req"); + ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); return -1; } mutex_lock(&tjetty->lock); @@ -1255,6 +852,8 @@ int ubcore_unbind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, ubcore_log_warn("failed to unbind tp\n"); return -1; } + ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); + mutex_lock(&tjetty->lock); tjetty->tp = NULL; mutex_unlock(&tjetty->lock); @@ -1290,9 +889,9 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, * and cannot be used in the uvs context ioctl to create tp */ new_tp = ubcore_create_tp(dev, &tp_cfg, udata); - if (new_tp == NULL) { + if (IS_ERR_OR_NULL(new_tp)) { ubcore_log_err("Failed to create tp"); - return -1; + return PTR_ERR(new_tp); } tp_node = ubcore_add_tp_node(advice->meta.ht, advice->meta.hash, &advice->meta.key, new_tp, &advice->ta); @@ -1318,6 +917,7 @@ EXPORT_SYMBOL(ubcore_advise_tp); int ubcore_unadvise_tp(struct ubcore_device *dev, struct ubcore_tp_advice *advice) { struct ubcore_vtp_param tp_param; + int ret; if (dev == NULL || advice == NULL) { ubcore_log_err("Invalid parameter.\n"); @@ -1325,7 +925,12 @@ int ubcore_unadvise_tp(struct ubcore_device *dev, struct ubcore_tp_advice *advic } ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RM, &tp_param); - return ubcore_send_del_tp_req(dev, &tp_param); + ret = ubcore_send_del_tp_req(dev, &tp_param); + if (ret != 0) + return ret; + + ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); + return 0; } EXPORT_SYMBOL(ubcore_unadvise_tp); @@ -1359,7 +964,7 @@ static struct ubcore_nlmsg *ubcore_get_restore_tp_req(struct ubcore_tp *tp) return NULL; req->transport_type = tp->ub_dev->transport_type; - req->msg_type = UBCORE_NL_RESTORE_TP_REQ; + req->msg_type = UBCORE_CMD_RESTORE_TP_REQ; restore = (struct ubcore_nl_restore_tp_req *)(void *)req->payload; restore->trans_mode = tp->trans_mode; restore->tpn = tp->tpn; @@ -1373,7 +978,7 @@ static struct ubcore_nlmsg *ubcore_get_restore_tp_req(struct ubcore_tp *tp) } static struct ubcore_nlmsg *ubcore_get_restore_tp_response(struct ubcore_nlmsg *req, - struct ubcore_tp *tp) + uint32_t rx_psn, enum ubcore_nl_resp_status status) { struct ubcore_nl_restore_tp_resp *restore_resp; struct ubcore_nlmsg *resp = NULL; @@ -1385,17 +990,17 @@ static struct ubcore_nlmsg *ubcore_get_restore_tp_response(struct ubcore_nlmsg * return NULL; } - resp->msg_type = UBCORE_NL_RESTORE_TP_RESP; + resp->msg_type = UBCORE_CMD_RESTORE_TP_RESP; resp->nlmsg_seq = req->nlmsg_seq; resp->transport_type = req->transport_type; restore_resp = (struct ubcore_nl_restore_tp_resp *)resp->payload; - if (tp == NULL) { + if (status == UBCORE_NL_RESP_FAIL) { restore_resp->ret = UBCORE_NL_RESP_FAIL; return resp; } - restore_resp->peer_rx_psn = tp->rx_psn; + restore_resp->peer_rx_psn = rx_psn; return resp; } @@ -1577,7 +1182,7 @@ static struct ubcore_nlmsg *ubcore_get_tp_error_req(struct ubcore_device *dev, s return NULL; req->transport_type = tp->ub_dev->transport_type; - req->msg_type = UBCORE_NL_TP_ERROR_REQ; + req->msg_type = UBCORE_CMD_TP_ERROR_REQ; error_req = (struct ubcore_tp_error_req *)(void *)req->payload; error_req->tpgn = tp->tpg->tpgn; error_req->tpn = tp->tpn; @@ -1645,7 +1250,7 @@ static struct ubcore_nlmsg *ubcore_get_tp_suspend_req(struct ubcore_device *dev, return NULL; req->transport_type = tp->ub_dev->transport_type; - req->msg_type = UBCORE_NL_TP_SUSPEND_REQ; + req->msg_type = UBCORE_CMD_TP_SUSPEND_REQ; suspend_req = (struct ubcore_tp_suspend_req *)(void *)req->payload; suspend_req->tpgn = tp->tpg->tpgn; suspend_req->tpn = tp->tpn; @@ -1681,8 +1286,8 @@ void ubcore_report_tp_suspend(struct ubcore_device *dev, struct ubcore_tp *tp) } /* restore target RM tp created by ubcore_advise_target_tp */ -static struct ubcore_tp *ubcore_restore_advised_target_tp(struct ubcore_device *dev, - struct ubcore_nl_restore_tp_req *restore) +static int ubcore_restore_advised_target_tp(struct ubcore_device *dev, + struct ubcore_nl_restore_tp_req *restore, uint32_t *rx_psn) { struct ubcore_tp_advice advice; struct ubcore_tp_node *tp_node; @@ -1692,53 +1297,60 @@ static struct ubcore_tp *ubcore_restore_advised_target_tp(struct ubcore_device * meta = &advice.meta; if (ubcore_parse_ta(dev, &restore->ta, &advice) != 0) { ubcore_log_err("Failed to parse ta with type %u", (uint32_t)restore->ta.ta_type); - return NULL; + return -1; } else if (meta->ht == NULL) { ubcore_log_err("tp table is already released"); - return NULL; + return -1; } - tp_node = ubcore_hash_table_lookup(meta->ht, meta->hash, &meta->key); + spin_lock(&meta->ht->lock); + tp_node = ubcore_hash_table_lookup_nolock(meta->ht, meta->hash, &meta->key); /* pair with get_tptable in parse_ta */ ubcore_put_tptable(meta->ht); if (tp_node == NULL) { + spin_unlock(&meta->ht->lock); ubcore_log_err("tp is not found%u", restore->peer_tpn); - return NULL; + return -1; } tp = tp_node->tp; if (ubcore_restore_tp_to_rts(dev, tp, get_random_u32(), restore->rx_psn) != 0) { + spin_unlock(&meta->ht->lock); ubcore_log_err("Failed to modify tp to rts %u", restore->rx_psn); - return NULL; + return -1; } - return tp; + *rx_psn = tp->rx_psn; + spin_unlock(&meta->ht->lock); + return 0; } -static struct ubcore_tp *ubcore_restore_bound_target_tp(struct ubcore_device *dev, - struct ubcore_nl_restore_tp_req *restore) +static int ubcore_restore_bound_target_tp(struct ubcore_device *dev, + struct ubcore_nl_restore_tp_req *restore, uint32_t *rx_psn) { - return ubcore_restore_advised_target_tp(dev, restore); + return ubcore_restore_advised_target_tp(dev, restore, rx_psn); } -static struct ubcore_tp *ubcore_handle_restore_tp(struct ubcore_device *dev, - struct ubcore_nl_restore_tp_req *restore) +static int ubcore_handle_restore_tp(struct ubcore_device *dev, + struct ubcore_nl_restore_tp_req *restore, uint32_t *rx_psn) { if (dev->transport_type != UBCORE_TRANSPORT_IB || restore == NULL || restore->trans_mode == UBCORE_TP_UM || restore->ta.ta_type == UBCORE_TA_NONE || restore->ta.ta_type >= UBCORE_TA_VIRT) - return NULL; + return -1; if (restore->trans_mode == UBCORE_TP_RM) - return ubcore_restore_advised_target_tp(dev, restore); + return ubcore_restore_advised_target_tp(dev, restore, rx_psn); else - return ubcore_restore_bound_target_tp(dev, restore); + return ubcore_restore_bound_target_tp(dev, restore, rx_psn); } struct ubcore_nlmsg *ubcore_handle_restore_tp_req(struct ubcore_nlmsg *req) { + enum ubcore_nl_resp_status status = UBCORE_NL_RESP_SUCCESS; struct ubcore_nl_restore_tp_req *restore; struct ubcore_device *dev; - struct ubcore_tp *tp; + uint32_t rx_psn = 0; + int ret = 0; if (req == NULL || req->payload_len != sizeof(struct ubcore_nl_restore_tp_req)) { ubcore_log_err("Invalid restore req"); @@ -1751,15 +1363,17 @@ struct ubcore_nlmsg *ubcore_handle_restore_tp_req(struct ubcore_nlmsg *req) if (dev != NULL) ubcore_put_device(dev); ubcore_log_err("Failed to find device or device ops invalid"); - return ubcore_get_restore_tp_response(req, NULL); + return ubcore_get_restore_tp_response(req, rx_psn, UBCORE_NL_RESP_FAIL); } - tp = ubcore_handle_restore_tp(dev, restore); - if (tp == NULL) + ret = ubcore_handle_restore_tp(dev, restore, &rx_psn); + if (ret != 0) { ubcore_log_err("Failed to restore target tp towards remote eid %pI6c", &req->src_eid); + status = UBCORE_NL_RESP_FAIL; + } ubcore_put_device(dev); - return ubcore_get_restore_tp_response(req, tp); + return ubcore_get_restore_tp_response(req, rx_psn, status); } EXPORT_SYMBOL(ubcore_handle_restore_tp_req); diff --git a/drivers/ub/urma/ubcore/ubcore_tp.h b/drivers/ub/urma/ubcore/ubcore_tp.h index a8b77a848298..723e9d13ce6c 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.h +++ b/drivers/ub/urma/ubcore/ubcore_tp.h @@ -47,8 +47,6 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, struct ubcore_tp_advice *advice, struct ubcore_udata *udata); int ubcore_unadvise_tp(struct ubcore_device *dev, struct ubcore_tp_advice *advice); -struct ubcore_nlmsg *ubcore_handle_create_tp_req(struct ubcore_nlmsg *req); -struct ubcore_nlmsg *ubcore_handle_destroy_tp_req(struct ubcore_nlmsg *req); struct ubcore_nlmsg *ubcore_handle_restore_tp_req(struct ubcore_nlmsg *req); /* bind tp APIs */ @@ -73,4 +71,6 @@ void ubcore_report_tp_error(struct ubcore_device *dev, struct ubcore_tp *tp); void ubcore_modify_tp_attr(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask mask); int ubcore_modify_tp_state_check(struct ubcore_tp *tp, enum ubcore_tp_state new_state); +void ubcore_tp_get(void *obj); +void ubcore_tp_kref_put(struct ubcore_tp *tp); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_tp_table.c b/drivers/ub/urma/ubcore/ubcore_tp_table.c index 95917ea0f0f6..b2b5ef2c7a32 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp_table.c +++ b/drivers/ub/urma/ubcore/ubcore_tp_table.c @@ -162,44 +162,17 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t } tp_node = ubcore_hash_table_lookup_nolock(ht, hash, key); if (tp_node != NULL) { + atomic_inc(&tp_node->tp->use_cnt); spin_unlock(&ht->lock); mutex_destroy(&new_tp_node->lock); kfree(new_tp_node); - atomic_inc(&tp_node->tp->use_cnt); return tp_node; } ubcore_hash_table_add_nolock(ht, &new_tp_node->hnode, hash); /* set private data for tp restore */ tp->priv = new_tp_node; - spin_unlock(&ht->lock); atomic_inc(&new_tp_node->tp->use_cnt); + spin_unlock(&ht->lock); return new_tp_node; } - -struct ubcore_tp_node *ubcore_add_tp_with_tpn(struct ubcore_device *dev, struct ubcore_tp *tp) -{ - struct ubcore_tp_node *tp_node; - int ret; - - tp_node = kzalloc(sizeof(struct ubcore_tp_node), GFP_KERNEL); - if (tp_node == NULL) - return NULL; - - tp_node->key.key_type = UBCORE_TP_KEY_TPN; - tp_node->key.tpn = tp->tpn; - tp_node->tp = tp; - mutex_init(&tp_node->lock); - - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TP], &tp_node->hnode, tp->tpn); - if (ret != 0) { - ubcore_log_err("Failed to add tp with tpn %u to tp table", tp->tpn); - mutex_destroy(&tp_node->lock); - kfree(tp_node); - return NULL; - } - /* set private data to find tp node fast */ - tp->priv = tp_node; - return tp_node; -} - diff --git a/drivers/ub/urma/ubcore/ubcore_tp_table.h b/drivers/ub/urma/ubcore/ubcore_tp_table.h index 8ef552f9ca2e..ed1045ff2ac1 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp_table.h +++ b/drivers/ub/urma/ubcore/ubcore_tp_table.h @@ -59,6 +59,4 @@ struct ubcore_hash_table *ubcore_create_tptable(void); void ubcore_destroy_tptable(struct ubcore_hash_table **pp_ht); struct ubcore_hash_table *ubcore_get_tptable(struct ubcore_hash_table *ht); void ubcore_put_tptable(struct ubcore_hash_table *ht); - -struct ubcore_tp_node *ubcore_add_tp_with_tpn(struct ubcore_device *dev, struct ubcore_tp *tp); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_tpg.c b/drivers/ub/urma/ubcore/ubcore_tpg.c index 539150bc93ca..25bd79221e5e 100644 --- a/drivers/ub/urma/ubcore/ubcore_tpg.c +++ b/drivers/ub/urma/ubcore/ubcore_tpg.c @@ -24,35 +24,59 @@ #include "ubcore_tp.h" #include "ubcore_tpg.h" +static int ubcore_free_wait_tpg(struct ubcore_device *dev, struct ubcore_tpg *tpg) +{ + ubcore_tpg_kref_put(tpg); + wait_for_completion(&tpg->comp); + return dev->ops->destroy_tpg(tpg); +} + struct ubcore_tpg *ubcore_create_tpg(struct ubcore_device *dev, struct ubcore_tpg_cfg *cfg) { struct ubcore_tpg *tpg; uint32_t i; - int ret; if (dev->ops == NULL || dev->ops->create_tpg == NULL) - return NULL; + return ERR_PTR(-EINVAL); tpg = dev->ops->create_tpg(dev, cfg, NULL); - if (tpg == NULL) { + if (IS_ERR_OR_NULL(tpg)) { ubcore_log_err("Failed to create tpg"); - return NULL; + if (tpg == NULL) + return ERR_PTR(-ENOEXEC); + return tpg; } tpg->ub_dev = dev; tpg->tpg_cfg = *cfg; for (i = 0; i < cfg->tp_cnt; i++) tpg->tp_list[i] = NULL; - atomic_set(&tpg->use_cnt, 1); + atomic_set(&tpg->use_cnt, 0); + kref_init(&tpg->ref_cnt); + init_completion(&tpg->comp); + mutex_init(&tpg->mutex); - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); - if (ret != 0) { - (void)dev->ops->destroy_tpg(tpg); - tpg = NULL; - ubcore_log_err("Failed to add tpg to the tpg table"); - } return tpg; } +static void ubcore_tpg_kref_release(struct kref *ref_cnt) +{ + struct ubcore_tpg *tpg = container_of(ref_cnt, struct ubcore_tpg, ref_cnt); + + complete(&tpg->comp); +} + +void ubcore_tpg_kref_put(struct ubcore_tpg *tpg) +{ + (void)kref_put(&tpg->ref_cnt, ubcore_tpg_kref_release); +} + +void ubcore_tpg_get(void *obj) +{ + struct ubcore_tpg *tpg = obj; + + kref_get(&tpg->ref_cnt); +} + int ubcore_destroy_tpg(struct ubcore_tpg *tpg) { struct ubcore_device *dev = tpg->ub_dev; @@ -61,14 +85,7 @@ int ubcore_destroy_tpg(struct ubcore_tpg *tpg) if (dev->ops == NULL || dev->ops->destroy_tpg == NULL) return -EINVAL; - if (atomic_dec_return(&tpg->use_cnt) > 0) { - ubcore_log_err("tpg in use"); - return -EBUSY; - } - - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); - - ret = dev->ops->destroy_tpg(tpg); + ret = ubcore_free_wait_tpg(dev, tpg); if (ret != 0) { (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); /* inc tpg use cnt? */ @@ -83,6 +100,74 @@ struct ubcore_tpg *ubcore_find_tpg(struct ubcore_device *dev, uint32_t tpgn) return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_TPG], tpgn, &tpgn); } +struct ubcore_tpg *ubcore_find_get_tpg(struct ubcore_device *dev, uint32_t tpgn) +{ + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_TPG], tpgn, &tpgn); +} + +struct ubcore_tpg *ubcore_find_remove_tpg(struct ubcore_device *dev, uint32_t tpgn) +{ + struct ubcore_tpg *tpg; + + spin_lock(&dev->ht[UBCORE_HT_TPG].lock); + if (&dev->ht[UBCORE_HT_TPG].head == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); + return NULL; + } + tpg = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_TPG], tpgn, &tpgn); + if (tpg == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); + return NULL; + } + if (atomic_read(&tpg->use_cnt) > 0) { + spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); + ubcore_log_err("Failed to remove tpg"); + return NULL; + } + ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); + spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); + + return tpg; +} + +int ubcore_add_tp(struct ubcore_device *dev, struct ubcore_tp *tp) +{ + return ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UB_TP], + &tp->hnode, tp->tpn); +} + +struct ubcore_tp *ubcore_find_get_tp(struct ubcore_device *dev, uint32_t tpn) +{ + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_UB_TP], tpn, &tpn); +} + +struct ubcore_tp *ubcore_find_remove_tp_node(struct ubcore_device *dev, uint32_t tpn) +{ + struct ubcore_tp *tp; + + spin_lock(&dev->ht[UBCORE_HT_UB_TP].lock); + if (&dev->ht[UBCORE_HT_UB_TP].head == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + return NULL; + } + tp = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_UB_TP], tpn, &tpn); + if (tp == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + return NULL; + } + + if (atomic_dec_return(&tp->use_cnt) > 0) { + spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + ubcore_log_warn("Failed to remove tp:%u and use cnt:%u", + tp->tpn, (uint32_t)atomic_read(&tp->use_cnt)); + return NULL; + } + ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_UB_TP], &tp->hnode); + spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + + return tp; +} + static void ubcore_set_tp_init_flag(union ubcore_tp_flag *flag, union ubcore_tp_cfg_flag in) { flag->bs.target = in.bs.target; @@ -116,60 +201,99 @@ static void ubcore_store_tp_init_cfg(struct ubcore_tpg *tpg, struct ubcore_tp *t int ubcore_create_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg, struct ubcore_tp_cfg *cfg) { - struct ubcore_tp *tp[UBCORE_MAX_TP_CNT_IN_GRP]; + struct ubcore_tp *tp[UBCORE_MAX_TP_CNT_IN_GRP] = {0}; uint32_t tp_cnt = tpg->tpg_cfg.tp_cnt; + int created_tp_cnt; uint32_t i; + uint32_t j; int ret; if (dev->ops == NULL || dev->ops->create_multi_tp == NULL || dev->ops->destroy_multi_tp == NULL) return -EINVAL; - ret = dev->ops->create_multi_tp(dev, tp_cnt, cfg, NULL, tp); - if (ret != (int)tp_cnt) { - if (ret > 0) - (void)dev->ops->destroy_multi_tp(ret, tp); + created_tp_cnt = dev->ops->create_multi_tp(dev, tp_cnt, cfg, NULL, tp); + if (created_tp_cnt != (int)tp_cnt) { + if (created_tp_cnt > 0) + (void)dev->ops->destroy_multi_tp(created_tp_cnt, tp); ubcore_log_err("Failed to create multi tp"); return -ENOSPC; } /* add tp to tpg */ for (i = 0; i < tp_cnt; i++) { - if (tp[i] == NULL) { + struct ubcore_tp *single_tp = tp[i]; + + if (single_tp == NULL) { ubcore_log_warn("create multi tp, buf tp is null_ptr"); continue; } - ubcore_store_tp_init_cfg(tpg, tp[i], dev, &cfg[i]); - tpg->tp_list[i] = tp[i]; + kref_init(&single_tp->ref_cnt); + init_completion(&single_tp->comp); + ubcore_store_tp_init_cfg(tpg, single_tp, dev, &cfg[i]); + tpg->tp_list[i] = single_tp; + + ret = ubcore_add_tp(dev, single_tp); + if (ret != 0) { + ubcore_log_err("Failed to add tp:%u to the tp table and tpg:%u, dev:%s", + single_tp->tpn, tpg->tpgn, dev->dev_name); + for (j = 0; j < i; j++) + (void)ubcore_find_remove_tp_node(dev, tp[j]->tpn); + + (void)dev->ops->destroy_multi_tp(created_tp_cnt, tp); + ubcore_log_err("Failed to create multi tp"); + return -EPERM; + } + ubcore_log_debug("success to add tp:%u to the tp table and tpg:%u, dev:%s", + single_tp->tpn, tpg->tpgn, dev->dev_name); } return 0; } -uint32_t ubcore_destroy_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg) +uint32_t ubcore_destroy_multi_tp_from_index(struct ubcore_device *dev, struct ubcore_tpg *tpg, + uint32_t from_index) { struct ubcore_tp *tp[UBCORE_MAX_TP_CNT_IN_GRP]; - uint32_t tp_cnt = tpg->tpg_cfg.tp_cnt; + uint32_t tp_cnt = tpg->tpg_cfg.tp_cnt - from_index; + struct ubcore_tp *single_tp; int ret; int i; if (dev->ops == NULL || dev->ops->destroy_multi_tp == NULL) return 0; - for (i = 0; i < (int)tp_cnt; i++) - tp[i] = tpg->tp_list[i]; + mutex_lock(&tpg->mutex); + for (i = 0; i < (int)tp_cnt; i++) { + tp[i] = tpg->tp_list[i + (int)from_index]; + tpg->tp_list[i + (int)from_index] = NULL; + ubcore_log_info("tp set null %d", i + (int)from_index); + } + mutex_unlock(&tpg->mutex); + + for (i = 0; i < (int)tp_cnt; i++) { + ubcore_tp_kref_put(tp[i]); + wait_for_completion(&tp[i]->comp); + + single_tp = ubcore_find_remove_tp_node(dev, tp[i]->tpn); + if (single_tp == NULL) + ubcore_log_err("failed to find tp with tpn %u and tpgn %u, dev:%s", + tp[i]->tpn, tp[i]->tpg->tpgn, dev->dev_name); + } /* todonext: modify to error, and reset first */ ret = dev->ops->destroy_multi_tp(tp_cnt, tp); if (ret != (int)tp_cnt) ubcore_log_err("Failed to destroy multi tp %d", ret); - for (i = 0; (i < ret) && (i < UBCORE_MAX_TP_CNT_IN_GRP); i++) - tpg->tp_list[i] = NULL; - return (ret > 0 ? (uint32_t)ret : 0); } +uint32_t ubcore_destroy_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg) +{ + return ubcore_destroy_multi_tp_from_index(dev, tpg, 0); +} + uint32_t ubcore_modify_tp_in_tpg(struct ubcore_device *dev, struct ubcore_tpg *tpg, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask *mask, struct ubcore_tp **failed_tp) { @@ -179,6 +303,11 @@ uint32_t ubcore_modify_tp_in_tpg(struct ubcore_device *dev, struct ubcore_tpg *t if (dev->ops == NULL || dev->ops->modify_multi_tp == NULL) return 0; + mutex_lock(&tpg->mutex); + for (i = 0; i < (int)tpg->tpg_cfg.tp_cnt; i++) + ubcore_tp_get(tpg->tp_list[i]); + mutex_unlock(&tpg->mutex); + ret = dev->ops->modify_multi_tp(tpg->tpg_cfg.tp_cnt, tpg->tp_list, attr, mask, failed_tp); if (ret != (int)tpg->tpg_cfg.tp_cnt) ubcore_log_err("Failed to modify multi tp %d and tpgn %u ", ret, tpg->tpgn); @@ -186,6 +315,8 @@ uint32_t ubcore_modify_tp_in_tpg(struct ubcore_device *dev, struct ubcore_tpg *t for (i = 0; (i < ret && i < UBCORE_MAX_TP_CNT_IN_GRP); i++) ubcore_modify_tp_attr(tpg->tp_list[i], &attr[i], mask[i]); + for (i = 0; i < (int)tpg->tpg_cfg.tp_cnt; i++) + ubcore_tp_kref_put(tpg->tp_list[i]); return (ret > 0 ? (uint32_t)ret : 0); } @@ -202,3 +333,22 @@ struct ubcore_tp *ubcore_find_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn) return NULL; } + +struct ubcore_tp *ubcore_find_get_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn) +{ + uint32_t i; + + mutex_lock(&tpg->mutex); + for (i = 0; i < tpg->tpg_cfg.tp_cnt; i++) { + if (tpg->tp_list[i] == NULL || tpg->tp_list[i]->tpn != tpn) + continue; + + ubcore_tp_get(tpg->tp_list[i]); + mutex_unlock(&tpg->mutex); + + return tpg->tp_list[i]; + } + mutex_unlock(&tpg->mutex); + + return NULL; +} diff --git a/drivers/ub/urma/ubcore/ubcore_tpg.h b/drivers/ub/urma/ubcore/ubcore_tpg.h index 7ef40bd0d222..56504b20ec6f 100644 --- a/drivers/ub/urma/ubcore/ubcore_tpg.h +++ b/drivers/ub/urma/ubcore/ubcore_tpg.h @@ -25,10 +25,20 @@ struct ubcore_tpg *ubcore_create_tpg(struct ubcore_device *dev, struct ubcore_tpg_cfg *cfg); int ubcore_destroy_tpg(struct ubcore_tpg *tpg); struct ubcore_tpg *ubcore_find_tpg(struct ubcore_device *dev, uint32_t tpgn); +struct ubcore_tpg *ubcore_find_get_tpg(struct ubcore_device *dev, uint32_t tpgn); int ubcore_create_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg, struct ubcore_tp_cfg *cfg); uint32_t ubcore_destroy_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg); +uint32_t ubcore_destroy_multi_tp_from_index(struct ubcore_device *dev, struct ubcore_tpg *tpg, + uint32_t from_index); uint32_t ubcore_modify_tp_in_tpg(struct ubcore_device *dev, struct ubcore_tpg *tpg, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask *mask, struct ubcore_tp **failed_tp); struct ubcore_tp *ubcore_find_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn); +struct ubcore_tp *ubcore_find_get_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn); +struct ubcore_tpg *ubcore_find_remove_tpg(struct ubcore_device *dev, uint32_t tpgn); +void ubcore_tpg_get(void *obj); +void ubcore_tpg_kref_put(struct ubcore_tpg *tpg); +int ubcore_add_tp(struct ubcore_device *dev, struct ubcore_tp *tp); +struct ubcore_tp *ubcore_find_get_tp(struct ubcore_device *dev, uint32_t tpn); +struct ubcore_tp *ubcore_find_remove_tp_node(struct ubcore_device *dev, uint32_t tpn); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_umem.c b/drivers/ub/urma/ubcore/ubcore_umem.c index 06decb95de97..c9528a409601 100644 --- a/drivers/ub/urma/ubcore/ubcore_umem.c +++ b/drivers/ub/urma/ubcore/ubcore_umem.c @@ -159,7 +159,7 @@ static int umem_dma_map(struct ubcore_umem *umem, uint64_t npages, unsigned long return 0; } -static void ubcore_fill_umem(struct ubcore_umem *umem, struct ubcore_device *dev, uint64_t va, +static int ubcore_fill_umem(struct ubcore_umem *umem, struct ubcore_device *dev, uint64_t va, uint64_t len, union ubcore_umem_flag flag) { umem->ub_dev = dev; @@ -167,7 +167,12 @@ static void ubcore_fill_umem(struct ubcore_umem *umem, struct ubcore_device *dev umem->length = len; umem->flag = flag; umem->owning_mm = current->mm; + if (!umem->owning_mm) { + ubcore_log_err("mm is null.\n"); + return -EINVAL; + } mmgrab(umem->owning_mm); + return 0; } static struct ubcore_umem *ubcore_get_target_umem(struct ubcore_device *dev, uint64_t va, @@ -187,7 +192,12 @@ static struct ubcore_umem *ubcore_get_target_umem(struct ubcore_device *dev, uin goto out; } - ubcore_fill_umem(umem, dev, va, len, flag); + ret = ubcore_fill_umem(umem, dev, va, len, flag); + if (ret != 0) { + kfree(umem); + goto out; + } + npages = umem_cal_npages(umem->va, umem->length); if (npages == 0 || npages > UINT_MAX) { ret = -EINVAL; diff --git a/drivers/ub/urma/ubcore/ubcore_utp.c b/drivers/ub/urma/ubcore/ubcore_utp.c index 8be3ac5eb9f0..215350a2e9db 100644 --- a/drivers/ub/urma/ubcore/ubcore_utp.c +++ b/drivers/ub/urma/ubcore/ubcore_utp.c @@ -21,9 +21,10 @@ #include #include "ubcore_log.h" #include "ubcore_hash_table.h" +#include "ubcore_device.h" #include "ubcore_utp.h" -static int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, +int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, enum ubcore_mtu *mtu) { struct ubcore_device_status st = { 0 }; @@ -45,25 +46,33 @@ static int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, return 0; } +static void ubcore_utp_kref_release(struct kref *ref_cnt) +{ + struct ubcore_utp *utp = container_of(ref_cnt, struct ubcore_utp, ref_cnt); + + complete(&utp->comp); +} + +void ubcore_utp_kref_put(struct ubcore_utp *utp) +{ + (void)kref_put(&utp->ref_cnt, ubcore_utp_kref_release); +} + +void ubcore_utp_get(void *obj) +{ + struct ubcore_utp *utp = obj; + + kref_get(&utp->ref_cnt); +} + struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_utp_cfg *cfg) { struct ubcore_utp *utp; - enum ubcore_mtu mtu; int ret; if (dev->ops == NULL || dev->ops->create_utp == NULL) return NULL; - if (((int32_t)cfg->mtu) == 0) { - ret = utp_get_active_mtu(dev, (uint8_t)cfg->port_id, &mtu); - if (ret < 0) { - ubcore_log_warn("Failed to get active mtu, use default 1024"); - mtu = UBCORE_MTU_1024; - } - cfg->mtu = mtu; - ubcore_log_info("Global cfg not config, device mtu is %d", (int32_t)cfg->mtu); - } - ubcore_log_info("Utp mtu config to %u", (uint32_t)cfg->mtu); utp = dev->ops->create_utp(dev, cfg, NULL); @@ -73,7 +82,9 @@ struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_ut } utp->ub_dev = dev; utp->utp_cfg = *cfg; - atomic_set(&utp->use_cnt, 1); + atomic_set(&utp->use_cnt, 0); + kref_init(&utp->ref_cnt); + init_completion(&utp->comp); ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UTP], &utp->hnode, utp->utpn); if (ret != 0) { @@ -96,13 +107,8 @@ int ubcore_destroy_utp(struct ubcore_utp *utp) if (dev->ops == NULL || dev->ops->destroy_utp == NULL) return -EINVAL; - if (atomic_dec_return(&utp->use_cnt) > 0) { - ubcore_log_err("utp in use"); - return -EBUSY; - } - - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_UTP], &utp->hnode); - + ubcore_utp_kref_put(utp); + wait_for_completion(&utp->comp); ret = dev->ops->destroy_utp(utp); if (ret != 0) { (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UTP], &utp->hnode, utp->utpn); @@ -119,3 +125,33 @@ struct ubcore_utp *ubcore_find_utp(struct ubcore_device *dev, uint32_t idx) { return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_UTP], idx, &idx); } + +struct ubcore_utp *ubcore_find_get_utp(struct ubcore_device *dev, uint32_t idx) +{ + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_UTP], idx, &idx); +} + +struct ubcore_utp *ubcore_find_remove_utp(struct ubcore_device *dev, uint32_t idx) +{ + struct ubcore_utp *utp; + + spin_lock(&dev->ht[UBCORE_HT_UTP].lock); + if (&dev->ht[UBCORE_HT_UTP].head == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); + return NULL; + } + utp = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_UTP], idx, &idx); + if (utp == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); + return NULL; + } + if (atomic_read(&utp->use_cnt) > 0) { + spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); + ubcore_log_err("Failed to remove utp"); + return NULL; + } + ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_UTP], &utp->hnode); + spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); + + return utp; +} diff --git a/drivers/ub/urma/ubcore/ubcore_utp.h b/drivers/ub/urma/ubcore/ubcore_utp.h index edfea4ca9b3d..5587d2825dcb 100644 --- a/drivers/ub/urma/ubcore/ubcore_utp.h +++ b/drivers/ub/urma/ubcore/ubcore_utp.h @@ -23,7 +23,13 @@ #include +int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, + enum ubcore_mtu *mtu); struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_utp_cfg *cfg); int ubcore_destroy_utp(struct ubcore_utp *utp); struct ubcore_utp *ubcore_find_utp(struct ubcore_device *dev, uint32_t idx); +struct ubcore_utp *ubcore_find_get_utp(struct ubcore_device *dev, uint32_t idx); +struct ubcore_utp *ubcore_find_remove_utp(struct ubcore_device *dev, uint32_t idx); +void ubcore_utp_get(void *obj); +void ubcore_utp_kref_put(struct ubcore_utp *utp); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c index b4e324ef71e1..87484aa8fdb6 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c @@ -21,6 +21,7 @@ #include #include #include +#include "ubcore_device.h" #include "ubcore_priv.h" #include "ubcore_tpg.h" #include "ubcore_utp.h" @@ -28,6 +29,8 @@ #include "ubcore_netdev.h" #include "ubcore_tp.h" #include +#include "ubcore_device.h" +#include "urma/ubcore_jetty.h" #include "ubcore_uvs_cmd.h" static int ubcore_uvs_cmd_channel_init(struct ubcore_cmd_hdr *hdr) @@ -40,6 +43,7 @@ static int ubcore_uvs_cmd_channel_init(struct ubcore_cmd_hdr *hdr) if (ret != 0) return -EPERM; + arg.in.userspace_in[UBCORE_CMD_CHANNEL_INIT_SIZE - 1] = '\0'; if (strlen(arg.in.userspace_in) == 0 || strcmp(arg.in.userspace_in, "Hello ubcore!") != 0) return -EPERM; @@ -109,8 +113,8 @@ static struct ubcore_tpg *ubcore_create_tpg_and_multi_tp(struct ubcore_device *d return ERR_PTR(-EINVAL); tpg = ubcore_create_tpg(dev, tpg_cfg); - if (tpg == NULL) - return ERR_PTR(-ENOSPC); + if (IS_ERR_OR_NULL(tpg)) + return tpg; /* create tp in the tpg */ tp_cfgs = ubcore_get_multi_tp_cfg(tpg_cfg->tp_cnt, tp_cfg_arg, tpg); @@ -229,9 +233,9 @@ static struct ubcore_tp_node *ubcore_get_tp_node(struct ubcore_device *dev, tp_node = ubcore_hash_table_lookup(advice->meta.ht, advice->meta.hash, &advice->meta.key); if (tp_node == NULL) { new_tp = ubcore_create_tp(dev, tp_cfg, udata); - if (new_tp == NULL) { + if (IS_ERR_OR_NULL(new_tp)) { ubcore_log_err("Failed to create tp"); - return NULL; + return (void *)new_tp; } tp_node = ubcore_add_tp_node(advice->meta.ht, advice->meta.hash, &advice->meta.key, new_tp, &advice->ta); @@ -267,11 +271,16 @@ static int ubcore_cmd_create_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_cr ubcore_log_err("tp table is already released"); goto put_device; } - tp_node = ubcore_hash_table_lookup(advice.meta.ht, advice.meta.hash, &advice.meta.key); - if (!tp_node) + spin_lock(&advice.meta.ht->lock); + tp_node = ubcore_hash_table_lookup_nolock(advice.meta.ht, + advice.meta.hash, &advice.meta.key); + if (!tp_node) { + spin_unlock(&advice.meta.ht->lock); goto put_tptable; + } ret = ubcore_copy_tpg_udrv_data(hdr, arg, tp_node); + spin_unlock(&advice.meta.ht->lock); if (ret) goto put_tptable; @@ -317,12 +326,21 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) if (ubcore_get_active_mtu(dev, 0, &arg->local_mtu) != 0) goto put_device; + if (ubcore_get_max_mtu(dev, 0, &arg->out.max_mtu) != 0) + goto put_device; + tpg = ubcore_create_tpg_and_multi_tp(dev, &arg->in.tpg_cfg, arg->in.tp_cfg); if (IS_ERR_OR_NULL(tpg)) { - ret = -EPERM; + ret = PTR_ERR(tpg); goto put_device; } + ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); + if (ret != 0) { + ubcore_log_err("Failed to add tpg to the tpg table"); + goto destroy_tpg; + } + /* fill output */ arg->out.tpgn = tpg->tpgn; for (i = 0; i < tpg->tpg_cfg.tp_cnt; i++) @@ -331,10 +349,14 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_tpg)); if (ret != 0) - goto destroy_tpg; + goto remove_tpg; else goto put_device; +remove_tpg: + ubcore_hash_table_remove(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); + if (atomic_read(&tpg->use_cnt) > 0) + ubcore_log_warn("tpg use_cnt still greater than 0 after remove"); destroy_tpg: (void)ubcore_destroy_multi_tp(dev, tpg); (void)ubcore_destroy_tpg(tpg); @@ -433,7 +455,7 @@ static int ubcore_cmd_create_vtp(struct ubcore_cmd_hdr *hdr) } /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg->in.tpgn); + tpg = ubcore_find_get_tpg(dev, arg->in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); @@ -463,9 +485,9 @@ static int ubcore_cmd_create_vtp(struct ubcore_cmd_hdr *hdr) } ubcore_set_vtp2tpg_cfg(&vtp_cfg, &arg->in.vtp, tpg); - vtp = ubcore_map_vtp(dev, &vtp_cfg); - if (vtp == NULL) { - ret = -EPERM; + vtp = ubcore_create_and_map_vtp(dev, &vtp_cfg); + if (IS_ERR_OR_NULL(vtp)) { + ret = PTR_ERR(vtp); goto to_user; } @@ -473,21 +495,21 @@ static int ubcore_cmd_create_vtp(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_vtp)); if (ret != 0) - goto unmap_vtp; - else - goto free_attr; + (void)ubcore_unmap_vtp(vtp); + + /* Pair with kref_init, then vtp ownership is transferred to vtp hash table */ + ubcore_vtp_kref_put(vtp); + goto free_attr; to_user: (void)ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_vtp)); -unmap_vtp: - if (vtp != NULL) - (void)ubcore_unmap_vtp(vtp); free_attr: if (rts_attr != NULL) kfree(rts_attr); if (rts_mask != NULL) kfree(rts_mask); + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); free_arg: @@ -574,6 +596,12 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) if (ret != 0) goto free_arg; + if (arg->in.peer_tp_cnt > UBCORE_MAX_TP_CNT_IN_GRP) { + ret = -EINVAL; + ubcore_log_err("arg->in.peer_tp_cnt %d too big", arg->in.peer_tp_cnt); + goto free_arg; + } + if (arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { ret = ubcore_cmd_modify_tp(hdr, arg); goto free_arg; @@ -586,13 +614,24 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) } /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg->in.tpgn); + tpg = ubcore_find_get_tpg(dev, arg->in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); goto put_device; } + if (tpg->tpg_cfg.tp_cnt > arg->in.peer_tp_cnt) { + ret = ubcore_destroy_multi_tp_from_index(dev, tpg, arg->in.peer_tp_cnt); + if (ret == (tpg->tpg_cfg.tp_cnt - arg->in.peer_tp_cnt)) { + tpg->tpg_cfg.tp_cnt = arg->in.peer_tp_cnt; + } else { + ubcore_log_err("ubcore_destroy_multi_tp_from_index failed %d", ret); + ret = -EPERM; + goto to_user; + } + } + /* modify to RTR */ arg->out.rtr_tp_cnt = ubcore_modify_tp_in_tpg(dev, tpg, arg->in.rtr_attr, arg->in.rtr_mask, failed_tp); @@ -625,6 +664,7 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) kfree(rts_attr); if (rts_mask != NULL) kfree(rts_mask); + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); free_arg: @@ -632,7 +672,7 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) return ret; } -static int ubcore_mark_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tp_meta *meta, +static int ubcore_mark_bind_tjetty(struct ubcore_jetty *jetty, struct ubcore_tp_meta *meta, struct ubcore_jetty_id *default_tjetty_id, struct ubcore_ta_data *ta_data) { spin_lock(&meta->ht->lock); @@ -645,7 +685,7 @@ static int ubcore_mark_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tp_m &ta_data->jetty_id, sizeof(struct ubcore_jetty_id)) != 0) { spin_unlock(&meta->ht->lock); ubcore_log_err("the same jetty_id: %u is binded with another remote jetty_id: %pI6c-%u.\n", - jetty->id, &meta->ht->rc_tjetty_id.eid, meta->ht->rc_tjetty_id.id); + jetty->jetty_id.id, &meta->ht->rc_tjetty_id.eid, meta->ht->rc_tjetty_id.id); return -1; } spin_unlock(&meta->ht->lock); @@ -682,7 +722,7 @@ static int ubcore_para_target_ta(struct ubcore_device *dev, struct ubcore_tp_adv meta->ht = ubcore_get_tptable(jetty->tptable); advice->ta.jetty = jetty; advice->ta.tjetty_id = ta_data->jetty_id; - ret = ubcore_mark_bind_jetty(jetty, meta, &default_tjetty_id, ta_data); + ret = ubcore_mark_bind_tjetty(jetty, meta, &default_tjetty_id, ta_data); } break; case UBCORE_TA_NONE: @@ -747,7 +787,7 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, { struct ubcore_udata udata = { 0 }; struct ubcore_device *dev = NULL; - struct ubcore_tp_node *tp_node; + struct ubcore_tp_node *tp_node = NULL; struct ubcore_tp_advice advice = { 0 }; struct ubcore_tp_cfg tp_cfg = { 0 }; struct ubcore_tp_attr *tp_attr = NULL; @@ -770,7 +810,7 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, ubcore_set_udata(&udata, &advice, (struct ubcore_udrv_priv *)&arg->udata); ubcore_set_tp_cfg_with_cmd(&tp_cfg, &arg->in.tp_cfg[0]); tp_node = ubcore_get_tp_node(dev, &advice, &tp_cfg, &udata); - if (!tp_node) + if (IS_ERR_OR_NULL(tp_node)) goto put_tptable; ret = ubcore_modify_target_tp_node(tp_node, tp_attr, &udata, arg); @@ -781,6 +821,18 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, if (ret) goto remove_tp_node; + /* The receiving side rm mode cannot switch the rts state */ + if (tp_node->tp->trans_mode == UBCORE_TP_RM && tp_node->tp->state == UBCORE_TP_STATE_RTR) { + ubcore_put_tptable(advice.meta.ht); + ubcore_put_device(dev); + return 0; + } + if (tp_node->tp->state == UBCORE_TP_STATE_RTR && + ubcore_modify_tp(dev, tp_node, tp_attr, udata) != 0) { + ubcore_log_err("Failed to modify tp"); + goto put_tptable; + } + ubcore_put_tptable(advice.meta.ht); ubcore_put_device(dev); return ret; @@ -791,35 +843,75 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, ubcore_put_tptable(advice.meta.ht); put_device: ubcore_put_device(dev); + if (IS_ERR(tp_node)) + return PTR_ERR(tp_node); return -1; } -static int ubcore_process_ub_mtu( - struct ubcore_cmd_create_target_tpg *arg, struct ubcore_device *dev) +static int ubcore_cmd_modify_tpg_tp_cnt(struct ubcore_cmd_hdr *hdr) { - enum ubcore_mtu active_mtu; - uint32_t i; - int ret; + struct ubcore_cmd_modify_tpg_tp_cnt *arg; + struct ubcore_device *dev; + struct ubcore_tpg *tpg; + int ret = 0; - ret = ubcore_get_active_mtu(dev, 0, &active_mtu); - if (ret != 0 && (arg->local_mtu == 0 || arg->peer_mtu == 0)) - return ret; + arg = kzalloc(sizeof(struct ubcore_cmd_modify_tpg_tp_cnt), GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; - if (arg->local_mtu == 0) - arg->local_mtu = active_mtu; - else if (active_mtu > 0) - arg->local_mtu = min(arg->local_mtu, active_mtu); + ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_modify_tpg_tp_cnt)); + if (ret != 0) + goto free_arg; - for (i = 0; i < arg->in.tpg_cfg.tp_cnt; i++) - arg->in.rtr_attr[i].mtu = min(arg->local_mtu, arg->peer_mtu); + dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); + if (dev == NULL) { + ret = -ENODEV; + goto free_arg; + } - return 0; + ubcore_log_info("tpgn_for_modify %d", arg->in.tpgn_for_modify); + /* deal with RM first */ + tpg = ubcore_find_tpg(dev, arg->in.tpgn_for_modify); + if (tpg == NULL) { + ret = -EINVAL; + ubcore_log_err("Failed to find tpg"); + goto put_device; + } + arg->out.tpgn = tpg->tpgn; + ret = 0; + if (tpg->tpg_cfg.tp_cnt > arg->in.tp_cnt && + arg->in.tp_cnt < UBCORE_MAX_TP_CNT_IN_GRP) { + if (ubcore_destroy_multi_tp_from_index(dev, tpg, arg->in.tp_cnt) == + (tpg->tpg_cfg.tp_cnt - arg->in.tp_cnt)) { + tpg->tpg_cfg.tp_cnt = arg->in.tp_cnt; + goto copy_to_user; + } else { + ret = -1; + goto put_device; + } + } + +copy_to_user: + /* fill output */ + arg->out.tpgn = tpg->tpgn; + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, + sizeof(struct ubcore_cmd_modify_tpg_tp_cnt)); + +put_device: + ubcore_put_device(dev); +free_arg: + kfree(arg); + return ret; } static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) { struct ubcore_tp *failed_tp[UBCORE_MAX_TP_CNT_IN_GRP]; + union ubcore_tp_attr_mask *rts_mask = NULL; struct ubcore_cmd_create_target_tpg *arg; + struct ubcore_tp_attr *rts_attr = NULL; struct ubcore_device *dev; struct ubcore_tpg *tpg; int ret = 0; @@ -845,24 +937,46 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) goto free_arg; } - ret = ubcore_process_ub_mtu(arg, dev); - if (ret != 0) - goto put_device; - tpg = ubcore_create_tpg_and_multi_tp(dev, &arg->in.tpg_cfg, arg->in.tp_cfg); if (IS_ERR_OR_NULL(tpg)) { - ret = -EPERM; + ret = PTR_ERR(tpg); goto put_device; } + ubcore_log_info("create target tpg and mtu is %u", (uint32_t)arg->in.rtr_attr[0].mtu); + + ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); + if (ret != 0) { + ubcore_log_err("Failed to add tpg to the tpg table"); + goto destroy_tpg; + } + /* modify to RTR */ if (ubcore_modify_tp_in_tpg(dev, tpg, arg->in.rtr_attr, arg->in.rtr_mask, failed_tp) != tpg->tpg_cfg.tp_cnt) { /* todonext: modify tp to reset ? */ ret = -EPERM; - goto destroy_tpg; + goto remove_tpg; + } + + /* modify to RTS */ + ret = ubcore_get_tp_state_attr_and_mask(UBCORE_TP_STATE_RTS, tpg->tpg_cfg.tp_cnt, + &rts_attr, &rts_mask); + if (ret != 0) + goto remove_tpg; + + arg->out.rts_tp_cnt = ubcore_modify_tp_in_tpg(dev, tpg, rts_attr, rts_mask, failed_tp); + if (arg->out.rts_tp_cnt != tpg->tpg_cfg.tp_cnt) { + /* todonext: modify tp to reset ? */ + ret = -EPERM; + kfree(rts_attr); + kfree(rts_mask); + goto remove_tpg; } + kfree(rts_attr); + kfree(rts_mask); + /* fill output */ arg->out.tpgn = tpg->tpgn; for (i = 0; i < tpg->tpg_cfg.tp_cnt; i++) @@ -871,10 +985,14 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_target_tpg)); if (ret) - goto destroy_tpg; + goto remove_tpg; else goto put_device; +remove_tpg: + ubcore_hash_table_remove(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); + if (atomic_read(&tpg->use_cnt) > 0) + ubcore_log_warn("tpg use_cnt still greater than 0 after remove"); destroy_tpg: (void)ubcore_destroy_multi_tp(dev, tpg); (void)ubcore_destroy_tpg(tpg); @@ -885,105 +1003,88 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) return ret; } -static int ubcore_cmd_modify_target_tp(struct ubcore_cmd_hdr *hdr, - struct ubcore_cmd_modify_target_tpg *arg) -{ - struct ubcore_device *dev = NULL; - struct ubcore_tp_node *tp_node; - struct ubcore_tp_advice advice = {0}; - struct ubcore_tp_attr rtr_attr = {0}; - struct ubcore_udata udata = {0}; - int ret = 0; - - dev = ubcore_find_device(&arg->ta_data.tjetty_id.eid, arg->ta_data.trans_type); - if (dev == NULL) - return -ENODEV; - - if (ubcore_para_target_ta(dev, &advice, &arg->ta_data) != 0) { - ubcore_log_err("Failed to parse ta with type %u", advice.ta.type); - goto put_device; - } else if (advice.meta.ht == NULL) { - ubcore_log_err("tp table is already released"); - goto put_device; - } - - tp_node = ubcore_hash_table_lookup(advice.meta.ht, advice.meta.hash, &advice.meta.key); - if (tp_node == NULL) { - ubcore_log_err("tp node is already released"); - goto put_tptable; - } - /* The receiving side rm mode cannot switch the rts state */ - if (tp_node->tp->trans_mode == UBCORE_TP_RM && tp_node->tp->state == UBCORE_TP_STATE_RTR) { - ubcore_put_tptable(advice.meta.ht); - ubcore_put_device(dev); - return 0; - } - if (tp_node->tp->state == UBCORE_TP_STATE_RTR && - ubcore_modify_tp(dev, tp_node, &rtr_attr, udata) != 0) { - ubcore_log_err("Failed to modify tp"); - goto put_tptable; - } - ubcore_put_tptable(advice.meta.ht); - ubcore_put_device(dev); - return ret; - -put_tptable: - ubcore_put_tptable(advice.meta.ht); -put_device: - ubcore_put_device(dev); - return -1; -} - static int ubcore_cmd_modify_target_tpg(struct ubcore_cmd_hdr *hdr) { struct ubcore_tp *failed_tp[UBCORE_MAX_TP_CNT_IN_GRP]; - struct ubcore_cmd_modify_target_tpg arg = {0}; union ubcore_tp_attr_mask *rts_mask = NULL; + struct ubcore_cmd_modify_target_tpg *arg; struct ubcore_tp_attr *rts_attr = NULL; struct ubcore_device *dev; struct ubcore_tpg *tpg; int ret; - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, + arg = kzalloc(sizeof(struct ubcore_cmd_modify_target_tpg), GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; + + ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, sizeof(struct ubcore_cmd_modify_target_tpg)); if (ret != 0) - return ret; + goto free_arg; - if (arg.ta_data.trans_type == UBCORE_TRANSPORT_IB) - return ubcore_cmd_modify_target_tp(hdr, &arg); + if (arg->in.peer_tp_cnt > UBCORE_MAX_TP_CNT_IN_GRP) { + ret = -EINVAL; + ubcore_log_err("arg->in.peer_tp_cnt %d too big", arg->in.peer_tp_cnt); + goto free_arg; + } - dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, arg.in.tpf.trans_type); - if (dev == NULL) - return -ENODEV; + dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); + if (dev == NULL) { + ret = -ENODEV; + goto free_arg; + } /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg.in.tpgn); + tpg = ubcore_find_get_tpg(dev, arg->in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); goto put_device; } + if (tpg->tpg_cfg.tp_cnt > arg->in.peer_tp_cnt) { + ret = ubcore_destroy_multi_tp_from_index(dev, tpg, arg->in.peer_tp_cnt); + if (ret == (tpg->tpg_cfg.tp_cnt - arg->in.peer_tp_cnt)) { + tpg->tpg_cfg.tp_cnt = arg->in.peer_tp_cnt; + } else { + ubcore_log_err("ubcore_destroy_multi_tp_from_index failed %d", ret); + ret = -EPERM; + goto put_tpg; + } + } + + /* modify to RTR */ + if (ubcore_modify_tp_in_tpg(dev, tpg, arg->in.rtr_attr, arg->in.rtr_mask, failed_tp) != + tpg->tpg_cfg.tp_cnt) { + /* todonext: modify tp to reset ? */ + ret = -EPERM; + goto put_tpg; + } + /* modify to RTS */ ret = ubcore_get_tp_state_attr_and_mask(UBCORE_TP_STATE_RTS, tpg->tpg_cfg.tp_cnt, &rts_attr, &rts_mask); if (ret != 0) - goto put_device; + goto put_tpg; - arg.out.rts_tp_cnt = ubcore_modify_tp_in_tpg(dev, tpg, rts_attr, rts_mask, failed_tp); - if (arg.out.rts_tp_cnt != tpg->tpg_cfg.tp_cnt) + arg->out.rts_tp_cnt = ubcore_modify_tp_in_tpg(dev, tpg, rts_attr, rts_mask, failed_tp); + if (arg->out.rts_tp_cnt != tpg->tpg_cfg.tp_cnt) /* todonext: modify tp to reset ? */ ret = -EPERM; /* do not modify ret if copy success */ - if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_modify_target_tpg)) != 0) ret = -EPERM; kfree(rts_attr); kfree(rts_mask); +put_tpg: + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); +free_arg: + kfree(arg); return ret; } @@ -1003,14 +1104,14 @@ static int ubcore_cmd_destroy_vtp(struct ubcore_cmd_hdr *hdr) if (dev == NULL) return -ENODEV; - vtp = ubcore_find_vtp(dev, arg.in.mode, &arg.in.local_eid, &arg.in.peer_eid); + vtp = ubcore_find_get_vtp(dev, arg.in.mode, &arg.in.local_eid, &arg.in.peer_eid); if (vtp == NULL) { ret = -EINVAL; goto put_device; } ret = ubcore_check_and_unmap_vtp(vtp, arg.in.role); - + ubcore_vtp_kref_put(vtp); put_device: ubcore_put_device(dev); return ret; @@ -1033,21 +1134,48 @@ static int ubcore_check_dev_name(char *dev_name) static int ubcore_cmd_opt_sip(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_opt_sip arg; + uint32_t sip_idx = UINT_MAX; int ret; + int op_res; ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, sizeof(struct ubcore_cmd_opt_sip)); if (ret != 0) return ret; + arg.in.info.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; + arg.in.info.netdev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; ret = ubcore_check_dev_name(arg.in.info.dev_name); if (ret != 0) return ret; - if (hdr->command == UBCORE_CMD_ADD_SIP) - return ubcore_add_sip(&arg.in.info); + if (hdr->command == UBCORE_CMD_ADD_SIP) { + op_res = ubcore_add_sip(&arg.in.info, &sip_idx); + arg.out.sip_idx = sip_idx; + } else { + op_res = ubcore_delete_sip(&arg.in.info); + } + + /* + * add opt may return exist, need send sip_idx to userspace, + * otherwise return failed immediately. + */ + if (op_res != 0 && op_res != -EEXIST) + return op_res; - return ubcore_delete_sip(&arg.in.info); + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + sizeof(struct ubcore_cmd_opt_sip)); + if (ret != 0) { + /* op_res is EEXIST means no need to rollback */ + if (hdr->command == UBCORE_CMD_ADD_SIP && op_res == 0) + (void)ubcore_delete_sip(&arg.in.info); + else if (hdr->command == UBCORE_CMD_DEL_SIP) + (void)ubcore_add_sip(&arg.in.info, &sip_idx); + return ret; + } + + /* we need return -EEXIST back to userspace */ + return (op_res == -EEXIST) ? op_res : ret; } static int ubcore_eidtbl_add_entry(struct ubcore_device *dev, union ubcore_eid *eid, @@ -1100,6 +1228,17 @@ static int ubcore_eidtbl_del_entry(struct ubcore_device *dev, union ubcore_eid * return 0; } +static inline void ubcore_dispatch_eid_change(struct ubcore_device *dev, uint32_t eid_idx) +{ + struct ubcore_event event; + + event.ub_dev = dev; + event.event_type = UBCORE_EVENT_EID_CHANGE; + event.element.eid_idx = eid_idx; + + ubcore_dispatch_async_event(&event); +} + static int ubcore_eidtbl_update_entry(struct ubcore_device *dev, union ubcore_eid *eid, uint32_t eid_idx, bool is_add, struct net *net) { @@ -1107,10 +1246,12 @@ static int ubcore_eidtbl_update_entry(struct ubcore_device *dev, union ubcore_ei ubcore_log_err("eid table is full\n"); return -1; } - if (is_add) + if (is_add) { dev->eid_table.eid_entries[eid_idx].eid = *eid; - else + } else { (void)memset(&dev->eid_table.eid_entries[eid_idx].eid, 0, sizeof(union ubcore_eid)); + ubcore_dispatch_eid_change(dev, eid_idx); + } dev->eid_table.eid_entries[eid_idx].valid = is_add; dev->eid_table.eid_entries[eid_idx].eid_index = eid_idx; @@ -1159,12 +1300,13 @@ static int ubcore_cmd_set_upi(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_upi_with_dev_name(arg.in.dev_name, &pattern3_upi); if (dev == NULL) { ubcore_log_err("device not found by name: %s\n", arg.in.dev_name); return -1; } - if (!(dev->dynamic_eid && dev->cfg.pattern == (uint8_t)UBCORE_PATTERN_3)) { + if (!(dev->dynamic_eid && dev->attr.pattern == (uint8_t)UBCORE_PATTERN_3)) { ubcore_log_err("This mode does not support setting upi\n"); return -1; } @@ -1198,6 +1340,7 @@ static int ubcore_cmd_show_upi(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_upi_with_dev_name(arg.in.dev_name, &arg.out.upi); if (dev == NULL) { ubcore_log_err("device not found by name: %s\n", arg.in.dev_name); @@ -1291,6 +1434,7 @@ static int ubcore_cmd_set_vport_cfg(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.vport_cfg.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.vport_cfg.dev_name); if (dev == NULL) { ubcore_log_err("find dev failed, arg_in: %s.\n", arg.in.vport_cfg.dev_name); @@ -1325,8 +1469,9 @@ static int ubcore_cmd_set_vport_cfg(struct ubcore_cmd_hdr *hdr) static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_get_dev_info arg; - struct ubcore_device *pf_dev; struct ubcore_device *tpf_dev; + struct ubcore_device *pf_dev; + enum ubcore_mtu max_mtu; int ret; ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, @@ -1334,6 +1479,7 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.target_pf_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; pf_dev = ubcore_find_device_with_name(arg.in.target_pf_name); if (pf_dev == NULL) { ubcore_log_err("failed to find pf_dev device with %s", arg.in.target_pf_name); @@ -1356,6 +1502,15 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) ubcore_log_info("get tpf device name %s", tpf_dev->dev_name); (void)memcpy(arg.out.target_tpf_name, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); + + ret = ubcore_get_max_mtu(tpf_dev, 0, &max_mtu); + if (ret != 0) { + ubcore_log_err("failed to get max mtu"); + ubcore_put_device(tpf_dev); + return ret; + } + arg.out.max_mtu = max_mtu; + ubcore_put_device(tpf_dev); if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, @@ -1365,7 +1520,9 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) return ret; } -static int ubcore_unmark_bind_jetty(struct ubcore_tp_advice *advice, struct ubcore_ta_data *ta_data) +/* Caller ensures that meta->ht is not NULL */ +static int ubcore_unmark_bind_tjetty(struct ubcore_tp_advice *advice, + struct ubcore_ta_data *ta_data) { struct ubcore_tp_meta *meta; struct ubcore_jetty *jetty; @@ -1374,13 +1531,13 @@ static int ubcore_unmark_bind_jetty(struct ubcore_tp_advice *advice, struct ubco jetty = advice->ta.jetty; spin_lock(&meta->ht->lock); if (jetty != NULL && jetty->jetty_cfg.trans_mode == UBCORE_TP_RC) { - if (meta->ht != NULL && memcmp(&meta->ht->rc_tjetty_id, &ta_data->tjetty_id, + if (memcmp(&meta->ht->rc_tjetty_id, &ta_data->jetty_id, sizeof(struct ubcore_jetty_id)) == 0) { (void)memset(&meta->ht->rc_tjetty_id, 0, sizeof(struct ubcore_jetty_id)); } else { spin_unlock(&meta->ht->lock); ubcore_log_err("The jetty_id: %u is not bound tjetty_id: %u\n", - jetty->id, ta_data->tjetty_id.id); + jetty->jetty_id.id, ta_data->jetty_id.id); return -1; } } @@ -1394,11 +1551,14 @@ static int ubcore_cmd_destroy_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_d struct ubcore_device *dev = NULL; int ret = 0; - dev = ubcore_find_device(&arg->ta_data.jetty_id.eid, arg->ta_data.trans_type); + if (!arg->ta_data.is_target) + return 0; + + dev = ubcore_find_device(&arg->ta_data.tjetty_id.eid, arg->ta_data.trans_type); if (dev == NULL) return -ENODEV; - if (ubcore_para_ta(dev, &advice, &arg->ta_data) != 0) { + if (ubcore_para_target_ta(dev, &advice, &arg->ta_data) != 0) { ubcore_log_err("Failed to parse ta with type %u", (uint32_t)advice.ta.type); ret = -1; goto put_device; @@ -1406,11 +1566,11 @@ static int ubcore_cmd_destroy_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_d ubcore_log_err("tp table is already released"); goto put_device; } - if (arg->ta_data.is_target) { - ret = ubcore_unmark_bind_jetty(&advice, &arg->ta_data); - if (ret != 0) - goto put_tptable; - } + + ret = ubcore_unmark_bind_tjetty(&advice, &arg->ta_data); + if (ret != 0) + goto put_tptable; + ubcore_find_remove_tp(advice.meta.ht, advice.meta.hash, &advice.meta.key); put_tptable: @@ -1440,7 +1600,7 @@ static int ubcore_cmd_destroy_tpg(struct ubcore_cmd_hdr *hdr) return -ENODEV; /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg.in.tpgn); + tpg = ubcore_find_remove_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); @@ -1469,15 +1629,28 @@ static int ubcore_cmd_destroy_tpg(struct ubcore_cmd_hdr *hdr) return ret; } +static void ubcore_put_tpg_utp_ctp_in_vtp(struct ubcore_cmd_vtp_cfg *cmd, + struct ubcore_tpg *tpg, struct ubcore_utp *utp, struct ubcore_ctp *ctp) +{ + if (cmd->flag.bs.clan_tp == 0) { + if (cmd->trans_mode != UBCORE_TP_UM && tpg != NULL) + ubcore_tpg_kref_put(tpg); + else if (cmd->trans_mode == UBCORE_TP_UM && utp != NULL) + ubcore_utp_kref_put(utp); + } else { + ubcore_ctp_kref_put(ctp); + } +} + static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_map_vtp *arg; struct ubcore_vtp_cfg vtp_cfg; struct ubcore_vtp *vtp = NULL; struct ubcore_device *dev; - struct ubcore_tpg *tpg; - struct ubcore_utp *utp; - struct ubcore_ctp *ctp; + struct ubcore_tpg *tpg = NULL; + struct ubcore_utp *utp = NULL; + struct ubcore_ctp *ctp = NULL; int ret; arg = kzalloc(sizeof(struct ubcore_cmd_map_vtp), GFP_KERNEL); @@ -1499,7 +1672,7 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) /* deal with trans domain -G */ if (arg->in.vtp.trans_mode != UBCORE_TP_UM) { /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg->in.vtp.tpgn); + tpg = ubcore_find_get_tpg(dev, arg->in.vtp.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); @@ -1508,7 +1681,7 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) ubcore_set_vtp2tpg_cfg(&vtp_cfg, &arg->in.vtp, tpg); } else { /* deal with UM */ - utp = ubcore_find_utp(dev, arg->in.vtp.utpn); + utp = ubcore_find_get_utp(dev, arg->in.vtp.utpn); if (utp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find utp"); @@ -1518,7 +1691,7 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) } } else { /* deal with trans domain -C */ - ctp = ubcore_find_ctp(dev, arg->in.vtp.ctpn); + ctp = ubcore_find_get_ctp(dev, arg->in.vtp.ctpn); if (ctp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find ctp"); @@ -1530,19 +1703,25 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) vtp = ubcore_check_and_map_vtp(dev, &vtp_cfg, arg->in.role); if (vtp == NULL) { ret = -EPERM; - goto put_device; + goto put_tpg_utp; } + vtp->eid_idx = arg->in.eid_idx; + vtp->upi = arg->in.upi; + vtp->share_mode = arg->in.share_mode; + arg->out.vtpn = vtp->cfg.vtpn; ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_map_vtp)); if (ret != 0) - goto unmap_vtp; - else - goto put_device; + (void)ubcore_check_and_unmap_vtp(vtp, arg->in.role); -unmap_vtp: - (void)ubcore_check_and_unmap_vtp(vtp, arg->in.role); + ubcore_vtp_kref_put(vtp); + + goto put_tpg_utp; + +put_tpg_utp: + ubcore_put_tpg_utp_ctp_in_vtp(&arg->in.vtp, tpg, utp, ctp); put_device: ubcore_put_device(dev); free_arg: @@ -1550,6 +1729,31 @@ static int ubcore_cmd_map_vtp(struct ubcore_cmd_hdr *hdr) return ret; } +static void ubcore_get_utp_mtu(struct ubcore_device *dev, struct ubcore_utp_cfg *cfg) +{ + enum ubcore_mtu mtu; + int ret; + + if (((int32_t)cfg->mtu) == 0) { + ret = utp_get_active_mtu(dev, (uint8_t)cfg->port_id, &mtu); + if (ret < 0) { + ubcore_log_warn("dev:%s, port_id:%u Failed to get active mtu", + dev->dev_name, cfg->port_id); + mtu = UBCORE_MTU_1024; + } + cfg->mtu = mtu; + ubcore_log_info("cfg not config, device mtu is %d", (int32_t)cfg->mtu); + } else { + ret = ubcore_get_max_mtu(dev, (uint8_t)cfg->port_id, &mtu); + if (ret < 0) { + mtu = UBCORE_MTU_1024; + ubcore_log_warn("dev:%s, port_id:%u Failed to get max mtu", + dev->dev_name, cfg->port_id); + } + cfg->mtu = min(cfg->mtu, mtu); + } +} + static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_create_utp *arg; @@ -1574,6 +1778,8 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) goto free_arg; } + ubcore_get_utp_mtu(dev, &arg->in.utp_cfg); + utp = ubcore_create_utp(dev, &arg->in.utp_cfg); if (utp == NULL) { ret = -EPERM; @@ -1581,9 +1787,9 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) } ubcore_set_vtp2utp_cfg(&vtp_cfg, &arg->in.vtp, utp); - vtp = ubcore_map_vtp(dev, &vtp_cfg); - if (vtp == NULL) { - ret = -EPERM; + vtp = ubcore_create_and_map_vtp(dev, &vtp_cfg); + if (IS_ERR_OR_NULL(vtp)) { + ret = PTR_ERR(vtp); goto destroy_utp; } @@ -1593,15 +1799,20 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_utp)); - if (ret) + if (ret) { goto unmap_vtp; - else + } else { + ubcore_vtp_kref_put(vtp); goto put_device; - + } unmap_vtp: (void)ubcore_unmap_vtp(vtp); + ubcore_vtp_kref_put(vtp); destroy_utp: - (void)dev->ops->destroy_utp(utp); + ubcore_hash_table_remove(&dev->ht[UBCORE_HT_UTP], &utp->hnode); + if (atomic_read(&utp->use_cnt) > 0) + ubcore_log_warn("utp use_cnt still greater than 0 after remove"); + (void)ubcore_destroy_utp(utp); put_device: ubcore_put_device(dev); free_arg: @@ -1631,6 +1842,8 @@ static int ubcore_cmd_only_create_utp(struct ubcore_cmd_hdr *hdr) goto free_arg; } + ubcore_get_utp_mtu(dev, &arg->in.utp_cfg); + utp = ubcore_create_utp(dev, &arg->in.utp_cfg); if (utp == NULL) { ret = -EPERM; @@ -1648,7 +1861,10 @@ static int ubcore_cmd_only_create_utp(struct ubcore_cmd_hdr *hdr) goto put_device; destroy_utp: - (void)dev->ops->destroy_utp(utp); + ubcore_hash_table_remove(&dev->ht[UBCORE_HT_UTP], &utp->hnode); + if (atomic_read(&utp->use_cnt) > 0) + ubcore_log_warn("utp use_cnt still greater than 0 after remove"); + (void)ubcore_destroy_utp(utp); put_device: ubcore_put_device(dev); free_arg: @@ -1672,19 +1888,17 @@ static int ubcore_cmd_destroy_utp(struct ubcore_cmd_hdr *hdr) if (dev == NULL) return -ENODEV; - utp = ubcore_find_utp(dev, arg.in.utp_idx); + utp = ubcore_find_remove_utp(dev, arg.in.utp_idx); if (utp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find utp"); goto put_device; } - /* todonext: rollback ? */ ret = ubcore_destroy_utp(utp); if (ret) ubcore_log_err("Failed to destroy utp"); - /* todonext: rollback ? */ put_device: ubcore_put_device(dev); return ret; @@ -1719,9 +1933,9 @@ static int ubcore_cmd_create_ctp(struct ubcore_cmd_hdr *hdr) goto put_device; ubcore_set_vtp2ctp_cfg(&vtp_cfg, &arg->in.vtp, ctp); - vtp = ubcore_map_vtp(dev, &vtp_cfg); - if (vtp == NULL) { - ret = -EPERM; + vtp = ubcore_create_and_map_vtp(dev, &vtp_cfg); + if (IS_ERR_OR_NULL(vtp)) { + ret = PTR_ERR(vtp); goto destroy_ctp; } @@ -1731,13 +1945,16 @@ static int ubcore_cmd_create_ctp(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_create_ctp)); - if (ret) + if (ret) { goto unmap_vtp; - else + } else { + ubcore_vtp_kref_put(vtp); goto put_device; + } unmap_vtp: (void)ubcore_unmap_vtp(vtp); + ubcore_vtp_kref_put(vtp); destroy_ctp: (void)dev->ops->destroy_ctp(ctp); put_device: @@ -1761,11 +1978,11 @@ static int ubcore_cmd_destroy_ctp(struct ubcore_cmd_hdr *hdr) dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, arg.in.tpf.trans_type); if (dev == NULL) { - ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr.net_addr); + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr); return -ENODEV; } - ctp = ubcore_find_ctp(dev, arg.in.ctp_idx); + ctp = ubcore_find_remove_ctp(dev, arg.in.ctp_idx); if (ctp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find ctp"); @@ -1786,7 +2003,6 @@ static int ubcore_cmd_restore_tp_error_op(struct ubcore_cmd_hdr *hdr, { struct ubcore_cmd_restore_tp_error arg = {0}; struct ubcore_device *dev; - struct ubcore_tpg *tpg; struct ubcore_tp *tp; int ret; @@ -1797,7 +2013,7 @@ static int ubcore_cmd_restore_tp_error_op(struct ubcore_cmd_hdr *hdr, dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, UBCORE_TRANSPORT_UB); if (dev == NULL) { - ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr.net_addr); + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr); return -ENODEV; } @@ -1806,17 +2022,10 @@ static int ubcore_cmd_restore_tp_error_op(struct ubcore_cmd_hdr *hdr, goto put_device; } - tpg = ubcore_find_tpg(dev, arg.in.tpgn); - if (tpg == NULL) { - ret = -EINVAL; - ubcore_log_err("Failed to find tpg %u, cmd:%u", arg.in.tpgn, hdr->command); - goto put_device; - } - - tp = ubcore_find_tp_in_tpg(tpg, arg.in.tpn); + tp = ubcore_find_get_tp(dev, arg.in.tpn); if (tp == NULL) { ret = -EINVAL; - ubcore_log_err("Failed to find tp %u, cmd:%u", arg.in.tpn, hdr->command); + ubcore_log_err("Failed to find tp"); goto put_device; } @@ -1825,18 +2034,21 @@ static int ubcore_cmd_restore_tp_error_op(struct ubcore_cmd_hdr *hdr, ret = -1; ubcore_log_err("Failed to restore error tp %u to rtr, cmd:%u", arg.in.tpn, hdr->command); - goto put_device; + goto put_tp; } if (set_to_rts && ubcore_restore_tp_error_to_rts(dev, tp) != 0) { ret = -1; ubcore_log_err("Failed to restore error tp %u to rts, cmd:%u", arg.in.tpn, hdr->command); - goto put_device; + goto put_tp; } ubcore_log_info("Success to restore tp %u error, cmd:%u", arg.in.tpn, hdr->command); +put_tp: + ubcore_tp_kref_put(tp); + put_device: ubcore_put_device(dev); return ret; @@ -1890,7 +2102,7 @@ static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, UBCORE_TRANSPORT_UB); if (dev == NULL) { - ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr.net_addr); + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr); return -ENODEV; } @@ -1899,24 +2111,25 @@ static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) goto put_device; } /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg.in.tpgn); + tpg = ubcore_find_get_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); goto put_device; } - tp = ubcore_find_tp_in_tpg(tpg, arg.in.tpn); + tp = ubcore_find_get_tp_in_tpg(tpg, arg.in.tpn); if (tp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tp"); - goto put_device; + goto put_tpg; } if (ubcore_modify_tp_state_check(tp, UBCORE_TP_STATE_RTS) != 0) { ubcore_log_err("Failed to modify tp to RTR from state %u and tpn = %u", (uint32_t)tp->state, tp->tpn); - return -1; + ret = -1; + goto put_tp; } ubcore_fill_attr_restore_tp_suspend(&arg, &mask, &attr); @@ -1924,7 +2137,7 @@ static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) ret = -1; ubcore_log_err("Failed to modify tp to RTR from state %u and tpn = %u", (uint32_t)tp->state, tp->tpn); - goto put_device; + goto put_tp; } tp->state = UBCORE_TP_STATE_RTS; tp->data_udp_start = arg.in.data_udp_start; @@ -1932,6 +2145,10 @@ static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) ubcore_log_info("Success to restore tp suspend"); +put_tp: + ubcore_tp_kref_put(tp); +put_tpg: + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); return ret; @@ -1948,6 +2165,7 @@ static int ubcore_cmd_get_dev_feature(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("no available devices found by dev_name: %s\n", arg.in.dev_name); @@ -1970,7 +2188,6 @@ static int ubcore_cmd_change_tp_to_error(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_change_tp_to_error arg = {0}; struct ubcore_device *dev; - struct ubcore_tpg *tpg; struct ubcore_tp *tp; int ret; @@ -1981,7 +2198,7 @@ static int ubcore_cmd_change_tp_to_error(struct ubcore_cmd_hdr *hdr) dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, UBCORE_TRANSPORT_UB); if (dev == NULL) { - ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr.net_addr); + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr); return -ENODEV; } @@ -1989,14 +2206,8 @@ static int ubcore_cmd_change_tp_to_error(struct ubcore_cmd_hdr *hdr) ret = -ENODEV; goto put_device; } - tpg = ubcore_find_tpg(dev, arg.in.tpgn); - if (tpg == NULL) { - ret = -EINVAL; - ubcore_log_err("Failed to find tpg"); - goto put_device; - } - tp = ubcore_find_tp_in_tpg(tpg, arg.in.tpn); + tp = ubcore_find_get_tp(dev, arg.in.tpn); if (tp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tp"); @@ -2007,17 +2218,19 @@ static int ubcore_cmd_change_tp_to_error(struct ubcore_cmd_hdr *hdr) if (tp->state == UBCORE_TP_STATE_RESET) { ubcore_log_warn("Found tp in RESET state, no need to change tp to error with tpn = %u", tp->tpn); - goto put_device; + goto put_tp; } if (ubcore_change_tp_to_err(dev, tp) != 0) { ret = -EINVAL; ubcore_log_err("Failed to change tp to error"); - goto put_device; + goto put_tp; } ubcore_log_info("Success to change tp to error"); +put_tp: + ubcore_tp_kref_put(tp); put_device: ubcore_put_device(dev); return ret; @@ -2039,7 +2252,7 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, UBCORE_TRANSPORT_UB); if (dev == NULL) { - ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr.net_addr); + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr); return -ENODEV; } @@ -2047,32 +2260,39 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) ret = -ENODEV; goto put_device; } - tpg = ubcore_find_tpg(dev, arg.in.tpgn); + tpg = ubcore_find_get_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg %u", arg.in.tpgn); goto put_device; } + mutex_lock(&tpg->mutex); for (i = 0; i < tpg->tpg_cfg.tp_cnt; i++) { tp = tpg->tp_list[i]; if (tp == NULL) { ubcore_log_warn("tp in tpg %u is NULL", arg.in.tpgn); continue; } + ubcore_tp_get(tp); if (tp->state == UBCORE_TP_STATE_RESET) { ubcore_log_info("TP:%u already in RESET", tp->tpn); + ubcore_tp_kref_put(tp); continue; } if (ubcore_change_tp_to_err(dev, tp) != 0) { ubcore_log_warn("Failed to change tp:%u, to error in tpg %u", tp->tpn, arg.in.tpgn); + ubcore_tp_kref_put(tp); continue; } arg.out.tp_error_cnt++; + ubcore_tp_kref_put(tp); } + mutex_unlock(&tpg->mutex); + ubcore_tpg_kref_put(tpg); ubcore_log_info("Success to finish change tpg to error, tp err cnt:%u, tpgn %u", arg.out.tp_error_cnt, arg.in.tpgn); @@ -2130,13 +2350,13 @@ static int ubcore_init_modify_vtp(struct ubcore_device *dev, struct ubcore_cmd_v vtp_param->peer_jetty = vtp->peer_jetty; if (vtp_param->trans_mode != UBCORE_TP_UM) { - vattr->tp.tpg = ubcore_find_tpg(dev, vtp->tpgn); + vattr->tp.tpg = ubcore_find_get_tpg(dev, vtp->tpgn); if (vattr->tp.tpg == NULL) { ubcore_log_err("fail to find tpg"); return -EPERM; } } else { - vattr->tp.utp = ubcore_find_utp(dev, vtp->utpn); + vattr->tp.utp = ubcore_find_get_utp(dev, vtp->utpn); if (vattr->tp.utp == NULL) { ubcore_log_err("fail to find utp"); return -EPERM; @@ -2147,6 +2367,15 @@ static int ubcore_init_modify_vtp(struct ubcore_device *dev, struct ubcore_cmd_v return 0; } +static void ubcore_uninit_modify_vtp(struct ubcore_vtp_attr *vattr, + struct ubcore_vtp_param *vtp_param) +{ + if (vtp_param->trans_mode != UBCORE_TP_UM) + ubcore_tpg_kref_put(vattr->tp.tpg); + else + ubcore_utp_kref_put(vattr->tp.utp); +} + static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_modify_vtp *arg; @@ -2168,7 +2397,7 @@ static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); if (dev == NULL) { - ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg->in.tpf.netaddr.net_addr); + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg->in.tpf.netaddr); ret = -ENODEV; goto free_arg; } @@ -2195,9 +2424,11 @@ static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) ret = ubcore_modify_vtp(dev, &vtp_param, &vattr, &vattr_mask); if (ret < 0) { + ubcore_uninit_modify_vtp(&vattr, &vtp_param); ubcore_log_err("fail to modify vtp"); goto put_device; } + ubcore_uninit_modify_vtp(&vattr, &vtp_param); } put_device: @@ -2217,6 +2448,8 @@ static int ubcore_cmd_opt_config_dscp_vl(struct ubcore_cmd_hdr *hdr) sizeof(struct ubcore_cmd_opt_config_dscp_vl)); if (ret != 0) return ret; + + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_warn("fail to find dev:%s\n", arg.in.dev_name); @@ -2251,6 +2484,7 @@ static int ubcore_cmd_opt_update_eid(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) return -1; @@ -2279,6 +2513,7 @@ static int ubcore_cmd_opt_query_fe_idx(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; dev = ubcore_find_device_with_name(arg.in.dev_name); if (dev == NULL) { ubcore_log_err("fail to query dev, dev:%s\n", arg.in.dev_name); @@ -2319,9 +2554,18 @@ static int ubcore_cmd_get_vtp_table_cnt(struct ubcore_cmd_hdr *hdr) arg.out.vtp_cnt = 0; dev_list = ubcore_get_all_tpf_device(UBCORE_TRANSPORT_UB, &dev_cnt); - for (i = 0; i < dev_cnt; ++i) { - arg.out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_RM_VTP]); - arg.out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_UM_VTP]); + if (dev_cnt != 0) { + if (dev_list == NULL) { + ubcore_log_err("get all tpf device failed.\n"); + return -1; + } + + for (i = 0; i < dev_cnt; ++i) { + arg.out.vtp_cnt += + ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_RM_VTP]); + arg.out.vtp_cnt += + ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_UM_VTP]); + } } ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, @@ -2337,13 +2581,14 @@ static int ubcore_cmd_get_vtp_table_cnt(struct ubcore_cmd_hdr *hdr) return ret; } -static void ubcore_assign_single_out_vtp_table(struct ubcore_vtp *vtp, +static int ubcore_assign_single_out_vtp_table(struct ubcore_device *dev, struct ubcore_vtp *vtp, struct ubcore_restored_vtp_entry *out_entry, const char *dev_name) { + struct ubcore_sip_info *sip_entry = NULL; uint32_t dev_tpn_idx = 0; if (vtp == NULL) - return; + return -1; out_entry->fe_idx = vtp->cfg.fe_idx; out_entry->vtpn = vtp->cfg.vtpn; @@ -2353,44 +2598,68 @@ static void ubcore_assign_single_out_vtp_table(struct ubcore_vtp *vtp, out_entry->peer_jetty = vtp->cfg.peer_jetty; out_entry->trans_mode = vtp->cfg.trans_mode; out_entry->role = vtp->role; + out_entry->eid_idx = vtp->eid_idx; + out_entry->upi = vtp->upi; + out_entry->share_mode = vtp->share_mode; if (vtp->cfg.trans_mode == UBCORE_TP_RM || vtp->cfg.trans_mode == UBCORE_TP_RC) { - if (vtp->cfg.tp == NULL) - return; - out_entry->local_net_addr_idx = vtp->cfg.tp->local_net_addr_idx; - if (vtp->cfg.tpg == NULL || vtp->cfg.tpg->tp_list == NULL) { - ubcore_log_err("tpg is null or tpg->tp_list is null"); - return; + if (vtp->cfg.tpg == NULL) { + ubcore_log_err("tpg is null"); + return -1; } + if (vtp->cfg.tpg->tp_list[0] == NULL) { + ubcore_log_err("tpg->tp_list[0] is null"); + return -1; + } + out_entry->local_net_addr_idx = vtp->cfg.tpg->tp_list[0]->local_net_addr_idx; + out_entry->dip = vtp->cfg.tpg->tp_list[0]->peer_net_addr; out_entry->tpgn = vtp->cfg.tpg->tpgn; out_entry->tp_cnt = vtp->cfg.tpg->tpg_cfg.tp_cnt; for (dev_tpn_idx = 0; dev_tpn_idx < out_entry->tp_cnt; dev_tpn_idx++) - out_entry->tpn[dev_tpn_idx] = vtp->cfg.tpg->tp_list[dev_tpn_idx]->tpn; + out_entry->tpn[dev_tpn_idx] = (vtp->cfg.tpg->tp_list[dev_tpn_idx] == NULL ? + 0 : vtp->cfg.tpg->tp_list[dev_tpn_idx]->tpn); } else { if (vtp->cfg.utp == NULL) { ubcore_log_err("utp is null"); - return; + return -1; } out_entry->local_net_addr_idx = vtp->cfg.utp->utp_cfg.local_net_addr_idx; out_entry->utp_idx = vtp->cfg.utp->utpn; + out_entry->dip = vtp->cfg.utp->utp_cfg.peer_net_addr; + } + + sip_entry = + ubcore_lookup_sip_info_without_lock(&dev->sip_table, out_entry->local_net_addr_idx); + if (sip_entry == NULL) { + ubcore_log_err("sip does not exist\n"); + return -1; } - (void)strcpy(out_entry->dev_name, dev_name); + out_entry->sip = sip_entry->addr; + (void)memcpy(out_entry->dev_name, dev_name, UBCORE_MAX_DEV_NAME); + return 0; } -static void ubcore_get_dev_vtp_table(struct ubcore_hash_table *dev_ht, const char *dev_name, +static void ubcore_get_dev_vtp_table(struct ubcore_device *dev, enum ubcore_hash_table_type type, uint32_t *out_entry_idx, struct ubcore_cmd_restored_vtp_entry *arg) { uint32_t dev_vtp_idx, dev_vtp_cnt = 0; struct ubcore_vtp **e = NULL; - e = ubcore_get_all_vtp(dev_ht, &dev_vtp_cnt); - for (dev_vtp_idx = 0; dev_vtp_idx < dev_vtp_cnt; dev_vtp_idx++, (*out_entry_idx)++) - ubcore_assign_single_out_vtp_table(e[dev_vtp_idx], - &arg->out.entry[*out_entry_idx], dev_name); + e = ubcore_get_all_vtp(&dev->ht[type], &dev_vtp_cnt); + if (dev_vtp_cnt == 0 || e == NULL) + return; - if (e != NULL) - kfree(e); + for (dev_vtp_idx = 0; dev_vtp_idx < dev_vtp_cnt; dev_vtp_idx++) { + if (ubcore_assign_single_out_vtp_table(dev, e[dev_vtp_idx], + &arg->out.entry[*out_entry_idx], dev->dev_name) != 0) { + continue; + } else { + (*out_entry_idx)++; + } + } + + kfree(e); } static int ubcore_cmd_restore_vtp_table(struct ubcore_cmd_hdr *hdr) @@ -2400,50 +2669,59 @@ static int ubcore_cmd_restore_vtp_table(struct ubcore_cmd_hdr *hdr) uint32_t dev_cnt, i = 0, out_idx = 0; int ret; + dev_list = ubcore_get_all_tpf_device(UBCORE_TRANSPORT_UB, &dev_cnt); + if (dev_cnt == 0) { + ubcore_log_info("dev count is 0\n"); + return 0; + } + + if (dev_list == NULL) { + ubcore_log_info("dev list is NULL\n"); + return -1; + } + + if (hdr->args_len > sizeof(struct ubcore_cmd_restored_vtp_entry) + + dev_cnt * UBCORE_MAX_VTP_CNT_PER_TPF * sizeof(struct ubcore_restored_vtp_entry)) { + ubcore_log_info("hdr->args_len too long to alloc\n"); + ret = -1; + goto free_dev; + } + arg = kcalloc(1, hdr->args_len, GFP_KERNEL); - if (arg == NULL) - return -ENOMEM; + if (arg == NULL) { + ret = -ENOMEM; + goto free_dev; + } ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, hdr->args_len); if (ret != 0) - return ret; - - arg->out.vtp_cnt = 0; - dev_list = ubcore_get_all_tpf_device(UBCORE_TRANSPORT_UB, &dev_cnt); - if (dev_cnt == 0) { - ubcore_log_info("dev count is 0\n"); goto free_arg; - } + arg->out.vtp_cnt = 0; for (i = 0; i < dev_cnt; ++i) { arg->out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_RM_VTP]); arg->out.vtp_cnt += ubcore_get_all_vtp_cnt(&dev_list[i]->ht[UBCORE_HT_UM_VTP]); } if (arg->out.vtp_cnt != arg->in.vtp_cnt) { ubcore_log_warn("input vtp_cnt: %u does not match current vtp_cnt: %u\n", - arg->out.vtp_cnt, arg->in.vtp_cnt); + arg->in.vtp_cnt, arg->out.vtp_cnt); ret = -1; goto free_arg; } for (i = 0; i < dev_cnt; ++i) { - ubcore_get_dev_vtp_table(&dev_list[i]->ht[UBCORE_HT_RM_VTP], - dev_list[i]->dev_name, &out_idx, arg); - ubcore_get_dev_vtp_table(&dev_list[i]->ht[UBCORE_HT_UM_VTP], - dev_list[i]->dev_name, &out_idx, arg); + ubcore_get_dev_vtp_table(dev_list[i], UBCORE_HT_RM_VTP, &out_idx, arg); + ubcore_get_dev_vtp_table(dev_list[i], UBCORE_HT_UM_VTP, &out_idx, arg); } if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, hdr->args_len) != 0) ret = -EPERM; - for (i = 0; i < dev_cnt; ++i) - ubcore_put_device(dev_list[i]); - - if (dev_list != NULL) - kfree(dev_list); - free_arg: kfree(arg); + +free_dev: + ubcore_put_devices(dev_list, dev_cnt); return ret; } @@ -2454,9 +2732,9 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) struct ubcore_vtp_cfg vtp_cfg; struct ubcore_vtp *vtp = NULL; struct ubcore_device *dev; - struct ubcore_tpg *tpg; - struct ubcore_utp *utp; - struct ubcore_ctp *ctp; + struct ubcore_tpg *tpg = NULL; + struct ubcore_utp *utp = NULL; + struct ubcore_ctp *ctp = NULL; int ret; arg = kzalloc(sizeof(struct ubcore_cmd_map_target_vtp), GFP_KERNEL); @@ -2478,7 +2756,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) /* deal with trans domain -G */ if (arg->in.vtp.trans_mode != UBCORE_TP_UM) { /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg->in.vtp.tpgn); + tpg = ubcore_find_get_tpg(dev, arg->in.vtp.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); @@ -2487,7 +2765,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) ubcore_set_vtp2tpg_cfg(&vtp_cfg, &arg->in.vtp, tpg); } else { /* deal with UM */ - utp = ubcore_find_utp(dev, arg->in.vtp.utpn); + utp = ubcore_find_get_utp(dev, arg->in.vtp.utpn); if (utp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find utp"); @@ -2497,7 +2775,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) } } else { /* deal with trans domain -C */ - ctp = ubcore_find_ctp(dev, arg->in.vtp.ctpn); + ctp = ubcore_find_get_ctp(dev, arg->in.vtp.ctpn); if (ctp == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find ctp"); @@ -2509,10 +2787,13 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) vtp = ubcore_check_and_map_target_vtp(dev, &vtp_cfg, arg->in.role); if (vtp == NULL) { ret = -EPERM; - goto put_device; + goto put_tpg_and_utp; } vtp->role = (vtp->role != arg->in.role ? UBCORE_VTP_DUPLEX : vtp->role); + ubcore_vtp_kref_put(vtp); +put_tpg_and_utp: + ubcore_put_tpg_utp_ctp_in_vtp(&arg->in.vtp, tpg, utp, ctp); put_device: ubcore_put_device(dev); free_arg: @@ -2521,54 +2802,67 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) } typedef int (*ubcore_uvs_cmd_handler)(struct ubcore_cmd_hdr *hdr); +struct ubcore_uvs_cmd_func { + ubcore_uvs_cmd_handler func; + bool need_cap_verify; +}; -static ubcore_uvs_cmd_handler g_ubcore_uvs_cmd_handlers[] = { - [0] = NULL, - [UBCORE_CMD_CHANNEL_INIT] = ubcore_uvs_cmd_channel_init, - [UBCORE_CMD_CREATE_TPG] = ubcore_cmd_create_tpg, - [UBCORE_CMD_CREATE_VTP] = ubcore_cmd_create_vtp, - [UBCORE_CMD_MODIFY_TPG] = ubcore_cmd_modify_tpg, - [UBCORE_CMD_CREATE_TARGET_TPG] = ubcore_cmd_create_target_tpg, - [UBCORE_CMD_MODIFY_TARGET_TPG] = ubcore_cmd_modify_target_tpg, - [UBCORE_CMD_DESTROY_VTP] = ubcore_cmd_destroy_vtp, - [UBCORE_CMD_DESTROY_TPG] = ubcore_cmd_destroy_tpg, - [UBCORE_CMD_ADD_SIP] = ubcore_cmd_opt_sip, - [UBCORE_CMD_DEL_SIP] = ubcore_cmd_opt_sip, - [UBCORE_CMD_MAP_VTP] = ubcore_cmd_map_vtp, - [UBCORE_CMD_CREATE_UTP] = ubcore_cmd_create_utp, - [UBCORE_CMD_ONLY_CREATE_UTP] = ubcore_cmd_only_create_utp, - [UBCORE_CMD_DESTROY_UTP] = ubcore_cmd_destroy_utp, - [UBCORE_CMD_RESTORE_TP_ERROR_RSP] = ubcore_cmd_restore_tp_error_rsp, - [UBCORE_CMD_RESTORE_TARGET_TP_ERROR_REQ] = ubcore_cmd_restore_target_tp_error_req, - [UBCORE_CMD_RESTORE_TARGET_TP_ERROR_ACK] = ubcore_cmd_restore_target_tp_error_ack, - [UBCORE_CMD_RESTORE_TP_SUSPEND] = ubcore_cmd_restore_tp_suspend, - [UBCORE_CMD_GET_DEV_FEATURE] = ubcore_cmd_get_dev_feature, - [UBCORE_CMD_CHANGE_TP_TO_ERROR] = ubcore_cmd_change_tp_to_error, - [UBCORE_CMD_SET_UPI] = ubcore_cmd_set_upi, - [UBCORE_CMD_SHOW_UPI] = ubcore_cmd_show_upi, - [UBCORE_CMD_SET_GLOBAL_CFG] = ubcore_cmd_set_global_cfg, - [UBCORE_CMD_CONFIG_FUNCTION_MIGRATE_STATE] = ubcore_cmd_config_function_migrate_state, - [UBCORE_CMD_SET_VPORT_CFG] = ubcore_cmd_set_vport_cfg, - [UBCORE_CMD_MODIFY_VTP] = ubcore_cmd_modify_vtp, - [UBCORE_CMD_GET_DEV_INFO] = ubcore_cmd_get_dev_info, - [UBCORE_CMD_CREATE_CTP] = ubcore_cmd_create_ctp, - [UBCORE_CMD_DESTROY_CTP] = ubcore_cmd_destroy_ctp, - [UBCORE_CMD_CHANGE_TPG_TO_ERROR] = ubcore_cmd_change_tpg_to_error, - [UBCORE_CMD_ALLOC_EID] = ubcore_cmd_opt_update_eid, - [UBCORE_CMD_DEALLOC_EID] = ubcore_cmd_opt_update_eid, - [UBCORE_CMD_QUERY_FE_IDX] = ubcore_cmd_opt_query_fe_idx, - [UBCORE_CMD_CONFIG_DSCP_VL] = ubcore_cmd_opt_config_dscp_vl, - [UBCORE_CMD_GET_VTP_TABLE_CNT] = ubcore_cmd_get_vtp_table_cnt, - [UBCORE_CMD_RESTORE_TABLE] = ubcore_cmd_restore_vtp_table, - [UBCORE_CMD_MAP_TARGET_VTP] = ubcore_cmd_map_target_vtp, +static struct ubcore_uvs_cmd_func g_ubcore_uvs_cmd_funcs[] = { + [0] = {NULL, false}, + [UBCORE_CMD_CHANNEL_INIT] = {ubcore_uvs_cmd_channel_init, false}, + [UBCORE_CMD_CREATE_TPG] = {ubcore_cmd_create_tpg, false}, + [UBCORE_CMD_CREATE_VTP] = {ubcore_cmd_create_vtp, false}, + [UBCORE_CMD_MODIFY_TPG] = {ubcore_cmd_modify_tpg, false}, + [UBCORE_CMD_MODIFY_TPG_TP_CNT] = {ubcore_cmd_modify_tpg_tp_cnt, false}, + [UBCORE_CMD_CREATE_TARGET_TPG] = {ubcore_cmd_create_target_tpg, false}, + [UBCORE_CMD_MODIFY_TARGET_TPG] = {ubcore_cmd_modify_target_tpg, false}, + [UBCORE_CMD_DESTROY_VTP] = {ubcore_cmd_destroy_vtp, false}, + [UBCORE_CMD_DESTROY_TPG] = {ubcore_cmd_destroy_tpg, false}, + [UBCORE_CMD_ADD_SIP] = {ubcore_cmd_opt_sip, true}, + [UBCORE_CMD_DEL_SIP] = {ubcore_cmd_opt_sip, true}, + [UBCORE_CMD_MAP_VTP] = {ubcore_cmd_map_vtp, false}, + [UBCORE_CMD_CREATE_UTP] = {ubcore_cmd_create_utp, false}, + [UBCORE_CMD_ONLY_CREATE_UTP] = {ubcore_cmd_only_create_utp, false}, + [UBCORE_CMD_DESTROY_UTP] = {ubcore_cmd_destroy_utp, false}, + [UBCORE_CMD_RESTORE_TP_ERROR_RSP] = {ubcore_cmd_restore_tp_error_rsp, false}, + [UBCORE_CMD_RESTORE_TARGET_TP_ERROR_REQ] = { + ubcore_cmd_restore_target_tp_error_req, false}, + [UBCORE_CMD_RESTORE_TARGET_TP_ERROR_ACK] = { + ubcore_cmd_restore_target_tp_error_ack, false}, + [UBCORE_CMD_RESTORE_TP_SUSPEND] = {ubcore_cmd_restore_tp_suspend, false}, + [UBCORE_CMD_GET_DEV_FEATURE] = {ubcore_cmd_get_dev_feature, false}, + [UBCORE_CMD_CHANGE_TP_TO_ERROR] = {ubcore_cmd_change_tp_to_error, false}, + [UBCORE_CMD_SET_UPI] = {ubcore_cmd_set_upi, true}, + [UBCORE_CMD_SHOW_UPI] = {ubcore_cmd_show_upi, false}, + [UBCORE_CMD_SET_GLOBAL_CFG] = {ubcore_cmd_set_global_cfg, true}, + [UBCORE_CMD_CONFIG_FUNCTION_MIGRATE_STATE] = { + ubcore_cmd_config_function_migrate_state, false}, + [UBCORE_CMD_SET_VPORT_CFG] = {ubcore_cmd_set_vport_cfg, true}, + [UBCORE_CMD_MODIFY_VTP] = {ubcore_cmd_modify_vtp, false}, + [UBCORE_CMD_GET_DEV_INFO] = {ubcore_cmd_get_dev_info, false}, + [UBCORE_CMD_CREATE_CTP] = {ubcore_cmd_create_ctp, false}, + [UBCORE_CMD_DESTROY_CTP] = {ubcore_cmd_destroy_ctp, false}, + [UBCORE_CMD_CHANGE_TPG_TO_ERROR] = {ubcore_cmd_change_tpg_to_error, false}, + [UBCORE_CMD_ALLOC_EID] = {ubcore_cmd_opt_update_eid, true}, + [UBCORE_CMD_DEALLOC_EID] = {ubcore_cmd_opt_update_eid, true}, + [UBCORE_CMD_QUERY_FE_IDX] = {ubcore_cmd_opt_query_fe_idx, false}, + [UBCORE_CMD_CONFIG_DSCP_VL] = {ubcore_cmd_opt_config_dscp_vl, true}, + [UBCORE_CMD_GET_VTP_TABLE_CNT] = {ubcore_cmd_get_vtp_table_cnt, false}, + [UBCORE_CMD_RESTORE_TABLE] = {ubcore_cmd_restore_vtp_table, false}, + [UBCORE_CMD_MAP_TARGET_VTP] = {ubcore_cmd_map_target_vtp, false}, }; int ubcore_uvs_cmd_parse(struct ubcore_cmd_hdr *hdr) { if (hdr->command < UBCORE_CMD_CHANNEL_INIT || hdr->command >= UBCORE_CMD_LAST || - g_ubcore_uvs_cmd_handlers[hdr->command] == NULL) { + g_ubcore_uvs_cmd_funcs[hdr->command].func == NULL) { ubcore_log_err("bad ubcore command: %d.\n", (int)hdr->command); return -EINVAL; } - return g_ubcore_uvs_cmd_handlers[hdr->command](hdr); + + if (g_ubcore_uvs_cmd_funcs[hdr->command].need_cap_verify && !capable(CAP_NET_ADMIN)) { + ubcore_log_err("failed cap verify, ubcore command: %d.\n", (int)hdr->command); + return -EPERM; + } + return g_ubcore_uvs_cmd_funcs[hdr->command].func(hdr); } diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h index 741d7ba2e65a..71cd42020bcd 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h @@ -33,7 +33,6 @@ #define UBCORE_UVS_CMD_MAGIC 'V' #define UBCORE_UVS_CMD _IOWR(UBCORE_UVS_CMD_MAGIC, 1, struct ubcore_cmd_hdr) #define UBCORE_CMD_CHANNEL_INIT_SIZE 32 -#define UBCORE_UVS_CMD_DEV_MAX 64 #define UBCORE_MAX_VTP_CFG_CNT 32 #define UBCORE_MAX_EID_CONFIG_CNT 32 #define UBCORE_MAX_DSCP_VL_NUM 64 @@ -44,8 +43,9 @@ enum ubcore_uvs_cmd { UBCORE_CMD_CREATE_TPG, /* initiator */ UBCORE_CMD_CREATE_VTP, /* initiator */ UBCORE_CMD_MODIFY_TPG, + UBCORE_CMD_MODIFY_TPG_TP_CNT, UBCORE_CMD_CREATE_TARGET_TPG, /* target */ - UBCORE_CMD_MODIFY_TARGET_TPG, /* target */ + UBCORE_CMD_MODIFY_TARGET_TPG, UBCORE_CMD_DESTROY_VTP, /* initiator or target */ UBCORE_CMD_DESTROY_TPG, /* initiator or target */ UBCORE_CMD_ADD_SIP, @@ -82,7 +82,7 @@ enum ubcore_uvs_cmd { struct ubcore_cmd_opt_eid { struct { - char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; uint32_t upi; uint16_t fe_idx; union ubcore_eid eid; @@ -92,7 +92,7 @@ struct ubcore_cmd_opt_eid { struct ubcore_cmd_opt_query_fe_idx { struct { - char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; struct ubcore_devid devid; } in; struct { @@ -102,7 +102,7 @@ struct ubcore_cmd_opt_query_fe_idx { struct ubcore_cmd_opt_config_dscp_vl { struct { - char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; uint8_t dscp[UBCORE_MAX_DSCP_VL_NUM]; uint8_t vl[UBCORE_MAX_DSCP_VL_NUM]; uint8_t num; @@ -120,7 +120,7 @@ struct ubcore_cmd_channel_init { struct ubcore_cmd_tpf { enum ubcore_transport_type trans_type; - struct ubcore_net_addr netaddr; + union ubcore_net_addr_union netaddr; }; struct ubcore_cmd_tp_cfg { @@ -161,6 +161,7 @@ struct ubcore_cmd_create_tpg { struct { uint32_t tpgn; uint32_t tpn[UBCORE_MAX_TP_CNT_IN_GRP]; + enum ubcore_mtu max_mtu; } out; /* for alpha */ struct ubcore_ta_data ta_data; @@ -190,6 +191,7 @@ struct ubcore_cmd_create_vtp { struct ubcore_cmd_modify_tpg { struct { struct ubcore_cmd_tpf tpf; + uint32_t peer_tp_cnt; /* modify tp to RTR */ uint32_t tpgn; struct ubcore_tp_attr rtr_attr[UBCORE_MAX_TP_CNT_IN_GRP]; @@ -205,6 +207,33 @@ struct ubcore_cmd_modify_tpg { struct ubcore_udrv_ext udrv_ext; }; +/* modify tps in the tpg to RTS at target */ +struct ubcore_cmd_modify_target_tpg { + struct { + struct ubcore_cmd_tpf tpf; + uint32_t peer_tp_cnt; + /* modify tp to RTR */ + uint32_t tpgn; + struct ubcore_tp_attr rtr_attr[UBCORE_MAX_TP_CNT_IN_GRP]; + union ubcore_tp_attr_mask rtr_mask[UBCORE_MAX_TP_CNT_IN_GRP]; + } in; + struct { + uint32_t rtr_tp_cnt; + uint32_t rts_tp_cnt; + } out; + /* for alpha */ +}; + +struct ubcore_cmd_modify_tpg_tp_cnt { + struct { + struct ubcore_cmd_tpf tpf; + uint32_t tpgn_for_modify; + uint32_t tp_cnt; + } in; + struct { + uint32_t tpgn; + } out; +}; /* create tpg, create and modify tps in it to RTR at target */ struct ubcore_cmd_create_target_tpg { struct { @@ -219,6 +248,7 @@ struct ubcore_cmd_create_target_tpg { struct { uint32_t tpgn; uint32_t tpn[UBCORE_MAX_TP_CNT_IN_GRP]; + uint32_t rts_tp_cnt; } out; /* for alpha */ struct ubcore_ta_data ta_data; @@ -228,19 +258,6 @@ struct ubcore_cmd_create_target_tpg { struct ubcore_udrv_ext udrv_ext; }; -/* modify tps in the tpg to RTS at target */ -struct ubcore_cmd_modify_target_tpg { - struct { - struct ubcore_cmd_tpf tpf; - uint32_t tpgn; - } in; - struct { - uint32_t rts_tp_cnt; - } out; - /* for alpha */ - struct ubcore_ta_data ta_data; -}; - struct ubcore_cmd_map_target_vtp { struct { struct ubcore_cmd_tpf tpf; @@ -280,6 +297,10 @@ struct ubcore_cmd_opt_sip { struct { struct ubcore_sip_info info; } in; + struct { + /* only valid in add succeed or add exist */ + uint32_t sip_idx; + } out; }; struct ubcore_cmd_map_vtp { @@ -288,6 +309,9 @@ struct ubcore_cmd_map_vtp { /* create vtp */ struct ubcore_cmd_vtp_cfg vtp; uint32_t role; + uint32_t eid_idx; + uint32_t upi; + bool share_mode; } in; struct { uint32_t vtpn; @@ -300,7 +324,6 @@ struct ubcore_cmd_create_utp { struct ubcore_cmd_tpf tpf; struct ubcore_utp_cfg utp_cfg; struct ubcore_cmd_vtp_cfg vtp; - /* todonext: add user data */ } in; struct { uint32_t idx; @@ -313,7 +336,6 @@ struct ubcore_cmd_destroy_utp { struct { struct ubcore_cmd_tpf tpf; uint32_t utp_idx; - /* todonext: add user data and ext */ } in; }; @@ -323,7 +345,6 @@ struct ubcore_cmd_create_ctp { struct ubcore_cmd_tpf tpf; struct ubcore_ctp_cfg ctp_cfg; struct ubcore_cmd_vtp_cfg vtp; - /* todonext: add user data */ } in; struct { uint32_t idx; @@ -336,7 +357,6 @@ struct ubcore_cmd_destroy_ctp { struct { struct ubcore_cmd_tpf tpf; uint32_t ctp_idx; - /* todonext: add user data and ext */ } in; }; @@ -353,7 +373,6 @@ struct ubcore_cmd_modify_vtp { struct ubcore_cmd_restore_tp_error { struct { struct ubcore_cmd_tpf tpf; - uint32_t tpgn; uint32_t tpn; uint16_t data_udp_start; uint16_t ack_udp_start; @@ -388,21 +407,20 @@ struct ubcore_cmd_get_dev_feature { struct ubcore_cmd_change_tp_to_error { struct { struct ubcore_cmd_tpf tpf; - uint32_t tpgn; uint32_t tpn; } in; }; struct ubcore_cmd_set_upi { struct { - char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; uint32_t upi; } in; }; struct ubcore_cmd_show_upi { struct { - char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + char dev_name[UBCORE_MAX_DEV_NAME]; } in; struct { uint32_t upi; @@ -411,12 +429,13 @@ struct ubcore_cmd_show_upi { struct ubcore_cmd_get_dev_info { struct { - char target_pf_name[UBCORE_UVS_CMD_DEV_MAX]; + char target_pf_name[UBCORE_MAX_DEV_NAME]; struct ubcore_cmd_tpf tpf; } in; struct { bool port_is_active; - char target_tpf_name[UBCORE_UVS_CMD_DEV_MAX]; + char target_tpf_name[UBCORE_MAX_DEV_NAME]; + enum ubcore_mtu max_mtu; } out; }; @@ -481,6 +500,11 @@ struct ubcore_restored_vtp_entry { uint32_t tp_cnt; uint32_t tpn[UBCORE_MAX_TP_CNT_IN_GRP]; uint32_t role; + struct ubcore_net_addr sip; + struct ubcore_net_addr dip; + uint32_t eid_idx; + uint32_t upi; + bool share_mode; }; struct ubcore_cmd_restored_vtp_entry { diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.c b/drivers/ub/urma/ubcore/ubcore_vtp.c index 10f6a29033bf..5c9b5cd60bc1 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.c +++ b/drivers/ub/urma/ubcore/ubcore_vtp.c @@ -33,26 +33,34 @@ static int ubcore_handle_create_vtp_resp(struct ubcore_device *dev, struct ubcore_create_vtp_resp *vtp_resp = (struct ubcore_create_vtp_resp *)resp->data; struct ubcore_vtpn *vtpn = (struct ubcore_vtpn *)user_arg; + if (resp == NULL || resp->len < sizeof(struct ubcore_create_vtp_resp)) { + ubcore_log_err("invalid ubcore_create_vtp_resp len"); + return (int)UBCORE_MSG_RESP_FAIL; + } + switch (vtp_resp->ret) { case UBCORE_MSG_RESP_FAIL: ubcore_log_err("failed to create vtp: response error.\n"); - return -1; + break; case UBCORE_MSG_RESP_IN_PROGRESS: - ubcore_log_err("failed to create vtp: response error.\n"); - return -1; + ubcore_log_err("failed: try to del vtp which is being created. Try again later.\n"); + break; case UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND: ubcore_log_err("failed: rc jetty already bind by other jetty.\n"); - return -1; + break; case UBCORE_MSG_RESP_LIMIT_RATE: ubcore_log_err("failed: the current link setup speed has reached the maximum value.\n"); - return -1; + break; case UBCORE_MSG_RESP_SUCCESS: + /* tpf may return a new vtpn */ + vtpn->vtpn = vtp_resp->vtpn; + break; default: + ubcore_log_err("unknown the state of vtp reply to create.\n"); break; } - /* tpf may return a new vtpn */ - vtpn->vtpn = vtp_resp->vtpn; - return 0; + + return vtp_resp->ret; } static int ubcore_send_create_vtp_req(struct ubcore_device *dev, @@ -72,6 +80,8 @@ static int ubcore_send_create_vtp_req(struct ubcore_device *dev, create = (struct ubcore_create_vtp_req *)req->data; create->vtpn = vtpn->vtpn; + create->sub_trans_mode = p->sub_trans_mode; + create->rc_share_tp = p->rc_share_tp; create->trans_mode = p->trans_mode; create->local_eid = p->local_eid; create->peer_eid = p->peer_eid; @@ -93,18 +103,32 @@ static int ubcore_handle_del_vtp_resp(struct ubcore_device *dev, { struct ubcore_destroy_vtp_resp *vtp_resp = (struct ubcore_destroy_vtp_resp *)resp->data; - if (vtp_resp->ret == UBCORE_MSG_RESP_FAIL) { + if (resp == NULL || resp->len < sizeof(struct ubcore_destroy_vtp_resp)) { + ubcore_log_err("invalid parameter"); + return (int)UBCORE_MSG_RESP_FAIL; + } + + switch (vtp_resp->ret) { + case UBCORE_MSG_RESP_SUCCESS: + break; + case UBCORE_MSG_RESP_FAIL: ubcore_log_err("failed to destroy vtp: response error"); - return -1; - } else if (vtp_resp->ret == UBCORE_MSG_RESP_IN_PROGRESS) { - ubcore_log_err("failed: try to del vtp which is being created. Try again later"); - return -1; + break; + case UBCORE_MSG_RESP_IN_PROGRESS: + ubcore_log_err("failed: try to del vtp which is being deleted. Try again later.\n"); + break; + /* the status of the delete vtp reply is unknown */ + case UBCORE_MSG_RESP_RC_JETTY_ALREADY_BIND: + case UBCORE_MSG_RESP_LIMIT_RATE: + default: + ubcore_log_err("failed: the state of vtp reply to del is unknown.\n"); + break; } - return 0; + return (int)vtp_resp->ret; } -static int ubcore_send_del_vtp_req(struct ubcore_vtpn *vtpn) +static int ubcore_send_del_vtp_req(struct ubcore_vtpn *vtpn, struct ubcore_vtp_param *param) { uint32_t data_len = (uint32_t)sizeof(struct ubcore_create_vtp_req); struct ubcore_create_vtp_req *destroy; @@ -121,6 +145,10 @@ static int ubcore_send_del_vtp_req(struct ubcore_vtpn *vtpn) destroy = (struct ubcore_create_vtp_req *)req->data; destroy->vtpn = vtpn->vtpn; destroy->trans_mode = vtpn->trans_mode; + if (param != NULL) { + destroy->sub_trans_mode = param->sub_trans_mode; + destroy->rc_share_tp = param->rc_share_tp; + } destroy->local_eid = vtpn->local_eid; destroy->peer_eid = vtpn->peer_eid; destroy->eid_index = vtpn->eid_index; @@ -142,12 +170,12 @@ static struct ubcore_vtpn *ubcore_alloc_vtpn(struct ubcore_device *dev, struct ubcore_vtpn *vtpn; if (dev->ops == NULL || dev->ops->alloc_vtpn == NULL) - return NULL; + return ERR_PTR(-EINVAL); vtpn = dev->ops->alloc_vtpn(dev); - if (vtpn == NULL) { + if (IS_ERR_OR_NULL(vtpn)) { ubcore_log_err("failed to alloc vtpn!, dev_name:%s", dev->dev_name); - return NULL; + return vtpn == NULL ? ERR_PTR(-ENOEXEC) : vtpn; } vtpn->ub_dev = dev; @@ -184,6 +212,33 @@ void ubcore_vtpn_get(void *obj) kref_get(&vtpn->ref_cnt); } +static void ubcore_vtp_kref_release(struct kref *ref_cnt) +{ + struct ubcore_vtp *vtp = container_of(ref_cnt, struct ubcore_vtp, ref_cnt); + struct ubcore_device *ub_dev = vtp->ub_dev; + + /* pseudo vtp */ + if (vtp->cfg.vtpn == UINT_MAX) { + kfree(vtp); + return; + } + if (ub_dev == NULL || ub_dev->ops == NULL || ub_dev->ops->destroy_vtp == NULL) + return; + ub_dev->ops->destroy_vtp(vtp); +} + +void ubcore_vtp_kref_put(struct ubcore_vtp *vtp) +{ + (void)kref_put(&vtp->ref_cnt, ubcore_vtp_kref_release); +} + +void ubcore_vtp_get(void *obj) +{ + struct ubcore_vtp *vtp = obj; + + kref_get(&vtp->ref_cnt); +} + static int ubcore_free_vtpn(struct ubcore_vtpn *vtpn) { struct ubcore_device *dev = vtpn->ub_dev; @@ -205,9 +260,11 @@ static int ubcore_free_vtpn(struct ubcore_vtpn *vtpn) } static struct ubcore_hash_table *ubcore_get_vtpn_ht(struct ubcore_device *dev, - enum ubcore_transport_mode trans_mode) + enum ubcore_transport_mode trans_mode, uint32_t sub_trans_mode, + uint32_t rc_share_tp) { - if (trans_mode == UBCORE_TP_RM) + if (trans_mode == UBCORE_TP_RM || + is_create_rc_shared_tp(trans_mode, sub_trans_mode, rc_share_tp)) return &dev->ht[UBCORE_HT_RM_VTPN]; if (trans_mode == UBCORE_TP_RC) @@ -219,13 +276,13 @@ static struct ubcore_hash_table *ubcore_get_vtpn_ht(struct ubcore_device *dev, return NULL; } -static struct ubcore_vtpn *ubcore_find_vtpn(struct ubcore_device *dev, +static struct ubcore_vtpn *ubcore_find_get_vtpn(struct ubcore_device *dev, struct ubcore_vtp_param *param) { struct ubcore_hash_table *ht; uint32_t hash; - ht = ubcore_get_vtpn_ht(dev, param->trans_mode); + ht = ubcore_get_vtpn_ht(dev, param->trans_mode, param->sub_trans_mode, param->rc_share_tp); if (ht == NULL) return NULL; @@ -233,13 +290,14 @@ static struct ubcore_vtpn *ubcore_find_vtpn(struct ubcore_device *dev, return ubcore_hash_table_lookup_get(ht, hash, ¶m->local_eid); } -static int ubcore_find_add_vtpn(struct ubcore_device *dev, - struct ubcore_vtpn *new_vtpn, struct ubcore_vtpn **exist_vtpn) +static int ubcore_find_add_vtpn(struct ubcore_device *dev, struct ubcore_vtpn *new_vtpn, + struct ubcore_vtpn **exist_vtpn, struct ubcore_vtp_param *p) { struct ubcore_hash_table *ht; uint32_t hash; - ht = ubcore_get_vtpn_ht(dev, new_vtpn->trans_mode); + ht = ubcore_get_vtpn_ht(dev, new_vtpn->trans_mode, + p->sub_trans_mode, p->rc_share_tp); if (ht == NULL || ht->head == NULL) { ubcore_log_err("hash table's head equals NULL"); return -EINVAL; @@ -253,16 +311,20 @@ static int ubcore_find_add_vtpn(struct ubcore_device *dev, return -EEXIST; } ubcore_hash_table_add_nolock(ht, &new_vtpn->hnode, hash); - ubcore_vtpn_kref_put(new_vtpn); spin_unlock(&ht->lock); return 0; } -void ubcore_hash_table_rmv_vtpn(struct ubcore_device *dev, struct ubcore_vtpn *vtpn) +void ubcore_hash_table_rmv_vtpn(struct ubcore_device *dev, struct ubcore_vtpn *vtpn, + struct ubcore_vtp_param *param) { struct ubcore_hash_table *ht; - ht = ubcore_get_vtpn_ht(dev, vtpn->trans_mode); + if (param != NULL) + ht = ubcore_get_vtpn_ht(dev, vtpn->trans_mode, + param->sub_trans_mode, param->rc_share_tp); + else + ht = ubcore_get_vtpn_ht(dev, vtpn->trans_mode, 0, 0); if (ht == NULL) return; ubcore_hash_table_remove(ht, &vtpn->hnode); @@ -288,8 +350,7 @@ static struct ubcore_vtpn *ubcore_reuse_vtpn(struct ubcore_device *dev, struct u } mutex_unlock(&vtpn->state_lock); - ubcore_log_err("Unknown states, vtpn:%u, state:%d", - vtpn->vtpn, (int)vtpn->state); + ubcore_log_err("Unknown states, vtpn:%u, state:%d", vtpn->vtpn, (int)vtpn->state); ubcore_vtpn_kref_put(vtpn); return NULL; } @@ -303,7 +364,7 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, if (dev == NULL || param == NULL) { ubcore_log_err("Invalid param"); - return NULL; + return ERR_PTR(-EINVAL); } if (ubcore_check_port_state(dev, 0) != 0) { @@ -312,19 +373,19 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, } // 1. try to reuse vtpn - vtpn = ubcore_find_vtpn(dev, param); + vtpn = ubcore_find_get_vtpn(dev, param); if (vtpn != NULL) return ubcore_reuse_vtpn(dev, vtpn); // 2. alloc new vtpn vtpn = ubcore_alloc_vtpn(dev, param); - if (vtpn == NULL) { + if (IS_ERR_OR_NULL(vtpn)) { ubcore_log_err("failed to alloc vtpn!"); - return NULL; + return vtpn; } // 3. add vtpn to hashtable - ret = ubcore_find_add_vtpn(dev, vtpn, &exist_vtpn); + ret = ubcore_find_add_vtpn(dev, vtpn, &exist_vtpn, param); if (ret == -EEXIST && exist_vtpn != NULL) { exist_vtpn = ubcore_reuse_vtpn(dev, exist_vtpn); // reuse immediately (void)ubcore_free_vtpn(vtpn); @@ -346,16 +407,16 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, // 5. failed roll back if (ret != 0) { ubcore_log_err("failed to send create vtp req, vtpn:%u", vtpn->vtpn); - ubcore_hash_table_rmv_vtpn(dev, vtpn); + ubcore_hash_table_rmv_vtpn(dev, vtpn, param); (void)ubcore_free_vtpn(vtpn); - return NULL; + return ERR_PTR(ret); } ubcore_log_info("connect vtpn:%u", vtpn->vtpn); return vtpn; } -int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn) +int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn, struct ubcore_vtp_param *param) { struct ubcore_device *dev; int ret = 0; @@ -376,14 +437,14 @@ int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn) return 0; } if (vtpn->state == UBCORE_VTPS_READY) { - ret = ubcore_send_del_vtp_req(vtpn); + ret = ubcore_send_del_vtp_req(vtpn, param); vtpn->state = UBCORE_VTPS_RESET; } mutex_unlock(&vtpn->state_lock); ubcore_log_info("disconnect vtpn:%u, ret:%d", vtpn->vtpn, ret); if (atomic_read(&vtpn->use_cnt) == 0) { - ubcore_hash_table_rmv_vtpn(dev, vtpn); + ubcore_hash_table_rmv_vtpn(dev, vtpn, param); (void)ubcore_free_vtpn(vtpn); } @@ -393,52 +454,70 @@ int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn) static int ubcore_find_add_vtp(struct ubcore_device *dev, enum ubcore_transport_mode mode, struct ubcore_vtp *vtp) { - int ret; + struct ubcore_hash_table *ht = NULL; + uint32_t hash; switch (mode) { case UBCORE_TP_RM: - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_RM_VTP], &vtp->hnode, - ubcore_get_vtp_hash(&vtp->cfg.local_eid)); + ht = &dev->ht[UBCORE_HT_RM_VTP]; + hash = ubcore_get_vtp_hash(&vtp->cfg.local_eid); break; case UBCORE_TP_RC: - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_RC_VTP], &vtp->hnode, - ubcore_get_rc_vtp_hash(&vtp->cfg.peer_eid)); + ht = &dev->ht[UBCORE_HT_RC_VTP]; + hash = ubcore_get_rc_vtp_hash(&vtp->cfg.peer_eid); break; case UBCORE_TP_UM: - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UM_VTP], &vtp->hnode, - ubcore_get_vtp_hash(&vtp->cfg.local_eid)); + ht = &dev->ht[UBCORE_HT_UM_VTP]; + hash = ubcore_get_vtp_hash(&vtp->cfg.local_eid); break; default: ubcore_log_err("unknown mode"); - ret = -EINVAL; - break; + return -EINVAL; + } + spin_lock(&ht->lock); + if (ht->head == NULL) { + spin_unlock(&ht->lock); + return -1; } + /* Old entry with the same key exists */ + if (ubcore_hash_table_lookup_nolock(ht, hash, + ubcore_ht_key(ht, &vtp->hnode)) != NULL) { + spin_unlock(&ht->lock); + ubcore_log_warn("find vtp vtpn:%u hash :%u", vtp->cfg.vtpn, hash); + return -1; + } + ubcore_hash_table_add_nolock(ht, &vtp->hnode, hash); + ubcore_vtp_get(vtp); + spin_unlock(&ht->lock); - return ret; + return 0; } -struct ubcore_vtp *ubcore_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg) +struct ubcore_vtp *ubcore_create_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg) { struct ubcore_vtp *vtp; int ret; if (dev->ops == NULL || dev->ops->create_vtp == NULL) - return NULL; + return ERR_PTR(-EINVAL); vtp = dev->ops->create_vtp(dev, cfg, NULL); - if (vtp == NULL) { + if (IS_ERR_OR_NULL(vtp)) { ubcore_log_err("Failed to create vtp"); - return NULL; + if (vtp == NULL) + return ERR_PTR(-ENOEXEC); + return vtp; } + kref_init(&vtp->ref_cnt); vtp->ub_dev = dev; ret = ubcore_find_add_vtp(dev, cfg->trans_mode, vtp); if (ret != 0) { - (void)dev->ops->destroy_vtp(vtp); + ubcore_vtp_kref_put(vtp); vtp = NULL; ubcore_log_err("Failed to add vtp to the vtp table"); - return vtp; + return ERR_PTR(-ENOEXEC); } if (cfg->flag.bs.clan_tp) { @@ -456,45 +535,59 @@ struct ubcore_vtp *ubcore_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_c static void ubcore_remove_vtp(struct ubcore_device *dev, enum ubcore_transport_mode mode, struct ubcore_vtp *vtp) { + struct ubcore_hash_table *ht = NULL; + struct ubcore_vtp *find_vtp = NULL; + uint32_t hash; + switch (mode) { case UBCORE_TP_RM: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_RM_VTP], &vtp->hnode); + ht = &dev->ht[UBCORE_HT_RM_VTP]; + hash = ubcore_get_vtp_hash(&vtp->cfg.local_eid); break; case UBCORE_TP_RC: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_RC_VTP], &vtp->hnode); + ht = &dev->ht[UBCORE_HT_RC_VTP]; + hash = ubcore_get_rc_vtp_hash(&vtp->cfg.peer_eid); break; case UBCORE_TP_UM: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_UM_VTP], &vtp->hnode); + ht = &dev->ht[UBCORE_HT_UM_VTP]; + hash = ubcore_get_vtp_hash(&vtp->cfg.local_eid); break; default: ubcore_log_err("unknown mode"); - break; + return; } + spin_lock(&ht->lock); + find_vtp = ubcore_hash_table_lookup_nolock(ht, hash, + ubcore_ht_key(ht, &vtp->hnode)); + if (find_vtp == NULL) { + spin_unlock(&ht->lock); + ubcore_log_warn("vtp:%d no find", vtp->cfg.vtpn); + return; + } + ubcore_hash_table_remove_nolock(ht, &find_vtp->hnode); + /* Pair with kref get in ubcore_find_add_vtp */ + ubcore_vtp_kref_put(find_vtp); + spin_unlock(&ht->lock); } int ubcore_unmap_vtp(struct ubcore_vtp *vtp) { - struct ubcore_device *dev = vtp->ub_dev; + struct ubcore_device *dev = NULL; struct ubcore_vtp_cfg cfg; int ret = 0; - if (vtp == NULL || dev == NULL || dev->ops == NULL || dev->ops->destroy_vtp == NULL) + if (vtp == NULL) + return -EINVAL; + + dev = vtp->ub_dev; + if (dev == NULL || dev->ops == NULL || dev->ops->destroy_vtp == NULL) return -EINVAL; cfg = vtp->cfg; ubcore_remove_vtp(dev, cfg.trans_mode, vtp); - - if (vtp->cfg.vtpn == UINT_MAX) { - kfree(vtp); - } else { - ret = dev->ops->destroy_vtp(vtp); - if (ret != 0) { - (void)ubcore_find_add_vtp(dev, cfg.trans_mode, vtp); - ubcore_log_err("Failed to destroy vtp"); - return ret; - } - + /* target vtp */ + if (vtp->cfg.vtpn != UINT_MAX) { if (cfg.flag.bs.clan_tp) { atomic_dec(&cfg.ctp->use_cnt); } else { @@ -536,15 +629,9 @@ int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role) new_vtp->role = UBCORE_VTP_TARGET; (void)memcpy(&new_vtp->cfg, &vtp->cfg, sizeof(struct ubcore_vtp_cfg)); new_vtp->cfg.vtpn = UINT_MAX; + kref_init(&new_vtp->ref_cnt); ubcore_remove_vtp(dev, cfg.trans_mode, vtp); - ret = dev->ops->destroy_vtp(vtp); - if (ret != 0) { - (void)ubcore_find_add_vtp(dev, cfg.trans_mode, vtp); - kfree(new_vtp); - ubcore_log_err("Failed to destroy vtp"); - return ret; - } if (cfg.flag.bs.clan_tp) { atomic_dec(&cfg.ctp->use_cnt); @@ -554,9 +641,10 @@ int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role) else atomic_dec(&cfg.utp->use_cnt); } + ret = ubcore_find_add_vtp(dev, new_vtp->cfg.trans_mode, new_vtp); + ubcore_vtp_kref_put(new_vtp); if (ret != 0) { - kfree(new_vtp); ubcore_log_err("Failed to add new vtp to the vtp table"); return -1; } @@ -592,6 +680,31 @@ struct ubcore_vtp *ubcore_find_vtp(struct ubcore_device *dev, return vtp_entry; } +struct ubcore_vtp *ubcore_find_get_vtp(struct ubcore_device *dev, + enum ubcore_transport_mode mode, union ubcore_eid *local_eid, union ubcore_eid *peer_eid) +{ + struct ubcore_vtp *vtp_entry; + + switch (mode) { + case UBCORE_TP_RM: + vtp_entry = ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_RM_VTP], + ubcore_get_vtp_hash(local_eid), local_eid); + break; + case UBCORE_TP_RC: + vtp_entry = ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_RC_VTP], + ubcore_get_rc_vtp_hash(peer_eid), peer_eid); + break; + case UBCORE_TP_UM: + vtp_entry = ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_UM_VTP], + ubcore_get_vtp_hash(local_eid), local_eid); + break; + default: + ubcore_log_err("unknown mode"); + vtp_entry = NULL; + } + return vtp_entry; +} + void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, struct ubcore_tjetty_cfg *cfg, struct ubcore_vtp_param *vtp_param) { @@ -602,6 +715,8 @@ void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, } vtp_param->trans_mode = cfg->trans_mode; + vtp_param->sub_trans_mode = cfg->flag.bs.sub_trans_mode; + vtp_param->rc_share_tp = cfg->flag.bs.rc_share_tp; /* * RM/UM VTP for userspace app: get local eid from ucontext * RM/UM VTP for kernel app: how to get local eid ? @@ -610,7 +725,7 @@ void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, vtp_param->local_eid = dev->eid_table.eid_entries[cfg->eid_index].eid; vtp_param->peer_eid = cfg->id.eid; if (jetty != NULL) - vtp_param->local_jetty = jetty->id; + vtp_param->local_jetty = jetty->jetty_id.id; else vtp_param->local_jetty = 0; @@ -654,7 +769,7 @@ int ubcore_modify_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *vtp_pa return ret; } - vtp = ubcore_find_vtp(dev, vtp_param->trans_mode, + vtp = ubcore_find_get_vtp(dev, vtp_param->trans_mode, &vtp_param->local_eid, &vtp_param->peer_eid); if (vtp == NULL) { ubcore_log_err("Fail to find vtp when modify vtp"); @@ -662,6 +777,7 @@ int ubcore_modify_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *vtp_pa } ret = dev->ops->modify_vtp(vtp, vattr, vattr_mask); + ubcore_vtp_kref_put(vtp); if (ret != 0) { ubcore_log_err("Fail to modify vtp when call ubcore ops"); return -EINVAL; @@ -680,20 +796,20 @@ struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ub if (dev->ops == NULL || dev->ops->create_vtp == NULL) return NULL; - vtp = ubcore_find_vtp(dev, cfg->trans_mode, &cfg->local_eid, &cfg->peer_eid); + vtp = ubcore_find_get_vtp(dev, cfg->trans_mode, &cfg->local_eid, &cfg->peer_eid); if (vtp != NULL) { ubcore_log_info("vtp already exists"); if (vtp->cfg.vtpn == UINT_MAX) { // only this may happen vtp_role = (role == vtp->role) ? role : UBCORE_VTP_DUPLEX; // delete original vtp - ubcore_log_info("vtpn is UINT_MAX, delete old one"); ubcore_remove_vtp(dev, cfg->trans_mode, vtp); - kfree(vtp); + ubcore_vtp_kref_put(vtp); } else { // this should never happen if (cfg->vtpn != UINT_MAX) { ubcore_log_warn("origin vtpn is not UINT_MAX, input vtpn is not UINT_MAX"); return vtp; } + ubcore_vtp_kref_put(vtp); ubcore_log_warn("origin vtpn is not UINT_MAX, input vtpn is UINT_MAX"); return NULL; } @@ -704,16 +820,15 @@ struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ub ubcore_log_err("Failed to create vtp"); return NULL; } - + kref_init(&vtp->ref_cnt); vtp->ub_dev = dev; vtp->role = vtp_role; ret = ubcore_find_add_vtp(dev, cfg->trans_mode, vtp); if (ret != 0) { - (void)dev->ops->destroy_vtp(vtp); - vtp = NULL; + ubcore_vtp_kref_put(vtp); ubcore_log_err("Failed to add vtp to the vtp table"); - return vtp; + return NULL; } if (cfg->flag.bs.clan_tp) { @@ -734,7 +849,7 @@ struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, struct ubcore_vtp *vtp = NULL; int ret; - vtp = ubcore_find_vtp(dev, cfg->trans_mode, &cfg->local_eid, &cfg->peer_eid); + vtp = ubcore_find_get_vtp(dev, cfg->trans_mode, &cfg->local_eid, &cfg->peer_eid); if (vtp != NULL) return vtp; @@ -745,13 +860,13 @@ struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, vtp->ub_dev = dev; (void)memcpy(&vtp->cfg, cfg, sizeof(struct ubcore_vtp_cfg)); vtp->role = role; + kref_init(&vtp->ref_cnt); ret = ubcore_find_add_vtp(dev, cfg->trans_mode, vtp); if (ret != 0) { - kfree(vtp); - vtp = NULL; + ubcore_vtp_kref_put(vtp); ubcore_log_err("Failed to add vtp to the vtp table"); - return vtp; + return NULL; } return vtp; @@ -787,6 +902,9 @@ struct ubcore_vtp **ubcore_get_all_vtp(struct ubcore_hash_table *ht, uint32_t i = 0, j = 0; *dev_vtp_cnt = ubcore_get_all_vtp_cnt(ht); + if (*dev_vtp_cnt == 0) + return NULL; + vtp_entry = kcalloc(1, (*dev_vtp_cnt) * (uint32_t)sizeof(struct ubcore_vtp *), GFP_KERNEL); if (vtp_entry == NULL) return NULL; @@ -794,6 +912,7 @@ struct ubcore_vtp **ubcore_get_all_vtp(struct ubcore_hash_table *ht, spin_lock(&ht->lock); if (ht->head == NULL) { spin_unlock(&ht->lock); + kfree(vtp_entry); return NULL; } diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.h b/drivers/ub/urma/ubcore/ubcore_vtp.h index 947068153341..a002313866ce 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.h +++ b/drivers/ub/urma/ubcore/ubcore_vtp.h @@ -33,6 +33,8 @@ struct ubcore_vtp_param { enum ubcore_transport_mode trans_mode; + uint32_t sub_trans_mode; + uint32_t rc_share_tp; /* vtpn key start */ union ubcore_eid local_eid; union ubcore_eid peer_eid; @@ -47,6 +49,8 @@ struct ubcore_vtp_param { struct ubcore_create_vtp_req { uint32_t vtpn; enum ubcore_transport_mode trans_mode; + uint32_t sub_trans_mode; + uint32_t rc_share_tp; union ubcore_eid local_eid; union ubcore_eid peer_eid; uint32_t eid_index; @@ -63,14 +67,12 @@ struct ubcore_create_vtp_req { }; struct ubcore_create_vtp_resp { - enum ubcore_msg_resp_status ret; + int ret; uint32_t vtpn; - uint32_t udrv_out_len; - uint8_t udrv_out_data[0]; }; struct ubcore_destroy_vtp_resp { - enum ubcore_msg_resp_status ret; + int ret; }; /* map vtpn to tpg, tp, utp or ctp */ @@ -100,9 +102,9 @@ struct ubcore_migrate_vtp_req { struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *param); -int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn); +int ubcore_disconnect_vtp(struct ubcore_vtpn *vtpn, struct ubcore_vtp_param *param); /* map vtp to tpg, utp .... */ -struct ubcore_vtp *ubcore_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg); +struct ubcore_vtp *ubcore_create_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg); struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg, uint32_t role); struct ubcore_vtp *ubcore_check_and_map_target_vtp(struct ubcore_device *dev, @@ -112,6 +114,8 @@ int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role); /* find mapped vtp */ struct ubcore_vtp *ubcore_find_vtp(struct ubcore_device *dev, enum ubcore_transport_mode mode, union ubcore_eid *local_eid, union ubcore_eid *peer_eid); +struct ubcore_vtp *ubcore_find_get_vtp(struct ubcore_device *dev, + enum ubcore_transport_mode mode, union ubcore_eid *local_eid, union ubcore_eid *peer_eid); void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, struct ubcore_tjetty_cfg *cfg, struct ubcore_vtp_param *vtp_param); @@ -126,5 +130,7 @@ uint32_t ubcore_get_all_vtp_cnt(struct ubcore_hash_table *ht); struct ubcore_vtp **ubcore_get_all_vtp(struct ubcore_hash_table *ht, uint32_t *dev_vtp_cnt); +void ubcore_vtp_get(void *obj); void ubcore_vtpn_get(void *obj); +void ubcore_vtp_kref_put(struct ubcore_vtp *vtp); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.c b/drivers/ub/urma/ubcore/ubcore_workqueue.c index 001bdb2af5bc..71ca0b577517 100644 --- a/drivers/ub/urma/ubcore/ubcore_workqueue.c +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.c @@ -44,8 +44,7 @@ void ubcore_flush_workqueue(int queue_type) int ubcore_alloc_workqueue(int queue_type) { if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] != NULL) { - ubcore_log_err("queue_type %d out of range or workqueue already exist\n", - queue_type); + ubcore_log_err("queue_type %d out of range or already exist\n", queue_type); return -EINVAL; } g_ubcore_workqueues[queue_type] = diff --git a/drivers/ub/urma/uburma/uburma_cmd.c b/drivers/ub/urma/uburma/uburma_cmd.c index 5912f5a99187..52c51f229484 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.c +++ b/drivers/ub/urma/uburma/uburma_cmd.c @@ -78,7 +78,7 @@ static int uburma_cmd_create_ctx(struct ubcore_device *ubc_dev, struct uburma_fi (struct ubcore_udrv_priv *)(void *)&arg.udata); if (IS_ERR_OR_NULL(ucontext)) { mutex_unlock(&file->mutex); - return -EPERM; + return PTR_ERR(ucontext); } ucontext->eid = eid; uobj = uobj_alloc(UOBJ_CLASS_JFAE, file); @@ -111,22 +111,6 @@ static int uburma_cmd_create_ctx(struct ubcore_device *ubc_dev, struct uburma_fi return ret; } -static int uburma_cmd_destroy_ctx(struct ubcore_device *ubc_dev, struct uburma_file *file, - struct uburma_cmd_hdr *hdr) -{ - mutex_lock(&file->mutex); - if (file->ucontext == NULL) { - mutex_unlock(&file->mutex); - return -EINVAL; - } - uburma_cleanup_uobjs(file, UBURMA_REMOVE_CLOSE); - ubcore_free_ucontext(ubc_dev, file->ucontext); - file->ucontext = NULL; - uburma_log_info("uburma destroy context success.\n"); - mutex_unlock(&file->mutex); - return 0; -} - static void uburma_fill_attr(struct ubcore_seg_cfg *cfg, struct uburma_cmd_register_seg *arg) { cfg->va = arg->in.va; @@ -161,7 +145,7 @@ static int uburma_cmd_alloc_token_id(struct ubcore_device *ubc_dev, struct uburm token_id = ubcore_alloc_token_id(ubc_dev, &udata); if (IS_ERR_OR_NULL(token_id)) { uburma_log_err("ubcore alloc token_id id failed.\n"); - ret = -EPERM; + ret = PTR_ERR(token_id); goto err_free_uobj; } uobj->object = token_id; @@ -210,6 +194,8 @@ static int uburma_cmd_free_token_id(struct ubcore_device *ubc_dev, struct uburma ret = uobj_remove_commit(uobj); if (ret != 0) uburma_log_err("ubcore remove commit token_id failed.\n"); + + uobj_put_del(uobj); return ret; } @@ -247,7 +233,7 @@ static int uburma_cmd_register_seg(struct ubcore_device *ubc_dev, struct uburma_ seg = ubcore_register_seg(ubc_dev, &cfg, &udata); if (IS_ERR_OR_NULL(seg)) { uburma_log_err("ubcore_register_seg failed.\n"); - ret = -EPERM; + ret = PTR_ERR(seg); goto err_free_uobj; } uobj->object = seg; @@ -294,6 +280,8 @@ static int uburma_cmd_unregister_seg(struct ubcore_device *ubc_dev, struct uburm ret = uobj_remove_commit(uobj); if (ret != 0) uburma_log_err("ubcore_unregister_seg failed.\n"); + + uobj_put_del(uobj); return ret; } @@ -422,7 +410,7 @@ static int uburma_cmd_create_jfs(struct ubcore_device *ubc_dev, jfs = ubcore_create_jfs(ubc_dev, &cfg, uburma_jfs_event_cb, &udata); if (IS_ERR_OR_NULL(jfs)) { uburma_log_err("create jfs or get jfs_id failed.\n"); - ret = -EPERM; + ret = PTR_ERR(jfs); goto err_put_jfc; } jfs_uobj->uobj.object = jfs; @@ -433,7 +421,7 @@ static int uburma_cmd_create_jfs(struct ubcore_device *ubc_dev, if (ret != 0) goto err_delete_jfs; - arg.out.id = jfs->id; + arg.out.id = jfs->jfs_id.id; arg.out.depth = jfs->jfs_cfg.depth; arg.out.max_sge = jfs->jfs_cfg.max_sge; arg.out.max_rsge = jfs->jfs_cfg.max_rsge; @@ -514,8 +502,8 @@ static int uburma_cmd_query_jfs(struct ubcore_device *ubc_dev, if (ret != 0) return ret; - uobj = uobj_get_write(UOBJ_CLASS_JFS, arg.in.handle, file); - if (IS_ERR(uobj)) { + uobj = uobj_get_read(UOBJ_CLASS_JFS, arg.in.handle, file); + if (IS_ERR_OR_NULL(uobj)) { uburma_log_err("failed to find jfs.\n"); return -EINVAL; } @@ -523,7 +511,7 @@ static int uburma_cmd_query_jfs(struct ubcore_device *ubc_dev, jfs = (struct ubcore_jfs *)uobj->object; ret = ubcore_query_jfs(jfs, &cfg, &attr); if (ret != 0) { - uobj_put_write(uobj); + uobj_put_read(uobj); uburma_log_err("query jfs failed, ret:%d.\n", ret); return ret; } @@ -541,7 +529,7 @@ static int uburma_cmd_query_jfs(struct ubcore_device *ubc_dev, ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_query_jfs)); - uobj_put_write(uobj); + uobj_put_read(uobj); return ret; } @@ -572,11 +560,13 @@ static int uburma_cmd_delete_jfs(struct ubcore_device *ubc_dev, if (ret != 0) { uburma_log_err("delete jfs failed, ret:%d.\n", ret); uobj_put(uobj); + uobj_put_del(uobj); return ret; } arg.out.async_events_reported = jfs_uobj->async_events_reported; uobj_put(uobj); + uobj_put_del(uobj); return uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_delete_jfs)); } @@ -613,7 +603,7 @@ static int uburma_cmd_import_seg(struct ubcore_device *ubc_dev, if (IS_ERR_OR_NULL(tseg)) { uburma_log_err("import seg failed.\n"); uobj_alloc_abort(uobj); - return -EPERM; + return PTR_ERR(tseg); } uobj->object = tseg; @@ -651,6 +641,7 @@ static int uburma_cmd_unimport_seg(struct ubcore_device *ubc_dev, if (ret != 0) uburma_log_err("unimport seg failed.\n"); + uobj_put_del(uobj); return ret; } @@ -700,7 +691,7 @@ static int uburma_cmd_create_jfr(struct ubcore_device *ubc_dev, jfr = ubcore_create_jfr(ubc_dev, &cfg, uburma_jfr_event_cb, &udata); if (IS_ERR_OR_NULL(jfr)) { uburma_log_err("create jfr or get jfr_id failed.\n"); - ret = -EPERM; + ret = PTR_ERR(jfr); goto err_put_jfc; } jfr_uobj->uobj.object = jfr; @@ -711,7 +702,7 @@ static int uburma_cmd_create_jfr(struct ubcore_device *ubc_dev, if (ret != 0) goto err_delete_jfr; - arg.out.id = jfr->id; + arg.out.id = jfr->jfr_id.id; arg.out.depth = jfr->jfr_cfg.depth; arg.out.max_sge = jfr->jfr_cfg.max_sge; arg.out.handle = jfr_uobj->uobj.id; @@ -791,8 +782,8 @@ static int uburma_cmd_query_jfr(struct ubcore_device *ubc_dev, if (ret != 0) return ret; - uobj = uobj_get_write(UOBJ_CLASS_JFR, arg.in.handle, file); - if (IS_ERR(uobj)) { + uobj = uobj_get_read(UOBJ_CLASS_JFR, arg.in.handle, file); + if (IS_ERR_OR_NULL(uobj)) { uburma_log_err("failed to find jfr.\n"); return -EINVAL; } @@ -800,7 +791,7 @@ static int uburma_cmd_query_jfr(struct ubcore_device *ubc_dev, jfr = (struct ubcore_jfr *)uobj->object; ret = ubcore_query_jfr(jfr, &cfg, &attr); if (ret != 0) { - uobj_put_write(uobj); + uobj_put_read(uobj); uburma_log_err("query jfr failed, ret:%d.\n", ret); return ret; } @@ -818,7 +809,7 @@ static int uburma_cmd_query_jfr(struct ubcore_device *ubc_dev, ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct unurma_cmd_query_jfr)); - uobj_put_write(uobj); + uobj_put_read(uobj); return ret; } @@ -849,11 +840,13 @@ static int uburma_cmd_delete_jfr(struct ubcore_device *ubc_dev, if (ret != 0) { uburma_log_err("delete jfr failed, ret:%d.\n", ret); uobj_put(uobj); + uobj_put_del(uobj); return ret; } arg.out.async_events_reported = jfr_uobj->async_events_reported; uobj_put(uobj); + uobj_put_del(uobj); return uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_delete_jfr)); } @@ -902,7 +895,7 @@ static int uburma_cmd_create_jfc(struct ubcore_device *ubc_dev, jfc = ubcore_create_jfc(ubc_dev, &cfg, uburma_jfce_handler, uburma_jfc_event_cb, &udata); if (IS_ERR_OR_NULL(jfc)) { uburma_log_err("create jfc or get jfc_id failed.\n"); - ret = -EPERM; + ret = PTR_ERR(jfc); goto err_alloc_abort; } @@ -1005,12 +998,14 @@ static int uburma_cmd_delete_jfc(struct ubcore_device *ubc_dev, if (ret != 0) { uburma_log_err("delete jfc failed, ret:%d.\n", ret); uobj_put(uobj); + uobj_put_del(uobj); return ret; } arg.out.comp_events_reported = jfc_uobj->comp_events_reported; arg.out.async_events_reported = jfc_uobj->async_events_reported; uobj_put(uobj); + uobj_put_del(uobj); return uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_delete_jfc)); } @@ -1040,7 +1035,7 @@ static void fill_create_jetty_attr(struct ubcore_jetty_cfg *cfg, static void fill_create_jetty_out(struct uburma_cmd_create_jetty *arg, struct ubcore_jetty *jetty) { - arg->out.id = jetty->id; + arg->out.id = jetty->jetty_id.id; arg->out.jfs_depth = jetty->jetty_cfg.jfs_depth; arg->out.jfr_depth = jetty->jetty_cfg.jfr_depth; arg->out.max_send_sge = jetty->jetty_cfg.max_send_sge; @@ -1115,7 +1110,7 @@ static int uburma_cmd_create_jetty(struct ubcore_device *ubc_dev, jetty = ubcore_create_jetty(ubc_dev, &cfg, uburma_jetty_event_cb, &udata); if (IS_ERR_OR_NULL(jetty)) { uburma_log_err("create jetty or get jetty_id failed.\n"); - ret = -EPERM; + ret = PTR_ERR(jetty); goto err_put; } @@ -1215,8 +1210,8 @@ static int uburma_cmd_query_jetty(struct ubcore_device *ubc_dev, if (ret != 0) return ret; - uobj = uobj_get_write(UOBJ_CLASS_JETTY, arg.in.handle, file); - if (IS_ERR(uobj)) { + uobj = uobj_get_read(UOBJ_CLASS_JETTY, arg.in.handle, file); + if (IS_ERR_OR_NULL(uobj)) { uburma_log_err("failed to find jetty.\n"); return -EINVAL; } @@ -1224,7 +1219,7 @@ static int uburma_cmd_query_jetty(struct ubcore_device *ubc_dev, jetty = (struct ubcore_jetty *)uobj->object; ret = ubcore_query_jetty(jetty, &cfg, &attr); if (ret != 0) { - uobj_put_write(uobj); + uobj_put_read(uobj); uburma_log_err("query jetty failed, ret:%d.\n", ret); return ret; } @@ -1255,7 +1250,7 @@ static int uburma_cmd_query_jetty(struct ubcore_device *ubc_dev, arg.out.state = (uint32_t)attr.state; ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_query_jetty)); - uobj_put_write(uobj); + uobj_put_read(uobj); return ret; } @@ -1286,11 +1281,13 @@ static int uburma_cmd_delete_jetty(struct ubcore_device *ubc_dev, if (ret != 0) { uburma_log_err("delete jetty failed, ret:%d.\n", ret); uobj_put(uobj); + uobj_put_del(uobj); return ret; } arg.out.async_events_reported = jetty_uobj->async_events_reported; uobj_put(uobj); + uobj_put_del(uobj); return uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_delete_jetty)); } @@ -1350,6 +1347,7 @@ static int uburma_cmd_import_jfr(struct ubcore_device *ubc_dev, (void)memcpy(cfg.id.eid.raw, arg.in.eid, UBCORE_EID_SIZE); cfg.id.id = arg.in.id; + cfg.flag.value = arg.in.flag; cfg.token_value.token = arg.in.token; cfg.trans_mode = arg.in.trans_mode; cfg.eid_index = file->ucontext->eid_index; @@ -1359,7 +1357,7 @@ static int uburma_cmd_import_jfr(struct ubcore_device *ubc_dev, if (IS_ERR_OR_NULL(tjfr)) { uburma_log_err("ubcore_import_jfr failed.\n"); uobj_alloc_abort(uobj); - return -EPERM; + return PTR_ERR(tjfr); } uobj->object = tjfr; @@ -1402,6 +1400,8 @@ static int uburma_cmd_unimport_jfr(struct ubcore_device *ubc_dev, ret = uobj_remove_commit(uobj); if (ret != 0) uburma_log_err("ubcore_unimport_jfr failed.\n"); + + uobj_put_del(uobj); return ret; } @@ -1430,6 +1430,7 @@ static int uburma_cmd_import_jetty(struct ubcore_device *ubc_dev, cfg.id.id = arg.in.id; cfg.token_value.token = arg.in.token; cfg.trans_mode = (enum ubcore_transport_mode)arg.in.trans_mode; + cfg.flag.value = arg.in.flag; cfg.policy = (enum ubcore_jetty_grp_policy)arg.in.policy; cfg.type = (enum ubcore_target_type)arg.in.type; cfg.eid_index = file->ucontext->eid_index; @@ -1439,7 +1440,7 @@ static int uburma_cmd_import_jetty(struct ubcore_device *ubc_dev, if (IS_ERR_OR_NULL(tjetty)) { uburma_log_err("ubcore_import_jetty failed.\n"); uobj_alloc_abort(uobj); - return -EPERM; + return PTR_ERR(tjetty); } uobj->object = tjetty; @@ -1482,6 +1483,8 @@ static int uburma_cmd_unimport_jetty(struct ubcore_device *ubc_dev, ret = uobj_remove_commit(uobj); if (ret != 0) uburma_log_err("ubcore_unimport_jetty failed.\n"); + + uobj_put_del(uobj); return ret; } @@ -1734,6 +1737,8 @@ static int uburma_cmd_create_jetty_grp(struct ubcore_device *ubc_dev, return ret; (void)memcpy(cfg.name, arg.in.name, UBCORE_JETTY_GRP_MAX_NAME); + cfg.name[UBCORE_JETTY_GRP_MAX_NAME - 1] = '\0'; + cfg.token_value.token = arg.in.token; cfg.id = arg.in.id; cfg.policy = (enum ubcore_jetty_grp_policy)arg.in.policy; @@ -1753,7 +1758,7 @@ static int uburma_cmd_create_jetty_grp(struct ubcore_device *ubc_dev, jetty_grp = ubcore_create_jetty_grp(ubc_dev, &cfg, uburma_jetty_grp_event_cb, &udata); if (IS_ERR_OR_NULL(jetty_grp)) { uburma_log_err("create jetty_grp failed.\n"); - ret = -EPERM; + ret = PTR_ERR(jetty_grp); goto err_alloc_abort; } jetty_grp_uobj->uobj.object = jetty_grp; @@ -1764,7 +1769,7 @@ static int uburma_cmd_create_jetty_grp(struct ubcore_device *ubc_dev, if (ret != 0) goto err_delete_jetty_grp; - arg.out.id = jetty_grp->id; + arg.out.id = jetty_grp->jetty_grp_id.id; arg.out.handle = jetty_grp_uobj->uobj.id; ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, @@ -1810,11 +1815,13 @@ static int uburma_cmd_delete_jetty_grp(struct ubcore_device *ubc_dev, if (ret != 0) { uburma_log_err("delete jfr failed, ret:%d.\n", ret); uobj_put(uobj); + uobj_put_del(uobj); return ret; } arg.out.async_events_reported = jetty_grp_uobj->async_events_reported; uobj_put(uobj); + uobj_put_del(uobj); return uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_delete_jetty_grp)); } @@ -1872,7 +1879,6 @@ typedef int (*uburma_cmd_handler)(struct ubcore_device *ubc_dev, static uburma_cmd_handler g_uburma_cmd_handlers[] = { [0] = NULL, [UBURMA_CMD_CREATE_CTX] = uburma_cmd_create_ctx, - [UBURMA_CMD_DESTROY_CTX] = uburma_cmd_destroy_ctx, [UBURMA_CMD_ALLOC_TOKEN_ID] = uburma_cmd_alloc_token_id, [UBURMA_CMD_FREE_TOKEN_ID] = uburma_cmd_free_token_id, [UBURMA_CMD_REGISTER_SEG] = uburma_cmd_register_seg, @@ -1924,18 +1930,23 @@ static int uburma_cmd_parse(struct ubcore_device *ubc_dev, struct uburma_file *f long uburma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct uburma_cmd_hdr *user_hdr = (struct uburma_cmd_hdr *)arg; - struct uburma_file *file = filp->private_data; - struct uburma_device *ubu_dev = file->ubu_dev; + struct uburma_device *ubu_dev; struct ubcore_device *ubc_dev; struct uburma_cmd_hdr hdr; + struct uburma_file *file; int srcu_idx; long ret; - if (ubu_dev == NULL || file == NULL) { + if (filp == NULL || filp->private_data == NULL) { + uburma_log_err("invalid param"); + return -EINVAL; + } + file = filp->private_data; + ubu_dev = file->ubu_dev; + if (ubu_dev == NULL) { uburma_log_err("invalid param"); return -EINVAL; } - uburma_cmd_inc(ubu_dev); srcu_idx = srcu_read_lock(&ubu_dev->ubc_dev_srcu); ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); diff --git a/drivers/ub/urma/uburma/uburma_cmd.h b/drivers/ub/urma/uburma/uburma_cmd.h index 903354c8e731..32e1a4783fbf 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.h +++ b/drivers/ub/urma/uburma/uburma_cmd.h @@ -39,7 +39,6 @@ struct uburma_cmd_hdr { enum uburma_cmd { UBURMA_CMD_CREATE_CTX = 1, - UBURMA_CMD_DESTROY_CTX, UBURMA_CMD_ALLOC_TOKEN_ID, UBURMA_CMD_FREE_TOKEN_ID, UBURMA_CMD_REGISTER_SEG, @@ -325,6 +324,7 @@ struct uburma_cmd_import_jfr { /* correspond to urma_jfr_id */ uint8_t eid[UBCORE_EID_SIZE]; uint32_t id; + uint32_t flag; /* correspond to urma_token_t */ uint32_t token; uint32_t trans_mode; diff --git a/drivers/ub/urma/uburma/uburma_event.c b/drivers/ub/urma/uburma/uburma_event.c index 3ea0a0b0510e..f01d1bcdf3c6 100644 --- a/drivers/ub/urma/uburma/uburma_event.c +++ b/drivers/ub/urma/uburma/uburma_event.c @@ -86,6 +86,8 @@ void uburma_write_event(struct uburma_jfe *jfe, uint64_t event_data, uint32_t ev list_add_tail(&event->node, &jfe->event_list); if (obj_event_list) list_add_tail(&event->obj_node, obj_event_list); + if (jfe->async_queue) + kill_fasync(&jfe->async_queue, SIGIO, POLL_IN); spin_unlock_irqrestore(&jfe->lock, flags); wake_up_interruptible(&jfe->poll_wait); } @@ -133,7 +135,10 @@ static int uburma_delete_jfce(struct inode *inode, struct file *filp) return 0; ufile = uobj->ufile; - mutex_lock(&ufile->mutex); + /* If the deletion fails, the user process exits and cleans up the jfce uobj. */ + if (mutex_trylock(&ufile->mutex) == 0) + return -ENOLCK; + uobj_get(uobj); /* will call uburma_hot_unplug_jfce if clean up is not going on */ uburma_close_uobj_fd(filp); @@ -326,11 +331,26 @@ static long uburma_jfce_ioctl(struct file *filp, unsigned int cmd, unsigned long return (long)ret; } +static int uburma_jfce_fasync(int fd, struct file *filp, int on) +{ + int ret; + struct uburma_uobj *uobj = filp->private_data; + struct uburma_jfce_uobj *jfce = container_of(uobj, struct uburma_jfce_uobj, uobj); + + if (uobj == NULL) + return -EINVAL; + spin_lock_irq(&jfce->jfe.lock); + ret = fasync_helper(fd, filp, on, &jfce->jfe.async_queue); + spin_unlock_irq(&jfce->jfe.lock); + return ret; +} + const struct file_operations uburma_jfce_fops = { .owner = THIS_MODULE, .poll = uburma_jfce_poll, .release = uburma_delete_jfce, .unlocked_ioctl = uburma_jfce_ioctl, + .fasync = uburma_jfce_fasync, }; void uburma_init_jfe(struct uburma_jfe *jfe) @@ -338,6 +358,7 @@ void uburma_init_jfe(struct uburma_jfe *jfe) spin_lock_init(&jfe->lock); INIT_LIST_HEAD(&jfe->event_list); init_waitqueue_head(&jfe->poll_wait); + jfe->async_queue = NULL; } static int uburma_delete_jfae(struct inode *inode, struct file *filp) @@ -350,7 +371,10 @@ static int uburma_delete_jfae(struct inode *inode, struct file *filp) return 0; ufile = uobj->ufile; - mutex_lock(&ufile->mutex); + /* If the deletion fails, the user process exits and cleans up the jfae uobj. */ + if (mutex_trylock(&ufile->mutex) == 0) + return -ENOLCK; + uobj_get(uobj); /* call uburma_hot_unplug_jfae when cleanup is not going on */ uburma_close_uobj_fd(filp); @@ -429,11 +453,26 @@ static long uburma_jfae_ioctl(struct file *filp, unsigned int cmd, unsigned long return (long)ret; } +static int uburma_jfae_fasync(int fd, struct file *filp, int on) +{ + int ret; + struct uburma_uobj *uobj = filp->private_data; + struct uburma_jfae_uobj *jfae = container_of(uobj, struct uburma_jfae_uobj, uobj); + + if (uobj == NULL) + return -EINVAL; + spin_lock_irq(&jfae->jfe.lock); + ret = fasync_helper(fd, filp, on, &jfae->jfe.async_queue); + spin_unlock_irq(&jfae->jfe.lock); + return ret; +} + const struct file_operations uburma_jfae_fops = { .owner = THIS_MODULE, .poll = uburma_jfae_poll, .release = uburma_delete_jfae, .unlocked_ioctl = uburma_jfae_ioctl, + .fasync = uburma_jfae_fasync, }; static void uburma_async_event_callback(struct ubcore_event *event, diff --git a/drivers/ub/urma/uburma/uburma_uobj.c b/drivers/ub/urma/uburma/uburma_uobj.c index 53db41018d0f..dfee43fc424c 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.c +++ b/drivers/ub/urma/uburma/uburma_uobj.c @@ -333,12 +333,12 @@ static void uobj_fd_alloc_commit(struct uburma_uobj *uobj) { struct file *filp = (struct file *)uobj->object; - fd_install(uobj->id, filp); - /* Do not set uobj->id = 0 as it may be read when remove uobj */ /* Get another reference as we export this to the fops */ uobj_get(uobj); + + fd_install(uobj->id, filp); } static void uobj_fd_alloc_abort(struct uburma_uobj *uobj) @@ -461,21 +461,16 @@ int __must_check uobj_remove_commit(struct uburma_uobj *uobj) struct uburma_file *ufile = uobj->ufile; int ret; - /* put the ref count we took at lookup_get */ - uobj_put(uobj); - down_read(&ufile->cleanup_rwsem); /* try Lock uobj for write with cleanup_rwsem locked */ ret = uobj_try_lock(uobj, true); if (ret) { - /* Do not rollback uobj_put here */ up_read(&ufile->cleanup_rwsem); uburma_log_warn("Failed to lock uobj\n"); return ret; } ret = uobj_remove_commit_internal(uobj, UBURMA_REMOVE_DESTROY); - up_read(&ufile->cleanup_rwsem); return ret; } diff --git a/drivers/ub/urma/uburma/uburma_uobj.h b/drivers/ub/urma/uburma/uburma_uobj.h index 919fc024fbdf..8397ff182b5d 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.h +++ b/drivers/ub/urma/uburma/uburma_uobj.h @@ -97,6 +97,7 @@ struct uburma_jfe { struct list_head event_list; wait_queue_head_t poll_wait; bool deleting; + struct fasync_struct *async_queue; }; struct uburma_jfce_uobj { @@ -226,6 +227,8 @@ static inline bool uobj_type_is_fd(const struct uburma_uobj *uobj) #define uobj_get_del(class_id, _id, ufile) \ uobj_lookup_get(uobj_get_type(class_id), ufile, _id, UOBJ_ACCESS_NOLOCK) +#define uobj_put_del(uobj) uobj_put(uobj) + extern const struct uobj_class_def uobj_class_UOBJ_CLASS_TOKEN; extern const struct uobj_class_def uobj_class_UOBJ_CLASS_SEG; extern const struct uobj_class_def uobj_class_UOBJ_CLASS_JFCE; diff --git a/include/urma/ubcore_api.h b/include/urma/ubcore_api.h index be632cb7f8b6..daa21e4441ac 100644 --- a/include/urma/ubcore_api.h +++ b/include/urma/ubcore_api.h @@ -56,26 +56,6 @@ struct ubcore_umem *ubcore_umem_get(struct ubcore_device *dev, uint64_t va, uint */ void ubcore_umem_release(struct ubcore_umem *umem); -/** - * Invoke create virtual tp on a PF device, called only by driver - * @param[in] dev: the ubcore device; - * @param[in] remote_eid: destination remote eid address of the tp to be created - * @param[in] trans_mode: transport mode of the tp to be created - * @param[in] udata: driver defined data - * @return: tp pointer on success, NULL on error - */ -struct ubcore_tp *ubcore_create_vtp(struct ubcore_device *dev, - union ubcore_eid *remote_eid, - enum ubcore_transport_mode trans_mode, - struct ubcore_udata *udata); - -/** - * Invoke destroy virtual tp from a PF device, called only by driver - * @param[in] tp: the tp to be destroyed - * @return: 0 on success, other value on error - */ -int ubcore_destroy_vtp(struct ubcore_tp *vtp); - /** * Invoke get mtu value, called only by driver * @param[in] mtu: specifies the MTU value of the NIC interface. @@ -136,7 +116,7 @@ void ubcore_put_port_netdev(struct ubcore_device *dev); * sip, mac, vlan, physical port list. * @return: 0 on success, other value on error */ -int ubcore_add_sip(struct ubcore_sip_info *sip); +int ubcore_add_sip(struct ubcore_sip_info *sip, uint32_t *sip_idx); /** * Invoke The management system calls ubcore interface through UVS to delete the sip information. diff --git a/include/urma/ubcore_jetty.h b/include/urma/ubcore_jetty.h new file mode 100644 index 000000000000..a1039d9c1b81 --- /dev/null +++ b/include/urma/ubcore_jetty.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore jetty find header file + * Author: Zhang jiayu + * Create: 2024-3-12 + * Note: + * History: 2024-3-12: Create file + */ + +#ifndef UBCORE_JETTY_H +#define UBCORE_JETTY_H + +#include "ubcore_types.h" + +/* The APIs below are deprecated, should not be called by driver or ubcore client */ +struct ubcore_jfc *ubcore_find_jfc(struct ubcore_device *dev, uint32_t jfc_id); + +struct ubcore_jfs *ubcore_find_jfs(struct ubcore_device *dev, uint32_t jfs_id); + +struct ubcore_jfr *ubcore_find_jfr(struct ubcore_device *dev, uint32_t jfr_id); + +struct ubcore_jetty *ubcore_find_jetty(struct ubcore_device *dev, uint32_t jetty_id); + +#endif diff --git a/include/urma/ubcore_types.h b/include/urma/ubcore_types.h index b816c553d4e7..ba085f55fb7c 100644 --- a/include/urma/ubcore_types.h +++ b/include/urma/ubcore_types.h @@ -42,7 +42,7 @@ #define UBCORE_GET_VERSION(a, b) (((a) << 16) + ((b) > 65535 ? 65535 : (b))) #define UBCORE_API_VERSION ((0 << 16) + 9) // Current Version: 0.9 -#define UBCORE_MAX_JETTY_IN_JETTY_GRP 16U +#define UBCORE_MAX_JETTY_IN_JETTY_GRP 32U // 1650: 32 #define UBCORE_MAX_PORT_CNT 16 #define UBCORE_MAX_FE_CNT 1024 #define UBCORE_MAX_DEV_NAME 64 @@ -57,6 +57,7 @@ #define UBCORE_GUID_SIZE (16) #define UBCORE_MAX_MSG 4096 #define UBCORE_MAX_EID_CNT 1024 +#define UBCORE_MAX_VTP_CNT_PER_TPF (128 * 1024) // Temporarily specify the upper limit #define EID_FMT \ "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x" @@ -65,7 +66,6 @@ eid[7], eid[8], eid[9], eid[10], eid[11], eid[12], eid[13], eid[14], eid[15]) #define EID_ARGS(eid) EID_RAW_ARGS((eid).raw) -#define UBCORE_MAX_UPI_CNT 1000 #define UBCORE_OWN_FE_IDX (0xffff) #define UBCORE_JETTY_GRP_MAX_NAME 64 #define UBCORE_MAX_TP_CNT_IN_GRP 32 @@ -177,12 +177,16 @@ union ubcore_jfc_flag { uint32_t value; }; +#define UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE (0x1) + union ubcore_jfs_flag { struct { uint32_t lock_free : 1; uint32_t error_suspend : 1; uint32_t outorder_comp : 1; - uint32_t reserved : 29; + /* (0x1): UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE */ + uint32_t sub_trans_mode : 8; + uint32_t reserved : 21; } bs; uint32_t value; }; @@ -195,10 +199,12 @@ union ubcore_jfr_flag { * 3: UBCORE_TOKEN_ALL_ENCRYPTED * 4: UBCORE_TOKEN_RESERVED */ - uint32_t token_policy : 3; - uint32_t tag_matching : 1; - uint32_t lock_free : 1; - uint32_t reserved : 27; + uint32_t token_policy : 3; + uint32_t tag_matching : 1; + uint32_t lock_free : 1; + /* (0x1): UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE */ + uint32_t sub_trans_mode : 8; + uint32_t reserved : 19; } bs; uint32_t value; }; @@ -526,12 +532,26 @@ struct ubcore_port_attr { enum ubcore_mtu max_mtu; /* MTU_256, MTU_512, MTU_1024 */ }; +enum ubcore_pattern { + UBCORE_PATTERN_1 = 0, + UBCORE_PATTERN_3 +}; + +enum ubcore_sub_trans_mode_cap { + UBCORE_RC_TP_DST_ORDERING = 0x1, /* rc mode with tp dst ordering */ + UBCORE_RC_TA_DST_ORDERING = 0x1 << 1, /* rc mode with ta dst ordering  */ +}; + struct ubcore_device_cap { union ubcore_device_feat feature; uint32_t max_jfc; uint32_t max_jfs; uint32_t max_jfr; uint32_t max_jetty; + uint32_t max_tp_cnt; + uint32_t max_tpg_cnt; + /* max_vtp_cnt_per_fe * max_fe_cnt Equal to the number of VTPs on the entire card */ + uint32_t max_vtp_cnt_per_fe; uint32_t max_jetty_grp; uint32_t max_jetty_in_jetty_grp; uint32_t max_rc; /* max rc queues */ @@ -550,10 +570,11 @@ struct ubcore_device_cap { uint32_t max_dip_cnt_per_fe; uint32_t max_seid_cnt_per_fe; uint16_t trans_mode; /* one or more from ubcore_transport_mode_t */ + uint16_t sub_trans_mode_cap; /* one or more from ubcore_sub_trans_mode_cap */ uint16_t congestion_ctrl_alg; /* one or more mode from ubcore_congestion_ctrl_alg_t */ uint16_t ceq_cnt; /* completion vector count */ uint32_t max_tp_in_tpg; - uint32_t utp_cnt; + uint32_t max_utp_cnt; uint32_t max_oor_cnt; /* max OOR window size by packet */ uint32_t mn; uint32_t min_slice; /* 32K (1823), 64K (1650) */ @@ -578,6 +599,7 @@ struct ubcore_device_attr { uint8_t port_cnt; bool virtualization; /* In VM or not, must set by driver when register device */ bool tp_maintainer; /* device used to maintain TP resource */ + enum ubcore_pattern pattern; }; union ubcore_device_cfg_mask { @@ -648,22 +670,25 @@ enum ubcore_net_addr_type { UBCORE_NET_ADDR_TYPE_IPV6 }; +union ubcore_net_addr_union { + uint8_t raw[UBCORE_NET_ADDR_BYTES]; + struct { + uint64_t reserved1; + uint32_t reserved2; + uint32_t addr; + } in4; + struct { + uint64_t subnet_prefix; + uint64_t interface_id; + } in6; +}; + struct ubcore_net_addr { enum ubcore_net_addr_type type; - union { - uint8_t raw[UBCORE_NET_ADDR_BYTES]; - struct { - uint64_t reserved1; - uint32_t reserved2; - uint32_t addr; - } in4; - struct { - uint64_t subnet_prefix; - uint64_t interface_id; - } in6; - } net_addr; + union ubcore_net_addr_union net_addr; uint64_t vlan; /* available for UBOE */ uint8_t mac[UBCORE_MAC_BYTES]; /* available for UBOE */ + uint32_t prefix_len; }; union ubcore_tp_cfg_flag { @@ -690,7 +715,8 @@ union ubcore_tp_mod_flag { uint32_t cc_en : 1; /* congestion control algorithm, 0: disable 1: enable */ uint32_t cc_alg : 4; /* The value is ubcore_tp_cc_alg_t */ uint32_t spray_en : 1; /* spray with src udp port, 0: disable 1: enable */ - uint32_t reserved : 24; + uint32_t clan : 1; /* clan domain, 0: disable 1: enable */ + uint32_t reserved : 23; } bs; uint32_t value; }; @@ -708,7 +734,8 @@ union ubcore_tp_flag { uint32_t ack_resp : 1; uint32_t dca_enable : 1; /* dynamic connection, 0: disable 1: enable */ uint32_t bonding : 1; - uint32_t reserved : 19; + uint32_t clan : 1; + uint32_t reserved : 18; } bs; uint32_t value; }; @@ -851,6 +878,8 @@ struct ubcore_tp { struct ubcore_tp_ext peer_ext; /* ubcore fill before modifying tp */ atomic_t use_cnt; struct hlist_node hnode; /* driver inaccessible */ + struct kref ref_cnt; + struct completion comp; void *priv; /* ubcore private data for tp management */ }; @@ -881,6 +910,9 @@ struct ubcore_tpg { struct ubcore_tp *tp_list[UBCORE_MAX_TP_CNT_IN_GRP]; // UBCORE_MAX_TP_CNT_IN_GRP=32 atomic_t use_cnt; struct hlist_node hnode; /* driver inaccessible */ + struct kref ref_cnt; + struct completion comp; + struct mutex mutex; }; struct ubcore_cc_entry { @@ -893,7 +925,8 @@ union ubcore_utp_cfg_flag { struct { uint32_t loopback : 1; uint32_t spray_en : 1; - uint32_t reserved : 30; + uint32_t clan : 1; + uint32_t reserved : 29; } bs; uint32_t value; }; @@ -918,6 +951,8 @@ struct ubcore_utp { struct ubcore_utp_cfg utp_cfg; /* filled by ubcore when createing utp. */ atomic_t use_cnt; struct hlist_node hnode; + struct kref ref_cnt; + struct completion comp; }; struct ubcore_ctp_cfg { @@ -931,6 +966,8 @@ struct ubcore_ctp { struct ubcore_ctp_cfg ctp_cfg; /* filled by ubcore when createing cp. */ atomic_t use_cnt; struct hlist_node hnode; + struct kref ref_cnt; + struct completion comp; }; enum ubcore_vtp_state { @@ -943,6 +980,8 @@ struct ubcore_vtpn { struct ubcore_device *ub_dev; /* ubcore private, inaccessible to driver */ enum ubcore_transport_mode trans_mode; + uint32_t sub_trans_mode; + uint32_t rc_share_tp; /* vtpn key start */ union ubcore_eid local_eid; union ubcore_eid peer_eid; @@ -991,6 +1030,10 @@ struct ubcore_vtp { struct ubcore_vtp_cfg cfg; /* driver fills */ struct hlist_node hnode; /* driver inaccessible */ uint32_t role; /* current side is initiator, target or duplex */ + uint32_t eid_idx; + uint32_t upi; + bool share_mode; + struct kref ref_cnt; }; struct ubcore_vtp_attr { @@ -1023,11 +1066,6 @@ enum ubcore_msg_opcode { UBCORE_MSG_MIG_VM_START }; -enum ubcore_pattern { - UBCORE_PATTERN_1 = 0, - UBCORE_PATTERN_3 -}; - struct ubcore_req { uint32_t msg_id; enum ubcore_msg_opcode opcode; @@ -1115,7 +1153,7 @@ struct ubcore_jfs { struct ubcore_device *ub_dev; struct ubcore_ucontext *uctx; struct ubcore_jfs_cfg jfs_cfg; - uint32_t id; /* allocted by driver */ + struct ubcore_jetty_id jfs_id; /* driver fill jfs_id->id */ ubcore_event_callback_t jfae_handler; uint64_t urma_jfs; /* user space jfs pointer */ struct hlist_node hnode; @@ -1140,21 +1178,28 @@ struct ubcore_jfr { struct ubcore_device *ub_dev; struct ubcore_ucontext *uctx; struct ubcore_jfr_cfg jfr_cfg; - uint32_t id; /* allocted by driver */ + struct ubcore_jetty_id jfr_id; /* driver fill jfr_id->id */ ubcore_event_callback_t jfae_handler; uint64_t urma_jfr; /* user space jfr pointer */ struct hlist_node hnode; atomic_t use_cnt; - struct ubcore_hash_table *tptable; /* Only for devices not natively supporting RM mode */ + /* Only for devices not natively supporting RM mode */ + struct ubcore_hash_table *tptable; }; union ubcore_jetty_flag { struct { - uint32_t share_jfr : 1; /* 0: URMA_NO_SHARE_JFR. 1: URMA_SHARE_JFR. */ + uint32_t share_jfr : 1; /* 0: URMA_NO_SHARE_JFR. 1: URMA_SHARE_JFR. */ uint32_t lock_free : 1; - uint32_t error_suspend : 1; - uint32_t outorder_comp : 1; - uint32_t reserved : 28; + uint32_t error_suspend : 1; + uint32_t outorder_comp : 1; + /* (0x1): UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE */ + uint32_t sub_trans_mode : 8; + /* (0x1): shared tp; (0x0): non_shared tp. + * When rc mode is not ta dst ordering, this flag can only be set to 0. + */ + uint32_t rc_share_tp : 1; + uint32_t reserved : 19; } bs; uint32_t value; }; @@ -1178,14 +1223,17 @@ struct ubcore_jetty_cfg { struct ubcore_jfc *send_jfc; struct ubcore_jfc *recv_jfc; /* must set */ struct ubcore_jfr *jfr; /* must set, shared jfr */ - struct ubcore_jetty_group *jetty_grp; /* [Optional] user specified jetty group */ + struct ubcore_jetty_group *jetty_grp; /* [Optional] user specified jetty group */ void *jetty_context; }; union ubcore_import_jetty_flag { struct { uint32_t token_policy : 3; - uint32_t reserved : 29; + /* (0x1): UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE */ + uint32_t sub_trans_mode : 8; + uint32_t rc_share_tp : 1; + uint32_t reserved : 20; } bs; uint32_t value; }; @@ -1214,7 +1262,7 @@ struct ubcore_jetty { struct ubcore_device *ub_dev; struct ubcore_ucontext *uctx; struct ubcore_jetty_cfg jetty_cfg; - uint32_t id; /* allocted by driver */ + struct ubcore_jetty_id jetty_id; /* driver fill jetty_id->id */ struct ubcore_tjetty *remote_jetty; // bind to remote jetty ubcore_event_callback_t jfae_handler; uint64_t urma_jetty; /* user space jetty pointer */ @@ -1245,7 +1293,7 @@ struct ubcore_jetty_group { struct ubcore_device *ub_dev; struct ubcore_ucontext *uctx; struct ubcore_jetty_grp_cfg jetty_grp_cfg; - uint32_t id; /* allocated by driver */ + struct ubcore_jetty_id jetty_grp_id; /* driver fill jetty_grp_id->id */ uint32_t jetty_cnt; /* current jetty cnt in the jetty group */ struct ubcore_jetty **jetty; ubcore_event_callback_t jfae_handler; @@ -1254,8 +1302,7 @@ struct ubcore_jetty_group { }; enum ubcore_res_key_type { - UBCORE_RES_KEY_UPI = 1, // key id: UPI ID - UBCORE_RES_KEY_VTP, // key id: VTPN + UBCORE_RES_KEY_VTP = 1, // key id: VTPN UBCORE_RES_KEY_TP, // key id: TPN UBCORE_RES_KEY_TPG, // key id: TPGN UBCORE_RES_KEY_UTP, // key id: UTP ID @@ -1266,7 +1313,8 @@ enum ubcore_res_key_type { UBCORE_RES_KEY_JFC, // key id: JFC ID UBCORE_RES_KEY_RC, // key id: RC ID UBCORE_RES_KEY_SEG, // key id: TOKEN ID - UBCORE_RES_KEY_URMA_DEV // key id: EID + UBCORE_RES_KEY_DEV_TA, // key id: EID + UBCORE_RES_KEY_DEV_TP // key id: EID }; struct ubcore_res_upi_val { @@ -1371,29 +1419,26 @@ struct ubcore_res_seg_val { struct ubcore_seg_info *seg_list; }; -struct ubcore_res_dev_val { +struct ubcore_res_list_val { + uint32_t cnt; + uint32_t *list; +}; + +struct ubcore_res_dev_ta_val { uint32_t seg_cnt; - struct ubcore_seg_info *seg_list; // SEG token_id list uint32_t jfs_cnt; - uint32_t *jfs_list; // JFS ID list uint32_t jfr_cnt; - uint32_t *jfr_list; // JFR ID list uint32_t jfc_cnt; - uint32_t *jfc_list; // JFC ID list uint32_t jetty_cnt; - uint32_t *jetty_list; // Jetty ID list uint32_t jetty_group_cnt; - uint32_t *jetty_group_list; // Jetty group ID list uint32_t rc_cnt; - uint32_t *rc_list; +}; + +struct ubcore_res_dev_tp_val { uint32_t vtp_cnt; - uint32_t *vtp_list; uint32_t tp_cnt; - uint32_t *tp_list; // RC uint32_t tpg_cnt; - uint32_t *tpg_list; // RM uint32_t utp_cnt; - uint32_t *utp_list; // UM }; struct ubcore_res_key { @@ -2307,7 +2352,7 @@ enum ubcore_hash_table_type { UBCORE_HT_JFR, /* jfr hash table */ UBCORE_HT_JFC, /* jfc hash table */ UBCORE_HT_JETTY, /* jetty hash table */ - UBCORE_HT_TP, /* tp table */ + UBCORE_HT_TP, /* tp table for IB */ UBCORE_HT_TPG, /* tpg table */ UBCORE_HT_RM_VTP, /* rm vtp table */ UBCORE_HT_RC_VTP, /* rc vtp table */ @@ -2317,6 +2362,7 @@ enum ubcore_hash_table_type { UBCORE_HT_UM_VTPN, /* um vtpn table */ UBCORE_HT_UTP, /* utp table */ UBCORE_HT_CTP, /* ctp table */ + UBCORE_HT_UB_TP, /* tp table for UB */ UBCORE_HT_NUM }; @@ -2335,7 +2381,8 @@ struct ubcore_eid_table { struct ubcore_sip_table { struct mutex lock; - struct ubcore_sip_info *entry[UBCORE_SIP_TABLE_SIZE]; + uint32_t max_sip_cnt; + struct ubcore_sip_info *entry; DECLARE_BITMAP(index_bitmap, UBCORE_MAX_SIP); }; @@ -2345,16 +2392,9 @@ struct ubcore_port_kobj { uint8_t port_id; }; -struct ubcore_eid_kobj { - struct kobject kobj; - struct ubcore_logic_device *ldev; - uint32_t eid_idx; -}; - struct ubcore_logic_device { struct device *dev; struct ubcore_port_kobj port[UBCORE_MAX_PORT_CNT]; - struct ubcore_eid_kobj *eid; struct list_head node; /* add to ldev list */ possible_net_t net; struct ubcore_device *ub_dev; @@ -2436,11 +2476,11 @@ struct ubcore_umem { struct ubcore_sip_info { char dev_name[UBCORE_MAX_DEV_NAME]; struct ubcore_net_addr addr; - uint32_t prefix_len; uint8_t port_cnt; uint8_t port_id[UBCORE_MAX_PORT_CNT]; uint32_t mtu; char netdev_name[UBCORE_MAX_DEV_NAME]; /* for change mtu */ + bool is_active; }; union ubcore_global_cfg_mask { diff --git a/include/urma/ubcore_uapi.h b/include/urma/ubcore_uapi.h index 26feb893b55f..20e8a13bb315 100644 --- a/include/urma/ubcore_uapi.h +++ b/include/urma/ubcore_uapi.h @@ -105,7 +105,7 @@ int ubcore_config_device(struct ubcore_device *dev, struct ubcore_device_cfg *cf * set ctx data of a client * @param[in] dev: the ubcore_device handle; * @param[in] client: ubcore client pointer - * @param[in] data: client private data to be set + * @param[in] data (optional): client private data to be set * @return: 0 on success, other value on error */ void ubcore_set_client_ctx_data(struct ubcore_device *dev, struct ubcore_client *client, @@ -545,13 +545,4 @@ void ubcore_cgroup_uncharge(struct ubcore_cg_object *cg_obj, struct ubcore_devic enum ubcore_resource_type type); #endif // CONFIG_CGROUP_RDMA -/* The APIs below are deprecated, should not be called by driver or ubcore client */ -struct ubcore_jfc *ubcore_find_jfc(struct ubcore_device *dev, uint32_t jfc_id); - -struct ubcore_jfs *ubcore_find_jfs(struct ubcore_device *dev, uint32_t jfs_id); - -struct ubcore_jfr *ubcore_find_jfr(struct ubcore_device *dev, uint32_t jfr_id); - -struct ubcore_jetty *ubcore_find_jetty(struct ubcore_device *dev, uint32_t jetty_id); - #endif -- Gitee From 5d130e2cfa3d2aaee4d10e18c075f6c3750600c5 Mon Sep 17 00:00:00 2001 From: WenChen Date: Fri, 17 May 2024 20:20:42 +0800 Subject: [PATCH 4/6] urma: upload kernel patch for 20240511_mig driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I91DSN CVE: NA -------------------------------- Upload kernel patch for 20240511_mig, detailed fixes are as follows: 1. Fix double free subport entry 2. Fix urma admin incorrect log information or redundant commands 3. Support ubcore_umem_find_best_page_size 4. Add uvs connect timeout. 5. Fix the UAF bug when using tp 6. Fix the system reset bug Fixes: 329bf7f33128 ("ubcore: fix the bug of tp negotiation concurrency") Signed-off-by: WenChen Signed-off-by: Weibo Zhao --- drivers/ub/urma/ubcore/ubcore_cdev_file.c | 168 +++++- drivers/ub/urma/ubcore/ubcore_cgroup.c | 4 +- drivers/ub/urma/ubcore/ubcore_cmd.h | 3 +- drivers/ub/urma/ubcore/ubcore_device.c | 529 +++++++++---------- drivers/ub/urma/ubcore/ubcore_device.h | 3 +- drivers/ub/urma/ubcore/ubcore_genl.c | 6 - drivers/ub/urma/ubcore/ubcore_genl_admin.c | 132 +---- drivers/ub/urma/ubcore/ubcore_hash_table.c | 16 +- drivers/ub/urma/ubcore/ubcore_hash_table.h | 1 + drivers/ub/urma/ubcore/ubcore_jetty.c | 197 ++++++- drivers/ub/urma/ubcore/ubcore_main.c | 555 +++++++++++--------- drivers/ub/urma/ubcore/ubcore_main.h | 46 ++ drivers/ub/urma/ubcore/ubcore_msg.c | 102 +++- drivers/ub/urma/ubcore/ubcore_msg.h | 34 ++ drivers/ub/urma/ubcore/ubcore_netdev.c | 122 +++-- drivers/ub/urma/ubcore/ubcore_netdev.h | 8 +- drivers/ub/urma/ubcore/ubcore_netlink.c | 23 +- drivers/ub/urma/ubcore/ubcore_netlink.h | 4 +- drivers/ub/urma/ubcore/ubcore_priv.h | 27 +- drivers/ub/urma/ubcore/ubcore_segment.c | 72 ++- drivers/ub/urma/ubcore/ubcore_tp.c | 145 +++-- drivers/ub/urma/ubcore/ubcore_tp.h | 2 + drivers/ub/urma/ubcore/ubcore_tp_table.c | 55 +- drivers/ub/urma/ubcore/ubcore_tp_table.h | 6 + drivers/ub/urma/ubcore/ubcore_tpg.c | 106 ++-- drivers/ub/urma/ubcore/ubcore_tpg.h | 5 +- drivers/ub/urma/ubcore/ubcore_umem.c | 37 ++ drivers/ub/urma/ubcore/ubcore_utp.c | 103 ++-- drivers/ub/urma/ubcore/ubcore_utp.h | 5 +- drivers/ub/urma/ubcore/ubcore_uvs_cmd.c | 582 +++++++++++++++------ drivers/ub/urma/ubcore/ubcore_uvs_cmd.h | 72 ++- drivers/ub/urma/ubcore/ubcore_vtp.c | 104 ++-- drivers/ub/urma/ubcore/ubcore_workqueue.c | 51 +- drivers/ub/urma/ubcore/ubcore_workqueue.h | 15 +- drivers/ub/urma/uburma/Makefile | 3 +- drivers/ub/urma/uburma/uburma_cmd.c | 134 ++++- drivers/ub/urma/uburma/uburma_cmd.h | 116 +++- drivers/ub/urma/uburma/uburma_dev_ops.c | 16 + drivers/ub/urma/uburma/uburma_mmap.c | 160 ++++++ drivers/ub/urma/uburma/uburma_mmap.h | 33 ++ drivers/ub/urma/uburma/uburma_types.h | 8 + drivers/ub/urma/uburma/uburma_uobj.c | 4 + include/urma/ubcore_api.h | 13 + include/urma/ubcore_jetty.h | 12 + include/urma/ubcore_types.h | 144 ++++- include/urma/ubcore_uapi.h | 3 +- 46 files changed, 2749 insertions(+), 1237 deletions(-) create mode 100644 drivers/ub/urma/ubcore/ubcore_main.h create mode 100644 drivers/ub/urma/uburma/uburma_mmap.c create mode 100644 drivers/ub/urma/uburma/uburma_mmap.h diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.c b/drivers/ub/urma/ubcore/ubcore_cdev_file.c index 3da675553aed..45f736a7797c 100644 --- a/drivers/ub/urma/ubcore/ubcore_cdev_file.c +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.c @@ -26,9 +26,11 @@ #include "urma/ubcore_uapi.h" #include "ubcore_log.h" +#include "ubcore_device.h" #include "ubcore_cdev_file.h" #define UBCORE_MAX_VALUE_LEN 24 +#define UBCORE_READ_ONLY_MODE 0444 /* callback information */ typedef ssize_t (*ubcore_show_attr_cb)(struct ubcore_device *dev, @@ -404,6 +406,42 @@ static ssize_t max_tp_in_tpg_show(struct device *dev, struct device_attribute *a static DEVICE_ATTR_RO(max_tp_in_tpg); +static ssize_t max_oor_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_oor_cnt); +} + +static ssize_t max_oor_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_oor_cnt_show_cb); +} + +static DEVICE_ATTR_RO(max_oor_cnt); + +static ssize_t mn_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.mn); +} + +static ssize_t mn_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, mn_show_cb); +} + +static DEVICE_ATTR_RO(mn); + +static ssize_t max_netaddr_cnt_show_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.dev_cap.max_netaddr_cnt); +} + +static ssize_t max_netaddr_cnt_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, max_netaddr_cnt_show_cb); +} + +static DEVICE_ATTR_RO(max_netaddr_cnt); + static ssize_t port_count_show_cb(struct ubcore_device *dev, char *buf) { return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", dev->attr.port_cnt); @@ -437,6 +475,17 @@ static ssize_t fe_cnt_show(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR_RO(fe_cnt); +static ssize_t show_page_size_cap_cb(struct ubcore_device *dev, char *buf) +{ + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "0x%llx\n", dev->attr.dev_cap.page_size_cap); +} + +static ssize_t page_size_cap_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, show_page_size_cap_cb); +} +static DEVICE_ATTR_RO(page_size_cap); + static ssize_t show_dynamic_eid_cb(struct ubcore_device *dev, char *buf) { return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%d\n", dev->dynamic_eid); @@ -492,31 +541,31 @@ static DEVICE_ATTR_RO(driver_name); */ #define UBCORE_MAX_EID_LINE 51 -static ssize_t eid_show_cb(struct ubcore_device *dev, char *buf, struct net *net) +static ssize_t eid_show_cb(struct ubcore_device *dev, char *buf, struct net *net, uint32_t eid_idx) { + union ubcore_eid invalid_eid = {0}; struct ubcore_eid_entry *e; ssize_t len = 0; - uint32_t i; - - if (dev->eid_table.eid_entries == NULL) - return -EINVAL; spin_lock(&dev->eid_table.lock); - for (i = 0; i < dev->eid_table.eid_cnt; i++) { - e = &dev->eid_table.eid_entries[i]; - if (!e->valid || !net_eq(e->net, net)) - continue; - len += snprintf(buf + len, UBCORE_MAX_EID_LINE, - "%u "EID_FMT"\n", i, EID_ARGS(e->eid)); - if (len >= (ssize_t)(PAGE_SIZE - UBCORE_MAX_EID_LINE)) - break; + if (dev->eid_table.eid_entries == NULL || eid_idx > dev->eid_table.eid_cnt) { + spin_unlock(&dev->eid_table.lock); + return -EINVAL; } + + e = &dev->eid_table.eid_entries[eid_idx]; + if (!e->valid || !net_eq(e->net, net)) + len = snprintf(buf, UBCORE_MAX_EID_LINE, ""EID_FMT"\n", EID_ARGS(invalid_eid)); + else + len = snprintf(buf, UBCORE_MAX_EID_LINE, ""EID_FMT"\n", EID_ARGS(e->eid)); + spin_unlock(&dev->eid_table.lock); return len; } static ssize_t eid_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct ubcore_eid_attr *eid_attr = container_of(attr, struct ubcore_eid_attr, attr); struct ubcore_logic_device *ldev = dev_get_drvdata(dev); struct ubcore_device *ub_dev = get_ubcore_device(ldev); @@ -525,10 +574,8 @@ static ssize_t eid_show(struct device *dev, struct device_attribute *attr, char return -EINVAL; } - return eid_show_cb(ub_dev, buf, read_pnet(&ldev->net)); + return eid_show_cb(ub_dev, buf, read_pnet(&ldev->net), eid_attr->eid_idx); } -static DEVICE_ATTR_RO(eid); - static struct attribute *ubcore_dev_attrs[] = { &dev_attr_ubdev.attr, @@ -557,14 +604,17 @@ static struct attribute *ubcore_dev_attrs[] = { &dev_attr_ceq_cnt.attr, &dev_attr_utp_cnt.attr, &dev_attr_max_tp_in_tpg.attr, + &dev_attr_max_oor_cnt.attr, + &dev_attr_mn.attr, + &dev_attr_max_netaddr_cnt.attr, &dev_attr_port_count.attr, &dev_attr_fe_cnt.attr, + &dev_attr_page_size_cap.attr, &dev_attr_max_eid_cnt.attr, &dev_attr_dynamic_eid.attr, &dev_attr_virtualization.attr, &dev_attr_transport_type.attr, &dev_attr_driver_name.attr, - &dev_attr_eid.attr, NULL, }; @@ -744,14 +794,93 @@ int ubcore_create_port_attr_files(struct ubcore_logic_device *ldev, "port%hhu", port_id); } +static struct attribute_group *ubcore_alloc_eids_group(struct ubcore_logic_device *ldev) +{ + struct ubcore_eid_attr *eid_attr_list = NULL; + struct attribute_group *attr_grp = NULL; + struct attribute **attr_list = NULL; + uint32_t eid_cnt = 0; + uint32_t i; + + eid_cnt = ldev->ub_dev->eid_table.eid_cnt; + if (eid_cnt == 0 || eid_cnt > UBCORE_MAX_EID_CNT) + return NULL; + + attr_grp = kcalloc(1, sizeof(*attr_grp), GFP_KERNEL); + if (!attr_grp) + return NULL; + + attr_list = kcalloc(eid_cnt + 1, sizeof(*attr_list), GFP_KERNEL); + if (!attr_list) + goto free_grp; + + eid_attr_list = kcalloc(eid_cnt, sizeof(struct ubcore_eid_attr), GFP_KERNEL); + if (!eid_attr_list) + goto free_attr_list; + + // create /sys/class/dev_name/eids/eid_x + for (i = 0; i < eid_cnt; i++) { + struct ubcore_eid_attr *eid_attr = &eid_attr_list[i]; + + if (snprintf(eid_attr->name, UBCORE_EID_GROUP_NAME_LEN - 1, "eid%d", i) < 0) + goto free_eid_attr; + + sysfs_attr_init(&eid_attr->attr.attr); + eid_attr->attr.attr.name = eid_attr->name; + eid_attr->attr.attr.mode = UBCORE_READ_ONLY_MODE; + eid_attr->attr.show = eid_show; + eid_attr->eid_idx = i; + attr_list[i] = &eid_attr->attr.attr; + } + + attr_grp->name = "eids"; + attr_grp->attrs = attr_list; + return attr_grp; + +free_eid_attr: + kfree(eid_attr_list); +free_attr_list: + kfree(attr_list); +free_grp: + kfree(attr_grp); + return NULL; +} + +static void ubcore_free_eids_group(struct ubcore_logic_device *ldev) +{ + const struct attribute_group *eid_grp; + struct ubcore_eid_attr *eid_attr_list; + struct device_attribute *dev_attr; + + eid_grp = ldev->dev_group[UBCORE_ATTR_GROUP_EIDS]; + if (eid_grp) { + if (eid_grp->attrs && eid_grp->attrs[0]) { + dev_attr = container_of(eid_grp->attrs[0], struct device_attribute, attr); + eid_attr_list = container_of(dev_attr, struct ubcore_eid_attr, attr); + kfree(eid_attr_list); + } + + kfree(eid_grp->attrs); + kfree(eid_grp); + + ldev->dev_group[UBCORE_ATTR_GROUP_EIDS] = NULL; + } +} int ubcore_create_dev_attr_files(struct ubcore_logic_device *ldev) { int ret; + const struct attribute_group *eid_grp; + + eid_grp = ubcore_alloc_eids_group(ldev); + ldev->dev_group[UBCORE_ATTR_GROUP_DEV_DEFAULT] = &ubcore_dev_attr_group; + ldev->dev_group[UBCORE_ATTR_GROUP_EIDS] = eid_grp; + ldev->dev_group[UBCORE_ATTR_GROUP_NULL] = NULL; - ret = sysfs_create_group(&ldev->dev->kobj, &ubcore_dev_attr_group); + ret = sysfs_create_groups(&ldev->dev->kobj, ldev->dev_group); if (ret != 0) { ubcore_log_err("sysfs create group failed, ret:%d.\n", ret); + ubcore_free_eids_group(ldev); return -1; } @@ -765,7 +894,8 @@ void ubcore_remove_port_attr_files(struct ubcore_logic_device *ldev, uint8_t por void ubcore_remove_dev_attr_files(struct ubcore_logic_device *ldev) { - sysfs_remove_group(&ldev->dev->kobj, &ubcore_dev_attr_group); + sysfs_remove_groups(&ldev->dev->kobj, ldev->dev_group); + ubcore_free_eids_group(ldev); } int ubcore_fill_logic_device_attr(struct ubcore_logic_device *ldev, diff --git a/drivers/ub/urma/ubcore/ubcore_cgroup.c b/drivers/ub/urma/ubcore/ubcore_cgroup.c index 12c602c50ee9..93a84226d368 100644 --- a/drivers/ub/urma/ubcore/ubcore_cgroup.c +++ b/drivers/ub/urma/ubcore/ubcore_cgroup.c @@ -31,8 +31,8 @@ static inline bool ubcore_is_use_cg(struct ubcore_device *dev) void ubcore_cgroup_reg_dev(struct ubcore_device *dev) { - if (dev == NULL) { - ubcore_log_err("dev is null"); + if (dev == NULL || strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { + ubcore_log_err("Invalid parameter"); return; } diff --git a/drivers/ub/urma/ubcore/ubcore_cmd.h b/drivers/ub/urma/ubcore/ubcore_cmd.h index d8ebd5d7e132..c7a813231d10 100644 --- a/drivers/ub/urma/ubcore/ubcore_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_cmd.h @@ -38,8 +38,7 @@ struct ubcore_cmd_hdr { /* only for ubcore device ioctl */ enum ubcore_cmd { - UBCORE_CMD_SHOW_UTP = 1, - UBCORE_CMD_QUERY_STATS, + UBCORE_CMD_QUERY_STATS = 1, UBCORE_CMD_QUERY_RES, UBCORE_CMD_ADD_EID, UBCORE_CMD_DEL_EID, diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index 2121ab9cac9f..3a7102abcb6b 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "urma/ubcore_types.h" #include "ubcore_log.h" @@ -41,6 +42,7 @@ #include "ubcore_hash_table.h" #include "ubcore_tp.h" #include "ubcore_tp_table.h" +#include "urma/ubcore_jetty.h" #include "ubcore_msg.h" #include "ubcore_netdev.h" #include "ubcore_utp.h" @@ -52,6 +54,7 @@ #include "ubcore_cdev_file.h" #include "ubcore_uvs_cmd.h" #include "ubcore_cmd.h" +#include "ubcore_main.h" #include "ubcore_device.h" #define UBCORE_DEVICE_NAME "ubcore" @@ -74,7 +77,6 @@ static DECLARE_RWSEM(g_device_rwsem); * g_clients_rwsem protect g_client_list. */ static DECLARE_RWSEM(g_clients_rwsem); -static struct ubcore_device *g_tpf; static DEFINE_MUTEX(g_upi_lock); static LIST_HEAD(g_upi_list); @@ -85,7 +87,7 @@ static DECLARE_RWSEM(g_ubcore_net_rwsem); static bool g_shared_ns = true; -static struct ubcore_ctx g_ubcore_ctx; +static struct ubcore_ctx g_ubcore_ctx = {0}; static const void *ubcore_net_namespace(struct device *dev) { @@ -319,6 +321,8 @@ struct ubcore_device *ubcore_find_device(union ubcore_eid *eid, enum ubcore_tran down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { + if (IS_ERR_OR_NULL(dev->eid_table.eid_entries)) + continue; for (idx = 0; idx < dev->attr.dev_cap.max_eid_cnt; idx++) { if (memcmp(&dev->eid_table.eid_entries[idx].eid, eid, sizeof(union ubcore_eid)) == 0 && dev->transport_type == type) { @@ -421,28 +425,32 @@ void ubcore_destroy_upi_list(struct ubcore_device *dev) mutex_unlock(&g_upi_lock); } -void ubcore_device_list_lock(void) +static bool ubcore_netdev_in_ubdev(struct ubcore_device *dev, struct net_device *netdev) { - down_read(&g_device_rwsem); -} + struct net_device *real_netdev = NULL; -void ubcore_device_list_unlock(void) -{ - up_read(&g_device_rwsem); + if (dev->transport_type == UBCORE_TRANSPORT_UB && is_vlan_dev(netdev)) + real_netdev = vlan_dev_real_dev(netdev); + else + real_netdev = netdev; + + return (dev->netdev == real_netdev); } -struct ubcore_device **ubcore_get_devices_from_netdev_nolock(struct net_device *netdev, +struct ubcore_device **ubcore_get_devices_from_netdev(struct net_device *netdev, uint32_t *cnt) { struct ubcore_device **devices; struct ubcore_device *dev; uint32_t i = 0; + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { /* Assume netdev is related to the first and only port */ - if (dev->netdev == netdev) + if (ubcore_netdev_in_ubdev(dev, netdev)) i++; } + up_read(&g_device_rwsem); if (i == 0) { *cnt = 0; @@ -457,13 +465,16 @@ struct ubcore_device **ubcore_get_devices_from_netdev_nolock(struct net_device * *cnt = i; i = 0; + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { - if (dev->netdev == netdev) { + if (ubcore_netdev_in_ubdev(dev, netdev)) { ubcore_get_device(dev); devices[i] = dev; i++; } } + up_read(&g_device_rwsem); + return devices; } @@ -501,28 +512,7 @@ void ubcore_put_device(struct ubcore_device *dev) complete(&dev->comp); } -struct ubcore_device *ubcore_find_tpf_device_legacy(void) -{ - if (g_tpf == NULL) - ubcore_log_err("tpf is not registered yet\n"); - - ubcore_get_device(g_tpf); - return g_tpf; -} - -struct ubcore_device *ubcore_find_tpf_by_dev(struct ubcore_device *dev, - enum ubcore_transport_type type) -{ - if (dev != NULL && dev->attr.tp_maintainer && dev->transport_type == type) { - ubcore_get_device(dev); - return dev; - } - - return ubcore_find_tpf_device_legacy(); -} - -struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name, - enum ubcore_transport_type type) +struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name) { struct ubcore_device *dev; @@ -532,11 +522,12 @@ struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name, return NULL; } - if (dev->attr.tp_maintainer && dev->transport_type == type) + if (dev->attr.tp_maintainer) return dev; + ubcore_log_err("dev:%s is not tpf", dev_name); ubcore_put_device(dev); - return ubcore_find_tpf_device_legacy(); + return NULL; } static uint32_t ubcore_get_all_tpf_device_cnt(enum ubcore_transport_type type) @@ -581,16 +572,10 @@ struct ubcore_device **ubcore_get_all_tpf_device(enum ubcore_transport_type type struct ubcore_device *ubcore_find_tpf_device(union ubcore_net_addr_union *netaddr, enum ubcore_transport_type type) { - struct ubcore_device *tpf_dev = NULL; - if (netaddr == NULL) - return ubcore_find_tpf_device_legacy(); - - tpf_dev = ubcore_lookup_tpf_by_sip_addr(netaddr); - if (tpf_dev == NULL) - return ubcore_find_tpf_device_legacy(); + return NULL; - return tpf_dev; + return ubcore_lookup_tpf_by_sip_addr(netaddr); } int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg) @@ -638,22 +623,22 @@ static void ubcore_free_driver_obj(void *obj) static struct ubcore_ht_param g_ht_params[] = { [UBCORE_HT_JFS] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfs, hnode), offsetof(struct ubcore_jfs, jfs_id) + offsetof(struct ubcore_jetty_id, id), - sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, + sizeof(uint32_t), NULL, ubcore_free_driver_obj, ubcore_jfs_get}, [UBCORE_HT_JFR] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfr, hnode), offsetof(struct ubcore_jfr, jfr_id) + offsetof(struct ubcore_jetty_id, id), - sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, + sizeof(uint32_t), NULL, ubcore_free_driver_obj, ubcore_jfr_get}, [UBCORE_HT_JFC] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jfc, hnode), offsetof(struct ubcore_jfc, id), sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, [UBCORE_HT_JETTY] = { UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_jetty, hnode), offsetof(struct ubcore_jetty, jetty_id) + offsetof(struct ubcore_jetty_id, id), - sizeof(uint32_t), NULL, ubcore_free_driver_obj, NULL}, + sizeof(uint32_t), NULL, ubcore_free_driver_obj, ubcore_jetty_get}, - [UBCORE_HT_TP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tp_node, hnode), - offsetof(struct ubcore_tp_node, key), sizeof(struct ubcore_tp_key), - NULL, NULL, ubcore_tp_get}, + [UBCORE_HT_TP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tp, hnode), + offsetof(struct ubcore_tp, tpn), sizeof(uint32_t), + NULL, ubcore_free_driver_obj, ubcore_tp_get}, [UBCORE_HT_TPG] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tpg, hnode), offsetof(struct ubcore_tpg, tpgn), sizeof(uint32_t), @@ -700,10 +685,6 @@ static struct ubcore_ht_param g_ht_params[] = { [UBCORE_HT_CTP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_ctp, hnode), offsetof(struct ubcore_ctp, ctpn), sizeof(uint32_t), NULL, ubcore_free_driver_obj, ubcore_ctp_get}, - - [UBCORE_HT_UB_TP] = {UBCORE_HASH_TABLE_SIZE, offsetof(struct ubcore_tp, hnode), - offsetof(struct ubcore_tp, tpn), sizeof(uint32_t), - NULL, ubcore_free_driver_obj, ubcore_tp_get}, }; static inline void ubcore_set_vtp_hash_table_size(uint32_t vtp_size) @@ -734,10 +715,8 @@ static void ubcore_update_hash_tables_size(const struct ubcore_device_cap *cap) g_ht_params[UBCORE_HT_JFC].size = cap->max_jfc; if (cap->max_jetty != 0 && cap->max_jetty < g_ht_params[UBCORE_HT_JETTY].size) g_ht_params[UBCORE_HT_JETTY].size = cap->max_jetty; - if (cap->max_tp_cnt != 0 && cap->max_tp_cnt < g_ht_params[UBCORE_HT_TP].size) { + if (cap->max_tp_cnt != 0 && cap->max_tp_cnt < g_ht_params[UBCORE_HT_TP].size) g_ht_params[UBCORE_HT_TP].size = cap->max_tp_cnt; - g_ht_params[UBCORE_HT_UB_TP].size = cap->max_tp_cnt; - } if (cap->max_tpg_cnt != 0 && cap->max_tpg_cnt < g_ht_params[UBCORE_HT_TPG].size) g_ht_params[UBCORE_HT_TPG].size = cap->max_tpg_cnt; if (cap->max_vtp_cnt_per_fe < UBCORE_HASH_TABLE_SIZE && @@ -811,18 +790,21 @@ static int ubcore_create_eidtable(struct ubcore_device *dev) static void ubcore_destroy_eidtable(struct ubcore_device *dev) { - if (dev->eid_table.eid_entries != NULL) { - kfree(dev->eid_table.eid_entries); - dev->eid_table.eid_entries = NULL; - } + struct ubcore_eid_entry *e = NULL; + + spin_lock(&dev->eid_table.lock); + e = dev->eid_table.eid_entries; + dev->eid_table.eid_entries = NULL; + spin_unlock(&dev->eid_table.lock); + if (e != NULL) + kfree(e); } static int ubcore_send_remove_tpf_dev_info(struct ubcore_device *dev) { - int ret; - struct ubcore_nlmsg *resp_msg, *req_msg; - struct ubcore_update_tpf_dev_info_resp *resp; struct ubcore_update_tpf_dev_info_req *data; + struct ubcore_nlmsg *req_msg; + int ret; req_msg = kcalloc(1, sizeof(struct ubcore_nlmsg) + sizeof(struct ubcore_update_tpf_dev_info_req), GFP_KERNEL); @@ -838,64 +820,61 @@ static int ubcore_send_remove_tpf_dev_info(struct ubcore_device *dev) data->dev_fea = dev->attr.dev_cap.feature; data->cc_entry_cnt = 0; data->opcode = UBCORE_UPDATE_TPF_DEL; - (void)strcpy(data->dev_name, dev->dev_name); + (void)strncpy(data->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); - resp_msg = ubcore_nl_send_wait(dev, req_msg); - if (resp_msg == NULL) { - ubcore_log_err("Failed to wait query response"); - kfree(req_msg); - return -1; - } - - resp = (struct ubcore_update_tpf_dev_info_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_CMD_UPDATE_TPF_DEV_INFO_RESP || resp == NULL || - resp->ret != UBCORE_NL_RESP_SUCCESS) { - ubcore_log_err("update tpf dev info request is rejected with type %d ret %d", - resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); - ret = -1; - } else { - ret = 0; - } + ret = ubcore_nl_send_nowait_without_cb(req_msg); + if (ret) + ubcore_log_err("Failed to send rmv tpf dev info request ret:%d", ret); + else + ubcore_log_info("Success to send rmv tpf dev:%s info request", dev->dev_name); - kfree(resp_msg); kfree(req_msg); return ret; } -struct ubcore_nlmsg *ubcore_new_tpf_dev_msg(struct ubcore_device *dev) +static struct ubcore_cc_entry *ubcore_get_cc_entry(struct ubcore_device *dev, + uint32_t *cc_entry_cnt) { - struct ubcore_update_tpf_dev_info_req *data; - struct ubcore_cc_entry *cc_entry; - struct ubcore_cc_entry *array; - struct ubcore_nlmsg *req_msg; - uint32_t cc_entry_cnt; - uint32_t cc_len; + struct ubcore_cc_entry *cc_entry = NULL; + *cc_entry_cnt = 0; if (dev->ops == NULL || dev->ops->query_cc == NULL) { ubcore_log_err("Invalid parameter!\n"); return NULL; } - cc_entry = dev->ops->query_cc(dev, &cc_entry_cnt); + cc_entry = dev->ops->query_cc(dev, cc_entry_cnt); if (cc_entry == NULL) { ubcore_log_err("Failed to query cc entry\n"); return NULL; } - if (cc_entry_cnt > UBCORE_CC_IDX_TABLE_SIZE || cc_entry_cnt == 0) { + if (*cc_entry_cnt > UBCORE_CC_IDX_TABLE_SIZE || *cc_entry_cnt == 0) { kfree(cc_entry); - ubcore_log_err("cc_entry_cnt invalid, %u.\n", cc_entry_cnt); + ubcore_log_err("cc_entry_cnt invalid, %u.\n", *cc_entry_cnt); return NULL; } + return cc_entry; +} + +struct ubcore_nlmsg *ubcore_new_tpf_dev_msg(struct ubcore_device *dev) +{ + struct ubcore_update_tpf_dev_info_req *data; + struct ubcore_cc_entry *cc_entry; + struct ubcore_cc_entry *array; + struct ubcore_nlmsg *req_msg; + uint32_t cc_entry_cnt; + uint32_t cc_len; + + // If not support cc, cc_entry may be NULL, cc_entry_cnt is 0 + cc_entry = ubcore_get_cc_entry(dev, &cc_entry_cnt); + cc_len = (uint32_t)sizeof(struct ubcore_update_tpf_dev_info_req) + cc_entry_cnt * (uint32_t)sizeof(struct ubcore_cc_entry); - req_msg = kcalloc(1, sizeof(struct ubcore_nlmsg) + cc_len, GFP_KERNEL); - if (req_msg == NULL) { - kfree(cc_entry); - return NULL; - } + if (req_msg == NULL) + goto out; /* fill msg head */ req_msg->msg_type = UBCORE_CMD_UPDATE_TPF_DEV_INFO_REQ; @@ -906,79 +885,52 @@ struct ubcore_nlmsg *ubcore_new_tpf_dev_msg(struct ubcore_device *dev) data = (struct ubcore_update_tpf_dev_info_req *)req_msg->payload; data->dev_fea = dev->attr.dev_cap.feature; data->cc_entry_cnt = cc_entry_cnt; - (void)strcpy(data->dev_name, dev->dev_name); + (void)strncpy(data->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); data->opcode = UBCORE_UPDATE_TPF_ADD; - if (dev->netdev != NULL) { - if (strnlen(dev->netdev->name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME) { - ubcore_log_err("Invalid parameter! netdev.\n"); - kfree(req_msg); - kfree(cc_entry); - return NULL; - } - (void)strcpy(data->netdev_name, dev->netdev->name); + if (dev->netdev != NULL && + strnlen(dev->netdev->name, UBCORE_MAX_DEV_NAME) < UBCORE_MAX_DEV_NAME) + (void)strncpy(data->netdev_name, dev->netdev->name, UBCORE_MAX_DEV_NAME - 1); + + if (cc_entry != NULL) { + array = (struct ubcore_cc_entry *)data->data; + (void)memcpy(array, cc_entry, sizeof(struct ubcore_cc_entry) * cc_entry_cnt); } - array = (struct ubcore_cc_entry *)data->data; - (void)memcpy(array, cc_entry, sizeof(struct ubcore_cc_entry) * cc_entry_cnt); - kfree(cc_entry); +out: + if (cc_entry != NULL) + kfree(cc_entry); return req_msg; } static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) { - struct ubcore_nlmsg *resp_msg, *req_msg; - struct ubcore_update_tpf_dev_info_resp *resp; + struct ubcore_nlmsg *req_msg; int ret; req_msg = ubcore_new_tpf_dev_msg(dev); if (req_msg == NULL) return -1; - resp_msg = ubcore_nl_send_wait(dev, req_msg); - if (resp_msg == NULL) { - ubcore_log_err("Failed to wait query response"); - kfree(req_msg); - return -1; - } - resp = (struct ubcore_update_tpf_dev_info_resp *)(void *)resp_msg->payload; - if (resp_msg->msg_type != UBCORE_CMD_UPDATE_TPF_DEV_INFO_RESP || resp == NULL || - resp->ret != UBCORE_NL_RESP_SUCCESS) { - ubcore_log_err("update tpf dev info del request is rejected with type %d ret %d", - resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); - ret = -1; - } else { - ret = 0; - } - - kfree(resp_msg); - kfree(req_msg); - return ret; -} -int ubcore_query_all_device_tpf_dev_info(void) -{ - struct ubcore_device *dev; - int ret = 0; + ret = ubcore_nl_send_nowait_without_cb(req_msg); + if (ret) + ubcore_log_err("Failed to nowait send query tpf dev info request"); + else + ubcore_log_info("Success to nowait send query tpf dev info request"); - down_read(&g_device_rwsem); - list_for_each_entry(dev, &g_device_list, list_node) { - if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { - if (ubcore_query_send_tpf_dev_info(dev) != 0) { - ubcore_log_warn("failed to update tpf dev info in ubcore with dev name %s", - dev->dev_name); - ret = -1; - } - } - } - up_read(&g_device_rwsem); + kfree(req_msg); return ret; } -static int ubcore_create_main_device(struct ubcore_device *dev, struct net *net) +static int ubcore_create_main_device(struct ubcore_device *dev) { struct ubcore_logic_device *ldev = &dev->ldev; + struct net *net = &init_net; int ret; + if (dev->transport_type == UBCORE_TRANSPORT_IP && dev->netdev != NULL) + net = dev_net(dev->netdev); + /* create /sys/class/ubcore/dev_name> */ write_pnet(&ldev->net, net); ldev->ub_dev = dev; @@ -1025,10 +977,6 @@ static int init_ubcore_device(struct ubcore_device *dev) return -1; } - /* set tpf device */ - if (dev->transport_type == UBCORE_TRANSPORT_UB && g_tpf == NULL && dev->attr.tp_maintainer) - g_tpf = dev; - if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { if (ubcore_sip_table_init(&dev->sip_table, dev->attr.dev_cap.max_netaddr_cnt) != 0) { @@ -1068,7 +1016,7 @@ static int init_ubcore_device(struct ubcore_device *dev) ubcore_log_err("alloc hash tables failed.\n"); return -1; } - ubcore_update_default_eid(dev, true); + ubcore_update_netdev_addr(dev, dev->netdev, UBCORE_ADD_NET_ADDR, false); mutex_init(&dev->ldev_mutex); INIT_LIST_HEAD(&dev->ldev_list); @@ -1096,16 +1044,13 @@ static void uninit_ubcore_device(struct ubcore_device *dev) mutex_destroy(&dev->ldev_mutex); ubcore_put_port_netdev(dev); - ubcore_update_default_eid(dev, false); + ubcore_update_netdev_addr(dev, dev->netdev, UBCORE_DEL_NET_ADDR, false); ubcore_free_hash_tables(dev); ubcore_destroy_eidtable(dev); if (!dev->attr.virtualization) ubcore_destroy_upi_list(dev); - if (g_tpf == dev && dev->attr.tp_maintainer) - g_tpf = NULL; - if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { ubcore_remove_uvs_sip_info(dev); ubcore_sip_table_uninit(&dev->sip_table); @@ -1114,6 +1059,76 @@ static void uninit_ubcore_device(struct ubcore_device *dev) } } +static int ubcore_nego_ver_rsp_msg_cb(struct ubcore_device *dev, + struct ubcore_resp *resp, void *msg_ctx) +{ + struct ubcore_msg_nego_ver_resp *data; + + if (resp == NULL || resp->len != sizeof(struct ubcore_msg_nego_ver_resp) || + resp->opcode != UBCORE_MSG_NEGO_VER) { + ubcore_log_err("Invalid version negotiation response.\n"); + return -EINVAL; + } + + data = (struct ubcore_msg_nego_ver_resp *)resp->data; + if (data->ret == UBCORE_MSG_RESP_FAIL) { + ubcore_log_err("Fail to negotiate version with backend ubcore.\n"); + return -1; + } + + ubcore_set_version(data->version); + ubcore_set_cap(data->cap); + return 0; +} + +static int ubcore_initiate_negotiation(struct ubcore_device *dev) +{ + struct ubcore_msg_nego_ver_req *data; + struct ubcore_req *req_msg; + struct ubcore_resp_cb cb = { + .callback = ubcore_nego_ver_rsp_msg_cb, + .user_arg = NULL + }; + uint32_t data_length; + int ret; + + if (dev->transport_type != UBCORE_TRANSPORT_UB) + return 0; + + if (ubcore_negotiated()) + return 0; + + if (!dev->attr.virtualization) { + ubcore_set_version(UBCORE_VERSION); + ubcore_set_cap(UBCORE_CAP); + return 0; + } + + data_length = sizeof(struct ubcore_msg_nego_ver_req) + + UBCORE_SUPPORT_VERION_NUM * sizeof(uint32_t); + req_msg = kcalloc(1, sizeof(struct ubcore_req) + data_length, GFP_KERNEL); + if (req_msg == NULL) + return -ENOMEM; + + req_msg->opcode = UBCORE_MSG_NEGO_VER; + req_msg->len = data_length; + + data = (struct ubcore_msg_nego_ver_req *)req_msg->data; + data->cap = UBCORE_CAP; + data->version_num = UBCORE_SUPPORT_VERION_NUM; + (void)memcpy(data->versions, ubcore_get_support_versions(), + UBCORE_SUPPORT_VERION_NUM * sizeof(uint32_t)); + + ret = ubcore_send_fe2tpf_msg(dev, req_msg, &cb); + /* Frontend request is freed after above blocking function. */ + kfree(req_msg); + if (ret != 0) { + ubcore_log_err("Fail to send fe2tpf version negitiation message.\n"); + return -1; + } + return ret; +} + static int ubcore_config_device_rsp_msg_cb(struct ubcore_device *dev, struct ubcore_resp *resp, void *msg_ctx) { @@ -1326,7 +1341,7 @@ static int ubcore_add_one_logic_device(struct ubcore_device *dev, struct net *ne mutex_lock(&dev->ldev_mutex); list_for_each_entry(ldev, &dev->ldev_list, node) { - if (net_eq(read_pnet(&dev->ldev.net), net)) { + if (net_eq(read_pnet(&ldev->net), net)) { mutex_unlock(&dev->ldev_mutex); return 0; } @@ -1416,6 +1431,11 @@ static int ubcore_register_sysfs(void) { int ret; + // If sysfs is created, return Success + // Need to add mutex + if (!IS_ERR_OR_NULL(g_ubcore_ctx.ubcore_dev)) + return 0; + ret = alloc_chrdev_region(&g_ubcore_ctx.ubcore_devno, 0, 1, UBCORE_DEVICE_NAME); if (ret != 0) { ubcore_log_err("alloc chrdev region failed, ret:%d.\n", ret); @@ -1436,6 +1456,7 @@ static int ubcore_register_sysfs(void) if (IS_ERR(g_ubcore_ctx.ubcore_dev)) { ret = (int)PTR_ERR(g_ubcore_ctx.ubcore_dev); ubcore_log_err("couldn't create device %s, ret:%d.\n", UBCORE_DEVICE_NAME, ret); + g_ubcore_ctx.ubcore_dev = NULL; goto del_cdev; } ubcore_log_info("ubcore device created success.\n"); @@ -1448,12 +1469,17 @@ static int ubcore_register_sysfs(void) return ret; } -static int ubcore_unregister_sysfs(void) +int ubcore_unregister_sysfs(void) { + // If sysfs is not created, return Success + // Need to add mutex + if (IS_ERR_OR_NULL(g_ubcore_ctx.ubcore_dev)) + return 0; + device_destroy(&g_ubcore_class, g_ubcore_ctx.ubcore_cdev.dev); cdev_del(&g_ubcore_ctx.ubcore_cdev); unregister_chrdev_region(g_ubcore_ctx.ubcore_devno, 1); - ubcore_log_info("ubcore device destroyed success.\n"); + ubcore_log_info("ubcore sysfs device destroyed success.\n"); return 0; } @@ -1518,7 +1544,7 @@ int ubcore_register_device(struct ubcore_device *dev) } } - ret = ubcore_create_main_device(dev, &init_net); + ret = ubcore_create_main_device(dev); if (ret) { if (dev->attr.tp_maintainer) (void)ubcore_device_cdev_proc(ubcore_unregister_sysfs); @@ -1527,6 +1553,12 @@ int ubcore_register_device(struct ubcore_device *dev) return ret; } + if (ubcore_initiate_negotiation(dev) != 0) { + ubcore_log_err("Fail to negotiate version.\n"); + ret = -1; + goto destroy_mdev; + } + if (ubcore_config_device_in_register(dev) != 0) { ubcore_log_err("failed to config ubcore device.\n"); ret = -EPERM; @@ -1586,16 +1618,13 @@ void ubcore_unregister_device(struct ubcore_device *dev) ubcore_remove_logic_devices(dev); ubcore_destroy_main_device(dev); - uninit_ubcore_device(dev); - if (dev->attr.tp_maintainer) - (void)ubcore_device_cdev_proc_withoutlock(ubcore_unregister_sysfs); - up_read(&g_device_rwsem); /* Pair with set use_cnt = 1 when init device */ ubcore_put_device(dev); /* Wait for use cnt == 0 */ wait_for_completion(&dev->comp); + uninit_ubcore_device(dev); /* Protect eid table access security based on ref cnt */ ubcore_log_info("ubcore device: %s unregister success.\n", dev->dev_name); } @@ -1670,43 +1699,46 @@ EXPORT_SYMBOL(ubcore_unregister_event_handler); static bool ubcore_preprocess_event(struct ubcore_event *event) { if (event->event_type == UBCORE_EVENT_TP_ERR && event->element.tp != NULL) { - ubcore_log_info("ubcore detect tp error event"); - if (event->ub_dev->transport_type == UBCORE_TRANSPORT_IB) { + ubcore_log_info("ubcore detect tp error event with tpn %u", event->element.tp->tpn); + if (event->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB) { ubcore_restore_tp(event->ub_dev, event->element.tp); } else if (event->ub_dev->transport_type == UBCORE_TRANSPORT_UB) { if (event->element.tp->state == UBCORE_TP_STATE_ERR || event->element.tp->state == UBCORE_TP_STATE_RESET) { - ubcore_log_warn("Tp already in state %d, ignore err event", - (int32_t)event->element.tp->state); + ubcore_log_warn("Tp %u already in state %d, ignore err event", + event->element.tp->tpn, (int32_t)event->element.tp->state); return true; } if (ubcore_change_tp_to_err(event->ub_dev, event->element.tp) != 0) - ubcore_log_info("ubcore change tp to error failed"); + ubcore_log_info("ubcore change tp %u to error failed", + event->element.tp->tpn); } return true; } else if (event->event_type == UBCORE_EVENT_TP_SUSPEND && event->element.tp != NULL) { - ubcore_log_info("ubcore detect tp suspend event"); + ubcore_log_info("ubcore detect tp %u suspend event", event->element.tp->tpn); ubcore_report_tp_suspend(event->ub_dev, event->element.tp); return true; } else if (event->event_type == UBCORE_EVENT_MIGRATE_VTP_SWITCH && event->element.vtp != NULL) { - ubcore_log_info("ubcore detect migrate vtp switch event"); + ubcore_log_info("ubcore detect migrate vtp %u switch event", + event->element.vtp->cfg.vtpn); ubcore_report_migrate_vtp(event->ub_dev, event->element.vtp, UBCORE_EVENT_MIGRATE_VTP_SWITCH); return true; } else if (event->event_type == UBCORE_EVENT_MIGRATE_VTP_ROLLBACK && event->element.vtp != NULL) { - ubcore_log_info("ubcore detect migrate vtp rollback event"); + ubcore_log_info("ubcore detect migrate vtp %u rollback event", + event->element.vtp->cfg.vtpn); ubcore_report_migrate_vtp(event->ub_dev, event->element.vtp, UBCORE_EVENT_MIGRATE_VTP_ROLLBACK); return true; } else if (event->event_type == UBCORE_EVENT_TP_FLUSH_DONE && event->element.tp != NULL) { - ubcore_log_info("ubcore detect tp flush done event"); + ubcore_log_info("ubcore detect tp %u flush done event", event->element.tp->tpn); if (event->element.tp->state == UBCORE_TP_STATE_RESET) { - ubcore_log_warn("Tp already in state %d, ignore flush done event", - (int32_t)event->element.tp->state); + ubcore_log_warn("Tp %u already in state %d, ignore flush done event", + event->element.tp->tpn, (int32_t)event->element.tp->state); return true; } /* flush done means tp already in error, @@ -1773,7 +1805,7 @@ struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_ if (dev == NULL || strnlen(dev->dev_name, UBCORE_MAX_DEV_NAME) >= UBCORE_MAX_DEV_NAME || dev->ops == NULL || dev->ops->alloc_ucontext == NULL || - eid_index >= UBCORE_MAX_EID_CNT) { + eid_index >= UBCORE_MAX_EID_CNT) { ubcore_log_err("Invalid argument.\n"); return ERR_PTR(-EINVAL); } @@ -1787,14 +1819,14 @@ struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_ ret = ubcore_cgroup_try_charge(&cg_obj, dev, UBCORE_RESOURCE_HCA_HANDLE); if (ret != 0) { ubcore_log_err("cgroup charge fail:%d ,dev_name :%s\n", ret, dev->dev_name); - return ERR_PTR(-EPERM); + return ERR_PTR(ret); } ucontext = dev->ops->alloc_ucontext(dev, eid_index, udrv_data); if (IS_ERR_OR_NULL(ucontext)) { ubcore_log_err("failed to alloc ucontext.\n"); ubcore_cgroup_uncharge(&cg_obj, dev, UBCORE_RESOURCE_HCA_HANDLE); - return ucontext == NULL ? ERR_PTR(-ENOEXEC) : ucontext; + return UBCORE_CHECK_RETURN_ERR_PTR(ucontext, ENOEXEC); } ucontext->eid_index = eid_index; @@ -1825,71 +1857,45 @@ void ubcore_free_ucontext(struct ubcore_device *dev, struct ubcore_ucontext *uco } EXPORT_SYMBOL(ubcore_free_ucontext); -static struct ubcore_device *ubcore_get_ueid_op_dev(struct ubcore_device *dev) -{ - if (dev == NULL) - return NULL; - - if (dev->transport_type != UBCORE_TRANSPORT_UB) { - ubcore_get_device(dev); - return dev; - } - - /* For UB dev, add_ueid and delete_ueid ops should operate on tpf */ - return ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); -} - int ubcore_add_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ueid_cfg *cfg) { - struct ubcore_device *op_dev = NULL; int ret; - op_dev = ubcore_get_ueid_op_dev(dev); - if (op_dev == NULL || cfg == NULL || op_dev->ops == NULL || op_dev->ops->add_ueid == NULL - || fe_idx >= UBCORE_MAX_FE_CNT) { + if (dev == NULL || cfg == NULL || dev->ops == NULL || fe_idx >= UBCORE_MAX_FE_CNT) { ubcore_log_err("Invalid argument.\n"); - ret = -EINVAL; - goto put_dev; + return -EINVAL; } - ret = op_dev->ops->add_ueid(op_dev, fe_idx, cfg); - if (ret != 0) { + if (dev->ops->add_ueid == NULL) + return 0; + + ret = dev->ops->add_ueid(dev, fe_idx, cfg); + if (ret != 0) ubcore_log_err("failed to add ueid, ret:%d\n", fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); - goto put_dev; - } -put_dev: - if (op_dev) - ubcore_put_device(op_dev); return ret; } EXPORT_SYMBOL(ubcore_add_ueid); int ubcore_delete_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ueid_cfg *cfg) { - struct ubcore_device *op_dev = NULL; int ret; - op_dev = ubcore_get_ueid_op_dev(dev); - if (op_dev == NULL || cfg == NULL || op_dev->ops == NULL || - op_dev->ops->delete_ueid == NULL || + if (dev == NULL || cfg == NULL || dev->ops == NULL || fe_idx >= UBCORE_MAX_FE_CNT) { ubcore_log_err("Invalid argument.\n"); - ret = -EINVAL; - goto put_dev; + return -EINVAL; } - ret = op_dev->ops->delete_ueid(op_dev, fe_idx, cfg); - if (ret != 0) { + if (dev->ops->delete_ueid == NULL) + return 0; + + ret = dev->ops->delete_ueid(dev, fe_idx, cfg); + if (ret != 0) ubcore_log_err("failed to add ueid, ret:%d\n", fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); - goto put_dev; - } -put_dev: - if (op_dev) - ubcore_put_device(op_dev); return ret; } EXPORT_SYMBOL(ubcore_delete_ueid); @@ -2024,9 +2030,9 @@ static int ubcore_add_device_sip(struct ubcore_sip_info *sip, uint32_t *sip_idx) return -1; } - dev = ubcore_find_tpf_device_by_name(sip->dev_name, UBCORE_TRANSPORT_UB); - if (!dev) { - ubcore_log_err("update sip find no tpf\n"); + dev = ubcore_find_tpf_device_by_name(sip->dev_name); + if (!dev || dev->transport_type != UBCORE_TRANSPORT_UB) { + ubcore_log_err("update sip, dev:%s no tpf, or not UB\n", sip->dev_name); return -1; } @@ -2073,9 +2079,9 @@ static int ubcore_del_device_sip(struct ubcore_sip_info *sip) return -1; } - dev = ubcore_find_tpf_device_by_name(sip->dev_name, UBCORE_TRANSPORT_UB); - if (!dev) { - ubcore_log_err("update sip find no tpf\n"); + dev = ubcore_find_tpf_device_by_name(sip->dev_name); + if (!dev || dev->transport_type != UBCORE_TRANSPORT_UB) { + ubcore_log_err("del sip, dev:%s no tpf, or dev not UB\n", sip->dev_name); return -1; } @@ -2139,7 +2145,8 @@ struct ubcore_eid_info *ubcore_get_eid_list(struct ubcore_device *dev, uint32_t uint32_t i; if (dev == NULL || dev->attr.dev_cap.max_eid_cnt == 0 || - dev->attr.dev_cap.max_eid_cnt > UBCORE_MAX_EID_CNT || cnt == NULL) { + dev->attr.dev_cap.max_eid_cnt > UBCORE_MAX_EID_CNT || cnt == NULL || + IS_ERR_OR_NULL(dev->eid_table.eid_entries)) { ubcore_log_err("invalid input parameter.\n"); return NULL; } @@ -2157,12 +2164,15 @@ struct ubcore_eid_info *ubcore_get_eid_list(struct ubcore_device *dev, uint32_t } } spin_unlock(&dev->eid_table.lock); + if (count == 0) { + vfree(tmp); + return NULL; + } *cnt = count; eid_list = vmalloc(count * sizeof(struct ubcore_eid_info)); if (eid_list == NULL) { vfree(tmp); - ubcore_log_err("failed to apply for memory.\n"); return NULL; } for (i = 0; i < count; i++) @@ -2180,33 +2190,6 @@ void ubcore_free_eid_list(struct ubcore_eid_info *eid_list) } EXPORT_SYMBOL(ubcore_free_eid_list); -void ubcore_sync_sip_table(void) -{ - struct ubcore_sip_table *sip_table; - struct ubcore_device *dev = NULL; - struct ubcore_sip_info *sip; - uint32_t i; - - down_read(&g_device_rwsem); - list_for_each_entry(dev, &g_device_list, list_node) { - if (dev != NULL && dev->attr.tp_maintainer == true) { - ubcore_get_device(dev); - sip_table = &dev->sip_table; - mutex_lock(&sip_table->lock); - for (i = 0; i < sip_table->max_sip_cnt; i++) { - sip = &sip_table->entry[i]; - if (!sip->is_active) - continue; - if (ubcore_get_netlink_valid() == true) - (void)ubcore_notify_uvs_add_sip(dev, sip, i); - } - mutex_unlock(&sip_table->lock); - ubcore_put_device(dev); - } - } - up_read(&g_device_rwsem); -} - static int ubcore_lookup_sip_by_addr(struct ubcore_device *dev, const union ubcore_net_addr_union *addr) { @@ -2395,7 +2378,7 @@ void ubcore_net_exit(struct net *net) if (unet == NULL) return; - ubcore_log_info("net exit %u", net->ns.inum); + ubcore_log_info("net exit %u, net:0x%p", net->ns.inum, net); down_write(&g_ubcore_net_rwsem); spin_lock_irqsave(&g_ubcore_net_lock, flags); if (list_empty(&unet->node)) { @@ -2407,23 +2390,25 @@ void ubcore_net_exit(struct net *net) spin_unlock_irqrestore(&g_ubcore_net_lock, flags); up_write(&g_ubcore_net_rwsem); - down_read(&g_device_rwsem); if (!g_shared_ns) { + down_read(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { - if (dev->transport_type != UBCORE_TRANSPORT_UB) + if (dev->transport_type != UBCORE_TRANSPORT_UB || + !net_eq(read_pnet(&dev->ldev.net), net)) continue; (void)ubcore_modify_dev_ns(dev, &init_net, true); } + up_read(&g_device_rwsem); } else { + down_write(&g_device_rwsem); list_for_each_entry(dev, &g_device_list, list_node) { - if (dev->transport_type != UBCORE_TRANSPORT_UB || - !net_eq(read_pnet(&dev->ldev.net), net)) + if (dev->transport_type != UBCORE_TRANSPORT_UB) continue; ubcore_remove_one_logic_device(dev, net); ubcore_invalidate_eid_ns(dev, net); } + up_write(&g_device_rwsem); } - up_read(&g_device_rwsem); } static int ubcore_net_init(struct net *net) @@ -2436,7 +2421,7 @@ static int ubcore_net_init(struct net *net) if (unet == NULL) return 0; - ubcore_log_info("net init %u", net->ns.inum); + ubcore_log_info("net init %u, net:0x%p", net->ns.inum, net); write_pnet(&unet->net, net); if (net_eq(net, &init_net)) { INIT_LIST_HEAD(&unet->node); @@ -2469,12 +2454,32 @@ static int ubcore_net_init(struct net *net) return 0; } -int ubcore_get_max_mtu(struct ubcore_device *dev, uint8_t port_num, enum ubcore_mtu *mtu) +int ubcore_get_max_mtu(struct ubcore_device *dev, enum ubcore_mtu *mtu) { - if (port_num >= dev->attr.port_cnt || port_num >= UBCORE_MAX_PORT_CNT) + enum ubcore_mtu mtu_min = UBCORE_MTU_8192; + enum ubcore_mtu mtu_tmp; + bool found = false; + uint32_t i; + + if (dev == NULL || mtu == NULL) { + ubcore_log_info("invalid parameter"); return -1; + } + + for (i = 0; i < UBCORE_MAX_PORT_CNT; i++) { + mtu_tmp = dev->attr.port_attr[i].max_mtu; + if ((uint32_t)mtu_tmp != 0 && mtu_tmp <= mtu_min) { + mtu_min = mtu_tmp; + found = true; + } + } + + if (!found) { + ubcore_log_err("Failed to find valid max_mtu"); + return -1; + } - *mtu = dev->attr.port_attr[port_num].max_mtu; + *mtu = mtu_min; return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_device.h b/drivers/ub/urma/ubcore/ubcore_device.h index 59f71ac9fae7..1f4f1c149a63 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.h +++ b/drivers/ub/urma/ubcore/ubcore_device.h @@ -25,10 +25,11 @@ int ubcore_register_pnet_ops(void); void ubcore_unregister_pnet_ops(void); int ubcore_class_register(void); void ubcore_class_unregister(void); +int ubcore_unregister_sysfs(void); int ubcore_set_ns_mode(bool shared); int ubcore_set_dev_ns(char *device_name, uint32_t ns_fd); bool ubcore_dev_accessible(struct ubcore_device *dev, struct net *net); -int ubcore_get_max_mtu(struct ubcore_device *dev, uint8_t port_num, enum ubcore_mtu *mtu); +int ubcore_get_max_mtu(struct ubcore_device *dev, enum ubcore_mtu *mtu); struct ubcore_nlmsg *ubcore_new_tpf_dev_msg(struct ubcore_device *dev); bool ubcore_eid_accessible(struct ubcore_device *dev, uint32_t eid_index); #endif // UBCORE_DEVICE_H diff --git a/drivers/ub/urma/ubcore/ubcore_genl.c b/drivers/ub/urma/ubcore/ubcore_genl.c index fd10fe8455e2..b112fe6f417d 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl.c +++ b/drivers/ub/urma/ubcore/ubcore_genl.c @@ -53,12 +53,6 @@ static const struct nla_policy ubcore_policy[NUM_UBCORE_ATTR] = { }; static const struct genl_ops ubcore_genl_ops[] = { - { - .cmd = UBCORE_CMD_SHOW_UTP, - .policy = ubcore_policy, - .maxattr = ARRAY_SIZE(ubcore_policy) - 1, - .doit = ubcore_show_utp_ops - }, { .cmd = UBCORE_CMD_QUERY_STATS, .policy = ubcore_policy, diff --git a/drivers/ub/urma/ubcore/ubcore_genl_admin.c b/drivers/ub/urma/ubcore/ubcore_genl_admin.c index 9220afd47b48..d7567442ed35 100644 --- a/drivers/ub/urma/ubcore/ubcore_genl_admin.c +++ b/drivers/ub/urma/ubcore/ubcore_genl_admin.c @@ -30,6 +30,7 @@ #include "ubcore_priv.h" #include "ubcore_cmd.h" #include "ubcore_device.h" +#include "ubcore_main.h" #include "ubcore_genl_admin.h" #define CB_ARGS_DEV_BUF 0 @@ -95,94 +96,6 @@ static int ubcore_parse_admin_res_cmd(struct netlink_callback *cb, void *dst, ui copy_len); } -static void ubcore_update_pattern1_eid(struct ubcore_device *dev, - union ubcore_eid *eid, bool is_add) -{ - struct ubcore_ueid_cfg cfg; - uint32_t eid_idx = 0; - - if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) - return; - - cfg.eid = *eid; - cfg.eid_index = eid_idx; - cfg.upi = 0; - if (is_add) - (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); - else - (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); -} - -static void ubcore_update_pattern3_eid(struct ubcore_device *dev, - union ubcore_eid *eid, bool is_add) -{ - struct ubcore_ueid_cfg cfg; - uint32_t pattern3_upi = 0; - uint32_t eid_idx = 0; - - if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) - return; - - if (dev->attr.virtualization || - ubcore_find_upi_with_dev_name(dev->dev_name, &pattern3_upi) == NULL) - return; - - if (pattern3_upi != (uint32_t)UCBORE_INVALID_UPI) { - cfg.eid = *eid; - cfg.eid_index = eid_idx; - cfg.upi = pattern3_upi; - if (is_add) - (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); - else - (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); - } else { - ubcore_log_err("upi not configured\n"); - } -} - -int ubcore_show_utp_ops(struct sk_buff *skb, struct genl_info *info) -{ - struct ubcore_res_utp_val utp_info = {0}; - struct ubcore_res_key key = {0}; - struct ubcore_res_val val = {0}; - struct ubcore_cmd_show_utp arg; - struct ubcore_device *dev; - uint64_t args_addr; - int ret = -EINVAL; - - if (!info->attrs[UBCORE_HDR_ARGS_LEN] || !info->attrs[UBCORE_HDR_ARGS_ADDR]) - return ret; - args_addr = nla_get_u64(info->attrs[UBCORE_HDR_ARGS_ADDR]); - ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)args_addr, - sizeof(struct ubcore_cmd_show_utp)); - if (ret != 0) - return -EPERM; - - arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; - dev = ubcore_find_device_with_name(arg.in.dev_name); - if (dev == NULL) { - ubcore_log_err("find dev failed, dev:%s, arg_in: %s.\n", - dev == NULL ? "NULL" : dev->dev_name, arg.in.dev_name); - return -EINVAL; - } - - key.type = UBCORE_RES_KEY_UTP; - key.key = arg.in.utpn; - val.addr = (uint64_t)&utp_info; - val.len = (uint32_t)sizeof(struct ubcore_res_utp_val); - if (dev->ops != NULL && dev->ops->query_res != NULL && - dev->ops->query_res(dev, &key, &val) != 0) { - ubcore_put_device(dev); - ubcore_log_err("failed to query res.\n"); - return -1; - } - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)arg.out.addr, &utp_info, - sizeof(struct ubcore_res_utp_val)); - - ubcore_put_device(dev); - return ret; -} - int ubcore_query_stats_ops(struct sk_buff *skb, struct genl_info *info) { struct ubcore_cmd_query_stats arg = {0}; @@ -292,6 +205,16 @@ static int ubcore_update_ueid(struct netlink_callback *cb, enum ubcore_msg_opcod return 0; } +static int ubcore_clear_eid(struct ubcore_device *dev, union ubcore_eid *eid) +{ + uint32_t eid_idx = 0; + + if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, false, NULL) != 0) + return -1; + + return ubcore_send_eid_update_req(dev, UBCORE_DEL_NET_ADDR, eid, eid_idx, NULL); +} + int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) { struct ubcore_cmd_set_eid_mode arg; @@ -316,10 +239,22 @@ int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) ubcore_log_err("find dev_name: %s failed.\n", arg.in.dev_name); return -EPERM; } + if ((dev->transport_type == UBCORE_TRANSPORT_IB || + dev->transport_type == UBCORE_TRANSPORT_IP) && + arg.in.eid_mode == 0) { + ubcore_log_err( + "only dynamic mode is supported for IB/IP dev_name: %s.\n", arg.in.dev_name); + ubcore_put_device(dev); + return -EINVAL; + } if (dev->dynamic_eid == arg.in.eid_mode) { ubcore_put_device(dev); return 0; } + if (IS_ERR_OR_NULL(dev->eid_table.eid_entries)) { + ubcore_put_device(dev); + return -EINVAL; + } /* change eid mode, need to flush eids */ event.ub_dev = dev; @@ -327,10 +262,7 @@ int ubcore_set_eid_mode_ops(struct sk_buff *skb, struct genl_info *info) for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { if (dev->eid_table.eid_entries[i].valid == true) { eid = dev->eid_table.eid_entries[i].eid; - if (dev->attr.pattern == (uint8_t)UBCORE_PATTERN_1) - ubcore_update_pattern1_eid(dev, &eid, false); - else - ubcore_update_pattern3_eid(dev, &eid, false); + (void)ubcore_clear_eid(dev, &eid); event.element.eid_idx = i; ubcore_dispatch_async_event(&event); } @@ -728,12 +660,6 @@ static uint32_t ubcore_get_list_res_len(uint32_t type, struct netlink_callback * case UBCORE_RES_KEY_SEG: cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_SEGVAL_SEG_CNT; return (uint32_t)sizeof(struct ubcore_res_seg_val); - case UBCORE_RES_KEY_DEV_TA: - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_SEG_CNT; - return (uint32_t)sizeof(struct ubcore_res_dev_ta_val); - case UBCORE_RES_KEY_DEV_TP: - cb->args[CB_ARGS_NEXT_TYPE] = UBCORE_RES_DEV_VTP_CNT; - return (uint32_t)sizeof(struct ubcore_res_dev_tp_val); default: break; } @@ -826,8 +752,6 @@ static int ubcore_list_res_done(struct netlink_callback *cb) uint32_t type = (uint32_t)(unsigned long)cb->args[CB_ARGS_CMD_TYPE]; void *res_buf = (void *)cb->args[CB_ARGS_DEV_BUF]; struct ubcore_res_seg_val *seg_val; - struct ubcore_res_dev_ta_val *ta_val; - struct ubcore_res_dev_tp_val *tp_val; struct ubcore_res_list_val *list_val; switch (type) { @@ -848,14 +772,6 @@ static int ubcore_list_res_done(struct netlink_callback *cb) seg_val = res_buf; vfree(seg_val->seg_list); break; - case UBCORE_RES_KEY_DEV_TA: - ta_val = res_buf; - vfree(ta_val); - break; - case UBCORE_RES_KEY_DEV_TP: - tp_val = res_buf; - vfree(tp_val); - break; default: break; } diff --git a/drivers/ub/urma/ubcore/ubcore_hash_table.c b/drivers/ub/urma/ubcore/ubcore_hash_table.c index 2c8ffe59f8fb..5ce0e289d78d 100644 --- a/drivers/ub/urma/ubcore/ubcore_hash_table.c +++ b/drivers/ub/urma/ubcore/ubcore_hash_table.c @@ -57,12 +57,14 @@ void ubcore_hash_table_free_with_cb(struct ubcore_hash_table *ht, void (*free_cb hlist_for_each_safe(pos, next, &ht->head[i]) { obj = ubcore_ht_obj(ht, pos); hlist_del(pos); + spin_unlock(&ht->lock); if (free_cb != NULL) free_cb(obj); else if (ht->p.free_f != NULL) ht->p.free_f(obj); else kfree(obj); + spin_lock(&ht->lock); } } head = ht->head; @@ -100,7 +102,7 @@ void ubcore_hash_table_remove_nolock(struct ubcore_hash_table *ht, struct hlist_ if (ht->head == NULL) return; - hlist_del(hnode); + hlist_del_init(hnode); } void ubcore_hash_table_remove(struct ubcore_hash_table *ht, struct hlist_node *hnode) @@ -110,6 +112,18 @@ void ubcore_hash_table_remove(struct ubcore_hash_table *ht, struct hlist_node *h spin_unlock(&ht->lock); } +int ubcore_hash_table_check_remove(struct ubcore_hash_table *ht, struct hlist_node *hnode) +{ + spin_lock(&ht->lock); + if (hlist_unhashed(hnode)) { + spin_unlock(&ht->lock); + return -EINVAL; + } + ubcore_hash_table_remove_nolock(ht, hnode); + spin_unlock(&ht->lock); + return 0; +} + void *ubcore_hash_table_lookup_nolock_get(struct ubcore_hash_table *ht, uint32_t hash, const void *key) { diff --git a/drivers/ub/urma/ubcore/ubcore_hash_table.h b/drivers/ub/urma/ubcore/ubcore_hash_table.h index 4de04ddadbae..44316e307f0e 100644 --- a/drivers/ub/urma/ubcore/ubcore_hash_table.h +++ b/drivers/ub/urma/ubcore/ubcore_hash_table.h @@ -43,6 +43,7 @@ void ubcore_hash_table_add(struct ubcore_hash_table *ht, struct hlist_node *hnod void ubcore_hash_table_add_nolock(struct ubcore_hash_table *ht, struct hlist_node *hnode, uint32_t hash); void ubcore_hash_table_remove(struct ubcore_hash_table *ht, struct hlist_node *hnode); +int ubcore_hash_table_check_remove(struct ubcore_hash_table *ht, struct hlist_node *hnode); void ubcore_hash_table_remove_nolock(struct ubcore_hash_table *ht, struct hlist_node *hnode); void *ubcore_hash_table_lookup(struct ubcore_hash_table *ht, uint32_t hash, const void *key); void *ubcore_hash_table_lookup_nolock(struct ubcore_hash_table *ht, uint32_t hash, diff --git a/drivers/ub/urma/ubcore/ubcore_jetty.c b/drivers/ub/urma/ubcore/ubcore_jetty.c index 71bbf694c999..edf8e2e53188 100644 --- a/drivers/ub/urma/ubcore/ubcore_jetty.c +++ b/drivers/ub/urma/ubcore/ubcore_jetty.c @@ -36,6 +36,94 @@ #include "ubcore_device.h" #include "urma/ubcore_jetty.h" +static void ubcore_jfs_kref_release(struct kref *ref_cnt) +{ + struct ubcore_jfs *jfs = container_of(ref_cnt, struct ubcore_jfs, ref_cnt); + + complete(&jfs->comp); +} + +void ubcore_put_jfs(struct ubcore_jfs *jfs) +{ + if (jfs != NULL) + (void)kref_put(&jfs->ref_cnt, ubcore_jfs_kref_release); +} + +void ubcore_jfs_get(void *obj) +{ + struct ubcore_jfs *jfs = obj; + + kref_get(&jfs->ref_cnt); +} + +static void ubcore_jfr_kref_release(struct kref *ref_cnt) +{ + struct ubcore_jfr *jfr = container_of(ref_cnt, struct ubcore_jfr, ref_cnt); + + complete(&jfr->comp); +} + +void ubcore_put_jfr(struct ubcore_jfr *jfr) +{ + if (jfr != NULL) + (void)kref_put(&jfr->ref_cnt, ubcore_jfr_kref_release); +} + +void ubcore_jfr_get(void *obj) +{ + struct ubcore_jfr *jfr = obj; + + kref_get(&jfr->ref_cnt); +} + +static void ubcore_jetty_kref_release(struct kref *ref_cnt) +{ + struct ubcore_jetty *jetty = container_of(ref_cnt, struct ubcore_jetty, ref_cnt); + + complete(&jetty->comp); +} + +void ubcore_put_jetty(struct ubcore_jetty *jetty) +{ + if (jetty != NULL) + (void)kref_put(&jetty->ref_cnt, ubcore_jetty_kref_release); +} + +void ubcore_jetty_get(void *obj) +{ + struct ubcore_jetty *jetty = obj; + + kref_get(&jetty->ref_cnt); +} + +struct ubcore_jfs *ubcore_find_get_jfs(struct ubcore_device *dev, uint32_t jfs_id) +{ + if (dev == NULL) { + ubcore_log_err("dev is NULL\n"); + return NULL; + } + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_JFS], jfs_id, &jfs_id); +} + +struct ubcore_jfr *ubcore_find_get_jfr(struct ubcore_device *dev, uint32_t jfr_id) +{ + if (dev == NULL) { + ubcore_log_err("dev is NULL\n"); + return NULL; + } + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_JFR], jfr_id, &jfr_id); +} + +struct ubcore_jetty *ubcore_find_get_jetty(struct ubcore_device *dev, uint32_t jetty_id) +{ + if (dev == NULL) { + ubcore_log_err("invalid parameter.\n"); + return NULL; + } + + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_JETTY], jetty_id, &jetty_id); +} + struct ubcore_jfc *ubcore_find_jfc(struct ubcore_device *dev, uint32_t jfc_id) { if (dev == NULL) { @@ -91,7 +179,7 @@ struct ubcore_jfc *ubcore_create_jfc(struct ubcore_device *dev, struct ubcore_jf jfc = dev->ops->create_jfc(dev, cfg, udata); if (IS_ERR_OR_NULL(jfc)) { ubcore_log_err("failed to create jfc.\n"); - return jfc == NULL ? ERR_PTR(-ENOEXEC) : jfc; + return UBCORE_CHECK_RETURN_ERR_PTR(jfc, ENOSPC); } if (check_and_fill_jfc_attr(&jfc->jfc_cfg, cfg) != 0) { @@ -171,6 +259,11 @@ EXPORT_SYMBOL(ubcore_delete_jfc); static int check_jfs_cfg(struct ubcore_device *dev, struct ubcore_jfs_cfg *cfg) { + if (ubcore_check_trans_mode_valid(cfg->trans_mode) != true) { + ubcore_log_err("Invalid parameter, trans_mode: %d.\n", (int)cfg->trans_mode); + return -EINVAL; + } + if (cfg->depth == 0 || cfg->depth > dev->attr.dev_cap.max_jfs_depth) { ubcore_log_err("Invalid parameter, depth:%u, max_depth:%u.\n", cfg->depth, dev->attr.dev_cap.max_jfs_depth); @@ -236,7 +329,7 @@ struct ubcore_jfs *ubcore_create_jfs(struct ubcore_device *dev, struct ubcore_jf jfs = dev->ops->create_jfs(dev, cfg, udata); if (IS_ERR_OR_NULL(jfs)) { ubcore_log_err("failed to create jfs.\n"); - return jfs == NULL ? ERR_PTR(-ENOEXEC) : jfs; + return UBCORE_CHECK_RETURN_ERR_PTR(jfs, ENOSPC); } /* Prevent ubcore private data from being modified */ @@ -258,6 +351,8 @@ struct ubcore_jfs *ubcore_create_jfs(struct ubcore_device *dev, struct ubcore_jf } } atomic_set(&jfs->use_cnt, 0); + kref_init(&jfs->ref_cnt); + init_completion(&jfs->comp); ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFS], &jfs->hnode, jfs->jfs_id.id); if (ret != 0) { @@ -328,8 +423,14 @@ int ubcore_delete_jfs(struct ubcore_jfs *jfs) jfc = jfs->jfs_cfg.jfc; jfs_id = jfs->jfs_id.id; dev = jfs->ub_dev; - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFS], &jfs->hnode); + + if (ubcore_hash_table_check_remove(&dev->ht[UBCORE_HT_JFS], &jfs->hnode) != 0) + return -EINVAL; ubcore_destroy_tptable(&jfs->tptable); + + ubcore_put_jfs(jfs); + wait_for_completion(&jfs->comp); + ret = dev->ops->destroy_jfs(jfs); if (ret != 0) { ubcore_log_err("UBEP failed to destroy jfs, jfs_id:%u.\n", jfs_id); @@ -341,6 +442,7 @@ int ubcore_delete_jfs(struct ubcore_jfs *jfs) return ret; rollback: + kref_get(&jfs->ref_cnt); if (ubcore_jfs_need_advise(jfs)) jfs->tptable = ubcore_create_tptable(); (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFS], &jfs->hnode, jfs->jfs_id.id); @@ -379,6 +481,16 @@ static int check_and_fill_jfr_attr(struct ubcore_jfr_cfg *cfg, struct ubcore_jfr return 0; } +static int ubcore_check_jfr_cfg(struct ubcore_jfr_cfg *cfg) +{ + if (ubcore_check_trans_mode_valid(cfg->trans_mode) != true) { + ubcore_log_err("Invalid parameter, trans_mode: %d.\n", (int)cfg->trans_mode); + return -1; + } + + return 0; +} + struct ubcore_jfr *ubcore_create_jfr(struct ubcore_device *dev, struct ubcore_jfr_cfg *cfg, ubcore_event_callback_t jfae_handler, struct ubcore_udata *udata) { @@ -390,10 +502,13 @@ struct ubcore_jfr *ubcore_create_jfr(struct ubcore_device *dev, struct ubcore_jf !ubcore_eid_accessible(dev, cfg->eid_index)) return ERR_PTR(-EINVAL); + if (ubcore_check_jfr_cfg(cfg) != 0) + return ERR_PTR(-EINVAL); + jfr = dev->ops->create_jfr(dev, cfg, udata); if (IS_ERR_OR_NULL(jfr)) { ubcore_log_err("failed to create jfr.\n"); - return jfr == NULL ? ERR_PTR(-ENOEXEC) : jfr; + return UBCORE_CHECK_RETURN_ERR_PTR(jfr, ENOSPC); } if (check_and_fill_jfr_attr(&jfr->jfr_cfg, cfg) != 0) { @@ -414,6 +529,8 @@ struct ubcore_jfr *ubcore_create_jfr(struct ubcore_device *dev, struct ubcore_jf } } atomic_set(&jfr->use_cnt, 0); + kref_init(&jfr->ref_cnt); + init_completion(&jfr->comp); ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFR], &jfr->hnode, jfr->jfr_id.id); if (ret != 0) { @@ -489,8 +606,14 @@ int ubcore_delete_jfr(struct ubcore_jfr *jfr) jfc = jfr->jfr_cfg.jfc; jfr_id = jfr->jfr_id.id; dev = jfr->ub_dev; - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JFR], &jfr->hnode); + + if (ubcore_hash_table_check_remove(&dev->ht[UBCORE_HT_JFR], &jfr->hnode) != 0) + return -EINVAL; ubcore_destroy_tptable(&jfr->tptable); + + ubcore_put_jfr(jfr); + wait_for_completion(&jfr->comp); + ret = dev->ops->destroy_jfr(jfr); if (ret != 0) { ubcore_log_err("UBEP failed to destroy jfr, jfr_id:%u.\n", jfr_id); @@ -502,6 +625,7 @@ int ubcore_delete_jfr(struct ubcore_jfr *jfr) return ret; rollback: + kref_get(&jfr->ref_cnt); if (ubcore_jfr_need_advise(jfr)) jfr->tptable = ubcore_create_tptable(); (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JFR], &jfr->hnode, jfr->jfr_id.id); @@ -631,7 +755,8 @@ static int check_jetty_cfg(struct ubcore_device *dev, struct ubcore_jetty_cfg *c return -1; } if (cfg->flag.bs.share_jfr != 0 && - (cfg->jfr == NULL || cfg->jfr->jfr_cfg.trans_mode != cfg->trans_mode)) { + (cfg->jfr == NULL || cfg->jfr->jfr_cfg.trans_mode != cfg->trans_mode || + cfg->jfr->jfr_cfg.flag.bs.sub_trans_mode != cfg->flag.bs.sub_trans_mode)) { ubcore_log_err("jfr is null or trans_mode invalid with shared jfr flag.\n"); return -1; } @@ -793,7 +918,7 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor jetty = dev->ops->create_jetty(dev, cfg, udata); if (IS_ERR_OR_NULL(jetty)) { ubcore_log_err("failed to create jetty.\n"); - return jetty == NULL ? ERR_PTR(-ENOEXEC) : jetty; + return UBCORE_CHECK_RETURN_ERR_PTR(jetty, ENOSPC); } jetty->ub_dev = dev; @@ -825,6 +950,8 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor jetty->tptable = NULL; /* To prevent kernel-mode drivers, malloc is not empty */ } atomic_set(&jetty->use_cnt, 0); + kref_init(&jetty->ref_cnt); + init_completion(&jetty->comp); ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode, jetty->jetty_id.id); @@ -893,17 +1020,8 @@ int ubcore_query_jetty(struct ubcore_jetty *jetty, struct ubcore_jetty_cfg *cfg, } EXPORT_SYMBOL(ubcore_query_jetty); -int ubcore_delete_jetty(struct ubcore_jetty *jetty) +static int ubcore_check_jetty_attr(struct ubcore_jetty *jetty) { - struct ubcore_jetty_group *jetty_grp; - struct ubcore_vtp_param vtp_param; - struct ubcore_jfc *send_jfc; - struct ubcore_jfc *recv_jfc; - struct ubcore_device *dev; - struct ubcore_jfr *jfr; - uint32_t jetty_id; - int ret; - if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops == NULL || jetty->ub_dev->ops->destroy_jetty == NULL) return -1; @@ -915,13 +1033,32 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) return -1; } + return 0; +} + +int ubcore_delete_jetty(struct ubcore_jetty *jetty) +{ + struct ubcore_jetty_group *jetty_grp; + struct ubcore_vtp_param vtp_param; + struct ubcore_jfc *send_jfc; + struct ubcore_jfc *recv_jfc; + struct ubcore_device *dev; + struct ubcore_jfr *jfr; + uint32_t jetty_id; + int ret; + + if (ubcore_check_jetty_attr(jetty) != 0) + return -EINVAL; + jetty_grp = jetty->jetty_cfg.jetty_grp; send_jfc = jetty->jetty_cfg.send_jfc; recv_jfc = jetty->jetty_cfg.recv_jfc; jfr = jetty->jetty_cfg.jfr; jetty_id = jetty->jetty_id.id; dev = jetty->ub_dev; - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode); + + if (ubcore_hash_table_check_remove(&dev->ht[UBCORE_HT_JETTY], &jetty->hnode) != 0) + return -EINVAL; ubcore_destroy_tptable(&jetty->tptable); if (jetty->ub_dev->transport_type == UBCORE_TRANSPORT_UB && jetty->remote_jetty != NULL) { @@ -937,6 +1074,9 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) ubcore_log_warn("jetty->remote_jetty != NULL and it has been handled"); } + ubcore_put_jetty(jetty); + wait_for_completion(&jetty->comp); + if (jetty_grp != NULL) (void)ubcore_remove_jetty_from_jetty_grp(jetty, jetty_grp); ret = dev->ops->destroy_jetty(jetty); @@ -954,6 +1094,7 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) return ret; rollback: + kref_get(&jetty->ref_cnt); if (jetty_grp != NULL) (void)ubcore_add_jetty_to_jetty_grp(jetty, jetty_grp); if (ubcore_jetty_need_advise(jetty) || jetty->jetty_cfg.trans_mode == UBCORE_TP_RC) @@ -990,7 +1131,7 @@ struct ubcore_tjetty *ubcore_import_jetty(struct ubcore_device *dev, tjetty = dev->ops->import_jetty(dev, cfg, udata); if (IS_ERR_OR_NULL(tjetty)) { ubcore_log_err("UBEP failed to import jetty, jetty_id:%u.\n", cfg->id.id); - return tjetty == NULL ? ERR_PTR(-ENOEXEC) : tjetty; + return UBCORE_CHECK_RETURN_ERR_PTR(tjetty, ENOEXEC); } tjetty->cfg = *cfg; tjetty->ub_dev = dev; @@ -1265,6 +1406,13 @@ static int ubcore_inner_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tje jetty->jetty_cfg.flag.bs.rc_share_tp)) { ubcore_set_vtp_param(dev, jetty, &tjetty->cfg, &vtp_param); mutex_lock(&tjetty->lock); + + if (tjetty->vtpn != NULL) { + mutex_unlock(&tjetty->lock); + ubcore_log_err("Duplicate bind\n"); + ret = -EEXIST; + goto unbind; + } vtpn = ubcore_connect_vtp(dev, &vtp_param); if (IS_ERR_OR_NULL(vtpn)) { mutex_unlock(&tjetty->lock); @@ -1277,7 +1425,8 @@ static int ubcore_inner_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tje tjetty->vtpn = vtpn; mutex_unlock(&tjetty->lock); } - } else if (dev->transport_type == UBCORE_TRANSPORT_IB) { + } else if (dev->transport_type == UBCORE_TRANSPORT_HNS_UB || + dev->transport_type == UBCORE_TRANSPORT_IB) { ret = ubcore_advice_jetty_tjetty(&advice, jetty, tjetty); if (ret != 0) return ret; @@ -1325,7 +1474,8 @@ int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, return -1; } - if (tjetty->vtpn != NULL) { + if (tjetty->vtpn != NULL && (!is_create_rc_shared_tp(tjetty->cfg.trans_mode, + tjetty->cfg.flag.bs.sub_trans_mode, tjetty->cfg.flag.bs.rc_share_tp))) { ubcore_log_err("The tjetty, has already connect vtpn, prevent duplicate bind.\n"); return -1; } @@ -1370,7 +1520,8 @@ int ubcore_unbind_jetty(struct ubcore_jetty *jetty) mutex_unlock(&tjetty->lock); } } - } else if (dev->transport_type == UBCORE_TRANSPORT_IB) { + } else if (dev->transport_type == UBCORE_TRANSPORT_HNS_UB || + dev->transport_type == UBCORE_TRANSPORT_IB) { ret = ubcore_advice_jetty_tjetty(&advice, jetty, tjetty); if (ret != 0) return ret; @@ -1440,7 +1591,7 @@ struct ubcore_jetty_group *ubcore_create_jetty_grp(struct ubcore_device *dev, jetty_grp = dev->ops->create_jetty_grp(dev, (struct ubcore_jetty_grp_cfg *)cfg, udata); if (IS_ERR_OR_NULL(jetty_grp)) { ubcore_log_err("failed to create jetty_grp.\n"); - return jetty_grp == NULL ? ERR_PTR(-ENOEXEC) : jetty_grp; + return UBCORE_CHECK_RETURN_ERR_PTR(jetty_grp, ENOSPC); } jetty_grp->jetty = kzalloc( diff --git a/drivers/ub/urma/ubcore/ubcore_main.c b/drivers/ub/urma/ubcore/ubcore_main.c index e7b859b11f7b..9914be8b9564 100644 --- a/drivers/ub/urma/ubcore/ubcore_main.c +++ b/drivers/ub/urma/ubcore/ubcore_main.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "ubcore_cmd.h" @@ -44,6 +43,8 @@ #include "ubcore_workqueue.h" #include "ubcore_device.h" +#include "ubcore_main.h" + #define UBCORE_LOG_FILE_PERMISSION (0644) module_param(g_ubcore_log_level, uint, UBCORE_LOG_FILE_PERMISSION); @@ -96,41 +97,72 @@ struct ubcore_notify_uvs_sip_event_work { uint32_t index; }; -static void ubcore_update_pattern1_eid(struct ubcore_device *dev, - union ubcore_eid *eid, uint32_t eid_idx, bool is_add) +struct ubcore_version { + uint32_t version; /* UBCORE_INVALID_VERSION: not negotiated yet. */ + uint32_t cap; /* Currently, not used. */ +}; + +static struct ubcore_version g_ubcore_version = {UBCORE_INVALID_VERSION, 0}; +/* Versions should be in decending order. */ +static uint32_t g_ubcore_support_versions[UBCORE_SUPPORT_VERION_NUM] = {UBCORE_VERSION0}; + +bool ubcore_negotiated(void) { - struct ubcore_ueid_cfg cfg; + return g_ubcore_version.version != UBCORE_INVALID_VERSION; +} - cfg.eid = *eid; - cfg.eid_index = eid_idx; - cfg.upi = 0; - if (is_add) - (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); - else - (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); +uint32_t ubcore_get_version(void) +{ + return g_ubcore_version.version; } -static void ubcore_update_pattern3_eid(struct ubcore_device *dev, - union ubcore_eid *eid, uint32_t eid_idx, bool is_add) +void ubcore_set_version(uint32_t version) { - uint32_t pattern3_upi = 0; - struct ubcore_ueid_cfg cfg; + g_ubcore_version.version = version; +} - if (dev->attr.virtualization || - ubcore_find_upi_with_dev_name(dev->dev_name, &pattern3_upi) == NULL) - return; +uint32_t ubcore_get_cap(void) +{ + return g_ubcore_version.cap; +} - if (pattern3_upi != (uint32_t)UCBORE_INVALID_UPI) { - cfg.eid = *eid; - cfg.eid_index = eid_idx; - cfg.upi = pattern3_upi; - if (is_add) - (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); - else - (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); - } else { - ubcore_log_err("upi not configured\n"); +void ubcore_set_cap(uint32_t cap) +{ + g_ubcore_version.cap = cap; +} + +uint32_t *ubcore_get_support_versions(void) +{ + return g_ubcore_support_versions; +} + +/* Caller should ensure parameters are not NULL. */ +int ubcore_negotiate_version(struct ubcore_msg_nego_ver_req *req, uint32_t *ver, uint32_t *cap) +{ + uint32_t ver_ = UBCORE_INVALID_VERSION; + uint32_t cap_ = UBCORE_CAP & req->cap; + uint32_t i, j; + + for (i = 0; i < req->version_num; i++) { + for (j = 0; j < UBCORE_SUPPORT_VERION_NUM; j++) { + if (req->versions[i] == g_ubcore_support_versions[j]) { + ver_ = req->versions[i]; + break; + } + } } + + if (ver_ == UBCORE_INVALID_VERSION) + return -1; + + *ver = ver_; + *cap = cap_; + return 0; +} + +int ubcore_open(struct inode *i_node, struct file *filp) +{ + return 0; } static void ubcore_ipv4_to_netaddr(struct ubcore_net_addr *netaddr, __be32 ipv4) @@ -175,18 +207,15 @@ static enum ubcore_mtu sip_get_mtu_with_ub(uint32_t mtu) return (enum ubcore_mtu)0; } -static void ubcore_sip_init(struct ubcore_sip_info *sip, struct ubcore_device *tpf_dev, - const struct ubcore_net_addr *netaddr, uint8_t *port_list, - uint8_t port_cnt, struct net_device *netdev) +static void ubcore_sip_init(struct ubcore_sip_info *sip, struct ubcore_device *dev, + const struct ubcore_net_addr *netaddr, struct net_device *netdev) { - (void)memcpy(sip->dev_name, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); + (void)memcpy(sip->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME); (void)memcpy(&sip->addr, netaddr, sizeof(struct ubcore_net_addr)); - if (port_list != NULL) - (void)memcpy(sip->port_id, port_list, UBCORE_MAX_PORT_CNT); - sip->port_cnt = port_cnt; - sip->mtu = tpf_dev->transport_type == UBCORE_TRANSPORT_UB ? - (uint32_t)sip_get_mtu_with_ub(netdev->mtu) : - (uint32_t)sip_get_mtu(netdev->mtu); + + ubcore_fill_port_netdev(dev, netdev, sip->port_id, &sip->port_cnt); + sip->mtu = dev->transport_type == UBCORE_TRANSPORT_UB ? + (uint32_t)sip_get_mtu_with_ub(netdev->mtu) : (uint32_t)sip_get_mtu(netdev->mtu); (void)memcpy(sip->netdev_name, netdev_name(netdev), UBCORE_MAX_DEV_NAME); } @@ -275,57 +304,133 @@ static int ubcore_notify_uvs_update_sip_manage(struct ubcore_device *tpf_dev, return ret; } -static void ubcore_add_net_addr(struct ubcore_device *tpf_dev, struct ubcore_device *pf_dev, - struct ubcore_net_addr *netaddr, struct net_device *netdev, bool async) + +static int ubcore_get_upi(char *dev_name, uint32_t pattern, uint32_t *upi) { - struct ubcore_sip_info sip = {0}; - uint8_t *port_list = NULL; - uint8_t port_cnt = 0; - uint32_t index; + if (pattern == UBCORE_PATTERN_1) { + *upi = 0; + return 0; + } + + if (pattern == UBCORE_PATTERN_3) { + if (ubcore_find_upi_with_dev_name(dev_name, upi) == NULL) { + ubcore_log_err("can not find dev:%s\n", dev_name); + return -EINVAL; + } + + if (*upi == (uint32_t)UCBORE_INVALID_UPI) { + ubcore_log_err("dev:%s not cfg upi in pattern3 mode\n", dev_name); + return -EINVAL; + } + return 0; + } + + ubcore_log_err("Invalid pattern\n"); + return -EINVAL; +} + +static int ubcore_handle_update_eid(struct ubcore_device *tpf_dev, uint32_t fe_idx, + enum ubcore_net_addr_op op, struct ubcore_eid_update_info *eid_info) +{ + struct ubcore_ueid_cfg cfg = {0}; + + cfg.eid = eid_info->eid; + cfg.eid_index = eid_info->eid_idx; + + if (eid_info->upi_present) { + cfg.upi = eid_info->upi; + } else { + if (ubcore_get_upi(eid_info->dev_name, eid_info->pattern, &cfg.upi) != 0) { + ubcore_log_err("Failed to upi, dev:%s, idx:%u", + eid_info->dev_name, eid_info->eid_idx); + return -ENXIO; + } + } + + if (op == UBCORE_ADD_NET_ADDR) + return ubcore_add_ueid(tpf_dev, fe_idx, &cfg); + + if (op == UBCORE_DEL_NET_ADDR) + return ubcore_delete_ueid(tpf_dev, fe_idx, &cfg); + + return -EINVAL; +} + +int ubcore_recv_eid_update_req(struct ubcore_device *tpf_dev, struct ubcore_req_host *req) +{ + struct ubcore_update_eid_req *msg_data = (struct ubcore_update_eid_req *)req->req.data; + + ubcore_handle_update_eid(tpf_dev, req->src_fe_idx, msg_data->op, &msg_data->eid_info); + return 0; +} + +int ubcore_send_eid_update_req(struct ubcore_device *dev, enum ubcore_net_addr_op op, + union ubcore_eid *eid, uint32_t eid_idx, uint32_t *upi) +{ + uint32_t data_len = (uint32_t)sizeof(struct ubcore_update_eid_req); + struct ubcore_update_eid_req *msg_data; + struct ubcore_req *req; int ret; - /* get driver set nedev port */ - ubcore_find_port_netdev(pf_dev, netdev, &port_list, &port_cnt); - ubcore_sip_init(&sip, tpf_dev, netaddr, port_list, port_cnt, netdev); + req = kzalloc(sizeof(struct ubcore_req) + data_len, GFP_KERNEL); + if (req == NULL) + return -ENOMEM; + req->opcode = UBCORE_MSP_UPDATE_EID; + req->len = data_len; + + msg_data = (struct ubcore_update_eid_req *)req->data; + + msg_data->op = op; + msg_data->eid_info.eid = *eid; + msg_data->eid_info.pattern = dev->attr.pattern; + if (upi) { + msg_data->eid_info.upi_present = true; + msg_data->eid_info.upi = *upi; + } + + if (dev->attr.tp_maintainer) + ret = ubcore_handle_update_eid(dev, dev->attr.fe_idx, + msg_data->op, &msg_data->eid_info); + else + /* handle by backend ubcore: ubcore_recv_eid_update_req */ + ret = ubcore_send_req(dev, req); + kfree(req); + return ret; +} - ret = ubcore_lookup_sip_idx(&tpf_dev->sip_table, &sip, &index); +static void ubcore_handle_add_sip(struct ubcore_device *tpf_dev, + struct ubcore_sip_info *sip, bool async) +{ + uint32_t index; + int ret; + + ret = ubcore_lookup_sip_idx(&tpf_dev->sip_table, sip, &index); if (ret == 0) { ubcore_log_err("sip already exists\n"); return; } + index = (uint32_t)ubcore_sip_idx_alloc(&tpf_dev->sip_table); if (tpf_dev->ops != NULL && tpf_dev->ops->add_net_addr != NULL && - tpf_dev->ops->add_net_addr(tpf_dev, netaddr, index) != 0) + tpf_dev->ops->add_net_addr(tpf_dev, &sip->addr, index) != 0) ubcore_log_err("Failed to set net addr"); /* add net_addr entry, record idx -> netaddr mapping */ - (void)ubcore_add_sip_entry(&tpf_dev->sip_table, &sip, index); + (void)ubcore_add_sip_entry(&tpf_dev->sip_table, sip, index); /* nodify uvs add sip info */ - if (ubcore_notify_uvs_update_sip_manage(tpf_dev, &sip, NULL, + if (ubcore_notify_uvs_update_sip_manage(tpf_dev, sip, NULL, UBCORE_SIP_ADD, index, async) != 0) - ubcore_log_err("kzalloc failed or queue type err"); - - /* The ubcore sip table and up/down events are updated synchronously, and the uvs - * is abnormally disconnected. After waiting for the pull-up, - * the sip table in the kernel state is actively synchronized. - */ + ubcore_log_err("notify uvs sip failed"); } -static void ubcore_delete_net_addr(struct ubcore_device *tpf_dev, struct ubcore_device *pf_dev, - struct ubcore_net_addr *netaddr, struct net_device *netdev, bool async) +static void ubcore_handle_delete_sip(struct ubcore_device *tpf_dev, + struct ubcore_sip_info *sip, bool async) { - struct ubcore_sip_info sip = {0}; - uint8_t *port_list = NULL; - uint8_t port_cnt = 0; uint32_t index; - ubcore_find_port_netdev(pf_dev, netdev, &port_list, &port_cnt); - - ubcore_sip_init(&sip, tpf_dev, - netaddr, port_list, port_cnt, netdev); - if (ubcore_lookup_sip_idx(&tpf_dev->sip_table, &sip, &index) != 0) + if (ubcore_lookup_sip_idx(&tpf_dev->sip_table, sip, &index) != 0) return; if (tpf_dev->ops != NULL && tpf_dev->ops->delete_net_addr != NULL && @@ -335,47 +440,103 @@ static void ubcore_delete_net_addr(struct ubcore_device *tpf_dev, struct ubcore_ (void)ubcore_del_sip_entry(&tpf_dev->sip_table, index); (void)ubcore_sip_idx_free(&tpf_dev->sip_table, index); /* nodify uvs delete sip info */ - if (ubcore_notify_uvs_update_sip_manage(tpf_dev, NULL, &sip, - UBCORE_SIP_DEL, index, async) != 0) - ubcore_log_err("kzalloc failed or queue type err"); + if (ubcore_notify_uvs_update_sip_manage( + tpf_dev, NULL, sip, UBCORE_SIP_DEL, index, async) != 0) + ubcore_log_err("notify uvs sip failed"); +} - /* The ubcore sip table and up/down events are updated synchronously, - * and the uvs is abnormally disconnected. After waiting for the pull-up, - * the sip table in the kernel state is actively synchronized - */ +static void ubcore_handle_update_sip(struct ubcore_device *tpf_dev, + struct ubcore_sip_info *sip, bool async) +{ + struct ubcore_sip_info old_sip = {0}; + uint32_t sip_idx; + int ret = 0; + + ret = ubcore_update_sip_entry(&tpf_dev->sip_table, sip, &sip_idx, &old_sip); + if (ret != 0) { + ubcore_log_err("Failed to update sip"); + return; + } + + if (ubcore_notify_uvs_update_sip_manage(tpf_dev, sip, &old_sip, UBCORE_SIP_UPDATE, + sip_idx, async) != 0) + ubcore_log_err("notify uvs sip failed"); +} + +static int ubcore_handle_update_net_addr(struct ubcore_device *tpf_dev, uint32_t fe_idx, + struct ubcore_update_net_addr_req *req, bool async) +{ + /* only UB dev need sip */ + if (tpf_dev->transport_type == UBCORE_TRANSPORT_UB && req->sip_present) { + if (req->op == UBCORE_ADD_NET_ADDR) + ubcore_handle_add_sip(tpf_dev, &req->sip_info, async); + else if (req->op == UBCORE_DEL_NET_ADDR) + ubcore_handle_delete_sip(tpf_dev, &req->sip_info, async); + else if (req->op == UBCORE_UPDATE_NET_ADDR) + ubcore_handle_update_sip(tpf_dev, &req->sip_info, async); + } + + if (req->eid_present) + return ubcore_handle_update_eid(tpf_dev, fe_idx, req->op, &req->eid_info); + + return 0; } -static void ubcore_update_eid(struct ubcore_device *dev, - struct ubcore_net_addr *netaddr, bool is_add) +int ubcore_recv_net_addr_update(struct ubcore_device *tpf_dev, struct ubcore_req_host *req) +{ + struct ubcore_update_net_addr_req *msg_data = + (struct ubcore_update_net_addr_req *)req->req.data; + + memcpy(msg_data->sip_info.dev_name, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); + + return ubcore_handle_update_net_addr(tpf_dev, req->src_fe_idx, msg_data, false); +} + +static int ubcore_send_net_addr_update_req(struct ubcore_device *dev, + struct ubcore_update_net_addr_req *add_req) +{ + uint32_t data_len = (uint32_t)sizeof(struct ubcore_update_net_addr_req); + struct ubcore_update_net_addr_req *msg_data; + struct ubcore_req *req; + int ret; + + req = kzalloc(sizeof(struct ubcore_req) + data_len, GFP_KERNEL); + if (req == NULL) + return -ENOMEM; + + req->opcode = UBCORE_MSG_UPDATE_NET_ADDR; + req->len = data_len; + + msg_data = (struct ubcore_update_net_addr_req *)req->data; + *msg_data = *add_req; + + ret = ubcore_send_req(dev, req); // handle by backend ubcore: ubcore_recv_net_addr_update + kfree(req); + return ret; +} + +static int ubcore_update_eid_tbl(struct ubcore_device *dev, + struct ubcore_net_addr *netaddr, bool is_add, struct net *net, uint32_t *eid_idx) { union ubcore_eid *eid; - uint32_t eid_idx = 0; if (dev->transport_type <= UBCORE_TRANSPORT_INVALID || dev->transport_type >= UBCORE_TRANSPORT_MAX) - return; + return -EINVAL; if (!dev->dynamic_eid) { ubcore_log_err("static mode does not allow modify of eid\n"); - return; + return -EINVAL; } eid = (union ubcore_eid *)(void *)&netaddr->net_addr; - if (ubcore_update_eidtbl_by_eid(dev, eid, &eid_idx, is_add) != 0) - return; - if (dev->attr.pattern == (uint8_t)UBCORE_PATTERN_1) - ubcore_update_pattern1_eid(dev, eid, eid_idx, is_add); - else - ubcore_update_pattern3_eid(dev, eid, eid_idx, is_add); + return ubcore_update_eidtbl_by_eid(dev, eid, eid_idx, is_add, net); } static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long event, struct ubcore_net_addr *netaddr) { - struct net_device *real_netdev; - struct ubcore_net_addr real_netaddr; struct ubcore_device **devices; uint32_t num_devices = 0; - struct ubcore_device *tpf_dev; struct ubcore_device *dev; uint32_t i; @@ -383,44 +544,28 @@ static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long if (netdev == NULL || netdev->reg_state >= NETREG_UNREGISTERING) return NOTIFY_DONE; - if (is_vlan_dev(netdev)) { - real_netdev = vlan_dev_real_dev(netdev); - (void)ubcore_fill_netaddr_macvlan(&real_netaddr, real_netdev, netaddr->type); - } else { - real_netdev = netdev; - real_netaddr = *netaddr; - } - ubcore_device_list_lock(); - devices = ubcore_get_devices_from_netdev_nolock(real_netdev, &num_devices); - if (devices == NULL) { - ubcore_device_list_unlock(); + devices = ubcore_get_devices_from_netdev(netdev, &num_devices); + if (devices == NULL) return NOTIFY_DONE; - } for (i = 0; i < num_devices; i++) { dev = devices[i]; if (dev->attr.virtualization) continue; - tpf_dev = ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); + switch (event) { case NETDEV_UP: - if (tpf_dev) - ubcore_add_net_addr(tpf_dev, dev, netaddr, netdev, true); - ubcore_update_eid(dev, netaddr, true); + ubcore_update_net_addr(dev, netdev, netaddr, UBCORE_ADD_NET_ADDR, true); break; case NETDEV_DOWN: - if (tpf_dev) - ubcore_delete_net_addr(tpf_dev, dev, netaddr, netdev, true); - ubcore_update_eid(dev, netaddr, false); + ubcore_update_net_addr(dev, netdev, netaddr, UBCORE_DEL_NET_ADDR, true); break; default: break; } - if (tpf_dev) - ubcore_put_device(tpf_dev); } ubcore_put_devices(devices, num_devices); - ubcore_device_list_unlock(); + return NOTIFY_OK; } @@ -536,11 +681,52 @@ static void ubcore_netdev_get_ipv6(struct net_device *netdev, struct list_head * in6_dev_put(in_dev); } -void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add) +int ubcore_update_net_addr(struct ubcore_device *dev, struct net_device *netdev, + struct ubcore_net_addr *netaddr, enum ubcore_net_addr_op op, bool async) +{ + struct ubcore_update_net_addr_req req = {0}; + uint32_t eid_idx = 0; + int ret = 0; + + req.op = op; + // Only UB DEV need save net_addr as sip + if (dev->transport_type == UBCORE_TRANSPORT_UB) { + ubcore_sip_init(&req.sip_info, dev, netaddr, netdev); + req.sip_present = true; + } + + // Add eid table entry + if ((op == UBCORE_ADD_NET_ADDR || op == UBCORE_DEL_NET_ADDR)) { + ret = ubcore_update_eid_tbl(dev, netaddr, op == UBCORE_ADD_NET_ADDR, + dev_net(netdev), &eid_idx); + if (ret == 0 && dev->dynamic_eid) { + req.eid_present = true; + req.eid_info.eid_idx = eid_idx; + req.eid_info.pattern = dev->attr.pattern; + + memcpy(req.eid_info.eid.raw, netaddr->net_addr.raw, UBCORE_NET_ADDR_BYTES); + memcpy(req.eid_info.dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME); + } + } + + // If dev is not TPF, send msg to TPF + if (dev->attr.tp_maintainer) + ret = ubcore_handle_update_net_addr(dev, dev->attr.fe_idx, &req, async); + else + /* handle by: ubcore_recv_net_addr_update */ + ret = ubcore_send_net_addr_update_req(dev, &req); + + // Delete eid entry if failed + if (ret != 0 && op == UBCORE_ADD_NET_ADDR && req.eid_present) + (void)ubcore_update_eid_tbl(dev, netaddr, false, dev_net(netdev), &eid_idx); + + return ret; +} + +void ubcore_update_netdev_addr(struct ubcore_device *dev, struct net_device *netdev, + enum ubcore_net_addr_op op, bool async) { - struct net_device *netdev = dev->netdev; struct ubcore_net_addr_node *na_entry; - struct ubcore_device *tpf_dev = NULL; struct ubcore_net_addr_node *next; LIST_HEAD(na_list); @@ -551,96 +737,20 @@ void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add) if (dev->attr.virtualization) return; - tpf_dev = ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); - ubcore_netdev_get_ipv4(netdev, &na_list); ubcore_netdev_get_ipv6(netdev, &na_list); list_for_each_entry_safe(na_entry, next, &na_list, node) { if (na_entry->addr.net_addr.in6.subnet_prefix == cpu_to_be64(UBCORE_LOCAL_SHUNET)) continue; - if (tpf_dev) - is_add == true ? - ubcore_add_net_addr(tpf_dev, dev, &na_entry->addr, - netdev, false) : - ubcore_delete_net_addr(tpf_dev, dev, &na_entry->addr, - netdev, false); - ubcore_update_eid(dev, &na_entry->addr, is_add); + ubcore_update_net_addr(dev, netdev, &na_entry->addr, op, async); list_del(&na_entry->node); kfree(na_entry); } - if (tpf_dev) - ubcore_put_device(tpf_dev); -} - -void ubcore_update_netaddr(struct ubcore_device *dev, struct net_device *netdev, bool add) -{ - struct ubcore_net_addr_node *na_entry; - struct ubcore_net_addr_node *next; - LIST_HEAD(na_list); - - /* ipv4 */ - ubcore_netdev_get_ipv4(netdev, &na_list); - ubcore_netdev_get_ipv6(netdev, &na_list); - - list_for_each_entry_safe(na_entry, next, &na_list, node) { - if (add) { - if (dev != NULL && dev->ops != NULL && dev->ops->add_net_addr != NULL && - dev->ops->add_net_addr(dev, &na_entry->addr, 0) != 0) - ubcore_log_err("Failed to add net addr"); - } else { - if (dev != NULL && dev->ops != NULL && dev->ops->delete_net_addr != NULL && - dev->ops->delete_net_addr(dev, 0) != 0) - ubcore_log_err("Failed to delete net addr"); - } - list_del(&na_entry->node); - kfree(na_entry); - } -} - -static int ubcore_add_netaddr(struct ubcore_device *dev, struct net_device *netdev) -{ - if (netdev->reg_state >= NETREG_UNREGISTERING) - return NOTIFY_DONE; - - ubcore_update_netaddr(dev, netdev, true); - return NOTIFY_OK; -} - -static int ubcore_remove_netaddr(struct ubcore_device *dev, struct net_device *netdev) -{ - if (netdev->reg_state >= NETREG_UNREGISTERED) - return NOTIFY_DONE; - - ubcore_update_netaddr(dev, netdev, false); - return NOTIFY_OK; } static void ubcore_change_mtu(struct ubcore_device *dev, struct net_device *netdev) { - struct ubcore_device *tpf_dev; - struct ubcore_sip_info *new_sip; - struct ubcore_sip_info old_sip; - uint32_t i; - - tpf_dev = ubcore_find_tpf_by_dev(dev, UBCORE_TRANSPORT_UB); - if (tpf_dev == NULL) - return; - - mutex_lock(&tpf_dev->sip_table.lock); - for (i = 0; i < tpf_dev->sip_table.max_sip_cnt; i++) { - new_sip = &tpf_dev->sip_table.entry[i]; - if (!new_sip->is_active || memcmp(new_sip->netdev_name, netdev_name(netdev), - UBCORE_MAX_DEV_NAME) != 0) - continue; - old_sip = *new_sip; - new_sip->mtu = tpf_dev->transport_type == UBCORE_TRANSPORT_UB ? - (uint32_t)sip_get_mtu_with_ub(netdev->mtu) : - (uint32_t)sip_get_mtu(netdev->mtu); - (void)ubcore_notify_uvs_update_sip_manage( - tpf_dev, new_sip, &old_sip, UBCORE_SIP_UPDATE, i, true); - } - mutex_unlock(&tpf_dev->sip_table.lock); - ubcore_put_device(tpf_dev); + ubcore_update_netdev_addr(dev, netdev, UBCORE_UPDATE_NET_ADDR, true); } static void ubcore_do_bond(struct ubcore_bond_event_work *l_bond_event) @@ -807,19 +917,11 @@ static void ubcore_do_netdev_notify(unsigned long event, struct ubcore_device *d switch (event) { case NETDEV_REGISTER: case NETDEV_UP: - if (dev->transport_type != UBCORE_TRANSPORT_UB) - ubcore_add_netaddr(dev, netdev); break; case NETDEV_UNREGISTER: case NETDEV_DOWN: - if (dev->transport_type != UBCORE_TRANSPORT_UB) - ubcore_remove_netaddr(dev, netdev); break; case NETDEV_CHANGEADDR: - if (dev->transport_type != UBCORE_TRANSPORT_UB) { - ubcore_remove_netaddr(dev, netdev); - ubcore_add_netaddr(dev, netdev); - } break; case NETDEV_CHANGEMTU: if (dev->transport_type == UBCORE_TRANSPORT_UB) @@ -846,42 +948,33 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve { struct net_device *netdev = netdev_notifier_info_to_dev(arg); struct ubcore_device **devices; - struct net_device *real_netdev; + struct net_device *master_netdev; uint32_t num_devices = 0; uint32_t i; if (netdev == NULL) return NOTIFY_DONE; - if (is_vlan_dev(netdev)) - real_netdev = vlan_dev_real_dev(netdev); - else - real_netdev = netdev; - ubcore_log_info("Get a net event %s from ubcore_dev %s%s", netdev_cmd_to_name(event), netdev_name(netdev), netdev_reg_state(netdev)); - ubcore_device_list_lock(); - devices = ubcore_get_devices_from_netdev_nolock(real_netdev, &num_devices); + devices = ubcore_get_devices_from_netdev(netdev, &num_devices); if (devices == NULL) { - if (event != NETDEV_CHANGEUPPER && event != NETDEV_CHANGELOWERSTATE) { - ubcore_device_list_unlock(); + if (event != NETDEV_CHANGEUPPER && event != NETDEV_CHANGELOWERSTATE) return NOTIFY_DONE; - } - real_netdev = ubcore_find_master_netdev(event, arg, netdev); - if (real_netdev == NULL) { - ubcore_device_list_unlock(); + + master_netdev = ubcore_find_master_netdev(event, arg, netdev); + if (master_netdev == NULL) { ubcore_log_warn("Can not find master netdev by slave netdev %s", netdev_name(netdev)); return NOTIFY_DONE; } ubcore_log_info("Success to find master netdev %s", - netdev_name(real_netdev)); - devices = ubcore_get_devices_from_netdev_nolock(real_netdev, &num_devices); + netdev_name(master_netdev)); + devices = ubcore_get_devices_from_netdev(master_netdev, &num_devices); if (devices == NULL) { - ubcore_device_list_unlock(); ubcore_log_warn("Can not find devices from master netdev %s", - netdev_name(real_netdev)); + netdev_name(master_netdev)); return NOTIFY_DONE; } } @@ -893,7 +986,6 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve ubcore_put_devices(devices, num_devices); else kfree(devices); - ubcore_device_list_unlock(); return NOTIFY_OK; } @@ -914,31 +1006,14 @@ static int ubcore_register_notifiers(void) { int ret; - ret = ubcore_alloc_workqueue((int)UBCORE_SIP_NOTIFY_WQ); - if (ret != 0) { - pr_err("Failed to alloc workqueue for sip notify, ret = %d\n", ret); - return -ENOMEM; - } - - ret = ubcore_alloc_workqueue((int)UBCORE_BOND_EVENT_WQ); - if (ret != 0) { - (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); - pr_err("Failed to alloc workqueue for bond event, ret = %d\n", ret); - return -ENOMEM; - } - ret = register_netdevice_notifier(&ubcore_net_notifier); if (ret != 0) { - (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); - (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); pr_err("Failed to register netdev notifier, ret = %d\n", ret); return ret; } ret = register_inetaddr_notifier(&ubcore_ipv4_notifier); if (ret != 0) { (void)unregister_netdevice_notifier(&ubcore_net_notifier); - (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); - (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); pr_err("Failed to register inetaddr notifier, ret = %d\n", ret); return -1; } @@ -946,8 +1021,6 @@ static int ubcore_register_notifiers(void) if (ret != 0) { (void)unregister_inetaddr_notifier(&ubcore_ipv4_notifier); (void)unregister_netdevice_notifier(&ubcore_net_notifier); - (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); - (void)ubcore_destroy_workqueue((int)UBCORE_SIP_NOTIFY_WQ); pr_err("Failed to register inet6addr notifier, ret = %d\n", ret); return -1; } @@ -959,8 +1032,6 @@ static void ubcore_unregister_notifiers(void) (void)unregister_inet6addr_notifier(&ubcore_ipv6_notifier); (void)unregister_inetaddr_notifier(&ubcore_ipv4_notifier); (void)unregister_netdevice_notifier(&ubcore_net_notifier); - (void)ubcore_destroy_workqueue((int)UBCORE_BOND_EVENT_WQ); - (void)ubcore_destroy_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); } static int __init ubcore_init(void) @@ -993,9 +1064,9 @@ static int __init ubcore_init(void) ubcore_class_unregister(); } - ret = ubcore_alloc_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); + ret = ubcore_create_workqueues(); if (ret != 0) { - pr_err("Failed to alloc workqueue, ret = %d\n", ret); + pr_err("Failed to create all the workqueues, ret = %d\n", ret); ubcore_unregister_pnet_ops(); ubcore_unregister_notifiers(); ubcore_genl_exit(); @@ -1008,9 +1079,11 @@ static int __init ubcore_init(void) static void __exit ubcore_exit(void) { + ubcore_destroy_workqueues(); ubcore_unregister_pnet_ops(); ubcore_unregister_notifiers(); ubcore_genl_exit(); + ubcore_unregister_sysfs(); ubcore_class_unregister(); ubcore_log_info("ubcore module exits.\n"); } diff --git a/drivers/ub/urma/ubcore/ubcore_main.h b/drivers/ub/urma/ubcore/ubcore_main.h new file mode 100644 index 000000000000..a588442075e5 --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_main.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: ubcore main header + * Author: Zhao Yusu + * Create: 2024-02-27 + * Note: + * History: 2024-02-27: Introduce ubcore version API + */ + +#ifndef UBCORE_MAIN_H +#define UBCORE_MAIN_H + +#include "ubcore_msg.h" + +#define UBCORE_VERSION0 0x0 +#define UBCORE_VERSION UBCORE_VERSION0 +#define UBCORE_INVALID_VERSION 0xffffffff +#define UBCORE_SUPPORT_VERION_NUM 1 +#define UBCORE_CAP 0x0 + +bool ubcore_negotiated(void); +uint32_t ubcore_get_version(void); +void ubcore_set_version(uint32_t version); +uint32_t ubcore_get_cap(void); +void ubcore_set_cap(uint32_t cap); +uint32_t *ubcore_get_support_versions(void); +int ubcore_negotiate_version(struct ubcore_msg_nego_ver_req *req, uint32_t *ver, uint32_t *cap); +int ubcore_recv_net_addr_update(struct ubcore_device *tpf_dev, struct ubcore_req_host *req); +int ubcore_send_eid_update_req(struct ubcore_device *dev, enum ubcore_net_addr_op op, + union ubcore_eid *eid, uint32_t eid_idx, uint32_t *upi); +int ubcore_recv_eid_update_req(struct ubcore_device *tpf_dev, struct ubcore_req_host *req); + +int ubcore_update_net_addr(struct ubcore_device *dev, struct net_device *netdev, + struct ubcore_net_addr *netaddr, enum ubcore_net_addr_op op, bool async); +#endif diff --git a/drivers/ub/urma/ubcore/ubcore_msg.c b/drivers/ub/urma/ubcore/ubcore_msg.c index fcea06f0759c..f99876ed2e00 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.c +++ b/drivers/ub/urma/ubcore/ubcore_msg.c @@ -27,6 +27,8 @@ #include "ubcore_vtp.h" #include "urma/ubcore_uapi.h" #include "ubcore_priv.h" +#include "ubcore_workqueue.h" +#include "ubcore_main.h" #include "ubcore_msg.h" #define MS_PER_SEC 1000 @@ -198,7 +200,8 @@ static void ubcore_fill_tpf_dev_name(struct ubcore_device *tpf_dev, case UBCORE_MSG_FLOW_STOPPED: case UBCORE_MSG_MIG_ROLLBACK: case UBCORE_MSG_MIG_VM_START: - ubcore_log_err("Wrong type when try to full tpf dev name\n"); + case UBCORE_MSG_NEGO_VER: + ubcore_log_err("Wrong type when try to fill tpf dev name\n"); break; default: ubcore_log_err("Unrecognized type of opcode %d\n", (int)req_host->req.opcode); @@ -213,7 +216,7 @@ static struct ubcore_req_host *ubcore_copy_req_host(struct ubcore_req_host *req_ uint32_t len = (uint32_t)sizeof(struct ubcore_req_host) + req_host->req.len; struct ubcore_req_host *resp; - resp = kzalloc(len, GFP_KERNEL); + resp = kzalloc(len, GFP_ATOMIC); if (resp == NULL) return NULL; @@ -258,11 +261,92 @@ static struct ubcore_req_host *ubcore_migrate_req(struct ubcore_device *dev, mig_resp = (struct ubcore_nl_function_mig_req *)req_copy->req.data; mig_resp->mig_fe_idx = mig_msg->mig_fe_idx; - (void)strncpy(mig_resp->dev_name, dev->dev_name, strlen(dev->dev_name)); + (void)strncpy(mig_resp->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); return req_copy; } +static void ubcore_handle_nego_ver(struct ubcore_device *dev, struct ubcore_req_host *req) +{ + struct ubcore_msg_nego_ver_resp *data; + struct ubcore_resp_host *rsp; + int rc; + + rsp = kzalloc(sizeof(struct ubcore_resp_host) + sizeof(struct ubcore_msg_nego_ver_resp), + GFP_KERNEL); + if (rsp == NULL) + return; + + rsp->dst_fe_idx = req->src_fe_idx; + rsp->resp.msg_id = req->req.msg_id; + rsp->resp.opcode = UBCORE_MSG_NEGO_VER; + rsp->resp.len = sizeof(struct ubcore_msg_nego_ver_resp); + + data = (struct ubcore_msg_nego_ver_resp *)rsp->resp.data; + rc = ubcore_negotiate_version((struct ubcore_msg_nego_ver_req *)req->req.data, + &data->version, &data->cap); + data->ret = rc == 0 ? UBCORE_MSG_RESP_SUCCESS : UBCORE_MSG_RESP_FAIL; + + (void)ubcore_send_resp(dev, rsp); + + /* Backend response is freed after "ubcore_send_resp" returns. */ + kfree(rsp); +} + +static void ubcore_handle_frontend_message(struct work_struct *work) +{ + struct ubcore_front_back_work *fb_work = + container_of(work, struct ubcore_front_back_work, work); + + switch (fb_work->req->req.opcode) { + case UBCORE_MSG_NEGO_VER: + ubcore_handle_nego_ver(fb_work->dev, fb_work->req); + break; + case UBCORE_MSG_UPDATE_NET_ADDR: + ubcore_recv_net_addr_update(fb_work->dev, fb_work->req); + break; + case UBCORE_MSP_UPDATE_EID: + ubcore_recv_eid_update_req(fb_work->dev, fb_work->req); + break; + default: + ubcore_log_err("Unsupported opcode: %d\n", (int)fb_work->req->req.opcode); + } + + /* Backend request is freed after it is handled. */ + kfree(fb_work->req); + kfree(fb_work); +} + +static int ubcore_queue_frontend_message(struct ubcore_device *dev, struct ubcore_req_host *req) +{ + struct ubcore_front_back_work *work; + struct ubcore_req_host *inner_req; + + inner_req = ubcore_copy_req_host(req); + if (inner_req == NULL) { + ubcore_log_err("Fail to copy frontend ubcore message.\n"); + return -ENOMEM; + } + + work = kzalloc(sizeof(struct ubcore_front_back_work), GFP_ATOMIC); + if (work == NULL) { + kfree(inner_req); + return -ENOMEM; + } + + work->dev = dev; + work->req = inner_req; + INIT_WORK(&work->work, ubcore_handle_frontend_message); + if (ubcore_queue_work((int)UBCORE_FRONT_BACK_WQ, &work->work) != 0) { + ubcore_log_err("Fail to queue work for frontend ubcore message.\n"); + kfree(inner_req); + kfree(work); + return -1; + } + + return 0; +} + int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req) { struct ubcore_req_host *handle_req; @@ -278,7 +362,9 @@ int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req) return -EINVAL; } - if (req->req.opcode >= UBCORE_MSG_STOP_PROC_VTP_MSG) { + if (req->req.opcode >= UBCORE_MSG_NEGO_VER) { + return ubcore_queue_frontend_message(dev, req); + } else if (req->req.opcode >= UBCORE_MSG_STOP_PROC_VTP_MSG) { handle_req = ubcore_migrate_req(dev, req); if (handle_req == NULL) { ubcore_log_err("null msg when handle migrate\n!"); @@ -507,10 +593,14 @@ int ubcore_update_uvs_eid_ret(struct ubcore_update_eid_ctx *ctx) ubcore_log_err("waiting req reply timeout, msg_id = %u, opcode = %hu, leavetime = %ld.\n", ctx->req_msg->msg_id, (uint16_t)ctx->req_msg->opcode, leave_time); - return 0; + return -EAGAIN; } + ubcore_log_info("waiting req reply success, msg_id = %u, opcode = %hu\n", ctx->req_msg->msg_id, (uint16_t)ctx->req_msg->opcode); - (void)ctx->cb.callback(ctx->dev, ctx->s->resp, ctx->cb.user_arg); + + if (ctx->cb.callback(ctx->dev, ctx->s->resp, ctx->cb.user_arg) != 0) + return -EINVAL; + return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_msg.h b/drivers/ub/urma/ubcore/ubcore_msg.h index b85ad3b8e9e2..efb2aed353e6 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.h +++ b/drivers/ub/urma/ubcore/ubcore_msg.h @@ -86,6 +86,18 @@ struct ubcore_msg_discover_eid_resp { uint16_t fe_idx; }; +struct ubcore_msg_nego_ver_req { + uint32_t cap; + uint32_t version_num; + uint32_t versions[0]; +}; + +struct ubcore_msg_nego_ver_resp { + int ret; + uint32_t cap; + uint32_t version; +}; + struct ubcore_function_mig_req { uint16_t mig_fe_idx; }; @@ -95,6 +107,28 @@ struct ubcore_function_mig_resp { enum ubcore_mig_resp_status status; }; +struct ubcore_eid_update_info { + uint32_t pattern; + uint32_t eid_idx; + union ubcore_eid eid; + char dev_name[UBCORE_MAX_DEV_NAME]; + bool upi_present; + uint32_t upi; +}; + +struct ubcore_update_net_addr_req { + enum ubcore_net_addr_op op; + bool sip_present; + struct ubcore_sip_info sip_info; + bool eid_present; + struct ubcore_eid_update_info eid_info; +}; + +struct ubcore_update_eid_req { + enum ubcore_net_addr_op op; + struct ubcore_eid_update_info eid_info; +}; + struct ubcore_update_eid_ctx { struct ubcore_device *dev; struct ubcore_req *req_msg; diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.c b/drivers/ub/urma/ubcore/ubcore_netdev.c index 49fb10c56124..92e8b19193d5 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.c +++ b/drivers/ub/urma/ubcore/ubcore_netdev.c @@ -19,6 +19,7 @@ */ #include #include +#include #include #include "ubcore_log.h" @@ -173,11 +174,12 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, return 0; } -int ubcore_check_port_state(struct ubcore_device *dev, uint8_t port_idx) +int ubcore_check_port_state(struct ubcore_device *dev) { - struct ubcore_device_status status; + struct ubcore_device_status status = {0}; + uint32_t i; - if (dev == NULL || port_idx >= UBCORE_MAX_PORT_CNT) { + if (dev == NULL) { ubcore_log_err("Invalid parameter.\n"); return -EINVAL; } @@ -188,24 +190,32 @@ int ubcore_check_port_state(struct ubcore_device *dev, uint8_t port_idx) return -EPERM; } - if (status.port_status[port_idx].state != UBCORE_PORT_ACTIVE) { - ubcore_log_err("port state is not active with dev name: %s and port_idx: %hhu\n", - dev->dev_name, port_idx); - return -EPERM; + for (i = 0; i < UBCORE_MAX_PORT_CNT; i++) { + if (status.port_status[i].state == UBCORE_PORT_ACTIVE) { + ubcore_log_debug("Success to query dev %s - port %u state and it's active.\n", + dev->dev_name, i); + return 0; + } } - ubcore_log_info("Success to query dev %s port state and it's active.\n", dev->dev_name); - return 0; + ubcore_log_err("port state is not active with dev name: %s\n", dev->dev_name); + return -EPERM; } -void ubcore_find_port_netdev(struct ubcore_device *dev, - struct net_device *ndev, uint8_t **port_list, uint8_t *port_cnt) +void ubcore_fill_port_netdev(struct ubcore_device *dev, + struct net_device *ndev, uint8_t *port_list, uint8_t *port_cnt) { + struct net_device *real_netdev = NULL; struct ubcore_ndev_port *port_info; + if (is_vlan_dev(ndev)) + real_netdev = vlan_dev_real_dev(ndev); + else + real_netdev = ndev; + down_write(&g_port_list_lock); list_for_each_entry(port_info, &dev->port_list, node) { - if (port_info->ndev == ndev) { - *port_list = port_info->port_list; + if (port_info->ndev == real_netdev) { + (void)memcpy(port_list, port_info->port_list, UBCORE_MAX_PORT_CNT); *port_cnt = port_info->port_cnt; up_write(&g_port_list_lock); ubcore_log_info("Success to fill in port_list with port cnt: %hhu and dev_name %s", @@ -255,39 +265,6 @@ static int ubcore_port_duplicate_check(struct ubcore_ndev_port *port_info, return 0; } -static void ubcore_sync_sip_port_list(struct ubcore_device *dev, - uint8_t *port_list, uint8_t port_cnt) -{ - struct ubcore_sip_info *new_sip; - struct ubcore_sip_info old_sip; - struct ubcore_device *tpf_dev; - uint32_t i; - - tpf_dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); - if (tpf_dev == NULL) - return; - - mutex_lock(&tpf_dev->sip_table.lock); - for (i = 0; i < tpf_dev->sip_table.max_sip_cnt; i++) { - new_sip = &tpf_dev->sip_table.entry[i]; - if (!new_sip->is_active) - continue; - old_sip = *new_sip; - (void)memcpy(new_sip->port_id, port_list, - UBCORE_MAX_PORT_CNT); - new_sip->port_cnt = port_cnt; - - if (ubcore_get_netlink_valid() == true) { - (void)ubcore_notify_uvs_del_sip(tpf_dev, &old_sip, i); - (void)ubcore_notify_uvs_add_sip(tpf_dev, new_sip, i); - } - ubcore_log_info("dev_name: %s, old port_cnt: %hhu, new port_cnt: %hhu\n", - dev->dev_name, old_sip.port_cnt, new_sip->port_cnt); - } - mutex_unlock(&tpf_dev->sip_table.lock); - ubcore_put_device(tpf_dev); -} - int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, unsigned int port_id) { @@ -313,9 +290,9 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, ubcore_log_err("Failed to ubcore_add_new_port"); return -1; } - /* sync to sip table */ - ubcore_sync_sip_port_list(dev, port_info->port_list, port_info->port_cnt); up_write(&g_port_list_lock); + /* sync to sip table */ + ubcore_update_netdev_addr(dev, dev->netdev, UBCORE_UPDATE_NET_ADDR, false); return 0; } } @@ -335,7 +312,7 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, list_add_tail(&new_node->node, &dev->port_list); up_write(&g_port_list_lock); ubcore_log_info("ndev:%s bound port[0]: %hhu\n", netdev_name(ndev), new_node->port_list[0]); - ubcore_sync_sip_port_list(dev, new_node->port_list, new_node->port_cnt); + ubcore_update_netdev_addr(dev, dev->netdev, UBCORE_UPDATE_NET_ADDR, false); return 0; } EXPORT_SYMBOL(ubcore_set_port_netdev); @@ -363,7 +340,6 @@ static int ubcore_del_port(struct ubcore_ndev_port *port_info, netdev_name(ndev), dev->dev_name, port_id); return -1; } - ubcore_sync_sip_port_list(dev, port_info->port_list, port_info->port_cnt); if (port_info->port_cnt == 0) { list_del(&port_info->node); @@ -394,6 +370,7 @@ int ubcore_unset_port_netdev(struct ubcore_device *dev, struct net_device *ndev, return -1; } up_write(&g_port_list_lock); + ubcore_update_netdev_addr(dev, dev->netdev, UBCORE_UPDATE_NET_ADDR, false); return 0; } } @@ -421,14 +398,14 @@ void ubcore_put_port_netdev(struct ubcore_device *dev) port_info->port_cnt = 0; (void)memset(port_info->port_list, 0, sizeof(uint8_t) * UBCORE_MAX_PORT_CNT); - ubcore_sync_sip_port_list(dev, port_info->port_list, - port_info->port_cnt); } list_del(&port_info->node); kfree(port_info); } } up_write(&g_port_list_lock); + + ubcore_update_netdev_addr(dev, dev->netdev, UBCORE_UPDATE_NET_ADDR, false); } EXPORT_SYMBOL(ubcore_put_port_netdev); @@ -504,8 +481,8 @@ int ubcore_add_sip_entry(struct ubcore_sip_table *sip_table, const struct ubcore (void)memcpy(&sip_table->entry[idx], sip, sizeof(struct ubcore_sip_info)); sip_table->entry[idx].is_active = true; mutex_unlock(&sip_table->lock); - ubcore_log_info("tpf_dev_name: %s sip table add entry idx: %d.\n", - sip->dev_name, idx); + ubcore_log_info("tpf_dev_name: %s sip table add entry idx: %d. addr: %pI6c\n", + sip->dev_name, idx, &sip->addr.net_addr); return 0; } @@ -518,8 +495,8 @@ int ubcore_del_sip_entry(struct ubcore_sip_table *sip_table, uint32_t idx) return -EINVAL; } - ubcore_log_info("tpf_name: %s del sip entry idx: %d.\n", - sip_table->entry[idx].dev_name, idx); + ubcore_log_info("tpf_name: %s del sip entry idx: %d, addr: %pI6c.\n", + sip_table->entry[idx].dev_name, idx, &sip_table->entry[idx].addr.net_addr); sip_table->entry[idx].is_active = false; mutex_unlock(&sip_table->lock); return 0; @@ -530,8 +507,8 @@ static bool ubcore_sip_compare(struct ubcore_sip_info *sip_entry, { if ((memcmp(sip_entry->dev_name, del_sip->dev_name, sizeof(char) * UBCORE_MAX_DEV_NAME) == 0) && - (memcmp(&sip_entry->addr, &del_sip->addr, - sizeof(struct ubcore_net_addr)) == 0) && + (memcmp(&sip_entry->addr.net_addr, &del_sip->addr.net_addr, + sizeof(union ubcore_net_addr_union)) == 0) && (memcmp(sip_entry->netdev_name, del_sip->netdev_name, sizeof(struct ubcore_net_addr)) == 0)) return true; @@ -539,6 +516,35 @@ static bool ubcore_sip_compare(struct ubcore_sip_info *sip_entry, return false; } +int ubcore_update_sip_entry(struct ubcore_sip_table *sip_table, struct ubcore_sip_info *new_sip, + uint32_t *sip_idx, struct ubcore_sip_info *old_sip) +{ + uint32_t i; + int ret = -ENOENT; + + if (!sip_table || !new_sip || !sip_idx || !old_sip) + return -EINVAL; + + mutex_lock(&sip_table->lock); + for (i = 0; i < sip_table->max_sip_cnt; i++) { + if (!sip_table->entry[i].is_active || + !ubcore_sip_compare(&sip_table->entry[i], new_sip)) + continue; + + *sip_idx = i; + *old_sip = sip_table->entry[i]; + + sip_table->entry[i] = *new_sip; + sip_table->entry[i].is_active = true; + ret = 0; + ubcore_log_info("tpf_name: %s update sip entry idx: %d, addr: %pI6c.", + sip_table->entry[i].dev_name, i, &sip_table->entry[i].addr.net_addr); + break; + } + mutex_unlock(&sip_table->lock); + return ret; +} + int ubcore_lookup_sip_idx(struct ubcore_sip_table *sip_table, struct ubcore_sip_info *sip, uint32_t *idx) { diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.h b/drivers/ub/urma/ubcore/ubcore_netdev.h index e0eb8534ac77..281cd1060dd6 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.h +++ b/drivers/ub/urma/ubcore/ubcore_netdev.h @@ -23,9 +23,9 @@ #include -int ubcore_check_port_state(struct ubcore_device *dev, uint8_t port_idx); -void ubcore_find_port_netdev(struct ubcore_device *dev, - struct net_device *ndev, uint8_t **port_list, uint8_t *port_cnt); +int ubcore_check_port_state(struct ubcore_device *dev); +void ubcore_fill_port_netdev(struct ubcore_device *dev, + struct net_device *ndev, uint8_t *port_list, uint8_t *port_cnt); int ubcore_sip_table_init(struct ubcore_sip_table *sip_table, uint32_t size); void ubcore_sip_table_uninit(struct ubcore_sip_table *sip_table); @@ -38,6 +38,8 @@ int ubcore_add_sip_entry(struct ubcore_sip_table *sip_table, struct ubcore_sip_i int ubcore_del_sip_entry(struct ubcore_sip_table *sip_table, uint32_t idx); int ubcore_lookup_sip_idx(struct ubcore_sip_table *sip_table, struct ubcore_sip_info *sip, uint32_t *idx); +int ubcore_update_sip_entry(struct ubcore_sip_table *sip_table, struct ubcore_sip_info *new_sip, + uint32_t *sip_idx, struct ubcore_sip_info *old_sip); struct ubcore_device *ubcore_lookup_tpf_by_sip_addr(union ubcore_net_addr_union *addr); int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, const struct ubcore_sip_info *sip, uint32_t index); diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.c b/drivers/ub/urma/ubcore/ubcore_netlink.c index 4d7f9e61b320..52fbea412cae 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.c +++ b/drivers/ub/urma/ubcore/ubcore_netlink.c @@ -38,6 +38,8 @@ #define CB_ARGS_SIP_IDX 3 #define CB_ARGS_INFO_TYPE 4 +#define UBCORE_MAX_NL_MSG_BUF_LEN 2048 + static LIST_HEAD(g_nl_session_list); static DEFINE_SPINLOCK(g_nl_session_lock); static atomic_t g_nlmsg_seq; @@ -84,7 +86,7 @@ static struct ubcore_nl_session *ubcore_create_nl_session(struct ubcore_device * spin_unlock_irqrestore(&g_nl_session_lock, flags); kref_init(&s->kref); init_completion(&s->comp); - (void)strncpy(s->dev_name, dev->dev_name, strlen(dev->dev_name)); + (void)strncpy(s->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); return s; } @@ -131,6 +133,11 @@ static struct ubcore_nlmsg *ubcore_get_genlmsg_data(struct genl_info *info) return NULL; payload_len = nla_get_u32(info->attrs[UBCORE_PAYLOAD_LEN]); + if (payload_len > UBCORE_MAX_NL_MSG_BUF_LEN) { + ubcore_log_err("Invalid payload len: %d", payload_len); + return NULL; + } + msg = kzalloc((size_t)(sizeof(struct ubcore_nlmsg) + payload_len), GFP_KERNEL); if (msg == NULL) return NULL; @@ -282,7 +289,7 @@ int ubcore_tpf2fe_resp_ops(struct sk_buff *skb, struct genl_info *info) int ubcore_update_tpf_dev_info_resp_ops(struct sk_buff *skb, struct genl_info *info) { - struct ubcore_nl_session *s; + struct ubcore_update_tpf_dev_info_resp *nl_resp; struct ubcore_nlmsg *resp; resp = ubcore_get_genlmsg_data(info); @@ -290,15 +297,15 @@ int ubcore_update_tpf_dev_info_resp_ops(struct sk_buff *skb, struct genl_info *i ubcore_log_err("Failed to calloc and copy response"); return -1; } - s = ubcore_find_nl_session(resp->nlmsg_seq); - if (s == NULL) { - ubcore_log_err("Failed to find nl session with seq %u", resp->nlmsg_seq); + + nl_resp = (struct ubcore_update_tpf_dev_info_resp *)(void *)resp->payload; + if (nl_resp->ret != UBCORE_NL_RESP_SUCCESS) { + ubcore_log_err("Failed to get tpf dev info resp"); kfree(resp); return -1; } - s->resp = resp; - (void)kref_put(&s->kref, ubcore_free_nl_session); - complete(&s->comp); + + kfree(resp); return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.h b/drivers/ub/urma/ubcore/ubcore_netlink.h index 5d60867ac3d9..9321304f7220 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.h +++ b/drivers/ub/urma/ubcore/ubcore_netlink.h @@ -35,12 +35,12 @@ enum ubcore_nl_resp_status { struct ubcore_nlmsg { uint32_t nlmsg_seq; enum ubcore_cmd msg_type; - enum ubcore_transport_type transport_type; union ubcore_eid src_eid; /* todo: delete */ union ubcore_eid dst_eid; /* todo: delete */ + enum ubcore_transport_type transport_type; uint32_t payload_len; uint8_t payload[0]; // limited by tpsa_nl_msg_t's payload len -} __packed; +}; struct ubcore_ta_data { enum ubcore_transport_type trans_type; diff --git a/drivers/ub/urma/ubcore/ubcore_priv.h b/drivers/ub/urma/ubcore/ubcore_priv.h index 5de967897337..4e19c80adf83 100644 --- a/drivers/ub/urma/ubcore/ubcore_priv.h +++ b/drivers/ub/urma/ubcore/ubcore_priv.h @@ -109,10 +109,7 @@ void ubcore_get_device(struct ubcore_device *dev); void ubcore_put_device(struct ubcore_device *dev); struct ubcore_device *ubcore_find_tpf_device(union ubcore_net_addr_union *netaddr, enum ubcore_transport_type type); -struct ubcore_device *ubcore_find_tpf_by_dev(struct ubcore_device *dev, - enum ubcore_transport_type type); -struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name, - enum ubcore_transport_type type); +struct ubcore_device *ubcore_find_tpf_device_by_name(char *dev_name); /* returned list should be freed by caller */ struct ubcore_device **ubcore_get_all_tpf_device(enum ubcore_transport_type type, uint32_t *dev_cnt); @@ -121,25 +118,21 @@ int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg); int ubcore_update_eidtbl_by_idx(struct ubcore_device *dev, union ubcore_eid *eid, uint32_t eid_idx, bool is_alloc_eid, struct net *net); int ubcore_update_eidtbl_by_eid(struct ubcore_device *dev, union ubcore_eid *eid, - uint32_t *eid_idx, bool is_alloc_eid); + uint32_t *eid_idx, bool is_alloc_eid, struct net *net); struct ubcore_device *ubcore_find_upi_with_dev_name(const char *dev_name, uint32_t *upi); int ubcore_add_upi_list(struct ubcore_device *dev, uint32_t upi); /* Must call ubcore_put_devices to put and release the returned devices */ -void ubcore_device_list_lock(void); -void ubcore_device_list_unlock(void); -struct ubcore_device **ubcore_get_devices_from_netdev_nolock(struct net_device *netdev, +struct ubcore_device **ubcore_get_devices_from_netdev(struct net_device *netdev, uint32_t *cnt); void ubcore_put_devices(struct ubcore_device **devices, uint32_t cnt); -void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add); +void ubcore_update_netdev_addr(struct ubcore_device *dev, struct net_device *netdev, + enum ubcore_net_addr_op op, bool async); void ubcore_update_netaddr(struct ubcore_device *dev, struct net_device *netdev, bool add); int ubcore_fill_netaddr_macvlan(struct ubcore_net_addr *netaddr, struct net_device *netdev, enum ubcore_net_addr_type type); -void ubcore_sync_sip_table(void); -int ubcore_query_all_device_tpf_dev_info(void); - void ubcore_set_tp_init_cfg(struct ubcore_tp *tp, struct ubcore_tp_cfg *cfg); struct ubcore_tp *ubcore_create_tp(struct ubcore_device *dev, struct ubcore_tp_cfg *cfg, struct ubcore_udata *udata); @@ -178,34 +171,34 @@ static inline uint32_t ubcore_get_vtpn_hash(struct ubcore_hash_table *ht, void * static inline bool ubcore_jfs_need_advise(struct ubcore_jfs *jfs) { - return jfs->ub_dev->transport_type == UBCORE_TRANSPORT_IB && + return jfs->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB && jfs->jfs_cfg.trans_mode == UBCORE_TP_RM; } static inline bool ubcore_jfs_tjfr_need_advise(struct ubcore_jfs *jfs, struct ubcore_tjetty *tjfr) { - return jfs->ub_dev->transport_type == UBCORE_TRANSPORT_IB && + return jfs->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB && jfs->jfs_cfg.trans_mode == UBCORE_TP_RM && tjfr->cfg.trans_mode == UBCORE_TP_RM; } static inline bool ubcore_jetty_need_advise(struct ubcore_jetty *jetty) { - return jetty->ub_dev->transport_type == UBCORE_TRANSPORT_IB && + return jetty->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB && jetty->jetty_cfg.trans_mode == UBCORE_TP_RM; } static inline bool ubcore_jetty_tjetty_need_advise(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty) { - return jetty->ub_dev->transport_type == UBCORE_TRANSPORT_IB && + return jetty->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB && jetty->jetty_cfg.trans_mode == UBCORE_TP_RM && tjetty->cfg.trans_mode == UBCORE_TP_RM; } static inline bool ubcore_jfr_need_advise(struct ubcore_jfr *jfr) { - return jfr->ub_dev->transport_type == UBCORE_TRANSPORT_IB && + return jfr->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB && jfr->jfr_cfg.trans_mode == UBCORE_TP_RM; } diff --git a/drivers/ub/urma/ubcore/ubcore_segment.c b/drivers/ub/urma/ubcore/ubcore_segment.c index db3db610f128..90568dc4de34 100644 --- a/drivers/ub/urma/ubcore/ubcore_segment.c +++ b/drivers/ub/urma/ubcore/ubcore_segment.c @@ -26,21 +26,27 @@ #include "ubcore_tp_table.h" struct ubcore_token_id *ubcore_alloc_token_id(struct ubcore_device *dev, - struct ubcore_udata *udata) + union ubcore_token_id_flag flag, struct ubcore_udata *udata) { struct ubcore_token_id *token_id; + if (flag.bs.pa == 1 && udata != NULL) { + ubcore_log_err("invalid parameter of pa.\n"); + return ERR_PTR(-EINVAL); + } + if (dev == NULL || dev->ops == NULL || dev->ops->alloc_token_id == NULL || dev->ops->free_token_id == NULL) { ubcore_log_err("invalid parameter.\n"); return ERR_PTR(-EINVAL); } - token_id = dev->ops->alloc_token_id(dev, udata); + token_id = dev->ops->alloc_token_id(dev, flag, udata); if (IS_ERR_OR_NULL(token_id)) { ubcore_log_err("failed to alloc token_id id.\n"); - return token_id == NULL ? ERR_PTR(-ENOEXEC) : token_id; + return UBCORE_CHECK_RETURN_ERR_PTR(token_id, ENOEXEC); } + token_id->flag = flag; token_id->ub_dev = dev; token_id->uctx = ubcore_get_uctx(udata); atomic_set(&token_id->use_cnt, 0); @@ -67,47 +73,60 @@ int ubcore_free_token_id(struct ubcore_token_id *token_id) } EXPORT_SYMBOL(ubcore_free_token_id); -static int ubcore_check_ops_register_seg(struct ubcore_device *dev, struct ubcore_seg_cfg *cfg) +static int ubcore_check_register_seg_para(struct ubcore_device *dev, + struct ubcore_seg_cfg *cfg, struct ubcore_udata *udata) { if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->register_seg == NULL || - dev->ops->unregister_seg == NULL) { + dev->ops->unregister_seg == NULL || IS_ERR_OR_NULL(dev->eid_table.eid_entries)) { ubcore_log_err("invalid parameter.\n"); return -1; } - return 0; -} -struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, - struct ubcore_seg_cfg *cfg, - struct ubcore_udata *udata) -{ - bool alloc_token_id = false; - struct ubcore_seg_cfg tmp_cfg; - struct ubcore_target_seg *tseg; - - if (ubcore_check_ops_register_seg(dev, cfg) != 0) - return ERR_PTR(-EINVAL); + if (cfg->flag.bs.pa == 1 && udata != NULL) { + ubcore_log_err("invalid parameter of pa.\n"); + return -1; + } if (dev->transport_type == UBCORE_TRANSPORT_UB && ((cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_VALID && cfg->token_id == NULL) || (cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_INVALID && cfg->token_id != NULL))) { ubcore_log_err("invalid parameter of token_id.\n"); - return ERR_PTR(-EINVAL); + return -1; + } + + if (dev->transport_type == UBCORE_TRANSPORT_UB && + cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_VALID && + cfg->token_id->flag.bs.pa != cfg->flag.bs.pa) { + ubcore_log_err("invalid parameter of token_id pa.\n"); + return -1; } if ((cfg->flag.bs.access & (UBCORE_ACCESS_REMOTE_WRITE | UBCORE_ACCESS_REMOTE_ATOMIC)) && - !(cfg->flag.bs.access & UBCORE_ACCESS_LOCAL_WRITE)) { + !(cfg->flag.bs.access & UBCORE_ACCESS_LOCAL_WRITE)) { ubcore_log_err( "Local write must be set when either remote write or remote atomic is declared.\n"); - return ERR_PTR(-EINVAL); + return -1; } if (cfg->eid_index >= dev->eid_table.eid_cnt) { - ubcore_log_warn( - "eid_index:%u >= eid_table cnt:%u.\n", + ubcore_log_warn("eid_index:%u >= eid_table cnt:%u.\n", cfg->eid_index, dev->eid_table.eid_cnt); - return ERR_PTR(-EINVAL); + return -1; } + return 0; +} + +struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, + struct ubcore_seg_cfg *cfg, + struct ubcore_udata *udata) +{ + union ubcore_token_id_flag flag = {0}; + bool alloc_token_id = false; + struct ubcore_seg_cfg tmp_cfg; + struct ubcore_target_seg *tseg; + + if (ubcore_check_register_seg_para(dev, cfg, udata) != 0) + return ERR_PTR(-EINVAL); if (udata == NULL && cfg->flag.bs.token_id_valid == UBCORE_TOKEN_ID_INVALID && dev->transport_type == UBCORE_TRANSPORT_UB) @@ -115,7 +134,8 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, tmp_cfg = *cfg; if (alloc_token_id == true) { - tmp_cfg.token_id = ubcore_alloc_token_id(dev, NULL); + flag.bs.pa = cfg->flag.bs.pa; + tmp_cfg.token_id = ubcore_alloc_token_id(dev, flag, NULL); if (IS_ERR_OR_NULL(tmp_cfg.token_id)) { ubcore_log_err("alloc token id failed.\n"); return (void *)tmp_cfg.token_id; @@ -127,7 +147,7 @@ struct ubcore_target_seg *ubcore_register_seg(struct ubcore_device *dev, ubcore_log_err("UBEP failed to register segment.\n"); if (alloc_token_id == true) (void)ubcore_free_token_id(tmp_cfg.token_id); - return tseg == NULL ? ERR_PTR(-ENOEXEC) : tseg; + return UBCORE_CHECK_RETURN_ERR_PTR(tseg, ENOEXEC); } tseg->ub_dev = dev; @@ -196,7 +216,7 @@ struct ubcore_target_seg *ubcore_import_seg(struct ubcore_device *dev, tseg = dev->ops->import_seg(dev, cfg, udata); if (IS_ERR_OR_NULL(tseg)) { ubcore_log_err("UBEP failed to import segment with va\n"); - return tseg == NULL ? ERR_PTR(-ENOEXEC) : tseg; + return UBCORE_CHECK_RETURN_ERR_PTR(tseg, ENOEXEC); } tseg->ub_dev = dev; tseg->uctx = ubcore_get_uctx(udata); diff --git a/drivers/ub/urma/ubcore/ubcore_tp.c b/drivers/ub/urma/ubcore/ubcore_tp.c index f67e1ea83208..f422a9b2aeb6 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.c +++ b/drivers/ub/urma/ubcore/ubcore_tp.c @@ -36,7 +36,10 @@ #define UB_PROTOCOL_HEAD_BYTES 313 #define UB_MTU_BITS_BASE_SHIFT 7 -#define UBCORE_TP_ATTR_MASK 0x7FFFF +/* to guarantee all bitmaps filled as 1 */ +#define UBCORE_TP_ATTR_MASK 0xFFFFFFFF +/* chip 1636 max extension address length */ +#define UBCORE_MAX_TP_EXT_LEN 2048 static inline uint32_t get_udrv_in_len(struct ubcore_udata *udata) { @@ -98,6 +101,9 @@ static int ubcore_set_tp_peer_ext(struct ubcore_tp_attr *attr, uint64_t ext_addr if (ext_len == 0 || ext_addr == 0) return 0; + if (ext_len > UBCORE_MAX_TP_EXT_LEN) + return -EINVAL; + /* copy resp ext from req or response */ peer_ext = kzalloc(ext_len, GFP_KERNEL); if (peer_ext == NULL) @@ -125,7 +131,8 @@ static void ubcore_get_ta_data_from_ta(const struct ubcore_ta *ta, switch (ta->type) { case UBCORE_TA_JFS_TJFR: jfs = ta->jfs; - if (jfs->jfs_cfg.eid_index >= jfs->ub_dev->eid_table.eid_cnt) + if (jfs->jfs_cfg.eid_index >= jfs->ub_dev->eid_table.eid_cnt || + IS_ERR_OR_NULL(jfs->ub_dev->eid_table.eid_entries)) return; ta_data->jetty_id.eid = jfs->ub_dev->eid_table.eid_entries[jfs->jfs_cfg.eid_index].eid; @@ -134,7 +141,8 @@ static void ubcore_get_ta_data_from_ta(const struct ubcore_ta *ta, break; case UBCORE_TA_JETTY_TJETTY: jetty = ta->jetty; - if (jetty->jetty_cfg.eid_index >= jetty->ub_dev->eid_table.eid_cnt) + if (jetty->jetty_cfg.eid_index >= jetty->ub_dev->eid_table.eid_cnt || + IS_ERR_OR_NULL(jetty->ub_dev->eid_table.eid_entries)) return; ta_data->jetty_id.eid = jetty->ub_dev->eid_table.eid_entries[jetty->jetty_cfg.eid_index].eid; @@ -215,7 +223,8 @@ static void ubcore_set_tp_flag(union ubcore_tp_flag *flag, struct ubcore_tp_cfg void ubcore_set_tp_init_cfg(struct ubcore_tp *tp, struct ubcore_tp_cfg *cfg) { ubcore_set_tp_flag(&tp->flag, cfg, tp->ub_dev); - if (tp->ub_dev->transport_type == UBCORE_TRANSPORT_IB || + if (tp->ub_dev->transport_type == UBCORE_TRANSPORT_HNS_UB || + tp->ub_dev->transport_type == UBCORE_TRANSPORT_IB || (tp->ub_dev->transport_type == UBCORE_TRANSPORT_UB && tp->trans_mode == UBCORE_TP_RC)) { tp->local_jetty = cfg->local_jetty; @@ -332,6 +341,8 @@ int ubcore_modify_tp_state_check(struct ubcore_tp *tp, enum ubcore_tp_state new_ int ubcore_modify_tp_state(struct ubcore_device *dev, struct ubcore_tp *tp, enum ubcore_tp_state new_state, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask mask) { + enum ubcore_tp_state old_state = tp->state; + if (ubcore_modify_tp_state_check(tp, new_state) != 0) return -1; @@ -349,7 +360,7 @@ int ubcore_modify_tp_state(struct ubcore_device *dev, struct ubcore_tp *tp, } tp->state = new_state; ubcore_log_info("tp state:(%u to %u) with tpn %u, peer_tpn %u", - (uint32_t)tp->state, (uint32_t)new_state, tp->tpn, tp->peer_tpn); + (uint32_t)old_state, (uint32_t)new_state, tp->tpn, tp->peer_tpn); return 0; } @@ -395,15 +406,19 @@ void ubcore_modify_tp_attr(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, ubcore_mod_tp_attr_with_mask(tp, attr, mtu, mask); ubcore_mod_tp_attr_with_mask(tp, attr, cc_pattern_idx, mask); ubcore_mod_tp_attr_with_mask(tp, attr, peer_ext, mask); + ubcore_mod_tp_attr_with_mask(tp, attr, oos_cnt, mask); ubcore_mod_tp_attr_with_mask(tp, attr, local_net_addr_idx, mask); ubcore_mod_tp_attr_with_mask(tp, attr, peer_net_addr, mask); + ubcore_mod_tp_attr_with_mask(tp, attr, data_udp_start, mask); + ubcore_mod_tp_attr_with_mask(tp, attr, ack_udp_start, mask); + ubcore_mod_tp_attr_with_mask(tp, attr, udp_range, mask); + ubcore_mod_tp_attr_with_mask(tp, attr, hop_limit, mask); ubcore_mod_tp_attr_with_mask(tp, attr, port_id, mask); } static int ubcore_set_target_peer(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask *mask, struct ubcore_tp_attr *tp_attr, struct ubcore_udata udata) { - mask->value = 0; mask->value = UBCORE_TP_ATTR_MASK; memset(attr, 0, sizeof(*attr)); @@ -430,7 +445,8 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, switch (ta->type) { case UBCORE_TA_JFS_TJFR: jfs = ta->jfs; - if (jfs->jfs_cfg.eid_index >= jfs->ub_dev->eid_table.eid_cnt) + if (jfs->jfs_cfg.eid_index >= jfs->ub_dev->eid_table.eid_cnt || + IS_ERR_OR_NULL(jfs->ub_dev->eid_table.eid_entries)) return; vtp_param->local_eid = jfs->ub_dev->eid_table.eid_entries[jfs->jfs_cfg.eid_index].eid; @@ -439,7 +455,8 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, break; case UBCORE_TA_JETTY_TJETTY: jetty = ta->jetty; - if (jetty->jetty_cfg.eid_index >= jetty->ub_dev->eid_table.eid_cnt) + if (jetty->jetty_cfg.eid_index >= jetty->ub_dev->eid_table.eid_cnt || + IS_ERR_OR_NULL(jetty->ub_dev->eid_table.eid_entries)) return; vtp_param->local_eid = jetty->ub_dev->eid_table.eid_entries[jetty->jetty_cfg.eid_index].eid; @@ -454,7 +471,6 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, vtp_param->trans_mode = trans_mode; vtp_param->peer_eid = ta->tjetty_id.eid; vtp_param->peer_jetty = ta->tjetty_id.id; - vtp_param->eid_index = 0; vtp_param->ta = *ta; } @@ -511,28 +527,22 @@ int ubcore_modify_tp(struct ubcore_device *dev, struct ubcore_tp_node *tp_node, } static int ubcore_parse_ta(struct ubcore_device *dev, struct ubcore_ta_data *ta_data, - struct ubcore_tp_advice *advice) + struct ubcore_tp_meta *meta) { - struct ubcore_tp_meta *meta; struct ubcore_jetty *jetty; struct ubcore_jfs *jfs; - (void)memset(advice, 0, sizeof(struct ubcore_tp_advice)); - meta = &advice->meta; - advice->ta.type = ta_data->ta_type; - switch (ta_data->ta_type) { case UBCORE_TA_JFS_TJFR: - jfs = ubcore_find_jfs(dev, ta_data->tjetty_id.id); + jfs = ubcore_find_get_jfs(dev, ta_data->tjetty_id.id); if (jfs != NULL) { meta->ht = ubcore_get_tptable(jfs->tptable); - advice->ta.jfs = jfs; - advice->ta.tjetty_id = ta_data->jetty_id; + ubcore_put_jfs(jfs); } break; case UBCORE_TA_JETTY_TJETTY: /* todonext: add kref to jetty, as it may be destroyed any time */ - jetty = ubcore_find_jetty(dev, ta_data->tjetty_id.id); + jetty = ubcore_find_get_jetty(dev, ta_data->tjetty_id.id); if (jetty != NULL) { if (jetty->jetty_cfg.trans_mode == UBCORE_TP_RC && jetty->remote_jetty != NULL && @@ -540,11 +550,11 @@ static int ubcore_parse_ta(struct ubcore_device *dev, struct ubcore_ta_data *ta_ sizeof(struct ubcore_jetty_id))) { ubcore_log_err( "the same jetty is binded with another remote jetty.\n"); + ubcore_put_jetty(jetty); return -1; } meta->ht = ubcore_get_tptable(jetty->tptable); - advice->ta.jetty = jetty; - advice->ta.tjetty_id = ta_data->jetty_id; + ubcore_put_jetty(jetty); } break; case UBCORE_TA_NONE: @@ -568,7 +578,7 @@ static int ubcore_init_create_tp_req(struct ubcore_device *dev, struct ubcore_vt data->eid_index = tp_param->eid_index; data->local_jetty = tp_param->local_jetty; data->peer_jetty = tp_param->peer_jetty; - (void)strcpy(data->dev_name, dev->dev_name); + (void)strncpy(data->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); data->virtualization = dev->attr.virtualization; ubcore_get_ta_data_from_ta(&tp_param->ta, dev->transport_type, &data->ta_data); @@ -674,7 +684,7 @@ static int ubcore_send_del_tp_req(struct ubcore_device *dev, struct ubcore_vtp_p data->eid_index = tp_param->eid_index; data->local_jetty = tp_param->local_jetty; data->peer_jetty = tp_param->peer_jetty; - (void)strcpy(data->dev_name, dev->dev_name); + (void)strncpy(data->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); data->virtualization = dev->attr.virtualization; /* for alpha start */ ubcore_get_ta_data_from_ta(&tp_param->ta, dev->transport_type, &data->ta_data); @@ -788,13 +798,6 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, return -EINVAL; } dev = jetty->ub_dev; - mutex_lock(&tjetty->lock); - if (tjetty->tp != NULL) { - mutex_unlock(&tjetty->lock); - ubcore_log_err("The same tjetty, different jetty, prevent duplicate bind.\n"); - return -1; - } - mutex_unlock(&tjetty->lock); ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RC, &tp_param); if (ubcore_query_initiator_tp_cfg(&tp_cfg, dev, &tp_param) != 0) { @@ -817,13 +820,25 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, (void)ubcore_destroy_tp(new_tp); new_tp = NULL; } + + mutex_lock(&tjetty->lock); + if (tjetty->tp != NULL) { + mutex_unlock(&tjetty->lock); + ubcore_tpnode_kref_put(tp_node); + ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); + ubcore_log_err("The same tjetty, different jetty, prevent duplicate bind.\n"); + return -1; + } + if (ubcore_send_create_tp_req(dev, &tp_param, tp_node->tp, udata) != 0) { ubcore_log_err("Failed to send tp req"); + mutex_unlock(&tjetty->lock); + ubcore_tpnode_kref_put(tp_node); ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); return -1; } - mutex_lock(&tjetty->lock); tjetty->tp = tp_node->tp; + ubcore_tpnode_kref_put(tp_node); mutex_unlock(&tjetty->lock); return 0; } @@ -850,7 +865,10 @@ int ubcore_unbind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RC, &tp_param); if (ubcore_send_del_tp_req(jetty->ub_dev, &tp_param) != 0) { ubcore_log_warn("failed to unbind tp\n"); - return -1; + /* It does not depend on the success of the peer TP, + * but depends on the success of the local cleanup, + * otherwise the TP remains. + */ } ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); @@ -876,9 +894,11 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, } /* Must call driver->create_tp with udata if we are advising jetty */ - tp_node = ubcore_hash_table_lookup(advice->meta.ht, advice->meta.hash, &advice->meta.key); - if (tp_node != NULL && tp_node->tp != NULL && !tp_node->tp->flag.bs.target) + tp_node = ubcore_lookup_tpnode(advice->meta.ht, advice->meta.hash, &advice->meta.key); + if (tp_node != NULL && tp_node->tp != NULL && !tp_node->tp->flag.bs.target) { + ubcore_tpnode_kref_put(tp_node); return 0; + } ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RM, &tp_param); if (ubcore_query_initiator_tp_cfg(&tp_cfg, dev, &tp_param) != 0) { @@ -905,11 +925,12 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, } if (ubcore_send_create_tp_req(dev, &tp_param, tp_node->tp, udata) != 0) { + ubcore_tpnode_kref_put(tp_node); ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); ubcore_log_err("Failed to send tp req"); return -1; } - + ubcore_tpnode_kref_put(tp_node); return 0; } EXPORT_SYMBOL(ubcore_advise_tp); @@ -926,9 +947,13 @@ int ubcore_unadvise_tp(struct ubcore_device *dev, struct ubcore_tp_advice *advic ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RM, &tp_param); ret = ubcore_send_del_tp_req(dev, &tp_param); - if (ret != 0) - return ret; - + if (ret != 0) { + ubcore_log_warn("failed to unadvise tp\n"); + /* It does not depend on the success of the peer TP, + * but depends on the success of the local cleanup, + * otherwise the TP remains. + */ + } ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); return 0; } @@ -1128,12 +1153,12 @@ void ubcore_restore_tp(struct ubcore_device *dev, struct ubcore_tp *tp) struct ubcore_nl_restore_tp_resp *resp; struct ubcore_nl_restore_tp_req *req; - /* Currently, only try to restore tp in the UBCORE_TRANSPORT_IB device, + /* Currently, only try to restore tp in the UBCORE_TRANSPORT_HNS_UB device, * Do not send retore tp req from target to inititor, * Do not restore UM TP, as it is only visable by the driver */ if (!ubcore_have_tp_ops(dev) || tp == NULL || - dev->transport_type != UBCORE_TRANSPORT_IB || tp->flag.bs.target || + dev->transport_type != UBCORE_TRANSPORT_HNS_UB || tp->flag.bs.target || tp->priv == NULL || tp->trans_mode == UBCORE_TP_UM || tp->state != UBCORE_TP_STATE_ERR) return; @@ -1285,42 +1310,56 @@ void ubcore_report_tp_suspend(struct ubcore_device *dev, struct ubcore_tp *tp) kfree(req_msg); } +void ubcore_put_ta_jetty(struct ubcore_ta *ta) +{ + if (ta->type == UBCORE_TA_JFS_TJFR) + ubcore_put_jfs(ta->jfs); + else if (ta->type == UBCORE_TA_JETTY_TJETTY) + ubcore_put_jetty(ta->jetty); +} + +void ubcore_put_target_ta_jetty(struct ubcore_ta *ta) +{ + if (ta->type == UBCORE_TA_JFS_TJFR) + ubcore_put_jfr(ta->jfr); + else if (ta->type == UBCORE_TA_JETTY_TJETTY) + ubcore_put_jetty(ta->jetty); +} + /* restore target RM tp created by ubcore_advise_target_tp */ static int ubcore_restore_advised_target_tp(struct ubcore_device *dev, struct ubcore_nl_restore_tp_req *restore, uint32_t *rx_psn) { - struct ubcore_tp_advice advice; + struct ubcore_tp_meta meta = {0}; struct ubcore_tp_node *tp_node; - struct ubcore_tp_meta *meta; struct ubcore_tp *tp; - meta = &advice.meta; - if (ubcore_parse_ta(dev, &restore->ta, &advice) != 0) { + if (ubcore_parse_ta(dev, &restore->ta, &meta) != 0) { ubcore_log_err("Failed to parse ta with type %u", (uint32_t)restore->ta.ta_type); return -1; - } else if (meta->ht == NULL) { - ubcore_log_err("tp table is already released"); + } else if (meta.ht == NULL) { + ubcore_log_info("tp table is already released"); return -1; } - spin_lock(&meta->ht->lock); - tp_node = ubcore_hash_table_lookup_nolock(meta->ht, meta->hash, &meta->key); + spin_lock(&meta.ht->lock); + tp_node = ubcore_hash_table_lookup_nolock(meta.ht, meta.hash, &meta.key); /* pair with get_tptable in parse_ta */ - ubcore_put_tptable(meta->ht); + ubcore_put_tptable(meta.ht); if (tp_node == NULL) { - spin_unlock(&meta->ht->lock); + spin_unlock(&meta.ht->lock); ubcore_log_err("tp is not found%u", restore->peer_tpn); return -1; } tp = tp_node->tp; if (ubcore_restore_tp_to_rts(dev, tp, get_random_u32(), restore->rx_psn) != 0) { - spin_unlock(&meta->ht->lock); + spin_unlock(&meta.ht->lock); ubcore_log_err("Failed to modify tp to rts %u", restore->rx_psn); return -1; } *rx_psn = tp->rx_psn; - spin_unlock(&meta->ht->lock); + spin_unlock(&meta.ht->lock); return 0; } @@ -1333,7 +1372,7 @@ static int ubcore_restore_bound_target_tp(struct ubcore_device *dev, static int ubcore_handle_restore_tp(struct ubcore_device *dev, struct ubcore_nl_restore_tp_req *restore, uint32_t *rx_psn) { - if (dev->transport_type != UBCORE_TRANSPORT_IB || + if (dev->transport_type != UBCORE_TRANSPORT_HNS_UB || restore == NULL || restore->trans_mode == UBCORE_TP_UM || restore->ta.ta_type == UBCORE_TA_NONE || restore->ta.ta_type >= UBCORE_TA_VIRT) return -1; diff --git a/drivers/ub/urma/ubcore/ubcore_tp.h b/drivers/ub/urma/ubcore/ubcore_tp.h index 723e9d13ce6c..f3671f06abb8 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.h +++ b/drivers/ub/urma/ubcore/ubcore_tp.h @@ -73,4 +73,6 @@ void ubcore_modify_tp_attr(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, int ubcore_modify_tp_state_check(struct ubcore_tp *tp, enum ubcore_tp_state new_state); void ubcore_tp_get(void *obj); void ubcore_tp_kref_put(struct ubcore_tp *tp); +void ubcore_put_ta_jetty(struct ubcore_ta *ta); +void ubcore_put_target_ta_jetty(struct ubcore_ta *ta); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_tp_table.c b/drivers/ub/urma/ubcore/ubcore_tp_table.c index b2b5ef2c7a32..dc9332599c6e 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp_table.c +++ b/drivers/ub/urma/ubcore/ubcore_tp_table.c @@ -41,6 +41,22 @@ void ubcore_remove_tp_node(struct ubcore_hash_table *ht, struct ubcore_tp_node * kfree(tp_node); } + +static void ubcore_tpnode_kref_release(struct kref *ref_cnt) +{ + struct ubcore_tp_node *tp_node = container_of(ref_cnt, struct ubcore_tp_node, ref_cnt); + + complete(&tp_node->comp); +} + +void ubcore_tpnode_kref_put(struct ubcore_tp_node *tp_node) +{ + if (tp_node == NULL) + return; + + (void)kref_put(&tp_node->ref_cnt, ubcore_tpnode_kref_release); +} + /* Find and remove the tp from table only if it is unreferenced */ void ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, const struct ubcore_tp_key *key) @@ -58,14 +74,16 @@ void ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, spin_unlock(&ht->lock); return; } - if (atomic_dec_return(&tp_node->tp->use_cnt) == 0) { - tp = tp_node->tp; - hlist_del(&tp_node->hnode); - mutex_destroy(&tp_node->lock); - kfree(tp_node); - (void)ubcore_destroy_tp(tp); - } + hlist_del_init(&tp_node->hnode); spin_unlock(&ht->lock); + + ubcore_tpnode_kref_put(tp_node); + wait_for_completion(&tp_node->comp); + + tp = tp_node->tp; + mutex_destroy(&tp_node->lock); + kfree(tp_node); + (void)ubcore_destroy_tp(tp); } struct ubcore_hash_table *ubcore_create_tptable(void) @@ -95,6 +113,10 @@ struct ubcore_hash_table *ubcore_create_tptable(void) static void ubcore_free_tp_node(void *obj) { struct ubcore_tp_node *tp_node = (struct ubcore_tp_node *)obj; + + ubcore_tpnode_kref_put(tp_node); + wait_for_completion(&tp_node->comp); + (void)ubcore_destroy_tp(tp_node->tp); kfree(tp_node); } @@ -152,6 +174,8 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t new_tp_node->tp = tp; new_tp_node->ta = *ta; mutex_init(&new_tp_node->lock); + kref_init(&new_tp_node->ref_cnt); + init_completion(&new_tp_node->comp); spin_lock(&ht->lock); if (ht->head == NULL) { @@ -162,7 +186,7 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t } tp_node = ubcore_hash_table_lookup_nolock(ht, hash, key); if (tp_node != NULL) { - atomic_inc(&tp_node->tp->use_cnt); + kref_get(&tp_node->ref_cnt); spin_unlock(&ht->lock); mutex_destroy(&new_tp_node->lock); kfree(new_tp_node); @@ -172,7 +196,20 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t ubcore_hash_table_add_nolock(ht, &new_tp_node->hnode, hash); /* set private data for tp restore */ tp->priv = new_tp_node; - atomic_inc(&new_tp_node->tp->use_cnt); + kref_get(&new_tp_node->ref_cnt); spin_unlock(&ht->lock); return new_tp_node; } + +struct ubcore_tp_node *ubcore_lookup_tpnode(struct ubcore_hash_table *ht, uint32_t hash, + const struct ubcore_tp_key *key) +{ + struct ubcore_tp_node *tp_node = NULL; + + spin_lock(&ht->lock); + tp_node = ubcore_hash_table_lookup_nolock(ht, hash, key); + if (tp_node != NULL) + kref_get(&tp_node->ref_cnt); + spin_unlock(&ht->lock); + return tp_node; +} diff --git a/drivers/ub/urma/ubcore/ubcore_tp_table.h b/drivers/ub/urma/ubcore/ubcore_tp_table.h index ed1045ff2ac1..28c0af963358 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp_table.h +++ b/drivers/ub/urma/ubcore/ubcore_tp_table.h @@ -40,6 +40,8 @@ struct ubcore_tp_node { struct ubcore_ta ta; struct hlist_node hnode; struct mutex lock; + struct kref ref_cnt; + struct completion comp; }; void ubcore_init_tp_key_jetty_id(struct ubcore_tp_key *key, @@ -54,6 +56,10 @@ void ubcore_remove_tp_node(struct ubcore_hash_table *ht, struct ubcore_tp_node * void ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, const struct ubcore_tp_key *key); +struct ubcore_tp_node *ubcore_lookup_tpnode(struct ubcore_hash_table *ht, uint32_t hash, + const struct ubcore_tp_key *key); +void ubcore_tpnode_kref_put(struct ubcore_tp_node *tp_node); + /* TP table ops for devices that do not natively support RM */ struct ubcore_hash_table *ubcore_create_tptable(void); void ubcore_destroy_tptable(struct ubcore_hash_table **pp_ht); diff --git a/drivers/ub/urma/ubcore/ubcore_tpg.c b/drivers/ub/urma/ubcore/ubcore_tpg.c index 25bd79221e5e..ac9f0faf8230 100644 --- a/drivers/ub/urma/ubcore/ubcore_tpg.c +++ b/drivers/ub/urma/ubcore/ubcore_tpg.c @@ -24,13 +24,6 @@ #include "ubcore_tp.h" #include "ubcore_tpg.h" -static int ubcore_free_wait_tpg(struct ubcore_device *dev, struct ubcore_tpg *tpg) -{ - ubcore_tpg_kref_put(tpg); - wait_for_completion(&tpg->comp); - return dev->ops->destroy_tpg(tpg); -} - struct ubcore_tpg *ubcore_create_tpg(struct ubcore_device *dev, struct ubcore_tpg_cfg *cfg) { struct ubcore_tpg *tpg; @@ -50,26 +43,13 @@ struct ubcore_tpg *ubcore_create_tpg(struct ubcore_device *dev, struct ubcore_tp tpg->tpg_cfg = *cfg; for (i = 0; i < cfg->tp_cnt; i++) tpg->tp_list[i] = NULL; - atomic_set(&tpg->use_cnt, 0); + kref_init(&tpg->ref_cnt); - init_completion(&tpg->comp); mutex_init(&tpg->mutex); return tpg; } -static void ubcore_tpg_kref_release(struct kref *ref_cnt) -{ - struct ubcore_tpg *tpg = container_of(ref_cnt, struct ubcore_tpg, ref_cnt); - - complete(&tpg->comp); -} - -void ubcore_tpg_kref_put(struct ubcore_tpg *tpg) -{ - (void)kref_put(&tpg->ref_cnt, ubcore_tpg_kref_release); -} - void ubcore_tpg_get(void *obj) { struct ubcore_tpg *tpg = obj; @@ -77,27 +57,34 @@ void ubcore_tpg_get(void *obj) kref_get(&tpg->ref_cnt); } -int ubcore_destroy_tpg(struct ubcore_tpg *tpg) +static void ubcore_destroy_tpg(struct ubcore_tpg *tpg) { struct ubcore_device *dev = tpg->ub_dev; int ret; if (dev->ops == NULL || dev->ops->destroy_tpg == NULL) - return -EINVAL; + return; - ret = ubcore_free_wait_tpg(dev, tpg); - if (ret != 0) { - (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); - /* inc tpg use cnt? */ - ubcore_log_err("Failed to destroy tpg"); - } + ret = dev->ops->destroy_tpg(tpg); + if (ret != 0) + ubcore_log_err("destrory tpg err:%d", ret); +} + +static void ubcore_tpg_kref_release(struct kref *ref_cnt) +{ + struct ubcore_tpg *tpg = container_of(ref_cnt, struct ubcore_tpg, ref_cnt); - return ret; + ubcore_destroy_tpg(tpg); } -struct ubcore_tpg *ubcore_find_tpg(struct ubcore_device *dev, uint32_t tpgn) +void ubcore_tpg_kref_put(struct ubcore_tpg *tpg) { - return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_TPG], tpgn, &tpgn); + (void)kref_put(&tpg->ref_cnt, ubcore_tpg_kref_release); +} + +void ubcore_tpg_kref_get(struct ubcore_tpg *tpg) +{ + kref_get(&tpg->ref_cnt); } struct ubcore_tpg *ubcore_find_get_tpg(struct ubcore_device *dev, uint32_t tpgn) @@ -105,65 +92,60 @@ struct ubcore_tpg *ubcore_find_get_tpg(struct ubcore_device *dev, uint32_t tpgn) return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_TPG], tpgn, &tpgn); } -struct ubcore_tpg *ubcore_find_remove_tpg(struct ubcore_device *dev, uint32_t tpgn) +int ubcore_find_remove_tpg(struct ubcore_device *dev, uint32_t tpgn) { struct ubcore_tpg *tpg; spin_lock(&dev->ht[UBCORE_HT_TPG].lock); if (&dev->ht[UBCORE_HT_TPG].head == NULL) { spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); - return NULL; + return -1; } tpg = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_TPG], tpgn, &tpgn); if (tpg == NULL) { spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); - return NULL; - } - if (atomic_read(&tpg->use_cnt) > 0) { - spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); - ubcore_log_err("Failed to remove tpg"); - return NULL; + return -1; } ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); + ubcore_tpg_kref_put(tpg); spin_unlock(&dev->ht[UBCORE_HT_TPG].lock); - - return tpg; + return 0; } int ubcore_add_tp(struct ubcore_device *dev, struct ubcore_tp *tp) { - return ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UB_TP], + return ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TP], &tp->hnode, tp->tpn); } struct ubcore_tp *ubcore_find_get_tp(struct ubcore_device *dev, uint32_t tpn) { - return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_UB_TP], tpn, &tpn); + return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_TP], tpn, &tpn); } struct ubcore_tp *ubcore_find_remove_tp_node(struct ubcore_device *dev, uint32_t tpn) { struct ubcore_tp *tp; - spin_lock(&dev->ht[UBCORE_HT_UB_TP].lock); - if (&dev->ht[UBCORE_HT_UB_TP].head == NULL) { - spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + spin_lock(&dev->ht[UBCORE_HT_TP].lock); + if (&dev->ht[UBCORE_HT_TP].head == NULL) { + spin_unlock(&dev->ht[UBCORE_HT_TP].lock); return NULL; } - tp = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_UB_TP], tpn, &tpn); + tp = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_TP], tpn, &tpn); if (tp == NULL) { - spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + spin_unlock(&dev->ht[UBCORE_HT_TP].lock); return NULL; } if (atomic_dec_return(&tp->use_cnt) > 0) { - spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + spin_unlock(&dev->ht[UBCORE_HT_TP].lock); ubcore_log_warn("Failed to remove tp:%u and use cnt:%u", tp->tpn, (uint32_t)atomic_read(&tp->use_cnt)); return NULL; } - ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_UB_TP], &tp->hnode); - spin_unlock(&dev->ht[UBCORE_HT_UB_TP].lock); + ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_TP], &tp->hnode); + spin_unlock(&dev->ht[UBCORE_HT_TP].lock); return tp; } @@ -352,3 +334,23 @@ struct ubcore_tp *ubcore_find_get_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn return NULL; } + +int ubcore_find_add_tpg(struct ubcore_device *dev, struct ubcore_tpg *tpg) +{ + struct ubcore_hash_table *ht = &dev->ht[UBCORE_HT_TPG]; + + spin_lock(&ht->lock); + if (ht->head == NULL) { + spin_unlock(&ht->lock); + return -EINVAL; + } + + if (ubcore_hash_table_lookup_nolock(ht, tpg->tpgn, &tpg->tpgn) != NULL) { + spin_unlock(&ht->lock); + return -EEXIST; + } + ubcore_hash_table_add_nolock(ht, &tpg->hnode, tpg->tpgn); + ubcore_tpg_kref_get(tpg); + spin_unlock(&ht->lock); + return 0; +} diff --git a/drivers/ub/urma/ubcore/ubcore_tpg.h b/drivers/ub/urma/ubcore/ubcore_tpg.h index 56504b20ec6f..8d1cd2b9eef2 100644 --- a/drivers/ub/urma/ubcore/ubcore_tpg.h +++ b/drivers/ub/urma/ubcore/ubcore_tpg.h @@ -23,8 +23,6 @@ #include struct ubcore_tpg *ubcore_create_tpg(struct ubcore_device *dev, struct ubcore_tpg_cfg *cfg); -int ubcore_destroy_tpg(struct ubcore_tpg *tpg); -struct ubcore_tpg *ubcore_find_tpg(struct ubcore_device *dev, uint32_t tpgn); struct ubcore_tpg *ubcore_find_get_tpg(struct ubcore_device *dev, uint32_t tpgn); int ubcore_create_multi_tp(struct ubcore_device *dev, struct ubcore_tpg *tpg, struct ubcore_tp_cfg *cfg); @@ -35,10 +33,11 @@ uint32_t ubcore_modify_tp_in_tpg(struct ubcore_device *dev, struct ubcore_tpg *t struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask *mask, struct ubcore_tp **failed_tp); struct ubcore_tp *ubcore_find_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn); struct ubcore_tp *ubcore_find_get_tp_in_tpg(struct ubcore_tpg *tpg, uint32_t tpn); -struct ubcore_tpg *ubcore_find_remove_tpg(struct ubcore_device *dev, uint32_t tpgn); +int ubcore_find_remove_tpg(struct ubcore_device *dev, uint32_t tpgn); void ubcore_tpg_get(void *obj); void ubcore_tpg_kref_put(struct ubcore_tpg *tpg); int ubcore_add_tp(struct ubcore_device *dev, struct ubcore_tp *tp); struct ubcore_tp *ubcore_find_get_tp(struct ubcore_device *dev, uint32_t tpn); struct ubcore_tp *ubcore_find_remove_tp_node(struct ubcore_device *dev, uint32_t tpn); +int ubcore_find_add_tpg(struct ubcore_device *dev, struct ubcore_tpg *tpg); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_umem.c b/drivers/ub/urma/ubcore/ubcore_umem.c index c9528a409601..fc461e3aa34f 100644 --- a/drivers/ub/urma/ubcore/ubcore_umem.c +++ b/drivers/ub/urma/ubcore/ubcore_umem.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include "ubcore_log.h" #include @@ -277,3 +280,37 @@ void ubcore_umem_release(struct ubcore_umem *umem) kfree(umem); } EXPORT_SYMBOL(ubcore_umem_release); + +uint64_t ubcore_umem_find_best_page_size(struct ubcore_umem *umem, uint64_t page_size_bitmap, + uint64_t va) +{ + uint64_t tmp_ps_bitmap; + struct scatterlist *sg; + uint64_t tmp_va, page_off; + dma_addr_t mask; + int i; + + if (IS_ERR_OR_NULL(umem)) { + ubcore_log_err("Invalid parameter.\n"); + return 0; + } + tmp_ps_bitmap = page_size_bitmap & GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT); + + tmp_va = va; + mask = tmp_ps_bitmap & GENMASK(BITS_PER_LONG - 1, bits_per((umem->length - 1 + va) ^ va)); + page_off = umem->va & ~PAGE_MASK; + + for_each_sg(umem->sg_head.sgl, sg, umem->sg_head.nents, i) { + mask |= (sg_dma_address(sg) + page_off) ^ tmp_va; + tmp_va += sg_dma_len(sg) - page_off; + if (i != (umem->sg_head.nents - 1)) + mask |= tmp_va; + page_off = 0; + } + + if (mask) + tmp_ps_bitmap &= GENMASK(count_trailing_zeros(mask), 0); + + return tmp_ps_bitmap ? rounddown_pow_of_two(tmp_ps_bitmap) : 0; +} +EXPORT_SYMBOL(ubcore_umem_find_best_page_size); diff --git a/drivers/ub/urma/ubcore/ubcore_utp.c b/drivers/ub/urma/ubcore/ubcore_utp.c index 215350a2e9db..463a8b8499f6 100644 --- a/drivers/ub/urma/ubcore/ubcore_utp.c +++ b/drivers/ub/urma/ubcore/ubcore_utp.c @@ -24,33 +24,27 @@ #include "ubcore_device.h" #include "ubcore_utp.h" -int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, - enum ubcore_mtu *mtu) +static void ubcore_destroy_utp(struct ubcore_utp *utp) { - struct ubcore_device_status st = { 0 }; + struct ubcore_device *dev = utp->ub_dev; + uint32_t utp_idx = utp->utpn; + int ret; - if (port_num >= dev->attr.port_cnt || dev->ops == NULL || - dev->ops->query_device_status == NULL || port_num >= UBCORE_MAX_PORT_CNT) { - ubcore_log_err("Invalid parameter"); - return -1; - } - if (dev->ops->query_device_status(dev, &st) != 0) { - ubcore_log_err("Failed to query query_device_status for port %hhu", port_num); - return -1; - } - if (st.port_status[port_num].state != UBCORE_PORT_ACTIVE) { - ubcore_log_err("Port %d is not active", port_num); - return -1; + if (dev->ops == NULL || dev->ops->destroy_utp == NULL) + return; + + ret = dev->ops->destroy_utp(utp); + if (ret != 0) { + ubcore_log_err("Failed to destroy utp:%u", utp_idx); + return; } - *mtu = st.port_status[port_num].active_mtu; - return 0; } static void ubcore_utp_kref_release(struct kref *ref_cnt) { struct ubcore_utp *utp = container_of(ref_cnt, struct ubcore_utp, ref_cnt); - complete(&utp->comp); + ubcore_destroy_utp(utp); } void ubcore_utp_kref_put(struct ubcore_utp *utp) @@ -65,6 +59,31 @@ void ubcore_utp_get(void *obj) kref_get(&utp->ref_cnt); } +static void ubcore_utp_kref_get(struct ubcore_utp *utp) +{ + kref_get(&utp->ref_cnt); +} + +static int ubcore_find_add_utp(struct ubcore_hash_table *ht, struct ubcore_utp *utp) +{ + struct hlist_node *hnode = &utp->hnode; + uint32_t hash = utp->utpn; + + spin_lock(&ht->lock); + if (ht->head == NULL) { + spin_unlock(&ht->lock); + return -EINVAL; + } + if (ubcore_hash_table_lookup_nolock(ht, hash, ubcore_ht_key(ht, hnode)) != NULL) { + spin_unlock(&ht->lock); + return -EEXIST; + } + ubcore_hash_table_add_nolock(ht, hnode, hash); + ubcore_utp_kref_get(utp); + spin_unlock(&ht->lock); + return 0; +} + struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_utp_cfg *cfg) { struct ubcore_utp *utp; @@ -82,45 +101,17 @@ struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_ut } utp->ub_dev = dev; utp->utp_cfg = *cfg; - atomic_set(&utp->use_cnt, 0); kref_init(&utp->ref_cnt); - init_completion(&utp->comp); - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UTP], &utp->hnode, utp->utpn); + ret = ubcore_find_add_utp(&dev->ht[UBCORE_HT_UTP], utp); if (ret != 0) { - (void)dev->ops->destroy_utp(utp); - utp = NULL; + ubcore_utp_kref_put(utp); ubcore_log_err("Failed to add utp to the utp table"); - return utp; + return NULL; } - - ubcore_log_info("Success to create utp, utp_idx %u", utp->utpn); return utp; } -int ubcore_destroy_utp(struct ubcore_utp *utp) -{ - struct ubcore_device *dev = utp->ub_dev; - uint32_t utp_idx = utp->utpn; - int ret; - - if (dev->ops == NULL || dev->ops->destroy_utp == NULL) - return -EINVAL; - - ubcore_utp_kref_put(utp); - wait_for_completion(&utp->comp); - ret = dev->ops->destroy_utp(utp); - if (ret != 0) { - (void)ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_UTP], &utp->hnode, utp->utpn); - /* inc utp use cnt? */ - ubcore_log_err("Failed to destroy utp"); - return ret; - } - - ubcore_log_info("Success to destroy utp, utp_idx %u", utp_idx); - return ret; -} - struct ubcore_utp *ubcore_find_utp(struct ubcore_device *dev, uint32_t idx) { return ubcore_hash_table_lookup(&dev->ht[UBCORE_HT_UTP], idx, &idx); @@ -131,27 +122,21 @@ struct ubcore_utp *ubcore_find_get_utp(struct ubcore_device *dev, uint32_t idx) return ubcore_hash_table_lookup_get(&dev->ht[UBCORE_HT_UTP], idx, &idx); } -struct ubcore_utp *ubcore_find_remove_utp(struct ubcore_device *dev, uint32_t idx) +void ubcore_find_remove_utp(struct ubcore_device *dev, uint32_t idx) { struct ubcore_utp *utp; spin_lock(&dev->ht[UBCORE_HT_UTP].lock); if (&dev->ht[UBCORE_HT_UTP].head == NULL) { spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); - return NULL; + return; } utp = ubcore_hash_table_lookup_nolock(&dev->ht[UBCORE_HT_UTP], idx, &idx); if (utp == NULL) { spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); - return NULL; - } - if (atomic_read(&utp->use_cnt) > 0) { - spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); - ubcore_log_err("Failed to remove utp"); - return NULL; + return; } ubcore_hash_table_remove_nolock(&dev->ht[UBCORE_HT_UTP], &utp->hnode); + ubcore_utp_kref_put(utp); spin_unlock(&dev->ht[UBCORE_HT_UTP].lock); - - return utp; } diff --git a/drivers/ub/urma/ubcore/ubcore_utp.h b/drivers/ub/urma/ubcore/ubcore_utp.h index 5587d2825dcb..062d19cf8105 100644 --- a/drivers/ub/urma/ubcore/ubcore_utp.h +++ b/drivers/ub/urma/ubcore/ubcore_utp.h @@ -23,13 +23,10 @@ #include -int utp_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, - enum ubcore_mtu *mtu); struct ubcore_utp *ubcore_create_utp(struct ubcore_device *dev, struct ubcore_utp_cfg *cfg); -int ubcore_destroy_utp(struct ubcore_utp *utp); struct ubcore_utp *ubcore_find_utp(struct ubcore_device *dev, uint32_t idx); struct ubcore_utp *ubcore_find_get_utp(struct ubcore_device *dev, uint32_t idx); -struct ubcore_utp *ubcore_find_remove_utp(struct ubcore_device *dev, uint32_t idx); +void ubcore_find_remove_utp(struct ubcore_device *dev, uint32_t idx); void ubcore_utp_get(void *obj); void ubcore_utp_kref_put(struct ubcore_utp *utp); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c index 87484aa8fdb6..e30faee7bb48 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c @@ -31,6 +31,7 @@ #include #include "ubcore_device.h" #include "urma/ubcore_jetty.h" +#include "ubcore_main.h" #include "ubcore_uvs_cmd.h" static int ubcore_uvs_cmd_channel_init(struct ubcore_cmd_hdr *hdr) @@ -132,11 +133,11 @@ static struct ubcore_tpg *ubcore_create_tpg_and_multi_tp(struct ubcore_device *d free_tp_cfg: kfree(tp_cfgs); destroy_tpg: - (void)ubcore_destroy_tpg(tpg); + ubcore_tpg_kref_put(tpg); return ERR_PTR(ret); } -static int ubcore_para_ta(struct ubcore_device *dev, struct ubcore_tp_advice *advice, +static int ubcore_parse_ta_get_jetty(struct ubcore_device *dev, struct ubcore_tp_advice *advice, struct ubcore_ta_data *ta_data) { struct ubcore_tp_meta *meta; @@ -148,7 +149,7 @@ static int ubcore_para_ta(struct ubcore_device *dev, struct ubcore_tp_advice *ad switch (ta_data->ta_type) { case UBCORE_TA_JFS_TJFR: - jfs = ubcore_find_jfs(dev, ta_data->jetty_id.id); + jfs = ubcore_find_get_jfs(dev, ta_data->jetty_id.id); if (jfs == NULL) { ubcore_log_err("Failed to find jfs by jetty id %u", ta_data->jetty_id.id); return -1; @@ -158,7 +159,7 @@ static int ubcore_para_ta(struct ubcore_device *dev, struct ubcore_tp_advice *ad advice->ta.tjetty_id = ta_data->tjetty_id; break; case UBCORE_TA_JETTY_TJETTY: - jetty = ubcore_find_jetty(dev, ta_data->jetty_id.id); + jetty = ubcore_find_get_jetty(dev, ta_data->jetty_id.id); if (jetty == NULL) { ubcore_log_err("Failed to find jetty by jetty id %u", ta_data->jetty_id.id); return -1; @@ -182,8 +183,9 @@ static int ubcore_get_active_mtu(struct ubcore_device *dev, uint8_t port_num, { struct ubcore_device_status st = { 0 }; - if (port_num >= dev->attr.port_cnt || dev->ops == NULL || - dev->ops->query_device_status == NULL) { + if (dev == NULL || dev->ops == NULL || + dev->ops->query_device_status == NULL || + port_num >= UBCORE_MAX_PORT_CNT) { ubcore_log_err("Invalid parameter"); return -1; } @@ -230,7 +232,7 @@ static struct ubcore_tp_node *ubcore_get_tp_node(struct ubcore_device *dev, struct ubcore_tp_node *tp_node = NULL; struct ubcore_tp *new_tp = NULL; - tp_node = ubcore_hash_table_lookup(advice->meta.ht, advice->meta.hash, &advice->meta.key); + tp_node = ubcore_lookup_tpnode(advice->meta.ht, advice->meta.hash, &advice->meta.key); if (tp_node == NULL) { new_tp = ubcore_create_tp(dev, tp_cfg, udata); if (IS_ERR_OR_NULL(new_tp)) { @@ -247,8 +249,6 @@ static struct ubcore_tp_node *ubcore_get_tp_node(struct ubcore_device *dev, (void)ubcore_destroy_tp(new_tp); new_tp = NULL; } - } else { - atomic_inc(&tp_node->tp->use_cnt); } return tp_node; } @@ -264,32 +264,32 @@ static int ubcore_cmd_create_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_cr if (dev == NULL) return -ENODEV; - if (ubcore_para_ta(dev, &advice, &arg->ta_data) != 0) { + if (ubcore_parse_ta_get_jetty(dev, &advice, &arg->ta_data) != 0) { ubcore_log_err("Failed to parse ta with type %u", advice.ta.type); goto put_device; } else if (advice.meta.ht == NULL) { - ubcore_log_err("tp table is already released"); - goto put_device; + ubcore_log_info("tp table is already released"); + goto put_jetty; } - spin_lock(&advice.meta.ht->lock); - tp_node = ubcore_hash_table_lookup_nolock(advice.meta.ht, - advice.meta.hash, &advice.meta.key); - if (!tp_node) { - spin_unlock(&advice.meta.ht->lock); + + tp_node = ubcore_lookup_tpnode(advice.meta.ht, advice.meta.hash, &advice.meta.key); + if (!tp_node) goto put_tptable; - } ret = ubcore_copy_tpg_udrv_data(hdr, arg, tp_node); - spin_unlock(&advice.meta.ht->lock); + ubcore_tpnode_kref_put(tp_node); if (ret) goto put_tptable; ubcore_put_tptable(advice.meta.ht); + ubcore_put_ta_jetty(&advice.ta); ubcore_put_device(dev); return ret; put_tptable: ubcore_put_tptable(advice.meta.ht); +put_jetty: + ubcore_put_ta_jetty(&advice.ta); put_device: ubcore_put_device(dev); return -1; @@ -312,7 +312,8 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) if (ret != 0) goto free_arg; - if (arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { + if (arg->ta_data.trans_type == UBCORE_TRANSPORT_HNS_UB || + arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { ret = ubcore_cmd_create_tp(hdr, arg); goto free_arg; } @@ -326,7 +327,7 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) if (ubcore_get_active_mtu(dev, 0, &arg->local_mtu) != 0) goto put_device; - if (ubcore_get_max_mtu(dev, 0, &arg->out.max_mtu) != 0) + if (ubcore_get_max_mtu(dev, &arg->out.max_mtu) != 0) goto put_device; tpg = ubcore_create_tpg_and_multi_tp(dev, &arg->in.tpg_cfg, arg->in.tp_cfg); @@ -335,7 +336,7 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) goto put_device; } - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); + ret = ubcore_find_add_tpg(dev, tpg); if (ret != 0) { ubcore_log_err("Failed to add tpg to the tpg table"); goto destroy_tpg; @@ -351,15 +352,14 @@ static int ubcore_cmd_create_tpg(struct ubcore_cmd_hdr *hdr) if (ret != 0) goto remove_tpg; else - goto put_device; + goto put_tpg; remove_tpg: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); - if (atomic_read(&tpg->use_cnt) > 0) - ubcore_log_warn("tpg use_cnt still greater than 0 after remove"); + ubcore_find_remove_tpg(dev, tpg->tpgn); destroy_tpg: (void)ubcore_destroy_multi_tp(dev, tpg); - (void)ubcore_destroy_tpg(tpg); +put_tpg: + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); free_arg: @@ -490,6 +490,9 @@ static int ubcore_cmd_create_vtp(struct ubcore_cmd_hdr *hdr) ret = PTR_ERR(vtp); goto to_user; } + vtp->eid_idx = arg->in.eid_idx; + vtp->upi = arg->in.upi; + vtp->share_mode = arg->in.share_mode; arg->out.vtpn = vtp->cfg.vtpn; ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, @@ -497,7 +500,9 @@ static int ubcore_cmd_create_vtp(struct ubcore_cmd_hdr *hdr) if (ret != 0) (void)ubcore_unmap_vtp(vtp); - /* Pair with kref_init, then vtp ownership is transferred to vtp hash table */ + /* Pair with kref_init, then vtp ownership is + * transferred to vtp hash table + */ ubcore_vtp_kref_put(vtp); goto free_attr; @@ -547,15 +552,15 @@ static int ubcore_cmd_modify_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_mo if (dev == NULL) return -ENODEV; - if (ubcore_para_ta(dev, &advice, &arg->ta_data) != 0) { + if (ubcore_parse_ta_get_jetty(dev, &advice, &arg->ta_data) != 0) { ubcore_log_err("Failed to parse ta with type %u", advice.ta.type); goto put_device; } else if (advice.meta.ht == NULL) { - ubcore_log_err("tp table is already released"); - goto put_device; + ubcore_log_info("tp table is already released"); + goto put_jetty; } - tp_node = ubcore_hash_table_lookup(advice.meta.ht, advice.meta.hash, &advice.meta.key); + tp_node = ubcore_lookup_tpnode(advice.meta.ht, advice.meta.hash, &advice.meta.key); if (tp_node == NULL) { ubcore_log_err("tp node is already released"); goto put_tptable; @@ -563,15 +568,19 @@ static int ubcore_cmd_modify_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_mo ubcore_set_udata(&udata, &advice, (struct ubcore_udrv_priv *)&arg->udrv_ext); ret = ubcore_modify_tp_node(tp_node, &arg->in.rtr_attr[0], &udata); + ubcore_tpnode_kref_put(tp_node); if (ret) goto put_tptable; ubcore_put_tptable(advice.meta.ht); + ubcore_put_ta_jetty(&advice.ta); ubcore_put_device(dev); return ret; put_tptable: ubcore_put_tptable(advice.meta.ht); +put_jetty: + ubcore_put_ta_jetty(&advice.ta); put_device: ubcore_put_device(dev); return -1; @@ -602,7 +611,8 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) goto free_arg; } - if (arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { + if (arg->ta_data.trans_type == UBCORE_TRANSPORT_HNS_UB || + arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { ret = ubcore_cmd_modify_tp(hdr, arg); goto free_arg; } @@ -672,6 +682,113 @@ static int ubcore_cmd_modify_tpg(struct ubcore_cmd_hdr *hdr) return ret; } +static int ubcore_cmd_modify_tpg_map_vtp(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_tp *failed_tp[UBCORE_MAX_TP_CNT_IN_GRP]; + union ubcore_tp_attr_mask *rts_mask = NULL; + struct ubcore_cmd_modify_tpg_map_vtp *arg; + struct ubcore_tp_attr *rts_attr = NULL; + struct ubcore_vtp_cfg vtp_cfg; + struct ubcore_vtp *vtp = NULL; + struct ubcore_device *dev; + struct ubcore_tpg *tpg; + int ret; + + arg = kzalloc(sizeof(struct ubcore_cmd_modify_tpg_map_vtp), GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; + + ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_modify_tpg_map_vtp)); + if (ret != 0) + goto free_arg; + + if (arg->in.peer_tp_cnt > UBCORE_MAX_TP_CNT_IN_GRP) { + ret = -EINVAL; + ubcore_log_err("arg->in.peer_tp_cnt %d too big", arg->in.peer_tp_cnt); + goto free_arg; + } + + dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); + if (dev == NULL) { + ret = -ENODEV; + goto free_arg; + } + + /* deal with RM first */ + tpg = ubcore_find_get_tpg(dev, arg->in.tpgn); + if (tpg == NULL) { + ret = -EINVAL; + ubcore_log_err("Failed to find tpg"); + goto put_device; + } + + if (tpg->tpg_cfg.tp_cnt > arg->in.peer_tp_cnt) { + ret = ubcore_destroy_multi_tp_from_index(dev, tpg, arg->in.peer_tp_cnt); + if (ret == (tpg->tpg_cfg.tp_cnt - arg->in.peer_tp_cnt)) { + tpg->tpg_cfg.tp_cnt = arg->in.peer_tp_cnt; + } else { + ubcore_log_err("ubcore_destroy_multi_tp_from_index failed %d", ret); + ret = -EPERM; + goto to_user; + } + } + + /* modify to RTR */ + arg->out.rtr_tp_cnt = ubcore_modify_tp_in_tpg(dev, tpg, arg->in.rtr_attr, + arg->in.rtr_mask, failed_tp); + if (arg->out.rtr_tp_cnt != tpg->tpg_cfg.tp_cnt) { + ret = -EPERM; + goto to_user; + } + + /* modify to RTS */ + ret = ubcore_get_tp_state_attr_and_mask(UBCORE_TP_STATE_RTS, tpg->tpg_cfg.tp_cnt, + &rts_attr, &rts_mask); + if (ret != 0) + goto to_user; + + arg->out.rts_tp_cnt = ubcore_modify_tp_in_tpg(dev, tpg, rts_attr, rts_mask, failed_tp); + if (arg->out.rts_tp_cnt != tpg->tpg_cfg.tp_cnt) { + ret = -EPERM; + goto to_user; + } + + ubcore_set_vtp2tpg_cfg(&vtp_cfg, &arg->in.vtp, tpg); + vtp = ubcore_check_and_map_vtp(dev, &vtp_cfg, arg->in.role); + if (vtp == NULL) { + ret = -EPERM; + goto to_user; + } + + vtp->eid_idx = arg->in.eid_idx; + vtp->upi = arg->in.upi; + vtp->share_mode = arg->in.share_mode; + + arg->out.vtpn = vtp->cfg.vtpn; + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, + sizeof(struct ubcore_cmd_modify_tpg_map_vtp)); + if (ret != 0) + (void)ubcore_check_and_unmap_vtp(vtp, arg->in.role); + + ubcore_vtp_kref_put(vtp); + +to_user: + if (ret) + ubcore_log_warn("ubcore cmd modify tpg map vtp to user failed"); + if (rts_attr != NULL) + kfree(rts_attr); + if (rts_mask != NULL) + kfree(rts_mask); + ubcore_tpg_kref_put(tpg); +put_device: + ubcore_put_device(dev); +free_arg: + kfree(arg); + return ret; +} + static int ubcore_mark_bind_tjetty(struct ubcore_jetty *jetty, struct ubcore_tp_meta *meta, struct ubcore_jetty_id *default_tjetty_id, struct ubcore_ta_data *ta_data) { @@ -692,8 +809,8 @@ static int ubcore_mark_bind_tjetty(struct ubcore_jetty *jetty, struct ubcore_tp_ return 0; } -static int ubcore_para_target_ta(struct ubcore_device *dev, struct ubcore_tp_advice *advice, - struct ubcore_ta_data *ta_data) +static int ubcore_para_target_ta_get_jetty(struct ubcore_device *dev, + struct ubcore_tp_advice *advice, struct ubcore_ta_data *ta_data) { struct ubcore_jetty_id default_tjetty_id; struct ubcore_tp_meta *meta; @@ -709,7 +826,7 @@ static int ubcore_para_target_ta(struct ubcore_device *dev, struct ubcore_tp_adv switch (ta_data->ta_type) { case UBCORE_TA_JFS_TJFR: - jfr = ubcore_find_jfr(dev, ta_data->tjetty_id.id); + jfr = ubcore_find_get_jfr(dev, ta_data->tjetty_id.id); if (jfr != NULL) { meta->ht = ubcore_get_tptable(jfr->tptable); advice->ta.jfr = jfr; @@ -717,12 +834,16 @@ static int ubcore_para_target_ta(struct ubcore_device *dev, struct ubcore_tp_adv } break; case UBCORE_TA_JETTY_TJETTY: - jetty = ubcore_find_jetty(dev, ta_data->tjetty_id.id); + jetty = ubcore_find_get_jetty(dev, ta_data->tjetty_id.id); if (jetty != NULL) { meta->ht = ubcore_get_tptable(jetty->tptable); advice->ta.jetty = jetty; advice->ta.tjetty_id = ta_data->jetty_id; ret = ubcore_mark_bind_tjetty(jetty, meta, &default_tjetty_id, ta_data); + if (ret != 0) { + ubcore_put_jetty(jetty); + advice->ta.jetty = NULL; + } } break; case UBCORE_TA_NONE: @@ -799,12 +920,12 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, if (dev == NULL) return -ENODEV; - if (ubcore_para_target_ta(dev, &advice, &arg->ta_data) != 0) { + if (ubcore_para_target_ta_get_jetty(dev, &advice, &arg->ta_data) != 0) { ubcore_log_err("Failed to parse ta with type %u", advice.ta.type); goto put_device; } else if (advice.meta.ht == NULL) { - ubcore_log_err("tp table is already released"); - goto put_device; + ubcore_log_info("tp table is already released"); + goto put_jetty; } ubcore_set_udata(&udata, &advice, (struct ubcore_udrv_priv *)&arg->udata); @@ -823,24 +944,32 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, /* The receiving side rm mode cannot switch the rts state */ if (tp_node->tp->trans_mode == UBCORE_TP_RM && tp_node->tp->state == UBCORE_TP_STATE_RTR) { + ubcore_tpnode_kref_put(tp_node); ubcore_put_tptable(advice.meta.ht); + ubcore_put_target_ta_jetty(&advice.ta); ubcore_put_device(dev); return 0; } if (tp_node->tp->state == UBCORE_TP_STATE_RTR && ubcore_modify_tp(dev, tp_node, tp_attr, udata) != 0) { ubcore_log_err("Failed to modify tp"); + ubcore_tpnode_kref_put(tp_node); goto put_tptable; } + ubcore_tpnode_kref_put(tp_node); ubcore_put_tptable(advice.meta.ht); + ubcore_put_target_ta_jetty(&advice.ta); ubcore_put_device(dev); return ret; remove_tp_node: + ubcore_tpnode_kref_put(tp_node); ubcore_find_remove_tp(advice.meta.ht, advice.meta.hash, &advice.meta.key); put_tptable: ubcore_put_tptable(advice.meta.ht); +put_jetty: + ubcore_put_target_ta_jetty(&advice.ta); put_device: ubcore_put_device(dev); if (IS_ERR(tp_node)) @@ -871,8 +1000,8 @@ static int ubcore_cmd_modify_tpg_tp_cnt(struct ubcore_cmd_hdr *hdr) } ubcore_log_info("tpgn_for_modify %d", arg->in.tpgn_for_modify); - /* deal with RM first */ - tpg = ubcore_find_tpg(dev, arg->in.tpgn_for_modify); + + tpg = ubcore_find_get_tpg(dev, arg->in.tpgn_for_modify); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); @@ -888,7 +1017,7 @@ static int ubcore_cmd_modify_tpg_tp_cnt(struct ubcore_cmd_hdr *hdr) goto copy_to_user; } else { ret = -1; - goto put_device; + goto put_tpg; } } @@ -898,7 +1027,8 @@ static int ubcore_cmd_modify_tpg_tp_cnt(struct ubcore_cmd_hdr *hdr) ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, sizeof(struct ubcore_cmd_modify_tpg_tp_cnt)); - +put_tpg: + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); free_arg: @@ -926,7 +1056,8 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) if (ret != 0) goto free_arg; - if (arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { + if (arg->ta_data.trans_type == UBCORE_TRANSPORT_HNS_UB || + arg->ta_data.trans_type == UBCORE_TRANSPORT_IB) { ret = ubcore_cmd_create_target_tp(hdr, arg); goto free_arg; } @@ -945,7 +1076,7 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) ubcore_log_info("create target tpg and mtu is %u", (uint32_t)arg->in.rtr_attr[0].mtu); - ret = ubcore_hash_table_find_add(&dev->ht[UBCORE_HT_TPG], &tpg->hnode, tpg->tpgn); + ret = ubcore_find_add_tpg(dev, tpg); if (ret != 0) { ubcore_log_err("Failed to add tpg to the tpg table"); goto destroy_tpg; @@ -987,15 +1118,14 @@ static int ubcore_cmd_create_target_tpg(struct ubcore_cmd_hdr *hdr) if (ret) goto remove_tpg; else - goto put_device; + goto put_tpg; remove_tpg: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_TPG], &tpg->hnode); - if (atomic_read(&tpg->use_cnt) > 0) - ubcore_log_warn("tpg use_cnt still greater than 0 after remove"); + ubcore_find_remove_tpg(dev, tpg->tpgn); destroy_tpg: (void)ubcore_destroy_multi_tp(dev, tpg); - (void)ubcore_destroy_tpg(tpg); +put_tpg: + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); free_arg: @@ -1034,7 +1164,6 @@ static int ubcore_cmd_modify_target_tpg(struct ubcore_cmd_hdr *hdr) goto free_arg; } - /* deal with RM first */ tpg = ubcore_find_get_tpg(dev, arg->in.tpgn); if (tpg == NULL) { ret = -EINVAL; @@ -1179,10 +1308,13 @@ static int ubcore_cmd_opt_sip(struct ubcore_cmd_hdr *hdr) } static int ubcore_eidtbl_add_entry(struct ubcore_device *dev, union ubcore_eid *eid, - uint32_t *eid_idx) + uint32_t *eid_idx, struct net *net) { uint32_t i; + if (dev->eid_table.eid_entries == NULL) + return -EINVAL; + for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { if (memcmp(dev->eid_table.eid_entries[i].eid.raw, eid->raw, UBCORE_EID_SIZE) == 0) { ubcore_log_warn("eid already exists\n"); @@ -1194,9 +1326,10 @@ static int ubcore_eidtbl_add_entry(struct ubcore_device *dev, union ubcore_eid * dev->eid_table.eid_entries[i].eid = *eid; dev->eid_table.eid_entries[i].valid = true; dev->eid_table.eid_entries[i].eid_index = i; - dev->eid_table.eid_entries[i].net = &init_net; + dev->eid_table.eid_entries[i].net = (net == NULL) ? &init_net : net; *eid_idx = i; - ubcore_log_info("add eid: %pI6c, idx: %u\n", eid, i); + ubcore_log_info("dev:%s, add eid: %pI6c, idx: %u, net:0x%p\n", + dev->dev_name, eid, i, net); break; } } @@ -1212,12 +1345,15 @@ static int ubcore_eidtbl_del_entry(struct ubcore_device *dev, union ubcore_eid * { uint32_t i; + if (dev->eid_table.eid_entries == NULL) + return -EINVAL; + for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { if (memcmp(dev->eid_table.eid_entries[i].eid.raw, eid->raw, UBCORE_EID_SIZE) == 0) { (void)memset(&dev->eid_table.eid_entries[i], 0, sizeof(struct ubcore_eid_entry)); *eid_idx = i; - ubcore_log_info("del eid: %pI6c, idx: %u\n", eid, i); + ubcore_log_info("dev:%s, del eid: %pI6c, idx: %u\n", dev->dev_name, eid, i); break; } } @@ -1242,6 +1378,9 @@ static inline void ubcore_dispatch_eid_change(struct ubcore_device *dev, uint32_ static int ubcore_eidtbl_update_entry(struct ubcore_device *dev, union ubcore_eid *eid, uint32_t eid_idx, bool is_add, struct net *net) { + if (dev->eid_table.eid_entries == NULL) + return -EINVAL; + if (eid_idx >= dev->attr.dev_cap.max_eid_cnt) { ubcore_log_err("eid table is full\n"); return -1; @@ -1261,13 +1400,13 @@ static int ubcore_eidtbl_update_entry(struct ubcore_device *dev, union ubcore_ei } int ubcore_update_eidtbl_by_eid(struct ubcore_device *dev, union ubcore_eid *eid, - uint32_t *eid_idx, bool is_alloc_eid) + uint32_t *eid_idx, bool is_alloc_eid, struct net *net) { int ret; spin_lock(&dev->eid_table.lock); if (is_alloc_eid) - ret = ubcore_eidtbl_add_entry(dev, eid, eid_idx); + ret = ubcore_eidtbl_add_entry(dev, eid, eid_idx, net); else ret = ubcore_eidtbl_del_entry(dev, eid, eid_idx); @@ -1289,9 +1428,9 @@ int ubcore_update_eidtbl_by_idx(struct ubcore_device *dev, union ubcore_eid *eid static int ubcore_cmd_set_upi(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_set_upi arg; - struct ubcore_ueid_cfg cfg; struct ubcore_device *dev; uint32_t pattern3_upi; + union ubcore_eid *eid; uint32_t i; int ret; @@ -1310,20 +1449,20 @@ static int ubcore_cmd_set_upi(struct ubcore_cmd_hdr *hdr) ubcore_log_err("This mode does not support setting upi\n"); return -1; } + if (dev->eid_table.eid_entries == NULL) + return -EINVAL; + for (i = 0; i < dev->attr.dev_cap.max_eid_cnt; i++) { - cfg.eid = dev->eid_table.eid_entries[i].eid; - cfg.eid_index = i; + eid = &dev->eid_table.eid_entries[i].eid; if (dev->eid_table.eid_entries[i].valid == false) continue; - if (pattern3_upi == UCBORE_INVALID_UPI) { - cfg.upi = arg.in.upi; - (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); - } else { - cfg.upi = pattern3_upi; - (void)ubcore_delete_ueid(dev, dev->attr.fe_idx, &cfg); - cfg.upi = arg.in.upi; - (void)ubcore_add_ueid(dev, dev->attr.fe_idx, &cfg); - } + + if (pattern3_upi != UCBORE_INVALID_UPI) + (void)ubcore_send_eid_update_req( + dev, UBCORE_DEL_NET_ADDR, eid, i, &pattern3_upi); + + (void)ubcore_send_eid_update_req( + dev, UBCORE_ADD_NET_ADDR, eid, i, &arg.in.upi); } (void)ubcore_add_upi_list(dev, arg.in.upi); return 0; @@ -1441,7 +1580,8 @@ static int ubcore_cmd_set_vport_cfg(struct ubcore_cmd_hdr *hdr) return -EINVAL; } - if (dev->transport_type == UBCORE_TRANSPORT_IB) { + if (dev->transport_type == UBCORE_TRANSPORT_HNS_UB || + dev->transport_type == UBCORE_TRANSPORT_IB) { ubcore_log_info("ib devices don't need to call ops->config_device"); ubcore_put_device(dev); return 0; @@ -1468,10 +1608,9 @@ static int ubcore_cmd_set_vport_cfg(struct ubcore_cmd_hdr *hdr) static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) { - struct ubcore_cmd_get_dev_info arg; + enum ubcore_mtu max_mtu = UBCORE_MTU_1024; + struct ubcore_cmd_get_dev_info arg = {0}; struct ubcore_device *tpf_dev; - struct ubcore_device *pf_dev; - enum ubcore_mtu max_mtu; int ret; ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, @@ -1479,31 +1618,14 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; - arg.in.target_pf_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; - pf_dev = ubcore_find_device_with_name(arg.in.target_pf_name); - if (pf_dev == NULL) { - ubcore_log_err("failed to find pf_dev device with %s", arg.in.target_pf_name); - return -1; - } - - arg.out.port_is_active = true; - if (ubcore_check_port_state(pf_dev, 0) != 0) { - arg.out.port_is_active = false; - ubcore_log_warn("port status unactive on target side, pf_dev: %s", - pf_dev->dev_name); - } - ubcore_put_device(pf_dev); - - tpf_dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, arg.in.tpf.trans_type); + arg.in.target_tpf_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; + tpf_dev = ubcore_find_device_with_name(arg.in.target_tpf_name); if (tpf_dev == NULL) { - ubcore_log_err("failed to find tpf device"); + ubcore_log_err("failed to find tpf_dev device with %s", arg.in.target_tpf_name); return -1; } - ubcore_log_info("get tpf device name %s", tpf_dev->dev_name); - - (void)memcpy(arg.out.target_tpf_name, tpf_dev->dev_name, UBCORE_MAX_DEV_NAME); - ret = ubcore_get_max_mtu(tpf_dev, 0, &max_mtu); + ret = ubcore_get_max_mtu(tpf_dev, &max_mtu); if (ret != 0) { ubcore_log_err("failed to get max mtu"); ubcore_put_device(tpf_dev); @@ -1558,13 +1680,13 @@ static int ubcore_cmd_destroy_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_d if (dev == NULL) return -ENODEV; - if (ubcore_para_target_ta(dev, &advice, &arg->ta_data) != 0) { + if (ubcore_para_target_ta_get_jetty(dev, &advice, &arg->ta_data) != 0) { ubcore_log_err("Failed to parse ta with type %u", (uint32_t)advice.ta.type); ret = -1; goto put_device; } else if (advice.meta.ht == NULL) { - ubcore_log_err("tp table is already released"); - goto put_device; + ubcore_log_info("tp table is already released"); + goto put_jetty; } ret = ubcore_unmark_bind_tjetty(&advice, &arg->ta_data); @@ -1575,6 +1697,8 @@ static int ubcore_cmd_destroy_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_d put_tptable: ubcore_put_tptable(advice.meta.ht); +put_jetty: + ubcore_put_target_ta_jetty(&advice.ta); put_device: ubcore_put_device(dev); return ret; @@ -1592,7 +1716,8 @@ static int ubcore_cmd_destroy_tpg(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; - if (arg.ta_data.trans_type == UBCORE_TRANSPORT_IB) + if (arg.ta_data.trans_type == UBCORE_TRANSPORT_HNS_UB || + arg.ta_data.trans_type == UBCORE_TRANSPORT_IB) return ubcore_cmd_destroy_tp(hdr, &arg); dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, arg.in.tpf.trans_type); @@ -1600,30 +1725,24 @@ static int ubcore_cmd_destroy_tpg(struct ubcore_cmd_hdr *hdr) return -ENODEV; /* deal with RM first */ - tpg = ubcore_find_remove_tpg(dev, arg.in.tpgn); + tpg = ubcore_find_get_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; ubcore_log_err("Failed to find tpg"); goto put_device; } + ret = ubcore_find_remove_tpg(dev, arg.in.tpgn); + if (ret == 0) + arg.out.destroyed_tp_cnt = ubcore_destroy_multi_tp(dev, tpg); - arg.out.destroyed_tp_cnt = ubcore_destroy_multi_tp(dev, tpg); - if (arg.out.destroyed_tp_cnt != tpg->tpg_cfg.tp_cnt) { + if (arg.out.destroyed_tp_cnt != tpg->tpg_cfg.tp_cnt) ret = -EPERM; - goto to_user; - } - /* todonext: rollback ? */ - ret = ubcore_destroy_tpg(tpg); - if (ret) - ubcore_log_err("Failed to destroy tpg"); - -to_user: /* do not modify ret if copy success */ if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct ubcore_cmd_destroy_tpg)) != 0) ret = -EPERM; - /* todonext: rollback ? */ + ubcore_tpg_kref_put(tpg); put_device: ubcore_put_device(dev); return ret; @@ -1734,24 +1853,13 @@ static void ubcore_get_utp_mtu(struct ubcore_device *dev, struct ubcore_utp_cfg enum ubcore_mtu mtu; int ret; - if (((int32_t)cfg->mtu) == 0) { - ret = utp_get_active_mtu(dev, (uint8_t)cfg->port_id, &mtu); - if (ret < 0) { - ubcore_log_warn("dev:%s, port_id:%u Failed to get active mtu", - dev->dev_name, cfg->port_id); - mtu = UBCORE_MTU_1024; - } - cfg->mtu = mtu; - ubcore_log_info("cfg not config, device mtu is %d", (int32_t)cfg->mtu); - } else { - ret = ubcore_get_max_mtu(dev, (uint8_t)cfg->port_id, &mtu); - if (ret < 0) { - mtu = UBCORE_MTU_1024; - ubcore_log_warn("dev:%s, port_id:%u Failed to get max mtu", - dev->dev_name, cfg->port_id); - } - cfg->mtu = min(cfg->mtu, mtu); + ret = ubcore_get_max_mtu(dev, &mtu); + if (ret < 0) { + mtu = UBCORE_MTU_1024; + ubcore_log_warn("dev:%s, port_id:%u Failed to get max mtu", + dev->dev_name, cfg->port_id); } + cfg->mtu = min(cfg->mtu, mtu); } static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) @@ -1792,6 +1900,9 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) ret = PTR_ERR(vtp); goto destroy_utp; } + vtp->eid_idx = arg->in.eid_idx; + vtp->upi = arg->in.upi; + vtp->share_mode = arg->in.share_mode; /* fill output */ arg->out.idx = utp->utpn; @@ -1803,16 +1914,15 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) goto unmap_vtp; } else { ubcore_vtp_kref_put(vtp); - goto put_device; + goto put_utp; } unmap_vtp: (void)ubcore_unmap_vtp(vtp); ubcore_vtp_kref_put(vtp); destroy_utp: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_UTP], &utp->hnode); - if (atomic_read(&utp->use_cnt) > 0) - ubcore_log_warn("utp use_cnt still greater than 0 after remove"); - (void)ubcore_destroy_utp(utp); + ubcore_find_remove_utp(dev, utp->utpn); +put_utp: + ubcore_utp_kref_put(utp); put_device: ubcore_put_device(dev); free_arg: @@ -1858,13 +1968,12 @@ static int ubcore_cmd_only_create_utp(struct ubcore_cmd_hdr *hdr) if (ret) goto destroy_utp; else - goto put_device; + goto put_utp; destroy_utp: - ubcore_hash_table_remove(&dev->ht[UBCORE_HT_UTP], &utp->hnode); - if (atomic_read(&utp->use_cnt) > 0) - ubcore_log_warn("utp use_cnt still greater than 0 after remove"); - (void)ubcore_destroy_utp(utp); + ubcore_find_remove_utp(dev, utp->utpn); +put_utp: + ubcore_utp_kref_put(utp); put_device: ubcore_put_device(dev); free_arg: @@ -1876,7 +1985,6 @@ static int ubcore_cmd_destroy_utp(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_destroy_utp arg = {0}; struct ubcore_device *dev; - struct ubcore_utp *utp; int ret; ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, @@ -1888,20 +1996,10 @@ static int ubcore_cmd_destroy_utp(struct ubcore_cmd_hdr *hdr) if (dev == NULL) return -ENODEV; - utp = ubcore_find_remove_utp(dev, arg.in.utp_idx); - if (utp == NULL) { - ret = -EINVAL; - ubcore_log_err("Failed to find utp"); - goto put_device; - } - - ret = ubcore_destroy_utp(utp); - if (ret) - ubcore_log_err("Failed to destroy utp"); + ubcore_find_remove_utp(dev, arg.in.utp_idx); -put_device: ubcore_put_device(dev); - return ret; + return 0; } static int ubcore_cmd_create_ctp(struct ubcore_cmd_hdr *hdr) @@ -2276,8 +2374,8 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) } ubcore_tp_get(tp); - if (tp->state == UBCORE_TP_STATE_RESET) { - ubcore_log_info("TP:%u already in RESET", tp->tpn); + if (tp->state == UBCORE_TP_STATE_RESET || tp->state == UBCORE_TP_STATE_ERR) { + ubcore_log_info("TP:%u already in %u", tp->tpn, (uint32_t)tp->state); ubcore_tp_kref_put(tp); continue; } @@ -2318,12 +2416,17 @@ static int ubcore_cmd_config_function_migrate_state(struct ubcore_cmd_hdr *hdr) return ret; dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, arg.in.tpf.trans_type); - if (dev == NULL || dev->ops == NULL || dev->ops->config_function_migrate_state == NULL) { + if (dev == NULL) { ret = -ENODEV; ubcore_log_err("fail to find tpf device"); return ret; } + if (dev->ops == NULL || dev->ops->config_function_migrate_state == NULL) { + ret = -EINVAL; + goto put_dev; + } + arg.out.cnt = (uint32_t)ubcore_config_function_migrate_state(dev, arg.in.fe_idx, arg.in.config_cnt, &arg.in.config[0], arg.in.state); @@ -2335,6 +2438,7 @@ static int ubcore_cmd_config_function_migrate_state(struct ubcore_cmd_hdr *hdr) sizeof(struct ubcore_cmd_config_function_migrate_state)) != 0) ret = -EPERM; +put_dev: ubcore_put_device(dev); return ret; } @@ -2428,7 +2532,6 @@ static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) ubcore_log_err("fail to modify vtp"); goto put_device; } - ubcore_uninit_modify_vtp(&vattr, &vtp_param); } put_device: @@ -2460,7 +2563,10 @@ static int ubcore_cmd_opt_config_dscp_vl(struct ubcore_cmd_hdr *hdr) ret = -ENODEV; goto put_device; } - + if (arg.in.num > UBCORE_MAX_DSCP_VL_NUM) { + ret = -EINVAL; + goto put_device; + } ret = dev->ops->config_dscp_vl(dev, arg.in.dscp, arg.in.vl, arg.in.num); if (ret != 0) { ubcore_log_err("fail to config dscp vl, dev:%s\n", arg.in.dev_name); @@ -2472,6 +2578,48 @@ static int ubcore_cmd_opt_config_dscp_vl(struct ubcore_cmd_hdr *hdr) return ret; } +static int ubcore_cmd_opt_query_dscp_vl(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_opt_query_dscp_vl arg; + struct ubcore_device *dev; + int ret; + + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_opt_query_dscp_vl)); + if (ret != 0) + return ret; + + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_warn("fail to find dev:%s\n", arg.in.dev_name); + return -ENODEV; + } + + if (dev->ops->query_dscp_vl == NULL) { + ret = -ENODEV; + goto put_device; + } + + if (arg.in.num > UBCORE_MAX_DSCP_VL_NUM) { + ret = -EINVAL; + goto put_device; + } + + ret = dev->ops->query_dscp_vl(dev, arg.in.dscp, arg.in.num, arg.out.vl); + if (ret != 0) { + ubcore_log_err("fail to query dscp vl, dev:%s\n", arg.in.dev_name); + goto put_device; + } + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + sizeof(struct ubcore_cmd_opt_query_dscp_vl)); + +put_device: + ubcore_put_device(dev); + return ret; +} + static int ubcore_cmd_opt_update_eid(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_opt_eid arg; @@ -2485,13 +2633,14 @@ static int ubcore_cmd_opt_update_eid(struct ubcore_cmd_hdr *hdr) return ret; arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; - dev = ubcore_find_device_with_name(arg.in.dev_name); + dev = ubcore_find_tpf_device_by_name(arg.in.dev_name); if (dev == NULL) - return -1; + return -EINVAL; cfg.eid = arg.in.eid; cfg.eid_index = arg.in.eid_index; cfg.upi = arg.in.upi; + cfg.uuid = arg.in.uuid; if (hdr->command == UBCORE_CMD_ALLOC_EID) ret = ubcore_add_ueid(dev, arg.in.fe_idx, &cfg); @@ -2601,6 +2750,7 @@ static int ubcore_assign_single_out_vtp_table(struct ubcore_device *dev, struct out_entry->eid_idx = vtp->eid_idx; out_entry->upi = vtp->upi; out_entry->share_mode = vtp->share_mode; + out_entry->restore_succeed = false; if (vtp->cfg.trans_mode == UBCORE_TP_RM || vtp->cfg.trans_mode == UBCORE_TP_RC) { if (vtp->cfg.tpg == NULL) { @@ -2629,8 +2779,8 @@ static int ubcore_assign_single_out_vtp_table(struct ubcore_device *dev, struct out_entry->dip = vtp->cfg.utp->utp_cfg.peer_net_addr; } - sip_entry = - ubcore_lookup_sip_info_without_lock(&dev->sip_table, out_entry->local_net_addr_idx); + sip_entry = ubcore_lookup_sip_info_without_lock( + &dev->sip_table, out_entry->local_net_addr_idx); if (sip_entry == NULL) { ubcore_log_err("sip does not exist\n"); return -1; @@ -2759,7 +2909,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) tpg = ubcore_find_get_tpg(dev, arg->in.vtp.tpgn); if (tpg == NULL) { ret = -EINVAL; - ubcore_log_err("Failed to find tpg"); + ubcore_log_err("Failed to find tpg, tpgn: %u.\n", arg->in.vtp.tpgn); goto put_device; } ubcore_set_vtp2tpg_cfg(&vtp_cfg, &arg->in.vtp, tpg); @@ -2768,7 +2918,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) utp = ubcore_find_get_utp(dev, arg->in.vtp.utpn); if (utp == NULL) { ret = -EINVAL; - ubcore_log_err("Failed to find utp"); + ubcore_log_err("Failed to find utp, utpn: %u.\n", arg->in.vtp.utpn); goto put_device; } ubcore_set_vtp2utp_cfg(&vtp_cfg, &arg->in.vtp, utp); @@ -2778,7 +2928,7 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) ctp = ubcore_find_get_ctp(dev, arg->in.vtp.ctpn); if (ctp == NULL) { ret = -EINVAL; - ubcore_log_err("Failed to find ctp"); + ubcore_log_err("Failed to find ctp, ctpn: %u.\n", arg->in.vtp.ctpn); goto put_device; } ubcore_set_vtp2ctp_cfg(&vtp_cfg, &arg->in.vtp, ctp); @@ -2790,6 +2940,9 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) goto put_tpg_and_utp; } vtp->role = (vtp->role != arg->in.role ? UBCORE_VTP_DUPLEX : vtp->role); + vtp->eid_idx = arg->in.eid_idx; + vtp->upi = arg->in.upi; + vtp->share_mode = arg->in.share_mode; ubcore_vtp_kref_put(vtp); put_tpg_and_utp: @@ -2801,6 +2954,106 @@ static int ubcore_cmd_map_target_vtp(struct ubcore_cmd_hdr *hdr) return ret; } +static int ubcore_query_fe_stats(struct ubcore_device *dev, + struct ubcore_list_migrate_entry_param *param, uint32_t cnt) +{ + int ret; + uint32_t i; + struct ubcore_fe_stats *stats = NULL; + uint16_t *fe_idx = NULL; + + if (dev->ops == NULL || dev->ops->query_fe_stats == NULL) { + ubcore_log_err("Device without query_fe_stats, dev_name: %s", dev->dev_name); + return -ENODEV; + } + + if (cnt > UBCORE_MAX_MIG_ENTRY_CNT) { + ubcore_log_warn("count too long to alloc, cnt = %u\n", cnt); + return -ENOMEM; + } + + fe_idx = kcalloc(1, cnt * sizeof(uint16_t), GFP_KERNEL); + if (fe_idx == NULL) + return -ENOMEM; + + stats = kcalloc(1, cnt * sizeof(struct ubcore_fe_stats), GFP_KERNEL); + if (fe_idx == NULL) { + ret = -ENOMEM; + goto free_idx; + } + + for (i = 0; i < cnt; i++) + fe_idx[i] = param[i].fe_idx; + + ret = dev->ops->query_fe_stats(dev, cnt, fe_idx, stats); + if (ret != 0) { + ubcore_log_err("Fail to query_fe_stats, ret: %d, dev_name: %s", ret, dev->dev_name); + goto free_stats; + } + + for (i = 0; i < cnt; i++) + param[i].stats = stats[i]; + +free_stats: + kfree(stats); +free_idx: + kfree(fe_idx); + return ret; +} + +static int ubcore_cmd_list_migrate_entry(struct ubcore_cmd_hdr *hdr) +{ + int ret = 0; + struct ubcore_cmd_list_migrate_entry *arg = NULL; + struct ubcore_device *dev = NULL; + uint32_t cnt = 0; + + if (hdr->args_len > sizeof(struct ubcore_cmd_list_migrate_entry) + + UBCORE_MAX_MIG_ENTRY_CNT * sizeof(struct ubcore_list_migrate_entry_param)) { + ubcore_log_warn("hdr->args_len too long to alloc, len = %u\n", hdr->args_len); + return -ENOMEM; + } + + arg = kcalloc(1, hdr->args_len, GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; + + ret = ubcore_copy_from_user(arg, (void __user *)(uintptr_t)hdr->args_addr, hdr->args_len); + if (ret != 0) + goto free_arg; + + cnt = arg->in.cnt; + if (cnt * sizeof(struct ubcore_list_migrate_entry_param) + + sizeof(ubcore_cmd_list_migrate_entry) != hdr->args_len) { + ret = -EINVAL; + ubcore_log_err("Invalid argument, args_len = %u, cnt = %u", hdr->args_len, cnt); + goto free_arg; + } + + dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); + if (dev == NULL) { + ret = -ENODEV; + ubcore_log_err("fail to find tpf device"); + goto free_arg; + } + + ret = ubcore_query_fe_stats(dev, arg->param, cnt); + if (ret != 0) + goto put_device; + + if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, + arg, hdr->args_len) != 0) { + ret = -EPERM; + goto put_device; + } + +put_device: + ubcore_put_device(dev); +free_arg: + kfree(arg); + return ret; +} + typedef int (*ubcore_uvs_cmd_handler)(struct ubcore_cmd_hdr *hdr); struct ubcore_uvs_cmd_func { ubcore_uvs_cmd_handler func; @@ -2813,6 +3066,7 @@ static struct ubcore_uvs_cmd_func g_ubcore_uvs_cmd_funcs[] = { [UBCORE_CMD_CREATE_TPG] = {ubcore_cmd_create_tpg, false}, [UBCORE_CMD_CREATE_VTP] = {ubcore_cmd_create_vtp, false}, [UBCORE_CMD_MODIFY_TPG] = {ubcore_cmd_modify_tpg, false}, + [UBCORE_CMD_MODIFY_TPG_MAP_VTP] = {ubcore_cmd_modify_tpg_map_vtp, false}, [UBCORE_CMD_MODIFY_TPG_TP_CNT] = {ubcore_cmd_modify_tpg_tp_cnt, false}, [UBCORE_CMD_CREATE_TARGET_TPG] = {ubcore_cmd_create_target_tpg, false}, [UBCORE_CMD_MODIFY_TARGET_TPG] = {ubcore_cmd_modify_target_tpg, false}, @@ -2850,6 +3104,8 @@ static struct ubcore_uvs_cmd_func g_ubcore_uvs_cmd_funcs[] = { [UBCORE_CMD_GET_VTP_TABLE_CNT] = {ubcore_cmd_get_vtp_table_cnt, false}, [UBCORE_CMD_RESTORE_TABLE] = {ubcore_cmd_restore_vtp_table, false}, [UBCORE_CMD_MAP_TARGET_VTP] = {ubcore_cmd_map_target_vtp, false}, + [UBCORE_CMD_LIST_MIGRATE_ENTRY] = {ubcore_cmd_list_migrate_entry, false}, + [UBCORE_CMD_QUERY_DSCP_VL] = {ubcore_cmd_opt_query_dscp_vl, false}, }; int ubcore_uvs_cmd_parse(struct ubcore_cmd_hdr *hdr) diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h index 71cd42020bcd..8e24180626d4 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h @@ -43,6 +43,7 @@ enum ubcore_uvs_cmd { UBCORE_CMD_CREATE_TPG, /* initiator */ UBCORE_CMD_CREATE_VTP, /* initiator */ UBCORE_CMD_MODIFY_TPG, + UBCORE_CMD_MODIFY_TPG_MAP_VTP, UBCORE_CMD_MODIFY_TPG_TP_CNT, UBCORE_CMD_CREATE_TARGET_TPG, /* target */ UBCORE_CMD_MODIFY_TARGET_TPG, @@ -77,6 +78,8 @@ enum ubcore_uvs_cmd { UBCORE_CMD_GET_VTP_TABLE_CNT, UBCORE_CMD_RESTORE_TABLE, UBCORE_CMD_MAP_TARGET_VTP, + UBCORE_CMD_LIST_MIGRATE_ENTRY, + UBCORE_CMD_QUERY_DSCP_VL, UBCORE_CMD_LAST }; @@ -86,6 +89,7 @@ struct ubcore_cmd_opt_eid { uint32_t upi; uint16_t fe_idx; union ubcore_eid eid; + uuid_t uuid; uint32_t eid_index; } in; }; @@ -109,6 +113,18 @@ struct ubcore_cmd_opt_config_dscp_vl { } in; }; +struct ubcore_cmd_opt_query_dscp_vl { + struct { + char dev_name[UBCORE_MAX_DEV_NAME]; + uint8_t dscp[UBCORE_MAX_DSCP_VL_NUM]; + uint8_t num; + } in; + + struct { + uint8_t vl[UBCORE_MAX_DSCP_VL_NUM]; + } out; +}; + struct ubcore_cmd_channel_init { struct { char userspace_in[UBCORE_CMD_CHANNEL_INIT_SIZE]; @@ -168,7 +184,9 @@ struct ubcore_cmd_create_tpg { enum ubcore_mtu local_mtu; }; -/* modify tps in the tp list of tpg to RTR, RTS, and then map vtpn to tpg */ +/* modify tps in the tp list of tpg to RTR, RTS, + * and then map vtpn to tpg only use in loopback + */ struct ubcore_cmd_create_vtp { struct { struct ubcore_cmd_tpf tpf; @@ -179,6 +197,9 @@ struct ubcore_cmd_create_vtp { /* modify tp to RTS */ /* create vtp */ struct ubcore_cmd_vtp_cfg vtp; + uint32_t eid_idx; + uint32_t upi; + bool share_mode; } in; struct { uint32_t rtr_tp_cnt; @@ -207,6 +228,30 @@ struct ubcore_cmd_modify_tpg { struct ubcore_udrv_ext udrv_ext; }; +/* modify tps in the tp list of tpg to RTR, RTS and map vtp, ub only */ +struct ubcore_cmd_modify_tpg_map_vtp { + struct { + struct ubcore_cmd_tpf tpf; + uint32_t peer_tp_cnt; + /* modify tp to RTR */ + uint32_t tpgn; + struct ubcore_tp_attr rtr_attr[UBCORE_MAX_TP_CNT_IN_GRP]; + union ubcore_tp_attr_mask rtr_mask[UBCORE_MAX_TP_CNT_IN_GRP]; + /* modify tp to RTS */ + /* map vtp */ + struct ubcore_cmd_vtp_cfg vtp; + uint32_t role; + uint32_t eid_idx; + uint32_t upi; + bool share_mode; + } in; + struct { + uint32_t rtr_tp_cnt; + uint32_t rts_tp_cnt; + uint32_t vtpn; + } out; +}; + /* modify tps in the tpg to RTS at target */ struct ubcore_cmd_modify_target_tpg { struct { @@ -263,9 +308,25 @@ struct ubcore_cmd_map_target_vtp { struct ubcore_cmd_tpf tpf; struct ubcore_cmd_vtp_cfg vtp; uint32_t role; + uint32_t eid_idx; + uint32_t upi; + bool share_mode; } in; }; +struct ubcore_list_migrate_entry_param { + uint16_t fe_idx; + struct ubcore_fe_stats stats; +}; + +struct ubcore_cmd_list_migrate_entry { + struct { + struct ubcore_cmd_tpf tpf; + uint32_t cnt; + } in; + struct ubcore_list_migrate_entry_param param[0]; +}; + struct ubcore_cmd_destroy_vtp { struct { struct ubcore_cmd_tpf tpf; @@ -324,6 +385,9 @@ struct ubcore_cmd_create_utp { struct ubcore_cmd_tpf tpf; struct ubcore_utp_cfg utp_cfg; struct ubcore_cmd_vtp_cfg vtp; + uint32_t eid_idx; + uint32_t upi; + bool share_mode; } in; struct { uint32_t idx; @@ -429,12 +493,9 @@ struct ubcore_cmd_show_upi { struct ubcore_cmd_get_dev_info { struct { - char target_pf_name[UBCORE_MAX_DEV_NAME]; - struct ubcore_cmd_tpf tpf; + char target_tpf_name[UBCORE_MAX_DEV_NAME]; } in; struct { - bool port_is_active; - char target_tpf_name[UBCORE_MAX_DEV_NAME]; enum ubcore_mtu max_mtu; } out; }; @@ -505,6 +566,7 @@ struct ubcore_restored_vtp_entry { uint32_t eid_idx; uint32_t upi; bool share_mode; + bool restore_succeed; }; struct ubcore_cmd_restored_vtp_entry { diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.c b/drivers/ub/urma/ubcore/ubcore_vtp.c index 5c9b5cd60bc1..8e2dc8094827 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.c +++ b/drivers/ub/urma/ubcore/ubcore_vtp.c @@ -25,6 +25,8 @@ #include "ubcore_priv.h" #include #include "ubcore_netdev.h" +#include "ubcore_tpg.h" +#include "ubcore_utp.h" #include "ubcore_vtp.h" static int ubcore_handle_create_vtp_resp(struct ubcore_device *dev, @@ -88,7 +90,7 @@ static int ubcore_send_create_vtp_req(struct ubcore_device *dev, create->eid_index = p->eid_index; create->local_jetty = p->local_jetty; create->peer_jetty = p->peer_jetty; - (void)strcpy(create->dev_name, dev->dev_name); + (void)strncpy(create->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME - 1); create->virtualization = dev->attr.virtualization; cb.callback = ubcore_handle_create_vtp_resp; @@ -175,7 +177,7 @@ static struct ubcore_vtpn *ubcore_alloc_vtpn(struct ubcore_device *dev, vtpn = dev->ops->alloc_vtpn(dev); if (IS_ERR_OR_NULL(vtpn)) { ubcore_log_err("failed to alloc vtpn!, dev_name:%s", dev->dev_name); - return vtpn == NULL ? ERR_PTR(-ENOEXEC) : vtpn; + return UBCORE_CHECK_RETURN_ERR_PTR(vtpn, ENOEXEC); } vtpn->ub_dev = dev; @@ -212,10 +214,26 @@ void ubcore_vtpn_get(void *obj) kref_get(&vtpn->ref_cnt); } +static void ubcore_vtp_unmap_attr(struct ubcore_vtp_cfg *cfg) +{ + if (cfg->vtpn == UINT_MAX) + return; + + if (cfg->flag.bs.clan_tp) { + atomic_dec(&cfg->ctp->use_cnt); + return; + } + if (cfg->trans_mode != UBCORE_TP_UM) + ubcore_tpg_kref_put(cfg->tpg); + else + ubcore_utp_kref_put(cfg->utp); +} + static void ubcore_vtp_kref_release(struct kref *ref_cnt) { struct ubcore_vtp *vtp = container_of(ref_cnt, struct ubcore_vtp, ref_cnt); struct ubcore_device *ub_dev = vtp->ub_dev; + struct ubcore_vtp_cfg cfg = vtp->cfg; /* pseudo vtp */ if (vtp->cfg.vtpn == UINT_MAX) { @@ -225,6 +243,7 @@ static void ubcore_vtp_kref_release(struct kref *ref_cnt) if (ub_dev == NULL || ub_dev->ops == NULL || ub_dev->ops->destroy_vtp == NULL) return; ub_dev->ops->destroy_vtp(vtp); + ubcore_vtp_unmap_attr(&cfg); } void ubcore_vtp_kref_put(struct ubcore_vtp *vtp) @@ -367,7 +386,7 @@ struct ubcore_vtpn *ubcore_connect_vtp(struct ubcore_device *dev, return ERR_PTR(-EINVAL); } - if (ubcore_check_port_state(dev, 0) != 0) { + if (ubcore_check_port_state(dev) != 0) { ubcore_log_err("Check port status Failed"); return NULL; } @@ -493,6 +512,30 @@ static int ubcore_find_add_vtp(struct ubcore_device *dev, return 0; } +static void ubcore_vtp_map_attr(struct ubcore_vtp *vtp, struct ubcore_vtp_cfg *cfg) +{ + vtp->cfg.fe_idx = cfg->fe_idx; + vtp->cfg.local_jetty = cfg->local_jetty; + vtp->cfg.local_eid = cfg->local_eid; + vtp->cfg.peer_eid = cfg->peer_eid; + vtp->cfg.peer_jetty = cfg->peer_jetty; + vtp->cfg.flag = cfg->flag; + vtp->cfg.trans_mode = cfg->trans_mode; + + if (cfg->flag.bs.clan_tp) { + vtp->cfg.ctp = cfg->ctp; + atomic_inc(&cfg->ctp->use_cnt); + return; + } + if (cfg->trans_mode != UBCORE_TP_UM) { + vtp->cfg.tpg = cfg->tpg; + ubcore_tpg_get(cfg->tpg); + } else { + vtp->cfg.utp = cfg->utp; + ubcore_utp_get(cfg->utp); + } +} + struct ubcore_vtp *ubcore_create_and_map_vtp(struct ubcore_device *dev, struct ubcore_vtp_cfg *cfg) { struct ubcore_vtp *vtp; @@ -519,15 +562,7 @@ struct ubcore_vtp *ubcore_create_and_map_vtp(struct ubcore_device *dev, struct u ubcore_log_err("Failed to add vtp to the vtp table"); return ERR_PTR(-ENOEXEC); } - - if (cfg->flag.bs.clan_tp) { - atomic_inc(&cfg->ctp->use_cnt); - } else { - if (cfg->trans_mode != UBCORE_TP_UM) - atomic_inc(&cfg->tpg->use_cnt); - else - atomic_inc(&cfg->utp->use_cnt); - } + ubcore_vtp_map_attr(vtp, cfg); return vtp; } @@ -586,17 +621,6 @@ int ubcore_unmap_vtp(struct ubcore_vtp *vtp) cfg = vtp->cfg; ubcore_remove_vtp(dev, cfg.trans_mode, vtp); - /* target vtp */ - if (vtp->cfg.vtpn != UINT_MAX) { - if (cfg.flag.bs.clan_tp) { - atomic_dec(&cfg.ctp->use_cnt); - } else { - if (cfg.trans_mode != UBCORE_TP_UM) - atomic_dec(&cfg.tpg->use_cnt); - else - atomic_dec(&cfg.utp->use_cnt); - } - } return ret; } @@ -627,21 +651,15 @@ int ubcore_check_and_unmap_vtp(struct ubcore_vtp *vtp, uint32_t role) new_vtp->ub_dev = dev; new_vtp->role = UBCORE_VTP_TARGET; + new_vtp->eid_idx = vtp->eid_idx; + new_vtp->upi = vtp->upi; + new_vtp->share_mode = vtp->share_mode; (void)memcpy(&new_vtp->cfg, &vtp->cfg, sizeof(struct ubcore_vtp_cfg)); new_vtp->cfg.vtpn = UINT_MAX; kref_init(&new_vtp->ref_cnt); ubcore_remove_vtp(dev, cfg.trans_mode, vtp); - if (cfg.flag.bs.clan_tp) { - atomic_dec(&cfg.ctp->use_cnt); - } else { - if (cfg.trans_mode != UBCORE_TP_UM) - atomic_dec(&cfg.tpg->use_cnt); - else - atomic_dec(&cfg.utp->use_cnt); - } - ret = ubcore_find_add_vtp(dev, new_vtp->cfg.trans_mode, new_vtp); ubcore_vtp_kref_put(new_vtp); if (ret != 0) { @@ -674,7 +692,7 @@ struct ubcore_vtp *ubcore_find_vtp(struct ubcore_device *dev, ubcore_get_vtp_hash(local_eid), local_eid); break; default: - ubcore_log_err("unknown mode"); + ubcore_log_err("unknown mode %u", mode); vtp_entry = NULL; } return vtp_entry; @@ -708,7 +726,8 @@ struct ubcore_vtp *ubcore_find_get_vtp(struct ubcore_device *dev, void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, struct ubcore_tjetty_cfg *cfg, struct ubcore_vtp_param *vtp_param) { - if (cfg->eid_index >= dev->eid_table.eid_cnt) { + if (cfg->eid_index >= dev->eid_table.eid_cnt || + IS_ERR_OR_NULL(dev->eid_table.eid_entries)) { ubcore_log_err("invalid param, eid_index[%u] >= eid_cnt[%u]", cfg->eid_index, dev->eid_table.eid_cnt); return; @@ -776,6 +795,13 @@ int ubcore_modify_vtp(struct ubcore_device *dev, struct ubcore_vtp_param *vtp_pa return -EINVAL; } + if (vtp->role != UBCORE_VTP_TARGET) { // switch to mig dest + if (vtp_param->trans_mode == UBCORE_TP_UM) + ubcore_utp_kref_put(vtp->cfg.utp); + else + ubcore_tpg_kref_put(vtp->cfg.tpg); + } + ret = dev->ops->modify_vtp(vtp, vattr, vattr_mask); ubcore_vtp_kref_put(vtp); if (ret != 0) { @@ -830,15 +856,7 @@ struct ubcore_vtp *ubcore_check_and_map_vtp(struct ubcore_device *dev, struct ub ubcore_log_err("Failed to add vtp to the vtp table"); return NULL; } - - if (cfg->flag.bs.clan_tp) { - atomic_inc(&cfg->ctp->use_cnt); - } else { - if (cfg->trans_mode != UBCORE_TP_UM) - atomic_inc(&cfg->tpg->use_cnt); - else - atomic_inc(&cfg->utp->use_cnt); - } + ubcore_vtp_map_attr(vtp, cfg); return vtp; } diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.c b/drivers/ub/urma/ubcore/ubcore_workqueue.c index 71ca0b577517..82909786b3cc 100644 --- a/drivers/ub/urma/ubcore/ubcore_workqueue.c +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.c @@ -23,7 +23,7 @@ static struct workqueue_struct *g_ubcore_workqueues[(int)UBCORE_QUEUE_TYPE_NUM]; const char UBCORE_QUEUE_NAMES[(int)UBCORE_QUEUE_TYPE_NUM][UBCORE_QUEUE_NAME_LEN] = { - {"ubcore-device-wq"}, {"ubcore-sip-wq"}, {"ubcore-bond-wq"}}; + {"ubcore-device-wq"}, {"ubcore-sip-wq"}, {"ubcore-bond-wq"}, {"ubcore-fb-wq"}}; static bool check_queue_type_valid(int queue_type) { @@ -41,21 +41,6 @@ void ubcore_flush_workqueue(int queue_type) flush_workqueue(g_ubcore_workqueues[queue_type]); } -int ubcore_alloc_workqueue(int queue_type) -{ - if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] != NULL) { - ubcore_log_err("queue_type %d out of range or already exist\n", queue_type); - return -EINVAL; - } - g_ubcore_workqueues[queue_type] = - alloc_workqueue("%s", 0, 0, UBCORE_QUEUE_NAMES[queue_type]); - if (g_ubcore_workqueues[queue_type] == NULL) { - ubcore_log_err("Failed to alloc workqueue, queue type %d\n", queue_type); - return -ENOMEM; - } - return 0; -} - int ubcore_queue_work(int queue_type, struct work_struct *work) { if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] == NULL) { @@ -65,13 +50,33 @@ int ubcore_queue_work(int queue_type, struct work_struct *work) return queue_work(g_ubcore_workqueues[queue_type], work) ? 0 : -1; } -int ubcore_destroy_workqueue(int queue_type) +int ubcore_create_workqueues(void) { - if (!check_queue_type_valid(queue_type) || g_ubcore_workqueues[queue_type] == NULL) { - ubcore_log_err("queue_type %d out of range or workqueue is NULL\n", queue_type); - return -EINVAL; + uint32_t i, j; + + for (i = 0; i < UBCORE_QUEUE_TYPE_NUM; i++) { + g_ubcore_workqueues[i] = alloc_workqueue("%s", 0, 0, UBCORE_QUEUE_NAMES[i]); + if (g_ubcore_workqueues[i] == NULL) { + ubcore_log_err("Fail to alloc workqueue, queue type %u.\n", i); + break; + } + } + + if (i == UBCORE_QUEUE_TYPE_NUM) + return 0; + + for (j = 0; j < i; j++) + destroy_workqueue(g_ubcore_workqueues[j]); + + return -1; +} + +void ubcore_destroy_workqueues(void) +{ + uint32_t i; + + for (i = 0; i < UBCORE_QUEUE_TYPE_NUM; i++) { + flush_workqueue(g_ubcore_workqueues[i]); + destroy_workqueue(g_ubcore_workqueues[i]); } - destroy_workqueue(g_ubcore_workqueues[queue_type]); - g_ubcore_workqueues[queue_type] = NULL; - return 0; } diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.h b/drivers/ub/urma/ubcore/ubcore_workqueue.h index b1487796bc57..dc2180a7aae7 100644 --- a/drivers/ub/urma/ubcore/ubcore_workqueue.h +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.h @@ -24,21 +24,30 @@ #include #include +#include "urma/ubcore_types.h" + #define UBCORE_QUEUE_NAME_LEN 20 enum ubcore_queue_type { UBCORE_DISPATCH_EVENT_WQ = 0, UBCORE_SIP_NOTIFY_WQ, UBCORE_BOND_EVENT_WQ, + UBCORE_FRONT_BACK_WQ, /* For frontend and backend ubcore communication. */ UBCORE_QUEUE_TYPE_NUM }; -void ubcore_flush_workqueue(int queue_type); +struct ubcore_front_back_work { + struct work_struct work; + struct ubcore_device *dev; + struct ubcore_req_host *req; +}; -int ubcore_alloc_workqueue(int queue_type); +void ubcore_flush_workqueue(int queue_type); int ubcore_queue_work(int queue_type, struct work_struct *work); -int ubcore_destroy_workqueue(int queue_type); +int ubcore_create_workqueues(void); + +void ubcore_destroy_workqueues(void); #endif diff --git a/drivers/ub/urma/uburma/Makefile b/drivers/ub/urma/uburma/Makefile index 1340fab0aa48..c476c2ed6aed 100644 --- a/drivers/ub/urma/uburma/Makefile +++ b/drivers/ub/urma/uburma/Makefile @@ -8,6 +8,7 @@ uburma-objs := uburma_main.o \ uburma_cmd.o \ uburma_event.o \ uburma_uobj.o \ - uburma_log.o + uburma_log.o \ + uburma_mmap.o obj-$(CONFIG_UB_URMA) += uburma.o diff --git a/drivers/ub/urma/uburma/uburma_cmd.c b/drivers/ub/urma/uburma/uburma_cmd.c index 52c51f229484..34df48a27901 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.c +++ b/drivers/ub/urma/uburma/uburma_cmd.c @@ -31,6 +31,7 @@ #include "uburma_cmd.h" #define UBURMA_INVALID_TPN UINT_MAX +#define UBURMA_CREATE_JETTY_ARG_IN_RC_SHARE_TP_SHIFT 11 void uburma_cmd_inc(struct uburma_device *ubu_dev) { @@ -124,6 +125,7 @@ static int uburma_cmd_alloc_token_id(struct ubcore_device *ubc_dev, struct uburm struct uburma_cmd_hdr *hdr) { struct uburma_cmd_alloc_token_id arg; + union ubcore_token_id_flag flag = {0}; struct ubcore_udata udata = { 0 }; struct ubcore_token_id *token_id; struct uburma_uobj *uobj; @@ -142,7 +144,7 @@ static int uburma_cmd_alloc_token_id(struct ubcore_device *ubc_dev, struct uburm return -ENOMEM; } - token_id = ubcore_alloc_token_id(ubc_dev, &udata); + token_id = ubcore_alloc_token_id(ubc_dev, flag, &udata); if (IS_ERR_OR_NULL(token_id)) { uburma_log_err("ubcore alloc token_id id failed.\n"); ret = PTR_ERR(token_id); @@ -1020,6 +1022,10 @@ static void fill_create_jetty_attr(struct ubcore_jetty_cfg *cfg, cfg->flag.bs.lock_free = ((union ubcore_jfs_flag)arg->in.jfs_flag).bs.lock_free; cfg->flag.bs.error_suspend = ((union ubcore_jfs_flag)arg->in.jfs_flag).bs.error_suspend; cfg->flag.bs.outorder_comp = ((union ubcore_jfs_flag)arg->in.jfs_flag).bs.outorder_comp; + cfg->flag.bs.sub_trans_mode = ((union ubcore_jfs_flag)arg->in.jfs_flag).bs.sub_trans_mode; + // see urma_jfs_flag + cfg->flag.bs.rc_share_tp = (arg->in.jfs_flag & + (0x1 << UBURMA_CREATE_JETTY_ARG_IN_RC_SHARE_TP_SHIFT)) > 0 ? 1 : 0; cfg->max_send_sge = arg->in.max_send_sge; cfg->max_send_rsge = arg->in.max_send_rsge; @@ -1850,6 +1856,61 @@ static int uburma_fill_user_ctl_info(struct ubcore_ucontext *ctx, return 0; } +static int uburma_fill_eid_list(struct ubcore_device *dev, + struct uburma_cmd_get_eid_list *eid_list) +{ + struct ubcore_eid_entry *e; + uint32_t max_eid_cnt = 0; + uint32_t eid_cnt = 0; + int i; + + spin_lock(&dev->eid_table.lock); + if (dev->eid_table.eid_entries == NULL) { + spin_unlock(&dev->eid_table.lock); + return -EINVAL; + } + + max_eid_cnt = min(dev->eid_table.eid_cnt, eid_list->in.max_eid_cnt); + for (i = 0; i < max_eid_cnt; i++) { + e = &dev->eid_table.eid_entries[i]; + if (!e->valid || !net_eq(e->net, current->nsproxy->net_ns)) + continue; + + eid_list->out.eid_list[eid_cnt].eid_index = e->eid_index; + eid_list->out.eid_list[eid_cnt].eid = e->eid; + eid_cnt++; + } + eid_list->out.eid_cnt = eid_cnt; + spin_unlock(&dev->eid_table.lock); + return 0; +} + +static int uburma_cmd_get_eid_list(struct ubcore_device *ubc_dev, + struct uburma_file *file, struct uburma_cmd_hdr *hdr) +{ + struct uburma_cmd_get_eid_list *args; + int ret; + + args = kcalloc(1, sizeof(struct uburma_cmd_get_eid_list), GFP_KERNEL); + if (args == NULL) + return -ENOMEM; + + ret = uburma_copy_from_user(args, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct uburma_cmd_get_eid_list)); + if (ret != 0) + goto out; + + ret = uburma_fill_eid_list(ubc_dev, args); + if (ret != 0) + goto out; + + ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, args, + sizeof(struct uburma_cmd_get_eid_list)); +out: + kfree(args); + return ret; +} + static int uburma_cmd_user_ctl(struct ubcore_device *ubc_dev, struct uburma_file *file, struct uburma_cmd_hdr *hdr) { @@ -1873,6 +1934,67 @@ static int uburma_cmd_user_ctl(struct ubcore_device *ubc_dev, return 0; } +static int uburma_fill_net_addr_list(struct ubcore_device *dev, + struct uburma_cmd_get_net_addr_list *netaddr_list) +{ + struct ubcore_sip_info *entry; + uint32_t max_netaddr_cnt; + uint32_t netaddr_cnt = 0; + int i; + + mutex_lock(&dev->sip_table.lock); + if (dev->sip_table.entry == NULL) { + mutex_unlock(&dev->sip_table.lock); + return -EINVAL; + } + + max_netaddr_cnt = min(dev->sip_table.max_sip_cnt, netaddr_list->in.max_netaddr_cnt); + for (i = 0; i < max_netaddr_cnt; i++) { + entry = &dev->sip_table.entry[i]; + if (entry->is_active) { + netaddr_list->out.netaddr_info[netaddr_cnt].netaddr = entry->addr; + netaddr_list->out.netaddr_info[netaddr_cnt].index = i; + netaddr_cnt++; + } + } + netaddr_list->out.netaddr_cnt = netaddr_cnt; + mutex_unlock(&dev->sip_table.lock); + + return 0; +} + +static int uburma_cmd_get_net_addr_list(struct ubcore_device *ubc_dev, + struct uburma_file *file, struct uburma_cmd_hdr *hdr) +{ + struct uburma_cmd_get_net_addr_list *args; + int ret; + + args = kcalloc(1, sizeof(struct uburma_cmd_get_net_addr_list), GFP_KERNEL); + if (args == NULL) + return -ENOMEM; + + ret = uburma_copy_from_user(args, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct uburma_cmd_get_net_addr_list)); + if (ret != 0) + goto out; + + ret = uburma_fill_net_addr_list(ubc_dev, args); + if (ret != 0) + goto out; + + ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, args, + sizeof(uburma_cmd_get_net_addr_list)); +out: + kfree(args); + return ret; +} + +static int uburma_cmd_modify_tp(struct ubcore_device *ubc_dev, + struct uburma_file *file, struct uburma_cmd_hdr *hdr) +{ + return 0; +} + typedef int (*uburma_cmd_handler)(struct ubcore_device *ubc_dev, struct uburma_file *file, struct uburma_cmd_hdr *hdr); @@ -1913,13 +2035,16 @@ static uburma_cmd_handler g_uburma_cmd_handlers[] = { [UBURMA_CMD_UNBIND_JETTY] = uburma_cmd_unbind_jetty, [UBURMA_CMD_CREATE_JETTY_GRP] = uburma_cmd_create_jetty_grp, [UBURMA_CMD_DESTROY_JETTY_GRP] = uburma_cmd_delete_jetty_grp, - [UBURMA_CMD_USER_CTL] = uburma_cmd_user_ctl + [UBURMA_CMD_USER_CTL] = uburma_cmd_user_ctl, + [UBURMA_CMD_GET_EID_LIST] = uburma_cmd_get_eid_list, + [UBURMA_CMD_GET_NETADDR_LIST] = uburma_cmd_get_net_addr_list, + [UBURMA_CMD_MODIFY_TP] = uburma_cmd_modify_tp, }; static int uburma_cmd_parse(struct ubcore_device *ubc_dev, struct uburma_file *file, struct uburma_cmd_hdr *hdr) { - if (hdr->command < UBURMA_CMD_CREATE_CTX || hdr->command > UBURMA_CMD_USER_CTL || + if (hdr->command < UBURMA_CMD_CREATE_CTX || hdr->command >= UBURMA_CMD_MAX || g_uburma_cmd_handlers[hdr->command] == NULL) { uburma_log_err("bad uburma command: %d.\n", (int)hdr->command); return -EINVAL; @@ -1959,7 +2084,8 @@ long uburma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (cmd == UBURMA_CMD) { ret = (long)copy_from_user(&hdr, user_hdr, sizeof(struct uburma_cmd_hdr)); if ((ret != 0) || (hdr.args_len > UBURMA_CMD_MAX_ARGS_SIZE) || - (hdr.command > UBURMA_CMD_CREATE_CTX && file->ucontext == NULL)) { + (hdr.command != UBURMA_CMD_CREATE_CTX && + hdr.command != UBURMA_CMD_GET_EID_LIST && file->ucontext == NULL)) { uburma_log_err( "invalid input, hdr.command: %d, ret:%ld, hdr.args_len: %d\n", hdr.command, ret, hdr.args_len); diff --git a/drivers/ub/urma/uburma/uburma_cmd.h b/drivers/ub/urma/uburma/uburma_cmd.h index 32e1a4783fbf..7b5fc331c64f 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.h +++ b/drivers/ub/urma/uburma/uburma_cmd.h @@ -22,7 +22,7 @@ #define UBURMA_CMD_H #include #include - +#include "urma/ubcore_types.h" #include "uburma_types.h" struct uburma_cmd_hdr { @@ -31,7 +31,7 @@ struct uburma_cmd_hdr { uint64_t args_addr; }; -#define UBURMA_CMD_MAX_ARGS_SIZE 4096 +#define UBURMA_CMD_MAX_ARGS_SIZE 25600 /* only for uburma device ioctl */ #define UBURMA_CMD_MAGIC 'U' @@ -73,7 +73,11 @@ enum uburma_cmd { UBURMA_CMD_UNBIND_JETTY, UBURMA_CMD_CREATE_JETTY_GRP, UBURMA_CMD_DESTROY_JETTY_GRP, - UBURMA_CMD_USER_CTL + UBURMA_CMD_USER_CTL, + UBURMA_CMD_GET_EID_LIST, + UBURMA_CMD_GET_NETADDR_LIST, + UBURMA_CMD_MODIFY_TP, + UBURMA_CMD_MAX }; struct uburma_cmd_udrv_priv { @@ -520,6 +524,16 @@ struct uburma_cmd_delete_jetty_grp { } out; }; +struct uburma_cmd_get_eid_list { + struct { + uint32_t max_eid_cnt; + } in; + struct { + uint32_t eid_cnt; + struct ubcore_eid_info eid_list[UBCORE_MAX_EID_CNT]; + } out; +}; + struct uburma_cmd_user_ctl { struct { uint64_t addr; @@ -539,6 +553,102 @@ struct uburma_cmd_user_ctl { } udrv; /* struct [udrv] should be consistent with [urma_udrv_t] */ }; +union uburma_cmd_tp_cfg_flag { + struct { + uint32_t target : 1; /* 0: initiator, 1: target */ + uint32_t loopback : 1; + uint32_t dca_enable : 1; + /* for the bonding case, the hardware selects the port + * ignoring the port of the tp context and + * selects the port based on the hash value + * along with the information in the bonding group table. + */ + uint32_t bonding : 1; + uint32_t reserved : 28; + } bs; + uint32_t value; +}; + +struct uburma_cmd_user_tp_cfg { + union uburma_cmd_tp_cfg_flag flag; /* flag of initial tp */ + enum ubcore_transport_mode trans_mode; /* tranport layer attributes */ + uint8_t retry_num; + uint8_t retry_factor; /* for calculate the time slot to retry */ + uint8_t ack_timeout; + uint8_t dscp; /* priority */ + uint32_t oor_cnt; /* OOR window size: by packet */ +}; + +struct uburma_cmd_tp_attr { + union ubcore_tp_mod_flag flag; /* consistend with urma_tp_mod_flag */ + uint32_t peer_tpn; + enum ubcore_tp_state state; + uint32_t tx_psn; + uint32_t rx_psn; + enum ubcore_mtu mtu; + uint8_t cc_pattern_idx; + uint32_t oos_cnt; /* out of standing packet cnt */ + uint32_t local_net_addr_idx; + struct ubcore_net_addr peer_net_addr; + uint16_t data_udp_start; + uint16_t ack_udp_start; + uint8_t udp_range; + uint8_t hop_limit; + uint32_t flow_label; + uint8_t port_id; + uint8_t mn; /* 0~15, a packet contains only one msg if mn is set as 0 */ + enum ubcore_transport_type peer_trans_type; +}; + +union uburma_cmd_tp_attr_mask { + struct { + uint32_t flag : 1; + uint32_t peer_tpn : 1; + uint32_t state : 1; + uint32_t tx_psn : 1; + uint32_t rx_psn : 1; /* modify both rx psn and tx psn when restore tp */ + uint32_t mtu : 1; + uint32_t cc_pattern_idx : 1; + uint32_t oos_cnt : 1; + uint32_t local_net_addr_idx : 1; + uint32_t peer_net_addr : 1; + uint32_t data_udp_start : 1; + uint32_t ack_udp_start : 1; + uint32_t udp_range : 1; + uint32_t hop_limit : 1; + uint32_t flow_label : 1; + uint32_t port_id : 1; + uint32_t mn : 1; + uint32_t peer_trans_type : 1; /* Only for user tp connection */ + uint32_t reserved : 13; + } bs; + uint32_t value; +}; + +struct uburma_cmd_net_addr_info { + struct ubcore_net_addr netaddr; + uint32_t index; +}; + +struct uburma_cmd_get_net_addr_list { + struct { + uint32_t max_netaddr_cnt; + } in; + struct { + uint32_t netaddr_cnt; + struct uburma_cmd_net_addr_info netaddr_info[UBCORE_MAX_SIP]; + } out; +}; + +struct uburma_cmd_modify_tp { + struct { + uint32_t tpn; + struct uburma_cmd_user_tp_cfg tp_cfg; + struct uburma_cmd_tp_attr attr; + union uburma_cmd_tp_attr_mask mask; + } in; +}; /* this struct should be consistent [urma_cmd_modify_tp_t] */ + /* only for event ioctl */ #define MAX_JFCE_EVENT_CNT 16 #define UBURMA_EVENT_CMD_MAGIC 'E' diff --git a/drivers/ub/urma/uburma/uburma_dev_ops.c b/drivers/ub/urma/uburma/uburma_dev_ops.c index b25d62bfaac4..01fdfeb7677b 100644 --- a/drivers/ub/urma/uburma/uburma_dev_ops.c +++ b/drivers/ub/urma/uburma/uburma_dev_ops.c @@ -29,12 +29,14 @@ #include "uburma_types.h" #include "uburma_uobj.h" #include "uburma_cmd.h" +#include "uburma_mmap.h" int uburma_mmap(struct file *filp, struct vm_area_struct *vma) { struct uburma_file *file = filp->private_data; struct uburma_device *ubu_dev; struct ubcore_device *ubc_dev; + struct uburma_umap_priv *priv; int srcu_idx; int ret; @@ -54,8 +56,17 @@ int uburma_mmap(struct file *filp, struct vm_area_struct *vma) goto out; } + vma->vm_ops = uburma_get_umap_ops(); ret = ubc_dev->ops->mmap(file->ucontext, vma); + if (!down_read_trylock(&file->cleanup_rwsem)) + goto out; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + goto unlock_read; + uburma_umap_priv_init(priv, vma); +unlock_read: + up_read(&file->cleanup_rwsem); out: srcu_read_unlock(&ubu_dev->ubc_dev_srcu, srcu_idx); uburma_cmd_dec(ubu_dev); @@ -76,6 +87,9 @@ void uburma_release_file(struct kref *ref) complete(&file->ubu_dev->comp); kobject_put(&file->ubu_dev->kobj); + if (file->fault_page) + __free_pages(file->fault_page, 0); + mutex_destroy(&file->umap_mutex); kfree(file); } @@ -114,6 +128,8 @@ int uburma_open(struct inode *inode, struct file *filp) kref_init(&file->ref); mutex_init(&file->mutex); uburma_init_uobj_context(file); + mutex_init(&file->umap_mutex); + INIT_LIST_HEAD(&file->umaps_list); filp->private_data = file; list_add_tail(&file->list, &ubu_dev->uburma_file_list); diff --git a/drivers/ub/urma/uburma/uburma_mmap.c b/drivers/ub/urma/uburma/uburma_mmap.c new file mode 100644 index 000000000000..5c4a3f4ea1d4 --- /dev/null +++ b/drivers/ub/urma/uburma/uburma_mmap.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: uburma mmap module + * Author: Wen Chen + * Create: 2024-03-18 + * Note: + * History: 2024-03-18: Create file + */ + +#include +#include + +#include + +#include "uburma_log.h" +#include "uburma_types.h" + +void uburma_umap_priv_init(struct uburma_umap_priv *priv, + struct vm_area_struct *vma) +{ + struct uburma_file *ufile = vma->vm_file->private_data; + + priv->vma = vma; + vma->vm_private_data = priv; + + mutex_lock(&ufile->umap_mutex); + list_add(&priv->node, &ufile->umaps_list); + mutex_unlock(&ufile->umap_mutex); +} + +void uburma_unmap_vma_pages(struct uburma_file *ufile) +{ + struct uburma_umap_priv *priv, *next_priv; + struct mm_struct *mm = NULL; + struct vm_area_struct *vma; + int ret; + + lockdep_assert_held(&ufile->cleanup_rwsem); + + while (1) { + mutex_lock(&ufile->umap_mutex); + list_for_each_entry_safe(priv, next_priv, &ufile->umaps_list, node) { + mm = priv->vma->vm_mm; + ret = mmget_not_zero(mm); + if (ret != 0) { + list_del_init(&priv->node); + mm = NULL; + continue; + } + break; + } + mutex_unlock(&ufile->umap_mutex); + if (!mm) + return; + + mmap_read_lock(mm); + mutex_lock(&ufile->umap_mutex); + list_for_each_entry_safe(priv, next_priv, &ufile->umaps_list, node) { + vma = priv->vma; + if (vma->vm_mm != mm) + continue; + list_del_init(&priv->node); + zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); + } + mutex_unlock(&ufile->umap_mutex); + mmap_read_unlock(mm); + mmput(mm); + } +} + +static void uburma_umap_open(struct vm_area_struct *vma) +{ + struct uburma_file *ufile = vma->vm_file->private_data; + struct uburma_umap_priv *priv; + + if (!down_read_trylock(&ufile->cleanup_rwsem)) + goto out_zap; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + goto out_unlock; + + uburma_umap_priv_init(priv, vma); + + up_read(&ufile->cleanup_rwsem); + return; + +out_unlock: + up_read(&ufile->cleanup_rwsem); +out_zap: + vma->vm_private_data = NULL; + zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); +} + +static void uburma_umap_close(struct vm_area_struct *vma) +{ + struct uburma_file *ufile = vma->vm_file->private_data; + struct uburma_umap_priv *priv = vma->vm_private_data; + + if (!priv) + return; + + mutex_lock(&ufile->umap_mutex); + list_del(&priv->node); + mutex_unlock(&ufile->umap_mutex); + kfree(priv); + vma->vm_private_data = NULL; +} + +static vm_fault_t uburma_umap_fault(struct vm_fault *vmf) +{ + struct uburma_file *ufile = vmf->vma->vm_file->private_data; + struct uburma_umap_priv *priv = vmf->vma->vm_private_data; + vm_fault_t ret = 0; + + if (!priv) + return VM_FAULT_SIGBUS; + + if (!(vmf->vma->vm_flags & (VM_WRITE | VM_MAYWRITE))) { + vmf->page = ZERO_PAGE(0); + get_page(vmf->page); + return 0; + } + + mutex_lock(&ufile->umap_mutex); + if (!ufile->fault_page) + ufile->fault_page = alloc_pages(vmf->gfp_mask | __GFP_ZERO, 0); + + if (ufile->fault_page) { + vmf->page = ufile->fault_page; + get_page(vmf->page); + } else { + ret = VM_FAULT_SIGBUS; + } + mutex_unlock(&ufile->umap_mutex); + + return ret; +} + +static const struct vm_operations_struct g_urma_umap_ops = { + .open = uburma_umap_open, + .close = uburma_umap_close, + .fault = uburma_umap_fault, +}; + +const struct vm_operations_struct *uburma_get_umap_ops(void) +{ + return (const struct vm_operations_struct *)&g_urma_umap_ops; +} diff --git a/drivers/ub/urma/uburma/uburma_mmap.h b/drivers/ub/urma/uburma/uburma_mmap.h new file mode 100644 index 000000000000..d3c0eb0987d7 --- /dev/null +++ b/drivers/ub/urma/uburma/uburma_mmap.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * Description: uburma mmap head file + * Author: Wen Chen + * Create: 2024-03-18 + * Note: + * History: 2024-03-18: Create file + */ + +#ifndef UBURMA_MMAP_H +#define UBURMA_MMAP_H + +#include + +#include "uburma_types.h" + +void uburma_unmap_vma_pages(struct uburma_file *ufile); +const struct vm_operations_struct *uburma_get_umap_ops(void); +void uburma_umap_priv_init(struct uburma_umap_priv *priv, + struct vm_area_struct *vma); + +#endif /* UBURMA_MMAP_H */ diff --git a/drivers/ub/urma/uburma/uburma_types.h b/drivers/ub/urma/uburma/uburma_types.h index 486df78ca8ee..838b695f213b 100644 --- a/drivers/ub/urma/uburma/uburma_types.h +++ b/drivers/ub/urma/uburma/uburma_types.h @@ -57,6 +57,9 @@ struct uburma_file { struct list_head list; int is_closed; + struct mutex umap_mutex; + struct list_head umaps_list; + struct page *fault_page; }; struct uburma_device { @@ -74,4 +77,9 @@ struct uburma_device { struct list_head uburma_file_list; }; +struct uburma_umap_priv { + struct vm_area_struct *vma; + struct list_head node; +}; + #endif /* UBURMA_TYPES_H */ diff --git a/drivers/ub/urma/uburma/uburma_uobj.c b/drivers/ub/urma/uburma/uburma_uobj.c index dfee43fc424c..567b02f04978 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.c +++ b/drivers/ub/urma/uburma/uburma_uobj.c @@ -30,6 +30,7 @@ #include "uburma_file_ops.h" #include "uburma_log.h" #include "uburma_event.h" +#include "uburma_mmap.h" #include "uburma_uobj.h" static bool g_is_zero_fd; @@ -534,6 +535,9 @@ void uburma_cleanup_uobjs(struct uburma_file *ufile, enum uburma_remove_reason w put_unused_fd(0); g_is_zero_fd = false; } + if (why == UBURMA_REMOVE_DRIVER_REMOVE) + uburma_unmap_vma_pages(ufile); + up_write(&ufile->cleanup_rwsem); } diff --git a/include/urma/ubcore_api.h b/include/urma/ubcore_api.h index daa21e4441ac..dda78f17cc1b 100644 --- a/include/urma/ubcore_api.h +++ b/include/urma/ubcore_api.h @@ -50,6 +50,19 @@ void ubcore_dispatch_async_event(struct ubcore_event *event); */ struct ubcore_umem *ubcore_umem_get(struct ubcore_device *dev, uint64_t va, uint64_t len, union ubcore_umem_flag flag); + +/** + * Find best HW page size to use for this segment + * @param[in] umem: umem struct, return of ubcore_umem_get; + * @param[in] page_size_bitmap: bitmap of HW supported page sizes, must include PAGE_SIZE; + * @param[in] va: Initial address of this segment. + * Return: before kernel 5.3: return 4K; + * kernel 5.3 and later: Returns 0 if the umem requires page sizes not supported by the + * driver to be mapped; returns non-zero on the best page size. + */ +uint64_t ubcore_umem_find_best_page_size(struct ubcore_umem *umem, uint64_t page_size_bitmap, + uint64_t va); + /** * Release umem allocated * @param[in] umem: the ubcore umem created before diff --git a/include/urma/ubcore_jetty.h b/include/urma/ubcore_jetty.h index a1039d9c1b81..0fa7711c2852 100644 --- a/include/urma/ubcore_jetty.h +++ b/include/urma/ubcore_jetty.h @@ -26,10 +26,22 @@ /* The APIs below are deprecated, should not be called by driver or ubcore client */ struct ubcore_jfc *ubcore_find_jfc(struct ubcore_device *dev, uint32_t jfc_id); +// Deprecated, use ubcore_find_get_jfs struct ubcore_jfs *ubcore_find_jfs(struct ubcore_device *dev, uint32_t jfs_id); +struct ubcore_jfs *ubcore_find_get_jfs(struct ubcore_device *dev, uint32_t jfs_id); +void ubcore_put_jfs(struct ubcore_jfs *jfs); +void ubcore_jfs_get(void *obj); +// Deprecated, use ubcore_find_get_jfr struct ubcore_jfr *ubcore_find_jfr(struct ubcore_device *dev, uint32_t jfr_id); +struct ubcore_jfr *ubcore_find_get_jfr(struct ubcore_device *dev, uint32_t jfr_id); +void ubcore_put_jfr(struct ubcore_jfr *jfr); +void ubcore_jfr_get(void *obj); +// Deprecated, use ubcore_find_get_jetty struct ubcore_jetty *ubcore_find_jetty(struct ubcore_device *dev, uint32_t jetty_id); +struct ubcore_jetty *ubcore_find_get_jetty(struct ubcore_device *dev, uint32_t jetty_id); +void ubcore_put_jetty(struct ubcore_jetty *jetty); +void ubcore_jetty_get(void *obj); #endif diff --git a/include/urma/ubcore_types.h b/include/urma/ubcore_types.h index ba085f55fb7c..9bab210d7fdb 100644 --- a/include/urma/ubcore_types.h +++ b/include/urma/ubcore_types.h @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_CGROUP_RDMA #include @@ -58,6 +59,8 @@ #define UBCORE_MAX_MSG 4096 #define UBCORE_MAX_EID_CNT 1024 #define UBCORE_MAX_VTP_CNT_PER_TPF (128 * 1024) // Temporarily specify the upper limit +#define UBCORE_EID_GROUP_NAME_LEN 10 +#define UBCORE_MAX_MIG_ENTRY_CNT 64 #define EID_FMT \ "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x" @@ -74,12 +77,17 @@ #define UBCORE_CC_IDX_TABLE_SIZE 64 #define UBCORE_SIP_TABLE_SIZE (1024) /* 1823: 16; 1650: 1024; 1636: N/A */ #define UBCORE_MAX_SIP UBCORE_SIP_TABLE_SIZE +#define UBCORE_CHECK_RETURN_ERR_PTR(ptr, err) \ + ((ptr) == NULL ? ERR_PTR(-(err)) : (ptr)) + +#define UBCORE_MAX_DSCP_NUM (64) enum ubcore_transport_type { UBCORE_TRANSPORT_INVALID = -1, - UBCORE_TRANSPORT_UB, - UBCORE_TRANSPORT_IB, - UBCORE_TRANSPORT_IP, + UBCORE_TRANSPORT_UB = 0, + UBCORE_TRANSPORT_IB = 1, + UBCORE_TRANSPORT_IP = 2, + UBCORE_TRANSPORT_HNS_UB = 5, UBCORE_TRANSPORT_MAX }; @@ -89,6 +97,13 @@ enum ubcore_resource_type { UBCORE_RESOURCE_HCA_MAX }; +enum ubcore_ldev_attr_group { + UBCORE_ATTR_GROUP_DEV_DEFAULT = 0, + UBCORE_ATTR_GROUP_EIDS = 1, + UBCORE_ATTR_GROUP_NULL = 2, + UBCORE_ATTR_GROUP_MAX = 3 +}; + #define UBCORE_ACCESS_LOCAL_WRITE 0x1 #define UBCORE_ACCESS_REMOTE_READ (0x1 << 1) #define UBCORE_ACCESS_REMOTE_WRITE (0x1 << 2) @@ -131,6 +146,7 @@ struct ubcore_ueid_cfg { union ubcore_eid eid; uint32_t upi; uint32_t eid_index; + uuid_t uuid; }; struct ubcore_devid { @@ -178,6 +194,7 @@ union ubcore_jfc_flag { }; #define UBCORE_SUB_TRANS_MODE_TA_DST_ORDERING_ENABLE (0x1) +#define UBCORE_SUB_TRANS_MODE_USER_TP (0x2) union ubcore_jfs_flag { struct { @@ -289,7 +306,8 @@ union ubcore_reg_seg_flag { uint32_t non_pin : 1; uint32_t user_iova : 1; uint32_t token_id_valid : 1; - uint32_t reserved : 18; + uint32_t pa : 1; + uint32_t reserved : 17; } bs; uint32_t value; }; @@ -358,10 +376,19 @@ enum ubcore_target_type { UBCORE_JETTY_GROUP }; +union ubcore_token_id_flag { + struct { + uint32_t pa : 1; + uint32_t reserved : 31; + } bs; + uint32_t value; +}; + struct ubcore_token_id { struct ubcore_device *ub_dev; struct ubcore_ucontext *uctx; - uint32_t token_id; + uint32_t token_id; // driver fill + union ubcore_token_id_flag flag; atomic_t use_cnt; }; @@ -384,8 +411,9 @@ union ubcore_seg_attr { uint32_t access : 6; uint32_t non_pin : 1; uint32_t user_iova : 1; - uint32_t user_token_id : 1; - uint32_t reserved : 18; + uint32_t user_token_id : 1; + uint32_t pa : 1; + uint32_t reserved : 17; } bs; uint32_t value; }; @@ -540,6 +568,7 @@ enum ubcore_pattern { enum ubcore_sub_trans_mode_cap { UBCORE_RC_TP_DST_ORDERING = 0x1, /* rc mode with tp dst ordering */ UBCORE_RC_TA_DST_ORDERING = 0x1 << 1, /* rc mode with ta dst ordering  */ + UBCORE_RC_USER_TP = 0x1 << 2, /* rc mode with user connection  */ }; struct ubcore_device_cap { @@ -585,6 +614,7 @@ struct ubcore_device_cap { uint32_t max_upi_cnt; uint32_t max_netaddr_cnt; uint16_t max_fe_cnt; /* PF: greater than or equal to 0; FE: must be 0 */ + uint64_t page_size_cap; }; struct ubcore_guid { @@ -778,12 +808,12 @@ struct ubcore_tp_cfg { union ubcore_eid peer_eid; struct ubcore_jetty_id peer_jetty; }; - /* tranport layer attributes */ + /* transport layer attributes */ enum ubcore_transport_mode trans_mode; uint8_t retry_num; uint8_t retry_factor; /* for calculate the time slot to retry */ uint8_t ack_timeout; - uint8_t dscp; /* priority */ + uint8_t dscp; uint32_t oor_cnt; /* OOR window size: by packet */ struct ubcore_tpg *tpg; /* NULL if no tpg, eg.UM mode */ }; @@ -813,7 +843,8 @@ union ubcore_tp_attr_mask { uint32_t flow_label : 1; uint32_t port_id : 1; uint32_t mn : 1; - uint32_t reserved : 14; + uint32_t peer_trans_type : 1; /* user tp only */ + uint32_t reserved : 13; } bs; uint32_t value; }; @@ -837,6 +868,7 @@ struct ubcore_tp_attr { uint32_t flow_label; uint8_t port_id; uint8_t mn; /* 0~15, a packet contains only one msg if mn is set as 0 */ + enum ubcore_transport_type peer_trans_type; /* Only for user tp connection */ }; struct ubcore_tp { @@ -908,10 +940,8 @@ struct ubcore_tpg { struct ubcore_tpg_ext tpg_ext; /* filled by ubn driver when creating tp */ struct ubcore_tpg_ext peer_ext; /* filled by ubcore before modifying tp */ struct ubcore_tp *tp_list[UBCORE_MAX_TP_CNT_IN_GRP]; // UBCORE_MAX_TP_CNT_IN_GRP=32 - atomic_t use_cnt; struct hlist_node hnode; /* driver inaccessible */ struct kref ref_cnt; - struct completion comp; struct mutex mutex; }; @@ -949,10 +979,8 @@ struct ubcore_utp { uint32_t utpn; /* driver fills */ struct ubcore_device *ub_dev; struct ubcore_utp_cfg utp_cfg; /* filled by ubcore when createing utp. */ - atomic_t use_cnt; struct hlist_node hnode; struct kref ref_cnt; - struct completion comp; }; struct ubcore_ctp_cfg { @@ -980,8 +1008,6 @@ struct ubcore_vtpn { struct ubcore_device *ub_dev; /* ubcore private, inaccessible to driver */ enum ubcore_transport_mode trans_mode; - uint32_t sub_trans_mode; - uint32_t rc_share_tp; /* vtpn key start */ union ubcore_eid local_eid; union ubcore_eid peer_eid; @@ -1054,16 +1080,22 @@ union ubcore_vtp_attr_mask { }; enum ubcore_msg_opcode { + /* Processed by UVS. */ UBCORE_MSG_CREATE_VTP = 0, UBCORE_MSG_DESTROY_VTP, UBCORE_MSG_ALLOC_EID, UBCORE_MSG_DEALLOC_EID, UBCORE_MSG_CONFIG_DEVICE, - UBCORE_MSG_STOP_PROC_VTP_MSG = 0x10, /* should be all migrate op after this opcode */ + /* Live migration, processed by UVS */ + UBCORE_MSG_STOP_PROC_VTP_MSG = 0x10, UBCORE_MSG_QUERY_VTP_MIG_STATUS, UBCORE_MSG_FLOW_STOPPED, UBCORE_MSG_MIG_ROLLBACK, - UBCORE_MSG_MIG_VM_START + UBCORE_MSG_MIG_VM_START, + /* Processed by backend ubcore. */ + UBCORE_MSG_NEGO_VER, + UBCORE_MSG_UPDATE_NET_ADDR, + UBCORE_MSP_UPDATE_EID }; struct ubcore_req { @@ -1158,6 +1190,8 @@ struct ubcore_jfs { uint64_t urma_jfs; /* user space jfs pointer */ struct hlist_node hnode; atomic_t use_cnt; + struct kref ref_cnt; + struct completion comp; struct ubcore_hash_table *tptable; /* Only for devices not natively supporting RM mode */ }; @@ -1183,8 +1217,9 @@ struct ubcore_jfr { uint64_t urma_jfr; /* user space jfr pointer */ struct hlist_node hnode; atomic_t use_cnt; - /* Only for devices not natively supporting RM mode */ - struct ubcore_hash_table *tptable; + struct kref ref_cnt; + struct completion comp; + struct ubcore_hash_table *tptable; /* Only for devices not natively supporting RM mode */ }; union ubcore_jetty_flag { @@ -1268,6 +1303,8 @@ struct ubcore_jetty { uint64_t urma_jetty; /* user space jetty pointer */ struct hlist_node hnode; atomic_t use_cnt; + struct kref ref_cnt; + struct completion comp; struct ubcore_hash_table *tptable; /* Only for devices not natively supporting RM mode */ }; @@ -1519,11 +1556,11 @@ struct ubcore_send_wr { }; struct ubcore_cas_wr { - struct ubcore_sge *dst; /* len is the data length of CAS operation, 8/16/32/64B */ + struct ubcore_sge *dst; /* len is the data length of CAS operation */ struct ubcore_sge *src; /* Local address for destination original value written back */ union { - uint64_t cmp_data; /* When the len is 8B, it indicates the CMP value. */ - uint64_t cmp_addr; /* When the len is 16/32/64B, it indicates the data address. */ + uint64_t cmp_data; /* When the len <= 8B, it indicates the CMP value. */ + uint64_t cmp_addr; /* When the len > 8B, it indicates the data address. */ }; union { /* If destination value is the same as cmp_data, @@ -1674,6 +1711,17 @@ enum ubcore_mig_resp_status { UBCORE_VTP_MIG_UNCOMPLETE }; +struct ubcore_fe_stats { + uint64_t tx_pkt; + uint64_t rx_pkt; + uint64_t tx_bytes; + uint64_t rx_bytes; + uint64_t tx_pkt_err; + uint64_t rx_pkt_err; + uint64_t tx_timeout_cnt; + uint64_t rx_ce_pkt; +}; + struct ubcore_ops { struct module *owner; /* kernel driver module */ char driver_name[UBCORE_MAX_DRIVER_NAME]; /* user space driver name */ @@ -1777,11 +1825,12 @@ struct ubcore_ops { /* segment part */ /** alloc token id to ubep * @param[in] dev: the ub device handle; + * @param[in] flag: token_id_flag; * @param[in] udata: ucontext and user space driver data * @return: token id pointer on success, NULL on error */ struct ubcore_token_id *(*alloc_token_id)(struct ubcore_device *dev, - struct ubcore_udata *udata); + union ubcore_token_id_flag flag, struct ubcore_udata *udata); /** free key id from ubep * @param[in] token_id: the token id alloced before; @@ -2086,6 +2135,17 @@ struct ubcore_ops { */ int (*modify_tp)(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask mask); + /** + * modify user tp. + * @param[in] dev: the ub device handle + * @param[in] tpn: tp number of the tp created before + * @param[in] cfg: user configuration of the tp + * @param[in] attr: tp attributes + * @param[in] mask: attr mask indicating the attributes to be modified + * @return: 0 on success, other value on error + */ + int (*modify_user_tp)(struct ubcore_device *dev, uint32_t tpn, struct ubcore_tp_cfg *cfg, + struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask mask); /** * destroy tp. * @param[in] tp: tp pointer created before @@ -2339,6 +2399,26 @@ struct ubcore_ops { */ int (*config_dscp_vl)(struct ubcore_device *dev, uint8_t *dscp, uint8_t *vl, uint8_t num); + /** + * query fe stats, for migration currently. + * @param[in] dev: the ub device handle; + * @param[in] cnt: array count; + * @param[in] fe_idx: fe id array; + * @param[out] stats: fe counters + * @return: 0 on success, other value on error + */ + int (*query_fe_stats)(struct ubcore_device *dev, uint32_t cnt, uint16_t *fe_idx, + struct ubcore_fe_stats *stats); + + /** + * query dscp-vl mapping + * @param[in] dev:the ub dev handle; + * @param[in] dscp: the dscp value array + * @param[in] num: array num + * @param[out] vl: the vl value array + * @return: 0 on success, other value on error + */ + int (*query_dscp_vl)(struct ubcore_device *dev, uint8_t *dscp, uint8_t num, uint8_t *vl); }; struct ubcore_bitmap { @@ -2352,7 +2432,7 @@ enum ubcore_hash_table_type { UBCORE_HT_JFR, /* jfr hash table */ UBCORE_HT_JFC, /* jfc hash table */ UBCORE_HT_JETTY, /* jetty hash table */ - UBCORE_HT_TP, /* tp table for IB */ + UBCORE_HT_TP, /* tp table */ UBCORE_HT_TPG, /* tpg table */ UBCORE_HT_RM_VTP, /* rm vtp table */ UBCORE_HT_RC_VTP, /* rc vtp table */ @@ -2362,7 +2442,6 @@ enum ubcore_hash_table_type { UBCORE_HT_UM_VTPN, /* um vtpn table */ UBCORE_HT_UTP, /* utp table */ UBCORE_HT_CTP, /* ctp table */ - UBCORE_HT_UB_TP, /* tp table for UB */ UBCORE_HT_NUM }; @@ -2392,12 +2471,19 @@ struct ubcore_port_kobj { uint8_t port_id; }; +struct ubcore_eid_attr { + char name[UBCORE_EID_GROUP_NAME_LEN]; + uint32_t eid_idx; + struct device_attribute attr; +}; + struct ubcore_logic_device { struct device *dev; struct ubcore_port_kobj port[UBCORE_MAX_PORT_CNT]; struct list_head node; /* add to ldev list */ possible_net_t net; struct ubcore_device *ub_dev; + const struct attribute_group *dev_group[UBCORE_ATTR_GROUP_MAX]; }; struct ubcore_device { @@ -2473,6 +2559,12 @@ struct ubcore_umem { uint32_t nmap; }; +enum ubcore_net_addr_op { + UBCORE_ADD_NET_ADDR = 0, + UBCORE_DEL_NET_ADDR = 1, + UBCORE_UPDATE_NET_ADDR = 2 +}; + struct ubcore_sip_info { char dev_name[UBCORE_MAX_DEV_NAME]; struct ubcore_net_addr addr; diff --git a/include/urma/ubcore_uapi.h b/include/urma/ubcore_uapi.h index 20e8a13bb315..19b762bb0d37 100644 --- a/include/urma/ubcore_uapi.h +++ b/include/urma/ubcore_uapi.h @@ -132,11 +132,12 @@ void ubcore_unregister_client(struct ubcore_client *rm_client); /** * alloc token to ubcore device * @param[in] dev: the ubcore device handle; + * @param[in] flag: token_id_flag; * @param[in] udata (optional): ucontext and user space driver data * @return: token id pointer on success, NULL on error */ struct ubcore_token_id *ubcore_alloc_token_id(struct ubcore_device *dev, - struct ubcore_udata *udata); + union ubcore_token_id_flag flag, struct ubcore_udata *udata); /** * free token id from ubcore device * @param[in] token_id: the token_id id alloced before; -- Gitee From 715feb719363c750976fd5dd0feb11e6c1ef9f8e Mon Sep 17 00:00:00 2001 From: WenChen Date: Mon, 20 May 2024 18:59:39 +0800 Subject: [PATCH 5/6] urma: upload kernel patch for 20240516_day driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I91DSN CVE: NA -------------------------------- Upload kernel patch for 20240516_day, detailed fixes are as follows: 1. Remove the -L parameter for cross compilation 2. Addition of modify tp implement 3. Change the content of the urma_admin help manual. 4. Improve uvs_alarm. 5. Modify bw_test for urma_tp_test. Fixes: 329bf7f33128 ("ubcore: fix the bug of tp negotiation concurrency") Signed-off-by: WenChen Signed-off-by: Weibo Zhao --- drivers/ub/urma/ubcore/ubcore_cdev_file.c | 108 ++++++++++ drivers/ub/urma/ubcore/ubcore_device.c | 15 +- drivers/ub/urma/ubcore/ubcore_main.c | 6 +- drivers/ub/urma/ubcore/ubcore_priv.h | 6 + drivers/ub/urma/ubcore/ubcore_uvs_cmd.c | 228 ++++++++++++++++++++++ drivers/ub/urma/ubcore/ubcore_uvs_cmd.h | 50 +++++ drivers/ub/urma/uburma/uburma_cmd.c | 152 ++++++++++++++- drivers/ub/urma/uburma/uburma_cmd.h | 22 ++- include/urma/ubcore_types.h | 10 +- 9 files changed, 582 insertions(+), 15 deletions(-) diff --git a/drivers/ub/urma/ubcore/ubcore_cdev_file.c b/drivers/ub/urma/ubcore/ubcore_cdev_file.c index 45f736a7797c..e430c77f002f 100644 --- a/drivers/ub/urma/ubcore/ubcore_cdev_file.c +++ b/drivers/ub/urma/ubcore/ubcore_cdev_file.c @@ -535,6 +535,112 @@ static ssize_t driver_name_show(struct device *dev, struct device_attribute *att static DEVICE_ATTR_RO(driver_name); +static ssize_t reserved_jetty_id_min_show_cb(struct ubcore_device *dev, char *buf) +{ + int ret = 0; + + ret = ubcore_query_device_attr(dev, &dev->attr); + if (ret != 0) { + ubcore_log_err("failed query device attr.\n"); + return ret; + } + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", + dev->attr.reserved_jetty_id_min); +} + +static ssize_t reserved_jetty_id_min_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, reserved_jetty_id_min_show_cb); +} + +static ssize_t reserved_jetty_id_min_store_cb(struct ubcore_device *dev, const char *buf, + size_t len) +{ + uint32_t value; + int ret; + struct ubcore_device_cfg cfg = {0}; + + ret = kstrtou32(buf, 0, &value); + if (ret != 0) + return -EINVAL; + + cfg.mask.bs.reserved_jetty_id_min = 1; + cfg.reserved_jetty_id_min = value; + + ret = ubcore_config_device(dev, &cfg); + if (ret != 0) + return -EINVAL; + + ret = ubcore_query_device_attr(dev, &dev->attr); + if (ret != 0) { + ubcore_log_err("failed query device attr.\n"); + return ret; + } + return (ssize_t)len; +} + +static ssize_t reserved_jetty_id_min_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + return ubcore_store_dev_attr(dev, attr, buf, len, reserved_jetty_id_min_store_cb); +} + +static DEVICE_ATTR_RW(reserved_jetty_id_min); // 0644 + +static ssize_t reserved_jetty_id_max_show_cb(struct ubcore_device *dev, char *buf) +{ + int ret = 0; + + ret = ubcore_query_device_attr(dev, &dev->attr); + if (ret != 0) { + ubcore_log_err("failed query device attr.\n"); + return ret; + } + return snprintf(buf, UBCORE_MAX_VALUE_LEN, "%u\n", + dev->attr.reserved_jetty_id_max); +} + +static ssize_t reserved_jetty_id_max_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return ubcore_show_dev_attr(dev, attr, buf, reserved_jetty_id_max_show_cb); +} + +static ssize_t reserved_jetty_id_max_store_cb(struct ubcore_device *dev, const char *buf, + size_t len) +{ + uint32_t value; + int ret; + struct ubcore_device_cfg cfg = {0}; + + ret = kstrtou32(buf, 0, &value); + if (ret != 0) + return -EINVAL; + + cfg.mask.bs.reserved_jetty_id_max = 1; + cfg.reserved_jetty_id_max = value; + + ret = ubcore_config_device(dev, &cfg); + if (ret != 0) + return -EINVAL; + + ret = ubcore_query_device_attr(dev, &dev->attr); + if (ret != 0) { + ubcore_log_err("failed query device attr.\n"); + return ret; + } + return (ssize_t)len; +} + +static ssize_t reserved_jetty_id_max_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + return ubcore_store_dev_attr(dev, attr, buf, len, reserved_jetty_id_max_store_cb); +} + +static DEVICE_ATTR_RW(reserved_jetty_id_max); // 0644 + /* One eid line has upto 51 bytes with the format: * "4294967295 0000:0000:0000:0000:0000:ffff:7f00:0001\n" * sysfs buf size is PAGESIZE, upto 80 eid lines are supported in the sysfs @@ -615,6 +721,8 @@ static struct attribute *ubcore_dev_attrs[] = { &dev_attr_virtualization.attr, &dev_attr_transport_type.attr, &dev_attr_driver_name.attr, + &dev_attr_reserved_jetty_id_min.attr, + &dev_attr_reserved_jetty_id_max.attr, NULL, }; diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index 3a7102abcb6b..2b8b8a0779f9 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -977,7 +977,7 @@ static int init_ubcore_device(struct ubcore_device *dev) return -1; } - if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { + if (ubcore_is_ub_device(dev) && dev->attr.tp_maintainer) { if (ubcore_sip_table_init(&dev->sip_table, dev->attr.dev_cap.max_netaddr_cnt) != 0) { ubcore_log_err("Failed init sip table.\n"); @@ -1057,6 +1057,9 @@ static void uninit_ubcore_device(struct ubcore_device *dev) if (ubcore_get_netlink_valid() && ubcore_send_remove_tpf_dev_info(dev) != 0) ubcore_log_warn("failed to remove tpf dev info %s", dev->dev_name); } + + if (dev->transport_type == UBCORE_TRANSPORT_HNS_UB && dev->attr.tp_maintainer) + ubcore_sip_table_uninit(&dev->sip_table); } static int ubcore_nego_ver_rsp_msg_cb(struct ubcore_device *dev, @@ -1153,6 +1156,11 @@ static int ubcore_config_device_rsp_msg_cb(struct ubcore_device *dev, cfg.rc_cfg.rc_cnt = data->rc_cnt; cfg.rc_cfg.depth = data->rc_depth; + cfg.mask.bs.reserved_jetty_id_min = 1; + cfg.mask.bs.reserved_jetty_id_max = 1; + cfg.reserved_jetty_id_min = UBCORE_RESERVED_JETTY_ID_MIN; + cfg.reserved_jetty_id_max = UBCORE_RESERVED_JETTY_ID_MAX; + cfg.mask.bs.slice = data->set_slice; cfg.slice = data->slice; @@ -1183,6 +1191,11 @@ static int ubcore_config_device_default(struct ubcore_device *dev) cfg.rc_cfg.rc_cnt = dev->attr.dev_cap.max_rc; cfg.rc_cfg.depth = dev->attr.dev_cap.max_rc_depth; + cfg.mask.bs.reserved_jetty_id_min = 1; + cfg.mask.bs.reserved_jetty_id_max = 1; + cfg.reserved_jetty_id_min = UBCORE_RESERVED_JETTY_ID_MIN; + cfg.reserved_jetty_id_max = UBCORE_RESERVED_JETTY_ID_MAX; + /* slice and mask.slice are set to 0 by default */ /* If suspend_period and cnt cannot be read, do not need to configure it */ diff --git a/drivers/ub/urma/ubcore/ubcore_main.c b/drivers/ub/urma/ubcore/ubcore_main.c index 9914be8b9564..a2131fc6b790 100644 --- a/drivers/ub/urma/ubcore/ubcore_main.c +++ b/drivers/ub/urma/ubcore/ubcore_main.c @@ -466,8 +466,7 @@ static void ubcore_handle_update_sip(struct ubcore_device *tpf_dev, static int ubcore_handle_update_net_addr(struct ubcore_device *tpf_dev, uint32_t fe_idx, struct ubcore_update_net_addr_req *req, bool async) { - /* only UB dev need sip */ - if (tpf_dev->transport_type == UBCORE_TRANSPORT_UB && req->sip_present) { + if (ubcore_is_ub_device(tpf_dev) && req->sip_present) { if (req->op == UBCORE_ADD_NET_ADDR) ubcore_handle_add_sip(tpf_dev, &req->sip_info, async); else if (req->op == UBCORE_DEL_NET_ADDR) @@ -689,8 +688,7 @@ int ubcore_update_net_addr(struct ubcore_device *dev, struct net_device *netdev, int ret = 0; req.op = op; - // Only UB DEV need save net_addr as sip - if (dev->transport_type == UBCORE_TRANSPORT_UB) { + if (ubcore_is_ub_device(dev) && dev->dynamic_eid) { ubcore_sip_init(&req.sip_info, dev, netaddr, netdev); req.sip_present = true; } diff --git a/drivers/ub/urma/ubcore/ubcore_priv.h b/drivers/ub/urma/ubcore/ubcore_priv.h index 4e19c80adf83..4231c7399e96 100644 --- a/drivers/ub/urma/ubcore/ubcore_priv.h +++ b/drivers/ub/urma/ubcore/ubcore_priv.h @@ -202,4 +202,10 @@ static inline bool ubcore_jfr_need_advise(struct ubcore_jfr *jfr) jfr->jfr_cfg.trans_mode == UBCORE_TP_RM; } +static inline bool ubcore_is_ub_device(struct ubcore_device *dev) +{ + return (dev->transport_type == UBCORE_TRANSPORT_UB || + dev->transport_type == UBCORE_TRANSPORT_HNS_UB); +} + #endif diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c index e30faee7bb48..cb8c94f97f59 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c @@ -3054,6 +3054,232 @@ static int ubcore_cmd_list_migrate_entry(struct ubcore_cmd_hdr *hdr) return ret; } +static void ubcore_fill_stats_val(struct ubcore_stats_com_val com_val, + struct ubcore_cmd_opt_dfx_query_stats *arg) +{ + arg->out.tx_pkt = com_val.tx_pkt; + arg->out.rx_pkt = com_val.rx_pkt; + arg->out.tx_bytes = com_val.tx_bytes; + arg->out.rx_bytes = com_val.rx_bytes; + arg->out.tx_pkt_err = com_val.tx_pkt_err; + arg->out.rx_pkt_err = com_val.rx_pkt_err; +} + +static void ubcore_fill_fe_stats_val(struct ubcore_fe_stats stats, + struct ubcore_cmd_opt_dfx_query_stats *arg) +{ + arg->out.tx_pkt = stats.tx_pkt; + arg->out.rx_pkt = stats.rx_pkt; + arg->out.tx_bytes = stats.tx_bytes; + arg->out.rx_bytes = stats.rx_bytes; + arg->out.tx_pkt_err = stats.tx_pkt_err; + arg->out.rx_pkt_err = stats.rx_pkt_err; + + arg->out.tx_timeout_cnt = stats.tx_timeout_cnt; + arg->out.rx_ce_pkt = stats.rx_ce_pkt; +} + +static int ubcore_dfx_query_stats(struct ubcore_device *dev, + struct ubcore_cmd_opt_dfx_query_stats *arg) +{ + struct ubcore_stats_com_val com_val; + struct ubcore_stats_key key; + struct ubcore_stats_val val; + int ret; + + if (dev->ops == NULL || dev->ops->query_stats == NULL) { + ubcore_log_warn("dev ops does not contain query_stats"); + return 0; + } + key.type = arg->in.type; + key.key = arg->in.id; + val.addr = (uint64_t)&com_val; + val.len = (uint32_t)sizeof(struct ubcore_stats_com_val); + + ret = ubcore_query_stats(dev, &key, &val); + if (ret != 0) { + ubcore_log_err("fail to query stats"); + return ret; + } + + ubcore_fill_stats_val(com_val, arg); + return ret; +} + +static int ubcore_dfx_query_fe_stats(struct ubcore_device *dev, + struct ubcore_cmd_opt_dfx_query_stats *arg) +{ + struct ubcore_fe_stats stats; + int ret; + + uint16_t fe_idx = (uint16_t)arg->in.id; + + if (dev == NULL || dev->ops == NULL || dev->ops->query_fe_stats == NULL) { + ubcore_log_err("Invalid dev.\n"); + return -1; + } + + ret = dev->ops->query_fe_stats(dev, 1, &fe_idx, &stats); + if (ret != 0) { + ubcore_log_err("Fail to query_fe_stats, ret: %d, dev_name: %s", ret, dev->dev_name); + return -1; + } + + ubcore_fill_fe_stats_val(stats, arg); + return ret; +} + +static int ubcore_cmd_opt_dfx_query_stats(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_opt_dfx_query_stats arg; + struct ubcore_device *dev; + int ret; + + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_opt_dfx_query_stats)); + if (ret != 0) + return ret; + + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_warn("fail to find dev:%s\n", arg.in.dev_name); + return -ENODEV; + } + + switch (arg.in.type) { + case UBCORE_STATS_KEY_VTP: + case UBCORE_STATS_KEY_TP: + case UBCORE_STATS_KEY_TPG: + ret = ubcore_dfx_query_stats(dev, &arg); + break; + case UBCORE_STATS_KEY_URMA_DEV: + ret = ubcore_dfx_query_fe_stats(dev, &arg); + break; + default: + ret = -1; + break; + } + + if (ret != 0) { + ubcore_log_err("fail to query stats, dev: %s, type: %u\n", + arg.in.dev_name, arg.in.type); + goto put_device; + } + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + sizeof(struct ubcore_cmd_opt_dfx_query_stats)); + +put_device: + ubcore_put_device(dev); + return ret; +} + +static int ubcore_fill_tpg_info(struct ubcore_device *dev, struct ubcore_res_tpg_val tpg, + struct ubcore_cmd_opt_dfx_query_res *arg) +{ + enum ubcore_tp_state tp_state[UBCORE_MAX_TP_CNT_IN_GRP] = {0}; + struct ubcore_tp *tp_infos = NULL; + int i = 0; + + for (i = 0; i < tpg.tp_cnt; i++) { + tp_infos = ubcore_find_get_tp(dev, tpg.tp_list[i]); + if (tp_infos == NULL) { + ubcore_log_err("Unknown tpn: %d", tpg.tp_list[i]); + return -1; + } + tp_state[i] = tp_infos->state; + ubcore_tp_kref_put(tp_infos); + } + (void)memcpy(arg->out.tpg.tp_state, + tp_state, sizeof(arg->out.tpg.tp_state)); + (void)memcpy(arg->out.tpg.tpn, tpg.tp_list, + tpg.tp_cnt * sizeof(*(tpg.tp_list))); + arg->out.tpg.dscp = tpg.dscp; + arg->out.tpg.tp_cnt = tpg.tp_cnt; + return 0; +} + +static int ubcore_cmd_opt_dfx_query_res_with_type(struct ubcore_device *dev, + struct ubcore_cmd_opt_dfx_query_res *arg) +{ + struct ubcore_res_tpg_val tpg = {0}; + struct ubcore_res_key key = {0}; + struct ubcore_res_val val = {0}; + int ret = -1; + + key.type = (uint8_t)arg->in.type; + key.key = arg->in.key; + key.key_ext = arg->in.key_ext; + key.key_cnt = arg->in.key_cnt; + + switch (arg->in.type) { + case UBCORE_RES_KEY_VTP: + val.addr = (uint64_t)&arg->out.vtp; + val.len = (uint32_t)sizeof(struct ubcore_res_vtp_val); + break; + case UBCORE_RES_KEY_TP: + val.addr = (uint64_t)&arg->out.tp; + val.len = (uint32_t)sizeof(struct ubcore_res_tp_val); + break; + case UBCORE_RES_KEY_TPG: + val.addr = (uint64_t)&tpg; + val.len = (uint32_t)sizeof(struct ubcore_res_tpg_val); + break; + case UBCORE_RES_KEY_UTP: + val.addr = (uint64_t)&arg->out.utp; + val.len = (uint32_t)sizeof(struct ubcore_res_utp_val); + break; + case UBCORE_RES_KEY_DEV_TP: + val.addr = (uint64_t)&arg->out.tpf; + val.len = (uint32_t)sizeof(struct ubcore_res_dev_tp_val); + break; + default: + ubcore_log_err("Unsupported type: %d", arg->in.type); + return -1; + } + + ret = ubcore_query_resource(dev, &key, &val); + if (ret == 0 && arg->in.type == UBCORE_RES_KEY_TPG) { + ret = ubcore_fill_tpg_info(dev, tpg, arg); + vfree(tpg.tp_list); + } + return ret; +} + +static int ubcore_cmd_opt_dfx_query_res(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_opt_dfx_query_res arg; + struct ubcore_device *dev; + int ret; + + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_opt_dfx_query_res)); + if (ret != 0) + return ret; + + arg.in.dev_name[UBCORE_MAX_DEV_NAME - 1] = '\0'; + dev = ubcore_find_device_with_name(arg.in.dev_name); + if (dev == NULL) { + ubcore_log_warn("fail to find dev:%s\n", arg.in.dev_name); + return -ENODEV; + } + + ret = ubcore_cmd_opt_dfx_query_res_with_type(dev, &arg); + if (ret != 0) { + ubcore_log_err("fail to query res, dev: %s, type: %u\n", + arg.in.dev_name, arg.in.type); + goto put_device; + } + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + sizeof(struct ubcore_cmd_opt_dfx_query_res)); + +put_device: + ubcore_put_device(dev); + return ret; +} + typedef int (*ubcore_uvs_cmd_handler)(struct ubcore_cmd_hdr *hdr); struct ubcore_uvs_cmd_func { ubcore_uvs_cmd_handler func; @@ -3106,6 +3332,8 @@ static struct ubcore_uvs_cmd_func g_ubcore_uvs_cmd_funcs[] = { [UBCORE_CMD_MAP_TARGET_VTP] = {ubcore_cmd_map_target_vtp, false}, [UBCORE_CMD_LIST_MIGRATE_ENTRY] = {ubcore_cmd_list_migrate_entry, false}, [UBCORE_CMD_QUERY_DSCP_VL] = {ubcore_cmd_opt_query_dscp_vl, false}, + [UBCORE_CMD_DFX_QUERY_STATS] = {ubcore_cmd_opt_dfx_query_stats, false}, + [UBCORE_CMD_DFX_QUERY_RES] = {ubcore_cmd_opt_dfx_query_res, false}, }; int ubcore_uvs_cmd_parse(struct ubcore_cmd_hdr *hdr) diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h index 8e24180626d4..4476ad47bdbf 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h @@ -80,6 +80,8 @@ enum ubcore_uvs_cmd { UBCORE_CMD_MAP_TARGET_VTP, UBCORE_CMD_LIST_MIGRATE_ENTRY, UBCORE_CMD_QUERY_DSCP_VL, + UBCORE_CMD_DFX_QUERY_STATS, + UBCORE_CMD_DFX_QUERY_RES, UBCORE_CMD_LAST }; @@ -125,6 +127,54 @@ struct ubcore_cmd_opt_query_dscp_vl { } out; }; + +struct ubcore_cmd_opt_dfx_query_stats { + struct { + char dev_name[UBCORE_MAX_DEV_NAME]; + uint8_t type; + uint32_t id; + uint32_t ext; + } in; + + struct { + uint64_t tx_pkt; + uint64_t rx_pkt; + uint64_t tx_bytes; + uint64_t rx_bytes; + uint64_t tx_pkt_err; + uint64_t rx_pkt_err; + uint64_t tx_timeout_cnt; + uint64_t rx_ce_pkt; + } out; +}; + +struct ubcore_res_dfx_tpg_info { + uint32_t tp_cnt; + uint8_t dscp; + enum ubcore_tp_state tp_state[UBCORE_MAX_TP_CNT_IN_GRP]; + uint32_t tpn[UBCORE_MAX_TP_CNT_IN_GRP]; +}; + +struct ubcore_cmd_opt_dfx_query_res { + struct { + char dev_name[UBCORE_MAX_DEV_NAME]; + uint8_t type; /* refer to ubcore_res_key_type_t */ + uint32_t key; /* as UPI, key is fe_idx */ + uint32_t key_ext; /* only for vtp */ + uint32_t key_cnt; /* only for rc */ + } in; + + struct { + union { + struct ubcore_res_vtp_val vtp; + struct ubcore_res_dfx_tpg_info tpg; + struct ubcore_res_tp_val tp; + struct ubcore_res_utp_val utp; + struct ubcore_res_dev_tp_val tpf; + }; + } out; +}; + struct ubcore_cmd_channel_init { struct { char userspace_in[UBCORE_CMD_CHANNEL_INIT_SIZE]; diff --git a/drivers/ub/urma/uburma/uburma_cmd.c b/drivers/ub/urma/uburma/uburma_cmd.c index 34df48a27901..0ff923c8e090 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.c +++ b/drivers/ub/urma/uburma/uburma_cmd.c @@ -1937,29 +1937,47 @@ static int uburma_cmd_user_ctl(struct ubcore_device *ubc_dev, static int uburma_fill_net_addr_list(struct ubcore_device *dev, struct uburma_cmd_get_net_addr_list *netaddr_list) { + struct uburma_cmd_net_addr_info *netaddr_info; struct ubcore_sip_info *entry; uint32_t max_netaddr_cnt; uint32_t netaddr_cnt = 0; + uint64_t len; int i; + max_netaddr_cnt = min(dev->sip_table.max_sip_cnt, + netaddr_list->in.max_netaddr_cnt); + len = max_netaddr_cnt * sizeof(struct uburma_cmd_net_addr_info); + netaddr_info = kcalloc(1, len, GFP_KERNEL); + if (netaddr_info == NULL) + return -ENOMEM; + mutex_lock(&dev->sip_table.lock); if (dev->sip_table.entry == NULL) { mutex_unlock(&dev->sip_table.lock); + kfree(netaddr_info); return -EINVAL; } - max_netaddr_cnt = min(dev->sip_table.max_sip_cnt, netaddr_list->in.max_netaddr_cnt); for (i = 0; i < max_netaddr_cnt; i++) { entry = &dev->sip_table.entry[i]; if (entry->is_active) { - netaddr_list->out.netaddr_info[netaddr_cnt].netaddr = entry->addr; - netaddr_list->out.netaddr_info[netaddr_cnt].index = i; + netaddr_info[netaddr_cnt].netaddr = entry->addr; + netaddr_info[netaddr_cnt].index = i; netaddr_cnt++; } } - netaddr_list->out.netaddr_cnt = netaddr_cnt; mutex_unlock(&dev->sip_table.lock); + netaddr_list->out.netaddr_cnt = netaddr_cnt; + netaddr_list->out.len = len; + if (uburma_copy_to_user((void __user *) + (uintptr_t)netaddr_list->out.addr, netaddr_info, + (unsigned long)len) != 0) { + kfree(netaddr_info); + return -1; + } + + kfree(netaddr_info); return 0; } @@ -1983,16 +2001,138 @@ static int uburma_cmd_get_net_addr_list(struct ubcore_device *ubc_dev, goto out; ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, args, - sizeof(uburma_cmd_get_net_addr_list)); + sizeof(struct uburma_cmd_get_net_addr_list)); out: kfree(args); return ret; } +static void uburma_fill_tp_cfg(struct uburma_cmd_user_tp_cfg *cmd_tp_cfg, + struct ubcore_tp_cfg *tp_cfg) +{ + /* Attention: ubcore_tp_cfg_flag is different with uburma_cmd_tp_cfg_flag */ + /* so we cannot fill by value */ + tp_cfg->flag.bs.target = cmd_tp_cfg->flag.bs.target; + tp_cfg->flag.bs.loopback = cmd_tp_cfg->flag.bs.loopback; + tp_cfg->flag.bs.dca_enable = cmd_tp_cfg->flag.bs.dca_enable; + tp_cfg->flag.bs.bonding = cmd_tp_cfg->flag.bs.bonding; + + tp_cfg->trans_mode = cmd_tp_cfg->trans_mode; + tp_cfg->retry_num = cmd_tp_cfg->retry_num; + tp_cfg->retry_factor = cmd_tp_cfg->retry_factor; + tp_cfg->ack_timeout = cmd_tp_cfg->ack_timeout; + tp_cfg->dscp = cmd_tp_cfg->dscp; + tp_cfg->oor_cnt = cmd_tp_cfg->oor_cnt; +} + +static void uburma_fill_peer_net_addr(struct uburma_cmd_net_addr *cmd_net_addr, + struct ubcore_net_addr *net_addr) +{ + if (cmd_net_addr->sin_family == AF_INET) { + net_addr->type = UBCORE_NET_ADDR_TYPE_IPV4; + net_addr->net_addr.in4.addr = cmd_net_addr->in4.s_addr; + } else if (cmd_net_addr->sin_family == AF_INET6) { + net_addr->type = UBCORE_NET_ADDR_TYPE_IPV6; + (void)memcpy(net_addr->net_addr.raw, &cmd_net_addr->in6, sizeof(struct in6_addr)); + } + + net_addr->vlan = cmd_net_addr->vlan; + (void)memcpy(net_addr->mac, cmd_net_addr->mac, UBCORE_MAC_BYTES); + net_addr->prefix_len = cmd_net_addr->prefix_len; +} + +static void uburma_fill_tp_attr(struct uburma_cmd_tp_attr *cmd_attr, + struct ubcore_tp_attr *attr) +{ + attr->flag.value = cmd_attr->flag.value; + attr->peer_tpn = cmd_attr->peer_tpn; + attr->state = cmd_attr->state; + attr->tx_psn = cmd_attr->tx_psn; + attr->rx_psn = cmd_attr->rx_psn; + attr->mtu = cmd_attr->mtu; + attr->cc_pattern_idx = cmd_attr->cc_pattern_idx; + attr->oos_cnt = cmd_attr->oos_cnt; + attr->local_net_addr_idx = cmd_attr->local_net_addr_idx; + uburma_fill_peer_net_addr(&cmd_attr->peer_net_addr, &attr->peer_net_addr); + attr->data_udp_start = cmd_attr->data_udp_start; + attr->ack_udp_start = cmd_attr->ack_udp_start; + attr->udp_range = cmd_attr->udp_range; + attr->hop_limit = cmd_attr->hop_limit; + attr->flow_label = cmd_attr->flow_label; + attr->port_id = cmd_attr->port_id; + attr->mn = cmd_attr->mn; + attr->peer_trans_type = cmd_attr->peer_trans_type; +} + +/* Attention: cmd_mask is different with mask, so we cannot fill by value */ +static void uburma_fill_tp_attr_mask(union uburma_cmd_tp_attr_mask *cmd_mask, + union ubcore_tp_attr_mask *mask) +{ + mask->bs.flag = cmd_mask->bs.flag; + mask->bs.peer_tpn = cmd_mask->bs.peer_tpn; + mask->bs.state = cmd_mask->bs.state; + mask->bs.tx_psn = cmd_mask->bs.tx_psn; + mask->bs.rx_psn = cmd_mask->bs.rx_psn; + mask->bs.mtu = cmd_mask->bs.mtu; + mask->bs.cc_pattern_idx = cmd_mask->bs.cc_pattern_idx; + mask->bs.oos_cnt = cmd_mask->bs.oos_cnt; + mask->bs.local_net_addr_idx = cmd_mask->bs.local_net_addr_idx; + mask->bs.peer_net_addr = cmd_mask->bs.peer_net_addr; + mask->bs.data_udp_start = cmd_mask->bs.data_udp_start; + mask->bs.ack_udp_start = cmd_mask->bs.ack_udp_start; + mask->bs.udp_range = cmd_mask->bs.udp_range; + mask->bs.hop_limit = cmd_mask->bs.hop_limit; + mask->bs.flow_label = cmd_mask->bs.flow_label; + mask->bs.port_id = cmd_mask->bs.port_id; + mask->bs.mn = cmd_mask->bs.mn; + mask->bs.peer_trans_type = cmd_mask->bs.peer_trans_type; +} + +static int uburma_modify_user_tp(struct ubcore_device *ubc_dev, + struct uburma_cmd_modify_tp *args) +{ + union ubcore_tp_attr_mask mask = {0}; + struct ubcore_tp_cfg tp_cfg = {0}; + struct ubcore_tp_attr attr = {0}; + int ret; + + if (ubc_dev == NULL || ubc_dev->ops == NULL || ubc_dev->ops->modify_user_tp == NULL) { + uburma_log_err("Invalid parameter.\n"); + return -1; + } + + uburma_fill_tp_cfg(&args->in.tp_cfg, &tp_cfg); + uburma_fill_tp_attr(&args->in.attr, &attr); + uburma_fill_tp_attr_mask(&args->in.mask, &mask); + + ret = ubc_dev->ops->modify_user_tp(ubc_dev, args->in.tpn, &tp_cfg, &attr, mask); + if (ret != 0) + uburma_log_err("Failed to modify user tp, ret: %d.\n", ret); + + return ret; +} + static int uburma_cmd_modify_tp(struct ubcore_device *ubc_dev, struct uburma_file *file, struct uburma_cmd_hdr *hdr) { - return 0; + struct uburma_cmd_modify_tp *args; + int ret; + + args = kcalloc(1, sizeof(struct uburma_cmd_modify_tp), GFP_KERNEL); + if (args == NULL) + return -ENOMEM; + + ret = uburma_copy_from_user(args, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct uburma_cmd_modify_tp)); + if (ret != 0) + goto out; + + ret = uburma_modify_user_tp(ubc_dev, args); + if (ret != 0) + uburma_log_err("Failed to modify user tp, tpn: %u.\n", args->in.tpn); +out: + kfree(args); + return ret; } typedef int (*uburma_cmd_handler)(struct ubcore_device *ubc_dev, diff --git a/drivers/ub/urma/uburma/uburma_cmd.h b/drivers/ub/urma/uburma/uburma_cmd.h index 7b5fc331c64f..77eb1df46eaa 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.h +++ b/drivers/ub/urma/uburma/uburma_cmd.h @@ -20,8 +20,12 @@ #ifndef UBURMA_CMD_H #define UBURMA_CMD_H + +#include +#include #include #include +#include #include "urma/ubcore_types.h" #include "uburma_types.h" @@ -579,6 +583,17 @@ struct uburma_cmd_user_tp_cfg { uint32_t oor_cnt; /* OOR window size: by packet */ }; +struct uburma_cmd_net_addr { + sa_family_t sin_family; /* AF_INET/AF_INET6 */ + union { + struct in_addr in4; + struct in6_addr in6; + }; + uint64_t vlan; + uint8_t mac[UBCORE_MAC_BYTES]; + uint32_t prefix_len; +}; + struct uburma_cmd_tp_attr { union ubcore_tp_mod_flag flag; /* consistend with urma_tp_mod_flag */ uint32_t peer_tpn; @@ -589,7 +604,7 @@ struct uburma_cmd_tp_attr { uint8_t cc_pattern_idx; uint32_t oos_cnt; /* out of standing packet cnt */ uint32_t local_net_addr_idx; - struct ubcore_net_addr peer_net_addr; + struct uburma_cmd_net_addr peer_net_addr; uint16_t data_udp_start; uint16_t ack_udp_start; uint8_t udp_range; @@ -620,7 +635,7 @@ union uburma_cmd_tp_attr_mask { uint32_t port_id : 1; uint32_t mn : 1; uint32_t peer_trans_type : 1; /* Only for user tp connection */ - uint32_t reserved : 13; + uint32_t reserved : 14; } bs; uint32_t value; }; @@ -636,7 +651,8 @@ struct uburma_cmd_get_net_addr_list { } in; struct { uint32_t netaddr_cnt; - struct uburma_cmd_net_addr_info netaddr_info[UBCORE_MAX_SIP]; + uint64_t addr; /* containing array of struct uburma_cmd_net_addr_info */ + uint64_t len; } out; }; diff --git a/include/urma/ubcore_types.h b/include/urma/ubcore_types.h index 9bab210d7fdb..67a82acd838f 100644 --- a/include/urma/ubcore_types.h +++ b/include/urma/ubcore_types.h @@ -61,6 +61,8 @@ #define UBCORE_MAX_VTP_CNT_PER_TPF (128 * 1024) // Temporarily specify the upper limit #define UBCORE_EID_GROUP_NAME_LEN 10 #define UBCORE_MAX_MIG_ENTRY_CNT 64 +#define UBCORE_RESERVED_JETTY_ID_MIN 0 +#define UBCORE_RESERVED_JETTY_ID_MAX 1023 #define EID_FMT \ "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x" @@ -625,6 +627,8 @@ struct ubcore_device_attr { struct ubcore_guid guid; uint16_t fe_idx; struct ubcore_device_cap dev_cap; + uint32_t reserved_jetty_id_min; + uint32_t reserved_jetty_id_max; struct ubcore_port_attr port_attr[UBCORE_MAX_PORT_CNT]; uint8_t port_cnt; bool virtualization; /* In VM or not, must set by driver when register device */ @@ -645,7 +649,9 @@ union ubcore_device_cfg_mask { uint32_t max_jetty_cnt : 1; uint32_t min_jfr_cnt : 1; uint32_t max_jfr_cnt : 1; - uint32_t reserved : 21; + uint32_t reserved_jetty_id_min : 1; + uint32_t reserved_jetty_id_max : 1; + uint32_t reserved : 19; } bs; uint32_t value; }; @@ -672,6 +678,8 @@ struct ubcore_device_cfg { uint32_t max_jetty_cnt; uint32_t min_jfr_cnt; uint32_t max_jfr_cnt; + uint32_t reserved_jetty_id_min; + uint32_t reserved_jetty_id_max; }; /* struct [struct ubcore_user_ctl_in] should be consistent with [urma_user_ctl_in_t] */ -- Gitee From fd9560ca13e3ac43e8fc298ebcc2d03afb30cc50 Mon Sep 17 00:00:00 2001 From: Jie Lei Date: Mon, 20 May 2024 17:08:25 +0800 Subject: [PATCH 6/6] hns3 udma: support user-mode TP connection API driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8V1IQ CVE: NA -------------------------------------------------------- This patch supports the user-mode TP connection function in RC mode. 1.In the Jetty creation phase, the TP is created based on the sub_trans_mode of user. 2.The urma_get_tpn API is supported. 3.The urma_modify_tp API is supported. Fixes: 4888db6edae7 ("hns3 udma: support create and destroy JETTY") Signed-off-by: ChunZhi Hu Signed-off-by: Weibo Zhao Signed-off-by: Jie Lei --- drivers/ub/hw/hns3/hns3_udma_common.h | 11 ++ drivers/ub/hw/hns3/hns3_udma_dca.c | 1 + drivers/ub/hw/hns3/hns3_udma_dca.h | 6 -- drivers/ub/hw/hns3/hns3_udma_device.h | 5 - drivers/ub/hw/hns3/hns3_udma_eid.h | 7 ++ drivers/ub/hw/hns3/hns3_udma_jetty.c | 141 +++++++++++++++---------- drivers/ub/hw/hns3/hns3_udma_jetty.h | 4 + drivers/ub/hw/hns3/hns3_udma_main.c | 3 +- drivers/ub/hw/hns3/hns3_udma_qp.c | 45 +------- drivers/ub/hw/hns3/hns3_udma_qp.h | 1 + drivers/ub/hw/hns3/hns3_udma_tp.c | 73 +++++++++++++ drivers/ub/hw/hns3/hns3_udma_tp.h | 8 ++ drivers/ub/urma/ubcore/ubcore_device.c | 6 +- 13 files changed, 198 insertions(+), 113 deletions(-) diff --git a/drivers/ub/hw/hns3/hns3_udma_common.h b/drivers/ub/hw/hns3/hns3_udma_common.h index 64fe7a0f6c0a..8e3845f294a4 100644 --- a/drivers/ub/hw/hns3/hns3_udma_common.h +++ b/drivers/ub/hw/hns3/hns3_udma_common.h @@ -25,6 +25,17 @@ #define DMA_WQE_SHIFT 3 #define DMA_DB_RECORD_SHIFT 1 +/* The minimum page size is 4K for hardware */ +#define UDMA_HW_PAGE_SHIFT 12 +#define UDMA_PAGE_SIZE (1 << UDMA_HW_PAGE_SHIFT) +#define UDMA_HW_PAGE_ALIGN(x) ALIGN(x, 1 << UDMA_HW_PAGE_SHIFT) + +static inline uint64_t umem_cal_npages(uint64_t va, uint64_t len) +{ + return (ALIGN(va + len, UDMA_PAGE_SIZE) - ALIGN_DOWN(va, UDMA_PAGE_SIZE)) / + UDMA_PAGE_SIZE; +} + #define udma_get_field(origin, mask, shift) \ ((le32_to_cpu(origin) & (mask)) >> (uint32_t)(shift)) #define udma_get_field64(origin, mask, shift) \ diff --git a/drivers/ub/hw/hns3/hns3_udma_dca.c b/drivers/ub/hw/hns3/hns3_udma_dca.c index b4afd0790083..cbc0db25f089 100644 --- a/drivers/ub/hw/hns3/hns3_udma_dca.c +++ b/drivers/ub/hw/hns3/hns3_udma_dca.c @@ -15,6 +15,7 @@ #include #include "urma/ubcore_api.h" +#include "hns3_udma_common.h" #include "hns3_udma_cmd.h" #include "hns3_udma_debugfs.h" #include "hns3_udma_dca.h" diff --git a/drivers/ub/hw/hns3/hns3_udma_dca.h b/drivers/ub/hw/hns3/hns3_udma_dca.h index ec88bc7b18ae..a23f1978a58f 100644 --- a/drivers/ub/hw/hns3/hns3_udma_dca.h +++ b/drivers/ub/hw/hns3/hns3_udma_dca.h @@ -116,12 +116,6 @@ struct dca_mem_enum_attr { udma_dca_enum_callback enum_fn; }; -static inline uint64_t umem_cal_npages(uint64_t va, uint64_t len) -{ - return (ALIGN(va + len, UDMA_PAGE_SIZE) - ALIGN_DOWN(va, UDMA_PAGE_SIZE)) / - UDMA_PAGE_SIZE; -} - static inline bool dca_page_is_attached(struct dca_page_state *state, uint32_t buf_id) { diff --git a/drivers/ub/hw/hns3/hns3_udma_device.h b/drivers/ub/hw/hns3/hns3_udma_device.h index 8f55e25341ac..190cf60408e9 100644 --- a/drivers/ub/hw/hns3/hns3_udma_device.h +++ b/drivers/ub/hw/hns3/hns3_udma_device.h @@ -58,11 +58,6 @@ #define UDMA_SGE_SIZE 16 #define UDMA_IDX_QUE_ENTRY_SZ 4 -/* The minimum page size is 4K for hardware */ -#define UDMA_HW_PAGE_SHIFT 12 -#define UDMA_PAGE_SIZE (1 << UDMA_HW_PAGE_SHIFT) -#define UDMA_HW_PAGE_ALIGN(x) ALIGN(x, 1 << UDMA_HW_PAGE_SHIFT) - #define UDMA_DWQE_SIZE 65536 #define UDMA_DWQE_MMAP_QP_NUM 1024 diff --git a/drivers/ub/hw/hns3/hns3_udma_eid.h b/drivers/ub/hw/hns3/hns3_udma_eid.h index 60fb5f4f70a3..2582aa3d5859 100644 --- a/drivers/ub/hw/hns3/hns3_udma_eid.h +++ b/drivers/ub/hw/hns3/hns3_udma_eid.h @@ -70,4 +70,11 @@ static inline enum udma_sgid_type get_sgid_type_from_eid(union ubcore_eid eid) return SGID_TYPE_IPV6; } +static inline void udma_ipv4_map_to_eid(uint32_t ipv4, union ubcore_eid *eid) +{ + eid->in4.reserved = 0; + eid->in4.prefix = cpu_to_be32(UDMA_IPV4_MAP_IPV6_PREFIX); + eid->in4.addr = ipv4; +} + #endif /* _UDMA_EID_H */ diff --git a/drivers/ub/hw/hns3/hns3_udma_jetty.c b/drivers/ub/hw/hns3/hns3_udma_jetty.c index 1cf3d454389c..d4cb461abb9d 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jetty.c +++ b/drivers/ub/hw/hns3/hns3_udma_jetty.c @@ -31,13 +31,12 @@ static void init_jetty_cfg(struct udma_jetty *jetty, jetty->send_jfc = to_udma_jfc(cfg->send_jfc); } -static void udma_fill_jetty_um_qp_attr(struct udma_dev *dev, - struct udma_jetty *jetty, - struct ubcore_ucontext *uctx, - struct ubcore_jetty_cfg *cfg) +void udma_fill_jetty_qp_attr(struct udma_dev *dev, struct udma_qp_attr *qp_attr, + struct udma_jetty *jetty, + struct ubcore_ucontext *uctx, + struct ubcore_jetty_cfg *cfg) { struct udma_ucontext *udma_ctx = to_udma_ucontext(uctx); - struct udma_qp_attr *qp_attr = &jetty->qp.qp_attr; qp_attr->is_tgt = false; qp_attr->is_jetty = true; @@ -49,11 +48,14 @@ static void udma_fill_jetty_um_qp_attr(struct udma_dev *dev, qp_attr->cap.max_send_sge = cfg->max_send_sge; qp_attr->cap.max_inline_data = cfg->max_inline_data; qp_attr->cap.rnr_retry = cfg->rnr_retry; + qp_attr->cap.min_rnr_timer = jetty->udma_jfr->ubcore_jfr.jfr_cfg.min_rnr_timer; qp_attr->cap.ack_timeout = cfg->err_timeout; - qp_attr->qp_type = QPT_UD; + qp_attr->qp_type = (cfg->trans_mode == UBCORE_TP_UM ? QPT_UD : QPT_RC); + qp_attr->tp_mode = jetty->tp_mode; qp_attr->jfr = jetty->udma_jfr; qp_attr->qpn_map = &jetty->qpn_map; qp_attr->recv_jfc = to_udma_jfc(cfg->recv_jfc); + qp_attr->local_eid = jetty->ubcore_jetty.jetty_id.eid; qp_attr->eid_index = udma_ctx->eid_index; if (jetty->ubcore_jetty.jetty_cfg.priority >= dev->caps.sl_num) { qp_attr->priority = @@ -65,6 +67,12 @@ static void udma_fill_jetty_um_qp_attr(struct udma_dev *dev, } else { qp_attr->priority = jetty->ubcore_jetty.jetty_cfg.priority; } + + if (is_rc_jetty(qp_attr) && !qp_attr->jetty->shared_jfr && + !qp_attr->jetty->dca_en) { + qp_attr->cap.max_recv_wr = jetty->udma_jfr->ubcore_jfr.jfr_cfg.depth; + qp_attr->cap.max_recv_sge = jetty->udma_jfr->ubcore_jfr.jfr_cfg.max_sge; + } } static int udma_modify_qp_jetty(struct udma_dev *dev, struct udma_jetty *jetty, @@ -117,7 +125,7 @@ static int alloc_jetty_um_qp(struct udma_dev *dev, struct udma_jetty *jetty, { int ret; - udma_fill_jetty_um_qp_attr(dev, jetty, udata->uctx, cfg); + udma_fill_jetty_qp_attr(dev, &jetty->qp.qp_attr, jetty, udata->uctx, cfg); ret = udma_create_qp_common(dev, &jetty->qp, udata); if (ret) { @@ -216,13 +224,69 @@ static int set_jetty_buf_attr(struct udma_dev *udma_dev, return 0; } +static int alloc_rc_jetty_buf(struct udma_dev *dev, struct udma_jetty *jetty, + struct hns3_udma_create_jetty_ucmd *ucmd, + struct ubcore_udata *udata) +{ + struct udma_ucontext *udma_uctx = to_udma_ucontext(udata->uctx); + struct udma_buf_attr buf_attr = {}; + int ret; + + ret = udma_db_map_user(udma_uctx, ucmd->sdb_addr, &jetty->rc_node.sdb); + if (ret) { + dev_err(dev->dev, + "failed to map user sdb_addr, ret = %d.\n", ret); + return ret; + } + + jetty->rc_node.buf_addr = ucmd->buf_addr; + jetty->rc_node.context = to_udma_ucontext(udata->uctx); + if (!ucmd->buf_addr) { + jetty->dca_en = true; + return 0; + } + + ret = set_jetty_buf_attr(dev, jetty, &buf_attr); + if (ret) { + dev_err(dev->dev, + "failed to set jetty buf attr, ret = %d.\n", ret); + udma_db_unmap_user(udma_uctx, &jetty->rc_node.sdb); + return ret; + } + + if (!jetty->shared_jfr) { + jetty->rc_node.mtr = jetty->udma_jfr->buf_mtr; + return 0; + } + + ret = udma_mtr_create(dev, &jetty->rc_node.mtr, &buf_attr, + PAGE_SHIFT + dev->caps.mtt_ba_pg_sz, + ucmd->buf_addr, !!udata); + if (ret) { + dev_err(dev->dev, + "failed to create WQE mtr for RC Jetty, ret = %d.\n", + ret); + udma_db_unmap_user(udma_uctx, &jetty->rc_node.sdb); + } + + return ret; +} + +static void free_rc_jetty_buf(struct udma_dev *dev, + struct udma_ucontext *udma_uctx, + struct udma_jetty *jetty) +{ + if (jetty->shared_jfr && !jetty->dca_en) + udma_mtr_destroy(dev, &jetty->rc_node.mtr); + udma_db_unmap_user(udma_uctx, &jetty->rc_node.sdb); +} + static int alloc_jetty_buf(struct udma_dev *dev, struct udma_jetty *jetty, struct ubcore_jetty_cfg *cfg, struct hns3_udma_create_jetty_ucmd *ucmd, struct ubcore_udata *udata) { struct udma_ucontext *udma_uctx = to_udma_ucontext(udata->uctx); - struct udma_buf_attr buf_attr = {}; int ret; ret = set_jetty_jfr(dev, jetty, cfg, ucmd->srqn); @@ -231,51 +295,22 @@ static int alloc_jetty_buf(struct udma_dev *dev, struct udma_jetty *jetty, if (cfg->trans_mode == UBCORE_TP_UM) { ret = alloc_jetty_um_qp(dev, jetty, cfg, udata); - if (ret) - return ret; } else { - ret = udma_db_map_user(udma_uctx, ucmd->sdb_addr, - &jetty->rc_node.sdb); - if (ret) { - dev_err(dev->dev, - "failed to map user sdb_addr, ret = %d.\n", - ret); - return ret; - } - - jetty->rc_node.buf_addr = ucmd->buf_addr; - jetty->rc_node.context = to_udma_ucontext(udata->uctx); - if (!ucmd->buf_addr) { - jetty->dca_en = true; - return 0; - } - - ret = set_jetty_buf_attr(dev, jetty, &buf_attr); - if (ret) { - dev_err(dev->dev, - "failed to set jetty buf attr, ret = %d.\n", - ret); - return ret; - } - - if (!jetty->shared_jfr) { - jetty->rc_node.mtr = jetty->udma_jfr->buf_mtr; - return 0; - } - - ret = udma_mtr_create(dev, &jetty->rc_node.mtr, &buf_attr, - PAGE_SHIFT + dev->caps.mtt_ba_pg_sz, - ucmd->buf_addr, !!udata); - if (ret) { - dev_err(dev->dev, - "failed to create WQE mtr for RC Jetty, ret = %d.\n", - ret); - udma_db_unmap_user(udma_uctx, &jetty->rc_node.sdb); + ret = alloc_rc_jetty_buf(dev, jetty, ucmd, udata); + if (ret) return ret; + if (cfg->flag.bs.sub_trans_mode == UBCORE_SUB_TRANS_MODE_USER_TP) { + jetty->rc_node.tp = udma_create_user_tp(dev, jetty, cfg, udata); + if (!jetty->rc_node.tp) { + free_rc_jetty_buf(dev, udma_uctx, jetty); + ret = -EINVAL; + } else { + jetty->rc_node.tpn = jetty->jetty_id; + } } } - return 0; + return ret; } static int alloc_common_jetty_id(struct udma_dev *udma_dev, struct udma_jetty *jetty, @@ -465,10 +500,11 @@ static int free_jetty_buf(struct udma_dev *dev, struct udma_jetty *jetty) jetty->qp.qpn); udma_destroy_qp_common(dev, &jetty->qp, NULL); - } else if (jetty->tp_mode == UBCORE_TP_RC && !jetty->dca_en) { - udma_db_unmap_user(udma_uctx, &jetty->rc_node.sdb); - if (jetty->shared_jfr) - udma_mtr_destroy(dev, &jetty->rc_node.mtr); + } else if (jetty->tp_mode == UBCORE_TP_RC) { + if (jetty->ubcore_jetty.jetty_cfg.flag.bs.sub_trans_mode == + UBCORE_SUB_TRANS_MODE_USER_TP) + udma_destroy_tp(&jetty->rc_node.tp->ubcore_tp); + free_rc_jetty_buf(dev, udma_uctx, jetty); } return ret; @@ -482,7 +518,6 @@ int udma_destroy_jetty(struct ubcore_jetty *jetty) udma_jetty = to_udma_jetty(jetty); udma_dev = to_udma_dev(jetty->ub_dev); - ret = free_jetty_buf(udma_dev, udma_jetty); if (dfx_switch) diff --git a/drivers/ub/hw/hns3/hns3_udma_jetty.h b/drivers/ub/hw/hns3/hns3_udma_jetty.h index 97ee4d30f5b7..447df95d35a4 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jetty.h +++ b/drivers/ub/hw/hns3/hns3_udma_jetty.h @@ -55,6 +55,10 @@ static inline struct udma_jetty *to_udma_jetty(struct ubcore_jetty *ubcore_jetty return container_of(ubcore_jetty, struct udma_jetty, ubcore_jetty); } +void udma_fill_jetty_qp_attr(struct udma_dev *dev, struct udma_qp_attr *qp_attr, + struct udma_jetty *jetty, + struct ubcore_ucontext *uctx, + struct ubcore_jetty_cfg *cfg); struct ubcore_jetty *udma_create_jetty(struct ubcore_device *dev, struct ubcore_jetty_cfg *cfg, struct ubcore_udata *udata); diff --git a/drivers/ub/hw/hns3/hns3_udma_main.c b/drivers/ub/hw/hns3/hns3_udma_main.c index 5cf864eee70d..1a6ba284e236 100644 --- a/drivers/ub/hw/hns3/hns3_udma_main.c +++ b/drivers/ub/hw/hns3/hns3_udma_main.c @@ -540,6 +540,7 @@ static struct ubcore_ops g_udma_dev_ops = { .unimport_jetty = udma_unimport_jetty, .create_tp = udma_create_tp, .modify_tp = udma_modify_tp, + .modify_user_tp = udma_modify_user_tp, .destroy_tp = udma_destroy_tp, .send_req = udma_send_req, .send_resp = udma_send_resp, @@ -1012,7 +1013,7 @@ static int udma_register_device(struct udma_dev *udma_dev) ub_dev = &udma_dev->ub_dev; uboe = &udma_dev->uboe; spin_lock_init(&uboe->lock); - ub_dev->transport_type = UBCORE_TRANSPORT_IB; + ub_dev->transport_type = UBCORE_TRANSPORT_HNS_UB; ub_dev->ops = &g_udma_dev_ops; ub_dev->dev.parent = udma_dev->dev; ub_dev->dma_dev = ub_dev->dev.parent; diff --git a/drivers/ub/hw/hns3/hns3_udma_qp.c b/drivers/ub/hw/hns3/hns3_udma_qp.c index 213d74f164bd..3329e603fcf8 100644 --- a/drivers/ub/hw/hns3/hns3_udma_qp.c +++ b/drivers/ub/hw/hns3/hns3_udma_qp.c @@ -38,7 +38,7 @@ static inline uint8_t get_qp_bankid(uint64_t qpn) return (uint8_t)(qpn & QP_BANKID_MASK); } -static bool is_rc_jetty(struct udma_qp_attr *qp_attr) +bool is_rc_jetty(struct udma_qp_attr *qp_attr) { if (qp_attr->is_jetty && qp_attr->jetty && qp_attr->tp_mode == UBCORE_TP_RC) @@ -1755,29 +1755,9 @@ void copy_send_jfc(struct udma_qp *from_qp, struct udma_qp *to_qp) udma_unlock_cqs(to_qp->qp_attr.send_jfc, NULL); } -static void add_qp_to_list(struct udma_dev *udma_dev, struct udma_qp *qp, - struct udma_jfc *send_jfc, struct udma_jfc *recv_jfc) -{ - unsigned long flags; - - spin_lock_irqsave(&udma_dev->qp_list_lock, flags); - udma_lock_cqs(send_jfc, recv_jfc); - - list_add_tail(&qp->node, &udma_dev->qp_list); - - if (send_jfc) - list_add_tail(&qp->sq_node, &send_jfc->sq_list); - if (recv_jfc) - list_add_tail(&qp->rq_node, &recv_jfc->rq_list); - - udma_unlock_cqs(send_jfc, recv_jfc); - spin_unlock_irqrestore(&udma_dev->qp_list_lock, flags); -} - static int udma_qp_store(struct udma_dev *udma_dev, struct udma_qp *qp) { - struct udma_qp_attr *qp_attr = &qp->qp_attr; struct xarray *xa = &udma_dev->qp_table.xa; struct udma_qp *temp_qp; unsigned long flags; @@ -1790,10 +1770,6 @@ static int udma_qp_store(struct udma_dev *udma_dev, xa_unlock_irqrestore(xa, flags); if (ret) dev_err(udma_dev->dev, "Failed to xa store for QPC\n"); - else - /* add QP to device's QP list for softwc */ - add_qp_to_list(udma_dev, qp, qp_attr->send_jfc, - qp_attr->recv_jfc); return ret; } @@ -1801,32 +1777,13 @@ static int udma_qp_store(struct udma_dev *udma_dev, static void udma_qp_remove(struct udma_dev *udma_dev, struct udma_qp *qp, struct ubcore_tp *fail_ret_tp) { - struct udma_qp_attr *qp_attr = &qp->qp_attr; struct xarray *xa = &udma_dev->qp_table.xa; - struct udma_jfc *send_jfc; - struct udma_jfc *recv_jfc; unsigned long flags; - send_jfc = qp_attr->send_jfc; - recv_jfc = qp_attr->recv_jfc; - xa_lock_irqsave(xa, flags); if (!fail_ret_tp) __xa_erase(xa, qp->qpn); xa_unlock_irqrestore(xa, flags); - - spin_lock_irqsave(&udma_dev->qp_list_lock, flags); - udma_lock_cqs(send_jfc, recv_jfc); - - list_del(&qp->node); - - if (send_jfc) - list_del(&qp->sq_node); - if (recv_jfc) - list_del(&qp->rq_node); - - udma_unlock_cqs(send_jfc, recv_jfc); - spin_unlock_irqrestore(&udma_dev->qp_list_lock, flags); } static void free_qpc(struct udma_dev *udma_dev, struct udma_qp *qp) diff --git a/drivers/ub/hw/hns3/hns3_udma_qp.h b/drivers/ub/hw/hns3/hns3_udma_qp.h index 7939d31e2ddd..85ff503cfc51 100644 --- a/drivers/ub/hw/hns3/hns3_udma_qp.h +++ b/drivers/ub/hw/hns3/hns3_udma_qp.h @@ -359,6 +359,7 @@ enum { #define gen_qpn(high, mid, low) ((high) | (mid) | (low)) +bool is_rc_jetty(struct udma_qp_attr *qp_attr); int udma_modify_qp_common(struct udma_qp *qp, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask ubcore_mask, diff --git a/drivers/ub/hw/hns3/hns3_udma_tp.c b/drivers/ub/hw/hns3/hns3_udma_tp.c index 02f77d6b0a5d..e3d9ffd37a6e 100644 --- a/drivers/ub/hw/hns3/hns3_udma_tp.c +++ b/drivers/ub/hw/hns3/hns3_udma_tp.c @@ -22,6 +22,7 @@ #include "hns3_udma_hem.h" #include "hns3_udma_dca.h" #include "hns3_udma_dfx.h" +#include "hns3_udma_eid.h" #include "hns3_udma_tp.h" struct udma_qp *get_qp(struct udma_dev *udma_device, uint32_t qpn) @@ -468,3 +469,75 @@ struct ubcore_tp *udma_create_tp(struct ubcore_device *dev, struct ubcore_tp_cfg return fail_ret_tp; } + +struct udma_tp *udma_create_user_tp(struct udma_dev *udma_dev, + struct udma_jetty *jetty, + struct ubcore_jetty_cfg *cfg, + struct ubcore_udata *udata) +{ + struct udma_tp *tp; + int ret; + + tp = kzalloc(sizeof(*tp), GFP_KERNEL); + if (!tp) + return ERR_PTR(-ENOMEM); + + udma_fill_jetty_qp_attr(udma_dev, &tp->qp.qp_attr, jetty, udata->uctx, cfg); + ret = udma_create_qp_common(udma_dev, &tp->qp, udata); + if (ret) { + dev_err(udma_dev->dev, + "Failed to create qp common, ret is %d.\n", ret); + goto failed_create_qp; + } + + tp->ubcore_tp.tpn = tp->qp.qpn; + tp->ubcore_tp.ub_dev = &udma_dev->ub_dev; + ret = udma_init_qpc(udma_dev, &tp->qp); + if (ret) + goto failed_init_qpc; + + if (dfx_switch) + store_tpn(udma_dev, tp); + + return tp; + +failed_init_qpc: + udma_destroy_qp_common(udma_dev, &tp->qp, NULL); +failed_create_qp: + kfree(tp); + + return NULL; +} + +int udma_modify_user_tp(struct ubcore_device *dev, uint32_t tpn, + struct ubcore_tp_cfg *cfg, + struct ubcore_tp_attr *attr, + union ubcore_tp_attr_mask mask) +{ + struct udma_dev *udma_dev = to_udma_dev(dev); + unsigned long flags; + struct udma_tp *tp; + struct udma_qp *qp; + int ret; + + xa_lock_irqsave(&udma_dev->qp_table.xa, flags); + qp = (struct udma_qp *)xa_load(&udma_dev->qp_table.xa, tpn); + if (qp) + refcount_inc(&qp->refcount); + xa_unlock_irqrestore(&udma_dev->qp_table.xa, flags); + + if (!qp) + return -EINVAL; + tp = container_of(qp, struct udma_tp, qp); + udma_set_tp(dev, cfg, tp); + udma_ipv4_map_to_eid(attr->peer_net_addr.net_addr.in4.addr, + &tp->ubcore_tp.peer_eid); + ret = udma_modify_tp(&tp->ubcore_tp, attr, mask); + if (ret) + dev_err(&dev->dev, "modify user tp failed, ret = %d.\n", ret); + + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); + + return ret; +} diff --git a/drivers/ub/hw/hns3/hns3_udma_tp.h b/drivers/ub/hw/hns3/hns3_udma_tp.h index 77e490eaf3f9..d4f5a10bf88a 100644 --- a/drivers/ub/hw/hns3/hns3_udma_tp.h +++ b/drivers/ub/hw/hns3/hns3_udma_tp.h @@ -42,5 +42,13 @@ int udma_destroy_tp(struct ubcore_tp *tp); int udma_modify_tp(struct ubcore_tp *tp, struct ubcore_tp_attr *attr, union ubcore_tp_attr_mask mask); struct udma_qp *get_qp(struct udma_dev *udma_device, uint32_t qpn); +struct udma_tp *udma_create_user_tp(struct udma_dev *udma_dev, + struct udma_jetty *jetty, + struct ubcore_jetty_cfg *cfg, + struct ubcore_udata *udata); +int udma_modify_user_tp(struct ubcore_device *dev, uint32_t tpn, + struct ubcore_tp_cfg *cfg, + struct ubcore_tp_attr *attr, + union ubcore_tp_attr_mask mask); #endif /* _UDMA_TP_H */ diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index 2b8b8a0779f9..3309d660ca3c 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -1884,8 +1884,7 @@ int ubcore_add_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore_ue ret = dev->ops->add_ueid(dev, fe_idx, cfg); if (ret != 0) - ubcore_log_err("failed to add ueid, ret:%d\n", - fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); + ubcore_log_err("failed to add ueid, ret:%d\n", ret); return ret; } @@ -1906,8 +1905,7 @@ int ubcore_delete_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore ret = dev->ops->delete_ueid(dev, fe_idx, cfg); if (ret != 0) - ubcore_log_err("failed to add ueid, ret:%d\n", - fe_idx, EID_ARGS(cfg->eid), cfg->upi, cfg->eid_index, ret); + ubcore_log_err("failed to add ueid, ret:%d\n", ret); return ret; } -- Gitee