From 329bf7f331286ee5d571d374e31ed50d2877b110 Mon Sep 17 00:00:00 2001 From: WenChen Date: Tue, 20 Feb 2024 17:26:37 +0800 Subject: [PATCH] ubcore: fix the bug of tp negotiation concurrency driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I91DSN CVE: NA -------------------------------- Upload kernel patch, detailed fixes are as follows: 1. Fixed reset scenario accessing released jfe resources 2. Fixed driver deletion TP and netty concurrency exception 3. Fixed hang-up problem in reset scenario 4. Fixed concurrent advise/bind jetty exception issue Signed-off-by: WenChen --- drivers/ub/urma/ubcore/Makefile | 3 +- drivers/ub/urma/ubcore/ubcore_cgroup.c | 97 ++++ drivers/ub/urma/ubcore/ubcore_cmd.h | 5 +- drivers/ub/urma/ubcore/ubcore_device.c | 181 +++++- drivers/ub/urma/ubcore/ubcore_hash_table.c | 7 +- drivers/ub/urma/ubcore/ubcore_jetty.c | 54 +- drivers/ub/urma/ubcore/ubcore_main.c | 613 ++++++++++----------- drivers/ub/urma/ubcore/ubcore_msg.c | 49 +- drivers/ub/urma/ubcore/ubcore_msg.h | 6 +- drivers/ub/urma/ubcore/ubcore_netdev.c | 110 +++- drivers/ub/urma/ubcore/ubcore_netdev.h | 8 +- drivers/ub/urma/ubcore/ubcore_netlink.c | 24 +- drivers/ub/urma/ubcore/ubcore_netlink.h | 26 +- drivers/ub/urma/ubcore/ubcore_priv.h | 10 +- drivers/ub/urma/ubcore/ubcore_tp.c | 474 +++++++++------- drivers/ub/urma/ubcore/ubcore_tp.h | 1 + drivers/ub/urma/ubcore/ubcore_tp_table.c | 20 +- drivers/ub/urma/ubcore/ubcore_tp_table.h | 3 +- drivers/ub/urma/ubcore/ubcore_umem.c | 2 + drivers/ub/urma/ubcore/ubcore_uvs_cmd.c | 428 ++++++++++---- drivers/ub/urma/ubcore/ubcore_uvs_cmd.h | 45 +- drivers/ub/urma/ubcore/ubcore_vtp.c | 14 +- drivers/ub/urma/ubcore/ubcore_vtp.h | 5 +- drivers/ub/urma/uburma/Makefile | 3 +- drivers/ub/urma/uburma/uburma_cdev_file.c | 16 +- drivers/ub/urma/uburma/uburma_cmd.c | 7 + drivers/ub/urma/uburma/uburma_dev_ops.c | 9 +- drivers/ub/urma/uburma/uburma_event.c | 17 +- drivers/ub/urma/uburma/uburma_main.c | 144 +++++ drivers/ub/urma/uburma/uburma_main.h | 29 + drivers/ub/urma/uburma/uburma_netlink.c | 133 +++++ drivers/ub/urma/uburma/uburma_netlink.h | 48 ++ drivers/ub/urma/uburma/uburma_uobj.c | 90 ++- drivers/ub/urma/uburma/uburma_uobj.h | 16 +- include/urma/ubcore_api.h | 10 +- include/urma/ubcore_types.h | 49 +- include/urma/ubcore_uapi.h | 47 +- 37 files changed, 2016 insertions(+), 787 deletions(-) create mode 100644 drivers/ub/urma/ubcore/ubcore_cgroup.c create mode 100644 drivers/ub/urma/uburma/uburma_main.h create mode 100644 drivers/ub/urma/uburma/uburma_netlink.c create mode 100644 drivers/ub/urma/uburma/uburma_netlink.h diff --git a/drivers/ub/urma/ubcore/Makefile b/drivers/ub/urma/ubcore/Makefile index 51ab913357fc..5806ca76cdf2 100644 --- a/drivers/ub/urma/ubcore/Makefile +++ b/drivers/ub/urma/ubcore/Makefile @@ -19,6 +19,7 @@ ubcore-objs := ubcore_main.o \ ubcore_tpg.o \ ubcore_utp.o \ ubcore_uvs_cmd.o \ - ubcore_vtp.o + ubcore_vtp.o \ + ubcore_cgroup.o obj-$(CONFIG_UB) += ubcore.o diff --git a/drivers/ub/urma/ubcore/ubcore_cgroup.c b/drivers/ub/urma/ubcore/ubcore_cgroup.c new file mode 100644 index 000000000000..1963f775cf2c --- /dev/null +++ b/drivers/ub/urma/ubcore/ubcore_cgroup.c @@ -0,0 +1,97 @@ +// 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: ubcore cgroup resource control + * Author: Xu Zhicong + * Create: 2023-12-25 + * Note: + * History: 2023-12-25: create file + */ + +#include "ubcore_log.h" +#include +#include + +#ifdef CONFIG_CGROUP_RDMA +static inline bool ubcore_is_use_cg(struct ubcore_device *dev) +{ + return (dev != NULL && dev->transport_type == UBCORE_TRANSPORT_UB && + dev->cg_device.dev.name != NULL); +} + +void ubcore_cgroup_reg_dev(struct ubcore_device *dev) +{ + dev->cg_device.dev.name = dev->dev_name; + if (!ubcore_is_use_cg(dev)) + return; + + (void)rdmacg_register_device(&dev->cg_device.dev); +} +EXPORT_SYMBOL(ubcore_cgroup_reg_dev); + +void ubcore_cgroup_unreg_dev(struct ubcore_device *dev) +{ + if (!ubcore_is_use_cg(dev)) + return; + + rdmacg_unregister_device(&dev->cg_device.dev); +} +EXPORT_SYMBOL(ubcore_cgroup_unreg_dev); + +static enum rdmacg_resource_type ubcore_get_rdma_resource_type(enum ubcore_resource_type type) +{ + switch (type) { + case UBCORE_RESOURCE_HCA_HANDLE: + return RDMACG_RESOURCE_HCA_HANDLE; + case UBCORE_RESOURCE_HCA_OBJECT: + return RDMACG_RESOURCE_HCA_OBJECT; + case UBCORE_RESOURCE_HCA_MAX: + default: + ubcore_log_err("not support cgroup resource type:%d", (int)type); + } + + return RDMACG_RESOURCE_MAX; +} + +int ubcore_cgroup_try_charge(struct ubcore_cg_object *cg_obj, struct ubcore_device *dev, + enum ubcore_resource_type type) +{ + enum rdmacg_resource_type rdma_cg_type; + + if (!ubcore_is_use_cg(dev)) + return 0; + + rdma_cg_type = ubcore_get_rdma_resource_type(type); + if (rdma_cg_type == RDMACG_RESOURCE_MAX) + return -EINVAL; + + return rdmacg_try_charge(&cg_obj->cg, &dev->cg_device.dev, rdma_cg_type); +} +EXPORT_SYMBOL(ubcore_cgroup_try_charge); + +void ubcore_cgroup_uncharge(struct ubcore_cg_object *cg_obj, struct ubcore_device *dev, + enum ubcore_resource_type type) +{ + enum rdmacg_resource_type rdma_cg_type; + + if (!ubcore_is_use_cg(dev)) + return; + + rdma_cg_type = ubcore_get_rdma_resource_type(type); + if (rdma_cg_type == RDMACG_RESOURCE_MAX) + return; + + rdmacg_uncharge(cg_obj->cg, &dev->cg_device.dev, rdma_cg_type); +} +EXPORT_SYMBOL(ubcore_cgroup_uncharge); +#endif // CONFIG_CGROUP_RDMA diff --git a/drivers/ub/urma/ubcore/ubcore_cmd.h b/drivers/ub/urma/ubcore/ubcore_cmd.h index 0bba7c0d16ab..31070b0f960f 100644 --- a/drivers/ub/urma/ubcore/ubcore_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_cmd.h @@ -71,10 +71,12 @@ struct ubcore_cmd_query_res { uint32_t key; uint32_t key_ext; uint32_t key_cnt; + bool query_cnt; } in; struct { uint64_t addr; uint32_t len; + uint64_t save_ptr; /* save ubcore address for second ioctl */ } out; }; @@ -89,10 +91,11 @@ struct ubcore_cmd_show_utp { } out; }; -struct ubcore_cmd_updata_ueid { +struct ubcore_cmd_update_ueid { struct { char dev_name[UBCORE_CMD_DEV_MAX]; uint32_t eid_index; + int ns_fd; } in; }; diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index 19a05796db94..84467540e922 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -390,8 +390,7 @@ void ubcore_put_device(struct ubcore_device *dev) complete(&dev->comp); } -struct ubcore_device *ubcore_find_tpf_device(struct ubcore_net_addr *netaddr, - enum ubcore_transport_type type) +struct ubcore_device *ubcore_find_tpf_device_legacy(void) { if (g_tpf == NULL) ubcore_log_err("tpf is not registered yet"); @@ -400,6 +399,51 @@ struct ubcore_device *ubcore_find_tpf_device(struct ubcore_net_addr *netaddr, 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 *dev; + + dev = ubcore_find_device_with_name(dev_name); + if (dev == NULL) { + ubcore_log_err("can not find dev by name:%s", dev_name); + return NULL; + } + + if (dev->attr.tp_maintainer && dev->transport_type == type) + return dev; + + ubcore_put_device(dev); + return ubcore_find_tpf_device_legacy(); +} + +struct ubcore_device *ubcore_find_tpf_device(struct ubcore_net_addr *netaddr, + enum ubcore_transport_type type) +{ + char dev_name[UBCORE_MAX_DEV_NAME] = {0}; + + if (netaddr == NULL) + return ubcore_find_tpf_device_legacy(); + + if (ubcore_lookup_sip_by_addr(netaddr, dev_name) < 0) { + ubcore_log_warn("can not find tpf by net_addr:ip %pI6c", &netaddr->net_addr); + return ubcore_find_tpf_device_legacy(); + } + + return ubcore_find_tpf_device_by_name(dev_name, type); +} + int ubcore_tpf_device_set_global_cfg(struct ubcore_set_global_cfg *cfg) { struct ubcore_device_cfg dev_cfg = {0}; @@ -540,6 +584,51 @@ static void ubcore_destroy_eidtable(struct ubcore_device *dev) } } +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; + + req_msg = kcalloc(1, sizeof(struct ubcore_nlmsg) + + sizeof(struct ubcore_update_tpf_dev_info_req), GFP_KERNEL); + if (req_msg == NULL) + return -ENOMEM; + + req_msg->msg_type = UBCORE_NL_UPDATE_TPF_DEV_INFO_REQ; + req_msg->transport_type = dev->transport_type; + req_msg->payload_len = sizeof(struct ubcore_update_tpf_dev_info_req); + + /* fill msg payload */ + data = (struct ubcore_update_tpf_dev_info_req *)req_msg->payload; + 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); + + 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_NL_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; + } + + kfree(resp_msg); + kfree(req_msg); + return ret; +} + static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) { struct ubcore_nlmsg *resp_msg, *req_msg; @@ -574,7 +663,6 @@ static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) req_msg = kcalloc(1, sizeof(struct ubcore_nlmsg) + cc_len, GFP_KERNEL); if (req_msg == NULL) { kfree(cc_entry); - ubcore_log_err("Failed to alloc update tpf dev req msg.\n"); return -ENOMEM; } @@ -588,10 +676,11 @@ static int ubcore_query_send_tpf_dev_info(struct ubcore_device *dev) data->dev_fea = dev->attr.dev_cap.feature; data->cc_entry_cnt = cc_entry_cnt; (void)strcpy(data->dev_name, dev->dev_name); + data->opcode = UBCORE_UPDATE_TPF_ADD; array = (struct ubcore_cc_entry *)data->data; (void)memcpy(array, cc_entry, sizeof(struct ubcore_cc_entry) * cc_entry_cnt); - resp_msg = ubcore_nl_send_wait(req_msg); + resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { ubcore_log_err("Failed to wait query response"); kfree(cc_entry); @@ -602,7 +691,7 @@ static int ubcore_query_send_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 || resp->ret != UBCORE_NL_RESP_SUCCESS) { - ubcore_log_err("update tpf dev info request is rejected with type %d ret %d", + 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 { @@ -688,15 +777,22 @@ static int init_ubcore_device(struct ubcore_device *dev) static void uninit_ubcore_device(struct ubcore_device *dev) { + ubcore_put_port_netdev(dev); ubcore_update_default_eid(dev, false); ubcore_free_hash_tables(dev); ubcore_destroy_eidtable(dev); if (!dev->attr.virtualization) ubcore_destroy_upi_list(); + if (g_tpf == dev && dev->attr.tp_maintainer) g_tpf = NULL; + if (dev->transport_type == UBCORE_TRANSPORT_UB && dev->attr.tp_maintainer) { + 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); } @@ -724,7 +820,7 @@ 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.slice = 1; + cfg.mask.bs.slice = data->set_slice; cfg.slice = data->slice; /* For a new TPF device, the suspend config needs to be set. */ @@ -754,8 +850,7 @@ 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.slice = 1; - cfg.slice = dev->attr.dev_cap.max_slice; + /* slice and mask.slice are set to 0 by default */ /* If suspend_period and cnt cannot be read, do not need to configure it */ return dev->ops->config_device(dev, &cfg); @@ -798,7 +893,8 @@ static int ubcore_config_device_in_register(struct ubcore_device *dev) /* New TPF devices need to be query suspend info. */ data->is_tpf_dev = dev->attr.tp_maintainer; - ret = ubcore_send_fe2tpf_msg(dev, req_msg, true, &cb); + ret = ubcore_send_fe2tpf_msg(dev, req_msg, &cb); + kfree(req_msg); if (ret != 0) { ubcore_log_err("send fe2tpf failed.\n"); return ubcore_config_device_default(dev); @@ -831,9 +927,10 @@ int ubcore_register_device(struct ubcore_device *dev) if (ubcore_config_device_in_register(dev) != 0) { ubcore_log_err("failed to config ubcore device.\n"); + uninit_ubcore_device(dev); return -EPERM; } - + ubcore_cgroup_reg_dev(dev); mutex_lock(&g_device_mutex); list_for_each_entry(client, &g_client_list, list_node) { @@ -877,6 +974,8 @@ void ubcore_unregister_device(struct ubcore_device *dev) } up_write(&g_lists_rwsem); + ubcore_cgroup_unreg_dev(dev); + uninit_ubcore_device(dev); mutex_unlock(&g_device_mutex); @@ -991,23 +1090,57 @@ 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) +{ + struct net *net; + + if (IS_ERR_OR_NULL(dev->eid_table.eid_entries)) + return false; + + spin_lock(&dev->eid_table.lock); + if (!dev->eid_table.eid_entries[eid_index].valid) { + spin_unlock(&dev->eid_table.lock); + return false; + } + net = dev->eid_table.eid_entries[eid_index].net; + spin_unlock(&dev->eid_table.lock); + return net_eq(net, current->nsproxy->net_ns); +} + struct ubcore_ucontext *ubcore_alloc_ucontext(struct ubcore_device *dev, uint32_t eid_index, struct ubcore_udrv_priv *udrv_data) { struct ubcore_ucontext *ucontext; + 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"); return NULL; } + + if (!ubcore_eid_accessible(dev, eid_index)) { + ubcore_log_err("eid is not accessible by current ns.\n"); + return NULL; + } + + 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; + } + ucontext = dev->ops->alloc_ucontext(dev, eid_index, udrv_data); if (ucontext == NULL) { ubcore_log_err("failed to alloc ucontext.\n"); + ubcore_cgroup_uncharge(&cg_obj, dev, UBCORE_RESOURCE_HCA_HANDLE); return NULL; } ucontext->eid_index = eid_index; ucontext->ub_dev = dev; + ucontext->cg_obj = cg_obj; + return ucontext; } EXPORT_SYMBOL(ubcore_alloc_ucontext); @@ -1015,16 +1148,20 @@ EXPORT_SYMBOL(ubcore_alloc_ucontext); void ubcore_free_ucontext(struct ubcore_device *dev, struct ubcore_ucontext *ucontext) { int ret; + struct ubcore_cg_object cg_obj; if (dev == NULL || ucontext == NULL || dev->ops == NULL || dev->ops->free_ucontext == NULL) { ubcore_log_err("Invalid argument.\n"); return; } + cg_obj = ucontext->cg_obj; ret = dev->ops->free_ucontext(ucontext); if (ret != 0) ubcore_log_err("failed to free_adu, ret: %d.\n", ret); + + ubcore_cgroup_uncharge(&cg_obj, dev, UBCORE_RESOURCE_HCA_HANDLE); } EXPORT_SYMBOL(ubcore_free_ucontext); @@ -1057,7 +1194,9 @@ 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", ret); + 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; } return ret; @@ -1068,14 +1207,16 @@ int ubcore_delete_ueid(struct ubcore_device *dev, uint16_t fe_idx, struct ubcore { int ret; - if (dev == NULL || dev->ops == NULL || dev->ops->delete_ueid == NULL) { + if (dev == NULL || cfg == NULL || dev->ops == NULL || dev->ops->delete_ueid == NULL) { ubcore_log_err("Invalid argument.\n"); return -EINVAL; } ret = dev->ops->delete_ueid(dev, fe_idx, cfg); if (ret != 0) { - ubcore_log_err("failed to delete eid, ret: %d.\n", ret); + 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; } return ret; @@ -1128,7 +1269,6 @@ int ubcore_query_resource(struct ubcore_device *dev, struct ubcore_res_key *key, ubcore_log_err("Invalid argument.\n"); return -EINVAL; } - ret = dev->ops->query_res(dev, key, val); if (ret != 0) { ubcore_log_err("failed to query res, ret: %d.\n", ret); @@ -1265,14 +1405,19 @@ static int ubcore_update_sip(struct ubcore_sip_info *sip, bool is_add) ubcore_log_err("There is an illegal parameter.\n"); return -1; } - tpf_dev = ubcore_find_tpf_device(&sip->addr, UBCORE_TRANSPORT_UB); + 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 (tpf_dev && ubcore_add_device_sip(tpf_dev, sip) != 0) { + if (ubcore_add_device_sip(tpf_dev, sip) != 0) { ubcore_put_device(tpf_dev); return -1; } } else { - if (tpf_dev && ubcore_del_device_sip(tpf_dev, sip) != 0) { + if (ubcore_del_device_sip(tpf_dev, sip) != 0) { ubcore_put_device(tpf_dev); return -1; } @@ -1307,7 +1452,7 @@ void ubcore_sync_sip_table(void) if (sip == NULL) continue; - tpf_dev = ubcore_find_tpf_device(&sip->addr, UBCORE_TRANSPORT_UB); + tpf_dev = ubcore_find_tpf_device_by_name(sip->dev_name, UBCORE_TRANSPORT_UB); if (tpf_dev) { (void)ubcore_notify_uvs_add_sip(tpf_dev, sip, i); ubcore_put_device(tpf_dev); diff --git a/drivers/ub/urma/ubcore/ubcore_hash_table.c b/drivers/ub/urma/ubcore/ubcore_hash_table.c index fbc9db4d1efc..12f6f335f1ce 100644 --- a/drivers/ub/urma/ubcore/ubcore_hash_table.c +++ b/drivers/ub/urma/ubcore/ubcore_hash_table.c @@ -30,10 +30,9 @@ int ubcore_hash_table_alloc(struct ubcore_hash_table *ht, const struct ubcore_ht return -1; ht->p = *p; ht->head = kcalloc(p->size, sizeof(struct hlist_head), GFP_KERNEL); - if (ht->head == NULL) { - ubcore_log_err("hash table allocation failed.\n"); - return -1; - } + if (ht->head == NULL) + return -ENOMEM; + for (i = 0; i < p->size; i++) INIT_HLIST_HEAD(&ht->head[i]); diff --git a/drivers/ub/urma/ubcore/ubcore_jetty.c b/drivers/ub/urma/ubcore/ubcore_jetty.c index 18d9ef3cf5bd..9776ec4132cf 100644 --- a/drivers/ub/urma/ubcore/ubcore_jetty.c +++ b/drivers/ub/urma/ubcore/ubcore_jetty.c @@ -595,7 +595,7 @@ static int check_and_fill_jetty_attr(struct ubcore_jetty_cfg *cfg, struct ubcore return 0; } -static int check_jetty_cfg(struct ubcore_jetty_cfg *cfg) +static int check_jetty_cfg(struct ubcore_device *dev, struct ubcore_jetty_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); @@ -607,6 +607,10 @@ static int check_jetty_cfg(struct ubcore_jetty_cfg *cfg) return -1; } + if (cfg->flag.bs.share_jfr == 0 && dev->transport_type == UBCORE_TRANSPORT_UB) { + ubcore_log_err("UB dev should use share jfr"); + return -1; + } if (cfg->flag.bs.share_jfr != 0 && (cfg->jfr == NULL || cfg->jfr->jfr_cfg.trans_mode != cfg->trans_mode)) { ubcore_log_err("jfr is null or trans_mode invalid with shared jfr flag.\n"); @@ -739,7 +743,7 @@ struct ubcore_jetty *ubcore_create_jetty(struct ubcore_device *dev, struct ubcor dev->ops->destroy_jetty == NULL) return NULL; - if (check_jetty_cfg(cfg) != 0) { + if (check_jetty_cfg(dev, cfg) != 0) { ubcore_log_err("failed to check jetty cfg.\n"); return NULL; } @@ -864,6 +868,13 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) if (jetty == NULL || jetty->ub_dev == NULL || jetty->ub_dev->ops->destroy_jetty == NULL) return -1; + if ((jetty->ub_dev->transport_type == UBCORE_TRANSPORT_UB && + jetty->jetty_cfg.trans_mode == UBCORE_TP_RC && jetty->remote_jetty != NULL) || + atomic_read(&jetty->use_cnt) > 0) { + ubcore_log_err("Failed to delete jetty in RC mode because it has remote jetty"); + return -1; + } + jetty_grp = jetty->jetty_cfg.jetty_grp; send_jfc = jetty->jetty_cfg.send_jfc; recv_jfc = jetty->jetty_cfg.recv_jfc; @@ -881,6 +892,7 @@ int ubcore_delete_jetty(struct ubcore_jetty *jetty) atomic_set(&jetty->remote_jetty->use_cnt, 0); /* The tjetty object will release remote jetty resources */ jetty->remote_jetty = NULL; + ubcore_log_warn("jetty->remote_jetty != NULL and it has been handled"); } if (jetty_grp != NULL) @@ -1189,17 +1201,26 @@ int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, } dev = jetty->ub_dev; + if (dev == NULL) { + ubcore_log_err("Invalid parameter with dev null_ptr.\n"); + return -1; + } + + if (dev->transport_type == UBCORE_TRANSPORT_UB) { + struct ubcore_vtpn *vtpn; + /* IB devices don't need to call bind_jetty and unbind_jetty */ + if (dev->ops == NULL || dev->ops->bind_jetty == NULL || + dev->ops->unbind_jetty == NULL) { + ubcore_log_err("Failed to bind jetty, no ops->bind_jetty\n"); + return -1; + } - if (dev->ops->bind_jetty != NULL && dev->ops->unbind_jetty != NULL) { ret = dev->ops->bind_jetty(jetty, tjetty, udata); if (ret != 0) { ubcore_log_err("Failed to bind jetty"); return ret; } - } - - if (dev->transport_type == UBCORE_TRANSPORT_UB) { - struct ubcore_vtpn *vtpn; + atomic_inc(&jetty->use_cnt); ubcore_set_vtp_param(dev, jetty, &tjetty->cfg, &vtp_param); mutex_lock(&tjetty->lock); @@ -1230,8 +1251,10 @@ int ubcore_bind_jetty(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, return 0; unbind: - if (dev->ops->bind_jetty != NULL && dev->ops->unbind_jetty != NULL) + if (dev->ops->bind_jetty != NULL && dev->ops->unbind_jetty != NULL) { (void)dev->ops->unbind_jetty(jetty); + atomic_dec(&jetty->use_cnt); + } return ret; } @@ -1256,6 +1279,10 @@ 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) { @@ -1282,13 +1309,22 @@ int ubcore_unbind_jetty(struct ubcore_jetty *jetty) } } ubcore_log_info("jetty: %u unbind tjetty: %u\n", jetty->id, tjetty->cfg.id.id); - if (dev->ops->bind_jetty != NULL && dev->ops->unbind_jetty != NULL) { + + /* IB devices don't need to call bind_jetty and unbind_jetty */ + if (dev->transport_type == UBCORE_TRANSPORT_UB) { + if (dev->ops == NULL || dev->ops->bind_jetty == NULL || + dev->ops->unbind_jetty == NULL) { + ubcore_log_err("Failed to unbind jetty, no ops->unbind_jetty\n"); + return -1; + } ret = dev->ops->unbind_jetty(jetty); if (ret != 0) { ubcore_log_err("Failed to unbind jetty"); return ret; } + atomic_dec(&jetty->use_cnt); } + atomic_dec(&tjetty->use_cnt); jetty->remote_jetty = NULL; return 0; diff --git a/drivers/ub/urma/ubcore/ubcore_main.c b/drivers/ub/urma/ubcore/ubcore_main.c index 1e53dc3ca1e0..fd51dccec0b1 100644 --- a/drivers/ub/urma/ubcore/ubcore_main.c +++ b/drivers/ub/urma/ubcore/ubcore_main.c @@ -144,15 +144,20 @@ static int ubcore_cmd_query_stats(struct ubcore_cmd_hdr *hdr) sizeof(struct ubcore_cmd_query_stats)); } -static int ubcore_cmd_updata_ueid(struct ubcore_cmd_hdr *hdr, enum ubcore_msg_opcode op) +static int ubcore_cmd_update_ueid(struct ubcore_cmd_hdr *hdr, enum ubcore_msg_opcode op) { - struct net *net = current->nsproxy->net_ns; - struct ubcore_cmd_updata_ueid arg; + struct ubcore_cmd_update_ueid arg; + struct net *net = &init_net; struct ubcore_device *dev; - int ret; + 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_updata_ueid)); + sizeof(struct ubcore_cmd_update_ueid)); if (ret != 0) return -EPERM; @@ -161,6 +166,7 @@ static int ubcore_cmd_updata_ueid(struct ubcore_cmd_hdr *hdr, enum ubcore_msg_op 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"); @@ -175,13 +181,23 @@ static int ubcore_cmd_updata_ueid(struct ubcore_cmd_hdr *hdr, enum ubcore_msg_op ubcore_put_device(dev); return -EPERM; } - if (ubcore_msg_discover_eid(dev, arg.in.eid_index, op, net) != 0) { - 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 0; + return ret; } static void ubcore_update_pattern1_eid(struct ubcore_device *dev, @@ -315,295 +331,168 @@ static uint32_t ubcore_get_query_res_len(uint32_t type) return 0; } -static void ubcore_dealloc_res_dev(struct ubcore_res_dev_val *ubcore_addr) -{ - if (ubcore_addr->seg_list != NULL) { - vfree(ubcore_addr->seg_list); - ubcore_addr->seg_list = NULL; - } - if (ubcore_addr->jfs_list != NULL) { - vfree(ubcore_addr->jfs_list); - ubcore_addr->jfs_list = NULL; - } - if (ubcore_addr->jfr_list != NULL) { - vfree(ubcore_addr->jfr_list); - ubcore_addr->jfr_list = NULL; - } - if (ubcore_addr->jfc_list != NULL) { - vfree(ubcore_addr->jfc_list); - ubcore_addr->jfc_list = NULL; - } - if (ubcore_addr->jetty_list != NULL) { - vfree(ubcore_addr->jetty_list); - ubcore_addr->jetty_list = NULL; - } - if (ubcore_addr->jetty_group_list != NULL) { - vfree(ubcore_addr->jetty_group_list); - ubcore_addr->jetty_group_list = NULL; - } - if (ubcore_addr->rc_list != NULL) { - vfree(ubcore_addr->rc_list); - ubcore_addr->rc_list = NULL; - } - if (ubcore_addr->vtp_list != NULL) { - vfree(ubcore_addr->vtp_list); - ubcore_addr->vtp_list = NULL; - } - if (ubcore_addr->tp_list != NULL) { - vfree(ubcore_addr->tp_list); - ubcore_addr->tp_list = NULL; - } - if (ubcore_addr->tpg_list != NULL) { - vfree(ubcore_addr->tpg_list); - ubcore_addr->tpg_list = NULL; - } - if (ubcore_addr->utp_list != NULL) { - vfree(ubcore_addr->utp_list); - ubcore_addr->utp_list = NULL; - } -} - -static int ubcore_fill_res_addr(struct ubcore_res_dev_val *ubcore_addr) -{ - ubcore_addr->seg_list = vmalloc(sizeof(struct ubcore_seg_info) * ubcore_addr->seg_cnt); - if (ubcore_addr->seg_list == NULL) - return -ENOMEM; - - ubcore_addr->jfs_list = vmalloc(sizeof(uint32_t) * ubcore_addr->jfs_cnt); - if (ubcore_addr->jfs_list == NULL) - goto free_seg_list; - - ubcore_addr->jfr_list = vmalloc(sizeof(uint32_t) * ubcore_addr->jfr_cnt); - if (ubcore_addr->jfr_list == NULL) - goto free_jfs_list; - - ubcore_addr->jfc_list = vmalloc(sizeof(uint32_t) * ubcore_addr->jfc_cnt); - if (ubcore_addr->jfc_list == NULL) - goto free_jfr_list; - - ubcore_addr->jetty_list = vmalloc(sizeof(uint32_t) * ubcore_addr->jetty_cnt); - if (ubcore_addr->jetty_list == NULL) - goto free_jfc_list; - - ubcore_addr->jetty_group_list = vmalloc(sizeof(uint32_t) * ubcore_addr->jetty_group_cnt); - if (ubcore_addr->jetty_group_list == NULL) - goto free_jetty_list; - - ubcore_addr->rc_list = vmalloc(sizeof(uint32_t) * ubcore_addr->rc_cnt); - if (ubcore_addr->rc_list == NULL) - goto free_jetty_group_list; - - ubcore_addr->vtp_list = vmalloc(sizeof(uint32_t) * ubcore_addr->vtp_cnt); - if (ubcore_addr->vtp_list == NULL) - goto free_rc_list; - - ubcore_addr->tp_list = vmalloc(sizeof(uint32_t) * ubcore_addr->tp_cnt); - if (ubcore_addr->tp_list == NULL) - goto free_vtp_list; - - ubcore_addr->tpg_list = vmalloc(sizeof(uint32_t) * ubcore_addr->tpg_cnt); - if (ubcore_addr->tpg_list == NULL) - goto free_tp_list; - - ubcore_addr->utp_list = vmalloc(sizeof(uint32_t) * ubcore_addr->utp_cnt); - if (ubcore_addr->utp_list == NULL) - goto free_tpg_list; - - return 0; -free_tpg_list: - vfree(ubcore_addr->tpg_list); -free_tp_list: - vfree(ubcore_addr->tp_list); -free_vtp_list: - vfree(ubcore_addr->vtp_list); -free_rc_list: - vfree(ubcore_addr->rc_list); -free_jetty_group_list: - vfree(ubcore_addr->jetty_group_list); -free_jetty_list: - vfree(ubcore_addr->jetty_list); -free_jfc_list: - vfree(ubcore_addr->jfc_list); -free_jfr_list: - vfree(ubcore_addr->jfr_list); -free_jfs_list: - vfree(ubcore_addr->jfs_list); -free_seg_list: - vfree(ubcore_addr->seg_list); - return -ENOMEM; -} - -static int ubcore_fill_user_res_dev(struct ubcore_res_dev_val *dev_val, - struct ubcore_res_dev_val *ubcore_addr) +static int ubcore_fill_user_res_dev(struct ubcore_res_dev_val *user_addr, + struct ubcore_res_dev_val *kernal_addr) { int ret; - dev_val->seg_cnt = ubcore_addr->seg_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->seg_list, - ubcore_addr->seg_list, - dev_val->seg_cnt * sizeof(struct ubcore_seg_info)); + 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; - dev_val->jfs_cnt = ubcore_addr->jfs_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->jfs_list, - ubcore_addr->jfs_list, dev_val->jfs_cnt * sizeof(uint32_t)); + 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; - dev_val->jfr_cnt = ubcore_addr->jfr_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->jfr_list, - ubcore_addr->jfr_list, dev_val->jfr_cnt * sizeof(uint32_t)); + 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; - dev_val->jfc_cnt = ubcore_addr->jfc_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->jfc_list, - ubcore_addr->jfc_list, dev_val->jfc_cnt * sizeof(uint32_t)); + 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; - dev_val->jetty_cnt = ubcore_addr->jetty_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->jetty_list, - ubcore_addr->jetty_list, dev_val->jetty_cnt * sizeof(uint32_t)); + 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; - dev_val->jetty_group_cnt = ubcore_addr->jetty_group_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->jetty_group_list, - ubcore_addr->jetty_group_list, - dev_val->jetty_group_cnt * sizeof(uint32_t)); + 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; - dev_val->rc_cnt = ubcore_addr->rc_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->rc_list, - ubcore_addr->rc_list, - dev_val->rc_cnt * sizeof(uint32_t)); + 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; - dev_val->vtp_cnt = ubcore_addr->vtp_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->vtp_list, - ubcore_addr->vtp_list, - dev_val->vtp_cnt * sizeof(uint32_t)); + 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; - dev_val->tp_cnt = ubcore_addr->tp_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->tp_list, - ubcore_addr->tp_list, dev_val->tp_cnt * sizeof(uint32_t)); + 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; - dev_val->tpg_cnt = ubcore_addr->tpg_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->tpg_list, - ubcore_addr->tpg_list, dev_val->tpg_cnt * sizeof(uint32_t)); + 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; - dev_val->utp_cnt = ubcore_addr->utp_cnt; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)(uint64_t)dev_val->utp_list, - ubcore_addr->utp_list, dev_val->utp_cnt * sizeof(uint32_t)); + 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_query_res_dev(struct ubcore_device *dev, struct ubcore_res_key *key, - struct ubcore_res_dev_val *dev_val) +static int ubcore_copy_to_usr_tp_list(uint64_t user_tp_list, struct ubcore_res_tpg_val *tpg) { - struct ubcore_res_dev_val ubcore_addr = { 0 }; - struct ubcore_res_val val = { 0 }; - int ret = 0; - - (void)memcpy(&ubcore_addr, dev_val, sizeof(struct ubcore_res_dev_val)); // save - - if (ubcore_fill_res_addr(&ubcore_addr) != 0) { - ubcore_log_err("Failed to fill dev dev_val.\n"); - return -ENOMEM; - } - - val.addr = (uint64_t)&ubcore_addr; - val.len = (uint32_t)sizeof(struct ubcore_res_dev_val); + int ret; - ret = ubcore_query_resource(dev, key, &val); + ret = ubcore_copy_to_user((void __user *)(uintptr_t)user_tp_list, + tpg->tp_list, sizeof(uint32_t) * tpg->tp_cnt); if (ret != 0) - goto ubcore_free_dev; - - ret = ubcore_fill_user_res_dev(dev_val, &ubcore_addr); -ubcore_free_dev: - ubcore_dealloc_res_dev(&ubcore_addr); - return ret; -} - -static void ubcore_dealloc_res_tp_list(uint64_t user_tp_list, struct ubcore_res_val *val) -{ - struct ubcore_res_tpg_val *tpg = (struct ubcore_res_tpg_val *)val->addr; - - if (ubcore_copy_to_user((void __user *)(uintptr_t)user_tp_list, - tpg->tp_list, sizeof(uint32_t) * tpg->tp_cnt) != 0) ubcore_log_err("ubcore_copy_to_user failed.\n"); - kfree(tpg->tp_list); + vfree(tpg->tp_list); + return ret; } -static int ubcore_alloc_res_tp_list(struct ubcore_res_val *val) -{ - struct ubcore_res_tpg_val *tpg; - - tpg = (struct ubcore_res_tpg_val *)val->addr; - tpg->tp_list = kzalloc(sizeof(uint32_t) * UBCORE_MAX_TP_CNT_IN_GRP, GFP_KERNEL); - if (tpg->tp_list == NULL) - return -ENOMEM; - - return 0; -} -static void ubcore_dealloc_res_jetty_list(uint64_t user_jetty_list, struct ubcore_res_val *val) +static int ubcore_copy_to_usr_jetty_list(uint64_t user_jetty_list, + struct ubcore_res_jetty_group_val *jetty_grp) { - struct ubcore_res_jetty_group_val *tpg; - - tpg = (struct ubcore_res_jetty_group_val *)val->addr; + int ret; - if (ubcore_copy_to_user((void __user *)(uintptr_t)user_jetty_list, tpg->jetty_list, - sizeof(uint32_t) * tpg->jetty_cnt) != 0) + 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.\n"); - kfree(tpg->jetty_list); + vfree(jetty_grp->jetty_list); + return ret; } -static int ubcore_alloc_res_jetty_list(struct ubcore_device *dev, struct ubcore_res_val *val) +static void ubcore_query_copy_cnt(struct ubcore_cmd_query_res *arg, + uint64_t val_addr, uint64_t user_addr) { - struct ubcore_res_jetty_group_val *tpg; + struct ubcore_res_tpg_val *tpg_val; + struct ubcore_res_tpg_val *tpg_user_val; - tpg = (struct ubcore_res_jetty_group_val *)val->addr; - tpg->jetty_list = kcalloc(1, sizeof(uint32_t) * dev->attr.dev_cap.max_jetty_in_jetty_grp, - GFP_KERNEL); - if (tpg->jetty_list == NULL) - return -ENOMEM; + struct ubcore_res_jetty_group_val *jgrp_val; + struct ubcore_res_jetty_group_val *jgrp_user_val; - return 0; + 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 *)val_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 *)val_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_URMA_DEV: + dev_val = (struct ubcore_res_dev_val *)val_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_res_arg(struct ubcore_device *dev, struct ubcore_cmd_query_res *arg, +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}; - uint64_t user_tp_list_addr = 0; // to saves and restores user-mode addresses - uint64_t user_jetty_list_addr = 0; // to saves and restores user-mode addresses - void *k_res_val; + void *kernal_addr; + void *user_addr; int ret; - k_res_val = kzalloc(res_len, GFP_KERNEL); - if (k_res_val == NULL) + kernal_addr = kzalloc(res_len, GFP_KERNEL); + if (kernal_addr == NULL) return -1; - ret = ubcore_copy_from_user(k_res_val, (void __user *)(uintptr_t)arg->out.addr, res_len); + 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); @@ -614,48 +503,90 @@ static int ubcore_query_res_arg(struct ubcore_device *dev, struct ubcore_cmd_que key.key = arg->in.key; key.key_ext = arg->in.key_ext; key.key_cnt = arg->in.key_cnt; - val.addr = (uint64_t)k_res_val; + val.addr = (uint64_t)kernal_addr; val.len = res_len; - if (arg->in.type == UBCORE_RES_KEY_TPG) { - user_tp_list_addr = - (uint64_t)(((struct ubcore_res_tpg_val *)k_res_val)->tp_list); // save - if (ubcore_alloc_res_tp_list(&val) != 0) - goto kfree_addr; - } + // urma only alloc memory for the struct + // driver will alloc memory for the list pointer in the struct; urma need to vfree it later - if (arg->in.type == UBCORE_RES_KEY_JETTY_GROUP) { - // save - user_jetty_list_addr = - (uint64_t)(((struct ubcore_res_jetty_group_val *)k_res_val)->jetty_list); - if (ubcore_alloc_res_jetty_list(dev, &val) != 0) - goto kfree_addr; - } + ret = ubcore_query_resource(dev, &key, &val); + if (ret != 0) + goto kfree_addr; - if (arg->in.type == UBCORE_RES_KEY_URMA_DEV) - ret = ubcore_query_res_dev(dev, &key, (struct ubcore_res_dev_val *)k_res_val); - else - ret = ubcore_query_resource(dev, &key, &val); + ubcore_query_copy_cnt(arg, val.addr, (uint64_t)user_addr); - if (arg->in.type == UBCORE_RES_KEY_TPG) { - ubcore_dealloc_res_tp_list(user_tp_list_addr, &val); - /* recover after use */ - ((struct ubcore_res_tpg_val *)k_res_val)->tp_list = (uint32_t *)user_tp_list_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; - if (arg->in.type == UBCORE_RES_KEY_JETTY_GROUP) { - ubcore_dealloc_res_jetty_list(user_jetty_list_addr, &val); - ((struct ubcore_res_jetty_group_val *)k_res_val)->jetty_list = - (uint32_t *)user_jetty_list_addr; // recover after use + if (arg->in.type == 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); + } else if (arg->in.type == 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); + } else if (arg->in.type == 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); + } else { + (void)memcpy(user_addr, k_addr, res_len); } if (ret != 0) goto kfree_addr; - ret = ubcore_copy_to_user((void __user *)(uintptr_t)arg->out.addr, k_res_val, res_len); + ret = ubcore_copy_to_user((void __user *)(uintptr_t)arg->out.addr, user_addr, res_len); kfree_addr: - kfree(k_res_val); + kfree(user_addr); + kfree(k_addr); /* release after second ioctl */ return ret; } @@ -684,7 +615,11 @@ static int ubcore_cmd_query_res(struct ubcore_cmd_hdr *hdr) return -EINVAL; } - ret = ubcore_query_res_arg(dev, &arg, res_len); + 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"); @@ -692,8 +627,9 @@ static int ubcore_cmd_query_res(struct ubcore_cmd_hdr *hdr) } ubcore_put_device(dev); + return ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, - sizeof(struct ubcore_cmd_query_res)); + sizeof(struct ubcore_cmd_query_res)); } static int ubcore_cmd_parse(struct ubcore_cmd_hdr *hdr) @@ -706,9 +642,9 @@ static int ubcore_cmd_parse(struct ubcore_cmd_hdr *hdr) case UBCORE_CMD_QUERY_RES: return ubcore_cmd_query_res(hdr); case UBCORE_CMD_ADD_EID: - return ubcore_cmd_updata_ueid(hdr, UBCORE_MSG_ALLOC_EID); + return ubcore_cmd_update_ueid(hdr, UBCORE_MSG_ALLOC_EID); case UBCORE_CMD_DEL_EID: - return ubcore_cmd_updata_ueid(hdr, UBCORE_MSG_DEALLOC_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: @@ -948,14 +884,17 @@ static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long real_netdev = netdev; real_netaddr = *netaddr; } - tpf_dev = ubcore_find_tpf_device(&real_netaddr, UBCORE_TRANSPORT_UB); + devices = ubcore_get_devices_from_netdev(real_netdev, &num_devices); - if (devices == NULL) { - ubcore_put_device(tpf_dev); + 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) @@ -970,8 +909,9 @@ static int ubcore_handle_inetaddr_event(struct net_device *netdev, unsigned long default: break; } + if (tpf_dev) + ubcore_put_device(tpf_dev); } - ubcore_put_device(tpf_dev); ubcore_put_devices(devices, num_devices); return NOTIFY_OK; } @@ -1094,29 +1034,32 @@ void ubcore_update_default_eid(struct ubcore_device *dev, bool is_add) struct ubcore_net_addr_node *next; LIST_HEAD(na_list); - /* Do not modify eid if the driver already set default eid other than 0 */ - if (netdev == NULL || !(dev->eid_table.eid_entries[0].eid.in6.interface_id == 0 && - dev->eid_table.eid_entries[0].eid.in6.subnet_prefix == 0)) + if (netdev == NULL) return; + /* In virtualization situation sip and eid are not from net_dev */ + 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; - tpf_dev = ubcore_find_tpf_device(&na_entry->addr, UBCORE_TRANSPORT_UB); if (tpf_dev) is_add == true ? ubcore_add_net_addr(tpf_dev, dev, &na_entry->addr, netdev, na_entry->prefix_len) : ubcore_delete_net_addr(tpf_dev, dev, &na_entry->addr, netdev, na_entry->prefix_len); - if (tpf_dev) - ubcore_put_device(tpf_dev); ubcore_update_eid(dev, &na_entry->addr, is_add); 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) @@ -1162,38 +1105,41 @@ static int ubcore_remove_netaddr(struct ubcore_device *dev, struct net_device *n return NOTIFY_OK; } -static void ubcore_chang_mtu(struct ubcore_device *dev, struct net_device *netdev) +static void ubcore_change_mtu(struct ubcore_device *dev, struct net_device *netdev) { + struct ubcore_sip_info new_sip = {0}; + struct ubcore_sip_info old_sip = {0}; struct ubcore_device *tpf_dev; - struct ubcore_sip_info *old_sip; - struct ubcore_sip_info new_sip; uint32_t max_cnt; uint32_t i; - if (ubcore_get_netlink_valid() == false) + tpf_dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); + if (tpf_dev == NULL) return; - tpf_dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); max_cnt = ubcore_get_sip_max_cnt(); for (i = 0; i < max_cnt; i++) { - if (tpf_dev) { - old_sip = ubcore_lookup_sip_info(i); - if (old_sip == NULL) - continue; - new_sip = *old_sip; - new_sip.mtu = netdev->mtu; - if (memcmp(old_sip->dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME) == 0) { - (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, mtu: %u change mtu: %u\n", - dev->dev_name, old_sip->mtu, new_sip.mtu); - old_sip->mtu = netdev->mtu; - } + if (ubcore_get_sip_info_copy(i, &new_sip) != 0) + continue; + + if (memcmp(new_sip.dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME) != 0) + continue; + + old_sip = new_sip; + new_sip.mtu = netdev->mtu; + if (ubcore_sip_info_update(i, (const struct ubcore_sip_info *)&new_sip) != 0) + continue; + + 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, mtu: %u change to mtu: %u\n", + dev->dev_name, old_sip.mtu, new_sip.mtu); } - if (tpf_dev) - ubcore_put_device(tpf_dev); + + ubcore_put_device(tpf_dev); } static int ubcore_netdev_event_change_upper(struct ubcore_device *dev, @@ -1284,6 +1230,47 @@ static struct net_device *ubcore_find_master_netdev(unsigned long event, return bond; } +static void ubcore_do_netdev_notify(unsigned long event, struct ubcore_device *dev, + struct net_device *netdev, void *arg) +{ + 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) + ubcore_change_mtu(dev, netdev); + break; + case NETDEV_CHANGEUPPER: + /* NETDEV_CHANGEUPPER event need to put_device ahead due to unregister dev */ + if (dev->transport_type == UBCORE_TRANSPORT_UB) + (void)ubcore_netdev_event_change_upper(dev, netdev, arg); + else + ubcore_put_device(dev); + + break; + case NETDEV_CHANGELOWERSTATE: + if (dev->transport_type == UBCORE_TRANSPORT_UB) + (void)ubcore_netdev_event_change_lower_state(dev, netdev, arg); + break; + default: + break; + } +} + static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long event, void *arg) { struct net_device *netdev = netdev_notifier_info_to_dev(arg); @@ -1326,41 +1313,13 @@ static int ubcore_net_notifier_call(struct notifier_block *nb, unsigned long eve for (i = 0; i < num_devices; i++) { dev = devices[i]; - 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) - ubcore_chang_mtu(dev, netdev); - break; - case NETDEV_CHANGEUPPER: - if (dev->transport_type == UBCORE_TRANSPORT_UB) - (void)ubcore_netdev_event_change_upper(dev, netdev, arg); - break; - case NETDEV_CHANGELOWERSTATE: - if (dev->transport_type == UBCORE_TRANSPORT_UB) - (void)ubcore_netdev_event_change_lower_state(dev, netdev, arg); - break; - default: - break; - } + ubcore_do_netdev_notify(event, dev, netdev, arg); } if (event != NETDEV_CHANGEUPPER) ubcore_put_devices(devices, num_devices); + else + kfree(devices); + return NOTIFY_OK; } @@ -1416,7 +1375,7 @@ static int __init ubcore_init(void) if (ret != 0) return ret; - (void)ubcore_sip_table_init(); + ubcore_sip_table_init(); if (ubcore_netlink_init() != 0) { ubcore_sip_table_uninit(); diff --git a/drivers/ub/urma/ubcore/ubcore_msg.c b/drivers/ub/urma/ubcore/ubcore_msg.c index 6995b3c5c5cc..71ec265b35da 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.c +++ b/drivers/ub/urma/ubcore/ubcore_msg.c @@ -127,8 +127,8 @@ static int ubcore_forward_fe2uvs_msg(struct ubcore_device *dev, struct ubcore_re return -ENOMEM; cb.callback = ubcore_forward_uvs2fe_msg; - cb.user_arg = dev; - ret = ubcore_nl_send_nowait(nlmsg, &cb); + cb.user_arg = NULL; /* If bind or advise tp timeout expires, dev may drive unregister */ + ret = ubcore_nl_send_nowait(dev, nlmsg, &cb); if (ret) { kfree(nlmsg); return -EIO; @@ -160,27 +160,20 @@ static int ubcore_tpf2fe_msg(struct ubcore_device *dev, struct ubcore_resp *resp } s->resp = resp; kref_put(&s->kref, ubcore_free_msg_session); + complete(&s->comp); - if (s->cb.callback == NULL) { - complete(&s->comp); - } else { - s->cb.callback(dev, resp, s->cb.user_arg); - kfree(resp); - kfree(s->req); - ubcore_destroy_msg_session(s); - } return 0; } -static void ubcore_fill_tpf_dev_name(struct ubcore_req_host *req_host) +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; - struct ubcore_device *tpf_dev; - tpf_dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); - if (tpf_dev == NULL) + /* for alpha dev */ + if (!tpf_dev->attr.tp_maintainer) return; switch (req_host->req.opcode) { @@ -215,7 +208,6 @@ static void ubcore_fill_tpf_dev_name(struct ubcore_req_host *req_host) default: ubcore_log_err("Unrecognized type of opcode %d\n", (int)req_host->req.opcode); } - ubcore_put_device(tpf_dev); } static struct ubcore_req_host *ubcore_copy_req_host(struct ubcore_req_host *req_host) @@ -295,8 +287,9 @@ int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req) ubcore_log_err("Failed to create handle msg req!\n"); return -ENOMEM; } + /* fill tpf_dev name */ - ubcore_fill_tpf_dev_name(handle_req); + ubcore_fill_tpf_dev_name(dev, handle_req); } ret = ubcore_fe2tpf_msg(dev, handle_req); @@ -364,7 +357,7 @@ int ubcore_send_resp(struct ubcore_device *dev, struct ubcore_resp_host *resp_ho } int ubcore_send_fe2tpf_msg(struct ubcore_device *dev, struct ubcore_req *req, - bool wait, struct ubcore_resp_cb *cb) + struct ubcore_resp_cb *cb) { unsigned long leavetime; struct ubcore_msg_session *s; @@ -385,11 +378,6 @@ int ubcore_send_fe2tpf_msg(struct ubcore_device *dev, struct ubcore_req *req, return -EIO; } - if (!wait) { - s->cb = *cb; - return 0; - } - leavetime = wait_for_completion_timeout(&s->comp, msecs_to_jiffies(UBCORE_MSG_TIMEOUT)); if (leavetime == 0) { ubcore_log_err("Failed to wait req reply, msg_id = %u, opcode = %hu, leavetime = %lu.\n", @@ -403,7 +391,6 @@ int ubcore_send_fe2tpf_msg(struct ubcore_device *dev, struct ubcore_req *req, ret = cb->callback(dev, s->resp, cb->user_arg); kfree(s->resp); - kfree(s->req); ubcore_destroy_msg_session(s); return ret; } @@ -433,10 +420,13 @@ static int ubcore_msg_discover_eid_cb(struct ubcore_device *dev, 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 (ubcore_add_ueid(dev, data->fe_idx, &cfg) != 0) + 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 (ubcore_delete_ueid(dev, data->fe_idx, &cfg) != 0) + 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; @@ -457,10 +447,9 @@ int ubcore_msg_discover_eid(struct ubcore_device *dev, uint32_t eid_index, 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) { - ubcore_log_err("alloc req_msg failed.\n"); + if (req_msg == NULL) return -ENOMEM; - } + req_msg->len = data_len; req_msg->opcode = op; data = (struct ubcore_msg_discover_eid_req *)req_msg->data; @@ -469,9 +458,9 @@ int ubcore_msg_discover_eid(struct ubcore_device *dev, uint32_t eid_index, 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, true, &cb); + ret = ubcore_send_fe2tpf_msg(dev, req_msg, &cb); if (ret != 0) ubcore_log_err("send fe2tpf failed.\n"); - + kfree(req_msg); return ret; } diff --git a/drivers/ub/urma/ubcore/ubcore_msg.h b/drivers/ub/urma/ubcore/ubcore_msg.h index 47c15ed60b3b..108de96ed7a9 100644 --- a/drivers/ub/urma/ubcore/ubcore_msg.h +++ b/drivers/ub/urma/ubcore/ubcore_msg.h @@ -64,6 +64,7 @@ struct ubcore_msg_config_device_resp { uint32_t rc_cnt; uint32_t rc_depth; uint32_t slice; /* TA slice size byte */ + uint32_t set_slice; bool is_tpf_dev; uint32_t suspend_period; uint32_t suspend_cnt; @@ -95,9 +96,10 @@ struct ubcore_function_mig_resp { }; 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); +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, - bool wait, struct ubcore_resp_cb *cb); + 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); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.c b/drivers/ub/urma/ubcore/ubcore_netdev.c index 104b3074a56e..3b6ebab066f3 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.c +++ b/drivers/ub/urma/ubcore/ubcore_netdev.c @@ -24,9 +24,11 @@ #include "ubcore_log.h" #include #include "ubcore_netlink.h" +#include "ubcore_priv.h" +#include "ubcore_netdev.h" #define UBCORE_MAX_SIP (1 << 24) /* 2^24 */ -#define UBCORE_SIP_TABLE_SIZE (10240) +#define UBCORE_SIP_TABLE_SIZE (1024) /* 1823: 16; 1650: 1024; 1636: N/A */ static DECLARE_BITMAP(g_sip_bitmap, UBCORE_MAX_SIP); static DEFINE_SPINLOCK(g_sip_spinlock); @@ -130,6 +132,47 @@ 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 = {0}; + struct ubcore_sip_info old_sip = {0}; + struct ubcore_device *tpf_dev; + uint32_t max_cnt; + uint32_t i; + + tpf_dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); + if (tpf_dev == NULL) + return; + + max_cnt = ubcore_get_sip_max_cnt(); + + for (i = 0; i < max_cnt; i++) { + if (ubcore_get_sip_info_copy(i, &new_sip) != 0) + continue; + + if (memcmp(new_sip.dev_name, dev->dev_name, UBCORE_MAX_DEV_NAME) != 0) + 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_sip_info_update(i, (const struct ubcore_sip_info *)&new_sip) != 0) + continue; + + 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); + } + + ubcore_put_device(tpf_dev); +} + int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, unsigned int port_id) { @@ -153,6 +196,8 @@ 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); return 0; } @@ -174,6 +219,7 @@ int ubcore_set_port_netdev(struct ubcore_device *dev, struct net_device *ndev, 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_sync_sip_port_list(dev, new_node->port_list, new_node->port_cnt); return 0; } EXPORT_SYMBOL(ubcore_set_port_netdev); @@ -201,6 +247,8 @@ 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); kfree(port_info); @@ -246,6 +294,13 @@ void ubcore_put_port_netdev(struct ubcore_device *dev) down_write(&g_port_list_lock); list_for_each_entry_safe(port_info, next, &dev->port_list, node) { if (port_info != NULL) { + if (port_info->port_cnt != 0) { + 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); } @@ -376,6 +431,27 @@ int ubcore_lookup_sip_idx(struct ubcore_sip_info *sip, uint32_t *idx) return 0; } +int ubcore_lookup_sip_by_addr(struct ubcore_net_addr *addr, char *dev_name) +{ + uint32_t i; + + mutex_lock(&g_sip_table.lock); + for (i = 0; i < UBCORE_SIP_TABLE_SIZE; i++) { + if (g_sip_table.entry[i] != NULL && memcmp(&g_sip_table.entry[i]->addr, addr, + sizeof(struct ubcore_net_addr)) == 0) { + (void)memcpy(dev_name, g_sip_table.entry[i]->dev_name, UBCORE_MAX_DEV_NAME); + break; + } + } + mutex_unlock(&g_sip_table.lock); + + if (i == UBCORE_SIP_TABLE_SIZE) { + ubcore_log_warn("no available idx found.\n"); + return -1; + } + return 0; +} + uint32_t ubcore_get_sip_max_cnt(void) { return UBCORE_SIP_TABLE_SIZE; @@ -392,6 +468,34 @@ struct ubcore_sip_info *ubcore_lookup_sip_info(uint32_t idx) return sip; } +int ubcore_get_sip_info_copy(uint32_t idx, struct ubcore_sip_info *sip) +{ + int ret = -1; + + mutex_lock(&g_sip_table.lock); + if (idx < UBCORE_SIP_TABLE_SIZE && g_sip_table.entry[idx] != NULL) { + (void)memcpy(sip, g_sip_table.entry[idx], + sizeof(struct ubcore_sip_info)); + ret = 0; + } + mutex_unlock(&g_sip_table.lock); + return ret; +} + +int ubcore_sip_info_update(uint32_t idx, const struct ubcore_sip_info *sip) +{ + int ret = -1; + + mutex_lock(&g_sip_table.lock); + if (idx < UBCORE_SIP_TABLE_SIZE && g_sip_table.entry[idx] != NULL) { + (void)memcpy(g_sip_table.entry[idx], sip, + sizeof(struct ubcore_sip_info)); + ret = 0; + } + mutex_unlock(&g_sip_table.lock); + return ret; +} + int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, const struct ubcore_sip_info *sip_info, uint32_t index) { @@ -414,7 +518,7 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, /* fill msg payload */ sip_req = (struct ubcore_del_sip_req *)(void *)req_msg->payload; sip_req->index = index; - resp_msg = ubcore_nl_send_wait(req_msg); + resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { ubcore_log_err("Failed to wait query response"); kfree(req_msg); @@ -463,7 +567,7 @@ int ubcore_notify_uvs_add_sip(struct ubcore_device *dev, sip_req->prefix_len = sip_info->prefix_len; sip_req->mtu = sip_info->mtu; - resp_msg = ubcore_nl_send_wait(req_msg); + resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { ubcore_log_err("Failed to wait query response"); kfree(req_msg); diff --git a/drivers/ub/urma/ubcore/ubcore_netdev.h b/drivers/ub/urma/ubcore/ubcore_netdev.h index 543f90081caf..de1c436bc808 100644 --- a/drivers/ub/urma/ubcore/ubcore_netdev.h +++ b/drivers/ub/urma/ubcore/ubcore_netdev.h @@ -32,15 +32,15 @@ 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_sip_table_init(void); +void ubcore_sip_table_init(void); void ubcore_sip_table_uninit(void); uint32_t ubcore_sip_idx_alloc(uint32_t idx); int ubcore_sip_idx_free(uint32_t idx); -int ubcore_add_sip_entry(struct ubcore_sip_info *sip, uint32_t idx); +int ubcore_add_sip_entry(const struct ubcore_sip_info *sip, uint32_t idx); int ubcore_del_sip_entry(uint32_t idx); int ubcore_lookup_sip_idx(struct ubcore_sip_info *sip, uint32_t *idx); - +int ubcore_lookup_sip_by_addr(struct ubcore_net_addr *addr, char *dev_name); 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, @@ -48,4 +48,6 @@ int ubcore_notify_uvs_del_sip(struct ubcore_device *dev, uint32_t ubcore_get_sip_max_cnt(void); struct ubcore_sip_info *ubcore_lookup_sip_info(uint32_t idx); +int ubcore_get_sip_info_copy(uint32_t idx, struct ubcore_sip_info *sip); +int ubcore_sip_info_update(uint32_t idx, const struct ubcore_sip_info *sip); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.c b/drivers/ub/urma/ubcore/ubcore_netlink.c index 68bc9e673445..2df78c230069 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.c +++ b/drivers/ub/urma/ubcore/ubcore_netlink.c @@ -29,7 +29,7 @@ #include "ubcore_netlink.h" #define UBCORE_NL_TYPE 24 /* same with agent netlink type */ -#define UBCORE_NL_TIMEOUT 10000 /* 10s */ +#define UBCORE_NL_TIMEOUT 30000 /* 30s */ #define UBCORE_NL_INVALID_PORT 0 static struct sock *nl_sock; @@ -64,7 +64,8 @@ struct ubcore_nlmsg *ubcore_alloc_nlmsg(size_t payload_len, return msg; } -static struct ubcore_nl_session *ubcore_create_nl_session(struct ubcore_nlmsg *req) +static struct ubcore_nl_session *ubcore_create_nl_session(struct ubcore_device *dev, + struct ubcore_nlmsg *req) { struct ubcore_nl_session *s; unsigned long flags; @@ -79,6 +80,7 @@ static struct ubcore_nl_session *ubcore_create_nl_session(struct ubcore_nlmsg *r spin_unlock_irqrestore(&g_nl_session_lock, flags); kref_init(&s->kref); init_completion(&s->comp); + (void)strcpy(s->dev_name, dev->dev_name); return s; } @@ -181,6 +183,7 @@ static void ubcore_nl_handle_tpf2fe_resp(struct nlmsghdr *nlh) { struct ubcore_nl_session *s; struct ubcore_nlmsg *resp; + struct ubcore_device *dev; resp = ubcore_get_nlmsg_data(nlh); if (resp == NULL) { @@ -196,7 +199,13 @@ static void ubcore_nl_handle_tpf2fe_resp(struct nlmsghdr *nlh) s->resp = resp; kref_put(&s->kref, ubcore_free_nl_session); - s->cb.callback(resp, s->cb.user_arg); + dev = ubcore_find_device_with_name(s->dev_name); + if (dev != NULL) { + s->cb.user_arg = (void *)dev; + s->cb.callback(resp, s->cb.user_arg); + } + ubcore_put_device(dev); + kfree(s->req); kfree(s->resp); ubcore_destroy_nl_session(s); @@ -365,7 +374,7 @@ static int ubcore_nl_unicast(struct ubcore_nlmsg *pbuf, uint32_t len) return ret < 0 ? ret : 0; } -struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_nlmsg *req) +struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_device *dev, struct ubcore_nlmsg *req) { unsigned long leavetime; struct ubcore_nl_session *s; @@ -373,7 +382,7 @@ struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_nlmsg *req) int ret; req->nlmsg_seq = ubcore_get_nlmsg_seq(); - s = ubcore_create_nl_session(req); + s = ubcore_create_nl_session(dev, req); if (s == NULL) { ubcore_log_err("Failed to create nl session"); return NULL; @@ -397,13 +406,14 @@ struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_nlmsg *req) return resp; } -int ubcore_nl_send_nowait(struct ubcore_nlmsg *req, struct ubcore_nl_resp_cb *cb) +int ubcore_nl_send_nowait(struct ubcore_device *dev, struct ubcore_nlmsg *req, + struct ubcore_nl_resp_cb *cb) { struct ubcore_nl_session *s; int ret; req->nlmsg_seq = ubcore_get_nlmsg_seq(); - s = ubcore_create_nl_session(req); + s = ubcore_create_nl_session(dev, req); if (s == NULL) { ubcore_log_err("Failed to create nl session"); return -ENOMEM; diff --git a/drivers/ub/urma/ubcore/ubcore_netlink.h b/drivers/ub/urma/ubcore/ubcore_netlink.h index 56c642e92262..efb99b721c36 100644 --- a/drivers/ub/urma/ubcore/ubcore_netlink.h +++ b/drivers/ub/urma/ubcore/ubcore_netlink.h @@ -120,16 +120,17 @@ struct ubcore_nl_destroy_tp_resp { struct ubcore_nl_query_tp_req { enum ubcore_transport_mode trans_mode; + char dev_name[UBCORE_MAX_DEV_NAME]; + uint16_t fe_idx; }; struct ubcore_nl_query_tp_resp { enum ubcore_nl_resp_status ret; - bool tp_exist; - uint32_t tpn; /* must set if tp exist is true */ - union ubcore_eid dst_eid; /* underlay */ - struct ubcore_net_addr src_addr; /* underlay */ - struct ubcore_net_addr dst_addr; /* underlay */ - struct ubcore_multipath_tp_cfg cfg; + uint8_t retry_num; + uint8_t retry_factor; + uint8_t ack_timeout; + uint8_t dscp; + uint32_t oor_cnt; }; struct ubcore_nl_restore_tp_req { @@ -157,6 +158,7 @@ struct ubcore_nl_session { struct kref kref; struct ubcore_nl_resp_cb cb; struct completion comp; /* Synchronization event of timeout sleep and thread wakeup */ + char dev_name[UBCORE_MAX_DEV_NAME]; }; struct ubcore_add_sip_req { @@ -209,10 +211,16 @@ struct ubcore_nl_function_mig_req { char dev_name[UBCORE_MAX_DEV_NAME]; }; +enum ubcore_update_tpf_opcode { + UBCORE_UPDATE_TPF_ADD = 0, + UBCORE_UPDATE_TPF_DEL +}; + struct ubcore_update_tpf_dev_info_req { char dev_name[UBCORE_MAX_DEV_NAME]; union ubcore_device_feat dev_fea; uint32_t cc_entry_cnt; + enum ubcore_update_tpf_opcode opcode; uint8_t data[0]; }; // same as tpsa_nl_update_tpf_dev_info_req @@ -230,9 +238,10 @@ 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_nlmsg *req); +struct ubcore_nlmsg *ubcore_nl_send_wait(struct ubcore_device *dev, struct ubcore_nlmsg *req); -int ubcore_nl_send_nowait(struct ubcore_nlmsg *req, struct ubcore_nl_resp_cb *cb); +int ubcore_nl_send_nowait(struct ubcore_device *dev, struct ubcore_nlmsg *req, + struct ubcore_nl_resp_cb *cb); int ubcore_nl_send_nowait_without_cb(struct ubcore_nlmsg *req); struct ubcore_nlmsg *ubcore_alloc_nlmsg(size_t payload_len, const union ubcore_eid *src_eid, const union ubcore_eid *dst_eid); @@ -240,3 +249,4 @@ 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); #endif + diff --git a/drivers/ub/urma/ubcore/ubcore_priv.h b/drivers/ub/urma/ubcore/ubcore_priv.h index e8bee35d7990..42d3193754bc 100644 --- a/drivers/ub/urma/ubcore/ubcore_priv.h +++ b/drivers/ub/urma/ubcore/ubcore_priv.h @@ -56,8 +56,9 @@ union ubcore_set_vport_cfg_mask { uint32_t max_jetty_cnt : 1; uint32_t min_jfr_cnt : 1; uint32_t max_jfr_cnt : 1; + uint32_t tp_cnt : 1; uint32_t slice : 1; - uint32_t reserved : 25; + uint32_t reserved : 24; } bs; uint32_t value; }; @@ -72,6 +73,7 @@ struct ubcore_set_vport_cfg { uint32_t max_jetty_cnt; uint32_t min_jfr_cnt; uint32_t max_jfr_cnt; + uint32_t tp_cnt; uint32_t slice; }; @@ -98,6 +100,11 @@ 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, 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); + 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); @@ -121,7 +128,6 @@ 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); -void ubcore_abort_tp(struct ubcore_tp *tp, struct ubcore_tp_meta *meta); int ubcore_modify_tp(struct ubcore_device *dev, struct ubcore_tp_node *tp_node, struct ubcore_tp_attr *tp_attr, struct ubcore_udata udata); diff --git a/drivers/ub/urma/ubcore/ubcore_tp.c b/drivers/ub/urma/ubcore/ubcore_tp.c index 7a75a7625c81..e6f372a9cec6 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.c +++ b/drivers/ub/urma/ubcore/ubcore_tp.c @@ -37,21 +37,11 @@ #define UB_MTU_BITS_BASE_SHIFT 7 #define UBCORE_TP_ATTR_MASK 0x7FFFF -struct ubcore_resp_args { - struct ubcore_udata *udata; - enum ubcore_transport_mode trans_mode; -}; - static inline uint32_t get_udrv_in_len(struct ubcore_udata *udata) { return ((udata == NULL || udata->udrv_data == NULL) ? 0 : udata->udrv_data->in_len); } -static inline uint32_t get_udrv_out_len(const struct ubcore_udata *udata) -{ - return ((udata == NULL || udata->udrv_data == NULL) ? 0 : udata->udrv_data->out_len); -} - 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) @@ -179,9 +169,6 @@ static int ubcore_nl_handle_create_tp_resp_cb(struct ubcore_device *dev, struct ubcore_resp *resp, void *user_arg) { struct ubcore_create_vtp_resp *vtp_resp; - struct ubcore_resp_args *input; - struct ubcore_udata *udata; - int ret = -1; vtp_resp = (struct ubcore_create_vtp_resp *)resp->data; if (vtp_resp->ret == UBCORE_MSG_RESP_FAIL) { @@ -194,26 +181,7 @@ static int ubcore_nl_handle_create_tp_resp_cb(struct ubcore_device *dev, ubcore_log_err("failed: rc jetty already bind by other jetty"); return -1; } - - input = (struct ubcore_resp_args *)user_arg; - if (input->trans_mode == UBCORE_TP_RM) - /* There is no need to copy udrv out data, otherwise it will be overwritten. */ - return 0; - - udata = (struct ubcore_udata *)input->udata; - if (udata == NULL) - return 0; - - if (udata->udrv_data->out_len < vtp_resp->udrv_out_len) { - ubcore_log_err( - "udata user mode len length is too small,udata->udrv_data->out_len: %u, resp_len: %u", - udata->udrv_data->out_len, vtp_resp->udrv_out_len); - return -1; - } - ret = (int)copy_to_user((void __user *)(uintptr_t)udata->udrv_data->out_addr, - (char *)vtp_resp->udrv_out_data, vtp_resp->udrv_out_len); - - return ret; + return 0; } int ubcore_destroy_tp(struct ubcore_tp *tp) @@ -275,6 +243,7 @@ struct ubcore_tp *ubcore_create_tp(struct ubcore_device *dev, 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; @@ -302,7 +271,7 @@ static int ubcore_destroy_peer_tp(struct ubcore_tp *tp, struct ubcore_ta *ta) return -1; } - resp_msg = ubcore_nl_send_wait(req_msg); + 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); @@ -339,21 +308,6 @@ static int ubcore_destroy_local_peer_tp(struct ubcore_tp *tp, struct ubcore_ta * return ubcore_destroy_tp(tp); } -void ubcore_abort_tp(struct ubcore_tp *tp, struct ubcore_tp_meta *meta) -{ - struct ubcore_tp *target; - - if (tp == NULL) - return; - - target = ubcore_find_remove_tp(meta->ht, meta->hash, &meta->key); - if (target == NULL || target != tp) { - ubcore_log_warn("TP is not found, already removed or under use\n"); - return; - } - (void)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) { @@ -392,6 +346,73 @@ int ubcore_fill_netaddr_macvlan(struct ubcore_net_addr *netaddr, struct net_devi return 0; } +/* check if current tp state can be truned into new tp state */ +int ubcore_modify_tp_state_check(struct ubcore_tp *tp, enum ubcore_tp_state new_state) +{ + int ret = 0; + + switch (tp->state) { + case UBCORE_TP_STATE_RESET: + if (new_state != UBCORE_TP_STATE_RTR) + ret = -1; + break; + case UBCORE_TP_STATE_RTR: + if (new_state != UBCORE_TP_STATE_ERR && new_state != UBCORE_TP_STATE_RTS) + ret = -1; + break; + case UBCORE_TP_STATE_RTS: + if (new_state != UBCORE_TP_STATE_ERR && new_state != UBCORE_TP_STATE_SUSPENDED) + ret = -1; + break; + case UBCORE_TP_STATE_SUSPENDED: + if (new_state != UBCORE_TP_STATE_RTS && new_state != UBCORE_TP_STATE_ERR) + ret = -1; + break; + case UBCORE_TP_STATE_ERR: + /* ERR -> ERR is allowed */ + if (new_state != UBCORE_TP_STATE_ERR && new_state != UBCORE_TP_STATE_RESET) + ret = -1; + break; + default: + ret = -1; + break; + } + + if (ret != 0) { + ubcore_log_err("modify_tp state check WARNING: tpn = %u; old_state %u -> new_state %u", + tp->tpn, (uint32_t)tp->state, (uint32_t)new_state); + } else { + ubcore_log_info("modify_tp state check: tpn = %u; old_state %u -> new_state %u", + tp->tpn, (uint32_t)tp->state, (uint32_t)new_state); + } + + return ret; +} + +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) +{ + if (ubcore_modify_tp_state_check(tp, new_state) != 0) + return -1; + + if (tp->state == UBCORE_TP_STATE_ERR && new_state == UBCORE_TP_STATE_ERR) { + ubcore_log_info("tp is already in ERR state and tpn = %u", + tp->tpn); + return 0; + } + + if (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); + return -1; + } + 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); + return 0; +} + static int ubcore_modify_tp_to_rts(const struct ubcore_device *dev, struct ubcore_tp *tp) { union ubcore_tp_attr_mask mask; @@ -408,6 +429,7 @@ static int ubcore_modify_tp_to_rts(const struct ubcore_device *dev, struct ubcor return -1; } tp->state = UBCORE_TP_STATE_RTS; + ubcore_log_info("tp state:(RTR to RTS) with tpn %u, peer_tpn %u", tp->tpn, tp->peer_tpn); return 0; } @@ -536,12 +558,14 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, 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->eid_index = jfs->jfs_cfg.eid_index; break; case UBCORE_TA_JETTY_TJETTY: jetty = ta->jetty; 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->eid_index = jetty->jetty_cfg.eid_index; break; case UBCORE_TA_NONE: case UBCORE_TA_VIRT: @@ -552,7 +576,6 @@ static void ubcore_set_jetty_for_tp_param(struct ubcore_ta *ta, vtp_param->peer_eid = ta->tjetty_id.eid; vtp_param->peer_jetty = ta->tjetty_id.id; vtp_param->eid_index = 0; - vtp_param->wait = true; vtp_param->ta = *ta; } @@ -809,19 +832,6 @@ struct ubcore_nlmsg *ubcore_handle_create_tp_req(struct ubcore_nlmsg *req) } EXPORT_SYMBOL(ubcore_handle_create_tp_req); -/* destroy target vtp created by ubcore_accept_target_vtp */ -static int ubcore_unaccept_target_vtp(struct ubcore_device *dev, - struct ubcore_nl_destroy_tp_req *destroy) -{ - struct ubcore_tp *tp = ubcore_remove_tp_with_tpn(dev, destroy->peer_tpn); - - if (tp == NULL) { - ubcore_log_warn("tp is not found or already destroyed %u", destroy->peer_tpn); - return 0; - } - return ubcore_destroy_tp(tp); -} - /* 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) @@ -839,15 +849,6 @@ static int ubcore_unadvise_target_tp(struct ubcore_device *dev, return 0; } - tp = ubcore_find_remove_tp(meta->ht, meta->hash, &meta->key); - /* pair with get_tptable in parse_ta */ - ubcore_put_tptable(meta->ht); - if (tp == NULL) { - ubcore_log_warn("tp is not found, already destroyed or under use %u", - destroy->peer_tpn); - return 0; - } - return ubcore_destroy_tp(tp); } @@ -879,7 +880,6 @@ struct ubcore_nlmsg *ubcore_handle_destroy_tp_req(struct ubcore_nlmsg *req) } if (destroy->ta.ta_type == UBCORE_TA_VIRT) { - ret = ubcore_unaccept_target_vtp(dev, destroy); } else if (destroy->trans_mode == UBCORE_TP_RC) { ret = ubcore_unbind_target_tp(dev, destroy); } else if (destroy->trans_mode == UBCORE_TP_RM && @@ -945,18 +945,44 @@ int ubcore_destroy_vtp(struct ubcore_tp *vtp) } 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) +{ + data->trans_mode = tp_param->trans_mode; + data->local_eid = tp_param->local_eid; + data->peer_eid = tp_param->peer_eid; + 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); + data->virtualization = dev->attr.virtualization; + + ubcore_get_ta_data_from_ta(&tp_param->ta, dev->transport_type, &data->ta_data); + data->udrv_in_len = get_udrv_in_len(udata); + data->ext_len = tp->tp_ext.len; + + if (get_udrv_in_data(data->udrv_ext, get_udrv_in_len(udata), udata) != 0) { + ubcore_log_err("Failed to get udrv data"); + return -1; + } + if (tp->tp_ext.len > 0) + (void)memcpy(data->udrv_ext + get_udrv_in_len(udata), + (void *)tp->tp_ext.addr, tp->tp_ext.len); + + return 0; +} + static int ubcore_send_create_tp_req(struct ubcore_device *dev, struct ubcore_vtp_param *tp_param, - struct ubcore_udata *udata) + struct ubcore_tp *tp, struct ubcore_udata *udata) { struct ubcore_create_vtp_req *data; - struct ubcore_resp_args user_arg; struct ubcore_req *req_msg; struct ubcore_resp_cb cb; uint32_t payload_len; int ret; - payload_len = (uint32_t)sizeof(struct ubcore_create_vtp_req) + get_udrv_in_len(udata); - + payload_len = (uint32_t)sizeof(struct ubcore_create_vtp_req) + + tp->tp_ext.len + get_udrv_in_len(udata); req_msg = kcalloc(1, sizeof(struct ubcore_req) + payload_len, GFP_KERNEL); if (req_msg == NULL) return -ENOMEM; @@ -964,6 +990,48 @@ 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; + /* for alpha end */ + cb.callback = ubcore_nl_handle_create_tp_resp_cb; + cb.user_arg = NULL; + ret = ubcore_send_fe2tpf_msg(dev, req_msg, &cb); + if (ret != 0) + ubcore_log_err("send fe2tpf failed.\n"); + kfree(req_msg); + return ret; +} + +static int ubcore_handle_del_tp_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; + + if (vtp_resp->ret == 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; + } + return 0; +} + +static int ubcore_send_del_tp_req(struct ubcore_device *dev, struct ubcore_vtp_param *tp_param) +{ + struct ubcore_create_vtp_req *data; + struct ubcore_req *req_msg; + struct ubcore_resp_cb cb; + int ret; + + req_msg = kcalloc(1, sizeof(struct ubcore_req) + + sizeof(struct ubcore_create_vtp_req), GFP_KERNEL); + if (req_msg == NULL) + return -ENOMEM; + + req_msg->opcode = UBCORE_MSG_DESTROY_VTP; + req_msg->len = sizeof(struct ubcore_create_vtp_req); + data = (struct ubcore_create_vtp_req *)req_msg->data; data->trans_mode = tp_param->trans_mode; data->local_eid = tp_param->local_eid; data->peer_eid = tp_param->peer_eid; @@ -974,31 +1042,109 @@ static int ubcore_send_create_tp_req(struct ubcore_device *dev, struct ubcore_vt data->virtualization = dev->attr.virtualization; /* for alpha start */ ubcore_get_ta_data_from_ta(&tp_param->ta, dev->transport_type, &data->ta_data); - data->udrv_in_len = get_udrv_in_len(udata); - data->udrv_out_len = get_udrv_out_len(udata); - if (get_udrv_in_data(data->udrv_data, get_udrv_in_len(udata), udata) != 0) { - ubcore_log_err("Failed to get udrv data"); - kfree(req_msg); - return -1; - } /* for alpha end */ - user_arg.udata = udata; - user_arg.trans_mode = tp_param->trans_mode; - cb.callback = ubcore_nl_handle_create_tp_resp_cb; - cb.user_arg = &user_arg; - ret = ubcore_send_fe2tpf_msg(dev, req_msg, true, &cb); + cb.callback = ubcore_handle_del_tp_resp; + cb.user_arg = NULL; + ret = ubcore_send_fe2tpf_msg(dev, req_msg, &cb); if (ret != 0) ubcore_log_err("send fe2tpf failed.\n"); + kfree(req_msg); + return ret; +} + +static struct ubcore_nlmsg *ubcore_get_query_tp_req(struct ubcore_device *dev, + enum ubcore_transport_mode trans_mode) +{ + uint32_t payload_len = sizeof(struct ubcore_nl_query_tp_req); + struct ubcore_nl_query_tp_req *query; + struct ubcore_nlmsg *req; + + req = kzalloc(sizeof(struct ubcore_nlmsg) + payload_len, GFP_KERNEL); + if (req == NULL) + return NULL; + + req->transport_type = dev->transport_type; + req->msg_type = UBCORE_NL_QUERY_TP_REQ; + req->payload_len = payload_len; + 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 */ + return req; +} + +static int ubcore_query_tp(struct ubcore_device *dev, + enum ubcore_transport_mode trans_mode, + struct ubcore_nl_query_tp_resp *query_tp_resp) +{ + struct ubcore_nlmsg *req_msg, *resp_msg; + struct ubcore_nl_query_tp_resp *resp; + int ret = 0; + + req_msg = ubcore_get_query_tp_req(dev, trans_mode); + if (req_msg == NULL) { + ubcore_log_err("Failed to get query tp req"); + 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_nl_query_tp_resp *)(void *)resp_msg->payload; + if (resp_msg->msg_type != UBCORE_NL_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", + resp_msg->msg_type, (resp == NULL ? 1 : resp->ret)); + } else { + (void)memcpy(query_tp_resp, resp, sizeof(struct ubcore_nl_query_tp_resp)); + } + kfree(resp_msg); + kfree(req_msg); return ret; } -int ubcore_bind_tp(struct ubcore_jetty *jetty, - struct ubcore_tjetty *tjetty, struct ubcore_tp_advice *advice, struct ubcore_udata *udata) +static void ubcore_set_initiator_tp_cfg(struct ubcore_tp_cfg *cfg, + struct ubcore_vtp_param *tp_param, struct ubcore_nl_query_tp_resp *query_tp_resp) +{ + cfg->flag.bs.target = 0; + cfg->local_jetty.eid = tp_param->local_eid; + cfg->local_jetty.id = tp_param->local_jetty; + cfg->peer_jetty.eid = tp_param->peer_eid; + cfg->peer_jetty.id = tp_param->peer_jetty; + cfg->trans_mode = tp_param->trans_mode; + cfg->retry_factor = query_tp_resp->retry_factor; + cfg->retry_num = query_tp_resp->retry_num; + cfg->ack_timeout = query_tp_resp->ack_timeout; + cfg->dscp = query_tp_resp->dscp; + cfg->oor_cnt = query_tp_resp->oor_cnt; +} + +static int ubcore_query_initiator_tp_cfg(struct ubcore_tp_cfg *cfg, struct ubcore_device *dev, + struct ubcore_vtp_param *tp_param) +{ + struct ubcore_nl_query_tp_resp query_tp_resp; + + if (ubcore_query_tp(dev, tp_param->trans_mode, &query_tp_resp) != 0) { + ubcore_log_err("Failed to query tp"); + return -1; + } + ubcore_set_initiator_tp_cfg(cfg, tp_param, &query_tp_resp); + return 0; +} + +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 }; mutex_lock(&tjetty->lock); if (tjetty->tp != NULL) { @@ -1009,17 +1155,31 @@ int ubcore_bind_tp(struct ubcore_jetty *jetty, mutex_unlock(&tjetty->lock); ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RC, &tp_param); - if (ubcore_send_create_tp_req(dev, &tp_param, udata) != 0) { - ubcore_log_err("Failed to send tp req"); + if (ubcore_query_initiator_tp_cfg(&tp_cfg, dev, &tp_param) != 0) { + ubcore_log_err("Failed to init tp cfg.\n"); return -1; } - mutex_lock(&tjetty->lock); - tp_node = (struct ubcore_tp_node *)ubcore_hash_table_lookup(advice->meta.ht, - advice->meta.hash, &advice->meta.key); + /* 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) { + ubcore_log_err("Failed to create tp"); + return -1; + } + tp_node = ubcore_add_tp_node(advice->meta.ht, advice->meta.hash, &advice->meta.key, + new_tp, &advice->ta); if (tp_node == NULL) { - mutex_unlock(&tjetty->lock); + (void)ubcore_destroy_tp(new_tp); + ubcore_log_err("Failed to find and add tp\n"); return -1; + } else if (tp_node != NULL && tp_node->tp != new_tp) { + (void)ubcore_destroy_tp(new_tp); + new_tp = NULL; } + if (ubcore_send_create_tp_req(dev, &tp_param, tp_node->tp, udata) != 0) { + ubcore_log_err("Failed to send tp req"); + return -1; + } + mutex_lock(&tjetty->lock); tjetty->tp = tp_node->tp; mutex_unlock(&tjetty->lock); return 0; @@ -1029,11 +1189,14 @@ EXPORT_SYMBOL(ubcore_bind_tp); int ubcore_unbind_tp(struct ubcore_jetty *jetty, struct ubcore_tjetty *tjetty, struct ubcore_tp_advice *advice) { + struct ubcore_vtp_param tp_param; + if (tjetty->tp == NULL) { ubcore_log_warn("TP is not found, already removed or under use\n"); return 0; } - if (ubcore_unadvise_tp(jetty->ub_dev, advice) != 0) { + 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; } @@ -1048,9 +1211,9 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, struct ubcore_tp_advice *advice, struct ubcore_udata *udata) { struct ubcore_vtp_param tp_param = {0}; + struct ubcore_tp_cfg tp_cfg = { 0 }; struct ubcore_tp_node *tp_node; struct ubcore_tp *new_tp; - struct ubcore_tp_cfg tp_cfg; /* 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); @@ -1058,11 +1221,10 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, return 0; ubcore_set_jetty_for_tp_param(&advice->ta, UBCORE_TP_RM, &tp_param); - tp_cfg.flag.bs.target = 0; - tp_cfg.local_eid = tp_param.local_eid; - tp_cfg.peer_eid = tp_param.peer_eid; - tp_cfg.trans_mode = tp_param.trans_mode; - + if (ubcore_query_initiator_tp_cfg(&tp_cfg, dev, &tp_param) != 0) { + ubcore_log_err("Failed to init tp cfg.\n"); + return -1; + } /* advise tp requires the user to pass in the pin memory operation * and cannot be used in the uvs context ioctl to create tp */ @@ -1082,8 +1244,8 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, new_tp = NULL; } - if (ubcore_send_create_tp_req(dev, &tp_param, udata) != 0) { - ubcore_abort_tp(tp_node->tp, &advice->meta); + if (ubcore_send_create_tp_req(dev, &tp_param, tp_node->tp, udata) != 0) { + ubcore_find_remove_tp(advice->meta.ht, advice->meta.hash, &advice->meta.key); ubcore_log_err("Failed to send tp req"); return -1; } @@ -1092,56 +1254,6 @@ int ubcore_advise_tp(struct ubcore_device *dev, union ubcore_eid *remote_eid, } EXPORT_SYMBOL(ubcore_advise_tp); -static int ubcore_handle_del_tp_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; - - if (vtp_resp->ret == 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; - } - return 0; -} - -static int ubcore_send_del_tp_req(struct ubcore_device *dev, struct ubcore_vtp_param *tp_param) -{ - struct ubcore_create_vtp_req *data; - struct ubcore_req *req_msg; - struct ubcore_resp_cb cb; - int ret; - - req_msg = kcalloc(1, sizeof(struct ubcore_req) + - sizeof(struct ubcore_create_vtp_req), GFP_KERNEL); - if (req_msg == NULL) - return -ENOMEM; - - req_msg->opcode = UBCORE_MSG_DESTROY_VTP; - req_msg->len = sizeof(struct ubcore_create_vtp_req); - data = (struct ubcore_create_vtp_req *)req_msg->data; - data->trans_mode = tp_param->trans_mode; - data->local_eid = tp_param->local_eid; - data->peer_eid = tp_param->peer_eid; - 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); - data->virtualization = dev->attr.virtualization; - /* for alpha start */ - ubcore_get_ta_data_from_ta(&tp_param->ta, dev->transport_type, &data->ta_data); - /* for alpha end */ - cb.callback = ubcore_handle_del_tp_resp; - cb.user_arg = NULL; - ret = ubcore_send_fe2tpf_msg(dev, req_msg, true, &cb); - if (ret != 0) - ubcore_log_err("send fe2tpf failed.\n"); - - return ret; -} - int ubcore_unadvise_tp(struct ubcore_device *dev, struct ubcore_tp_advice *advice) { struct ubcore_vtp_param tp_param; @@ -1232,12 +1344,9 @@ static int ubcore_restore_tp_to_reset(struct ubcore_device *dev, struct ubcore_t ubcore_log_info("restore tp to reset(mask): state: %u", mask.bs.state); ubcore_log_info("restore tp to reset(attr): state: %u", (uint32_t)attr.state); - if (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"); + if (ubcore_modify_tp_state(dev, tp, UBCORE_TP_STATE_RESET, &attr, mask) != 0) return -1; - } - tp->state = UBCORE_TP_STATE_RESET; + return 0; } @@ -1260,13 +1369,9 @@ static int ubcore_restore_tp_to_rts(struct ubcore_device *dev, struct ubcore_tp ubcore_log_info("restore tp to rts(attr): state: %u, rx_psn: %u, tx_psn: %u", (uint32_t)attr.state, attr.rx_psn, attr.tx_psn); - if (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"); + if (ubcore_modify_tp_state(dev, tp, UBCORE_TP_STATE_RESET, &attr, mask) != 0) return -1; - } - tp->state = UBCORE_TP_STATE_RTS; tp->rx_psn = rx_psn; tp->tx_psn = tx_psn; @@ -1300,13 +1405,9 @@ int ubcore_restore_tp_error_to_rtr(struct ubcore_device *dev, struct ubcore_tp * (uint32_t)attr.state, attr.rx_psn, attr.tx_psn, attr.data_udp_start, attr.ack_udp_start); - if (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"); + if (ubcore_modify_tp_state(dev, tp, UBCORE_TP_STATE_RESET, &attr, mask) != 0) return -1; - } - tp->state = UBCORE_TP_STATE_RTR; tp->rx_psn = rx_psn; tp->tx_psn = tx_psn; tp->data_udp_start = data_udp_start; @@ -1328,13 +1429,8 @@ int ubcore_restore_tp_error_to_rts(struct ubcore_device *dev, struct ubcore_tp * ubcore_log_info("restore tp to rts, state mask: %u state: %u", mask.bs.state, (uint32_t)attr.state); - if (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"); + if (ubcore_modify_tp_state(dev, tp, UBCORE_TP_STATE_RESET, &attr, mask) != 0) return -1; - } - - tp->state = UBCORE_TP_STATE_RTS; return 0; } @@ -1349,13 +1445,8 @@ int ubcore_change_tp_to_err(struct ubcore_device *dev, struct ubcore_tp *tp) attr.state = UBCORE_TP_STATE_ERR; - if (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"); + if (ubcore_modify_tp_state(dev, tp, UBCORE_TP_STATE_RESET, &attr, mask) != 0) return -1; - } - - tp->state = UBCORE_TP_STATE_ERR; return 0; } @@ -1381,7 +1472,7 @@ void ubcore_restore_tp(struct ubcore_device *dev, struct ubcore_tp *tp) return; } - resp_msg = ubcore_nl_send_wait(req_msg); + resp_msg = ubcore_nl_send_wait(dev, req_msg); if (resp_msg == NULL) { ubcore_log_err("Failed to wait restore tp response %pI6c", &tp->peer_eid); kfree(req_msg); @@ -1446,9 +1537,16 @@ void ubcore_report_tp_error(struct ubcore_device *dev, struct ubcore_tp *tp) struct ubcore_nlmsg *req_msg; int ret; - if (ubcore_restore_tp_to_reset(dev, tp) != 0) { - ubcore_log_err("Failed to restore tp to reset"); - return; + if (tp->state != UBCORE_TP_STATE_RESET) { + if (ubcore_change_tp_to_err(dev, tp) != 0) { + ubcore_log_err("Failed to change tp to err"); + return; + } + + if (ubcore_restore_tp_to_reset(dev, tp) != 0) { + ubcore_log_err("Failed to restore tp to reset"); + return; + } } req_msg = ubcore_get_tp_error_req(tp); @@ -1465,7 +1563,6 @@ void ubcore_report_tp_error(struct ubcore_device *dev, struct ubcore_tp *tp) kfree(req_msg); } -EXPORT_SYMBOL(ubcore_report_tp_error); static struct ubcore_nlmsg *ubcore_get_tp_suspend_req(struct ubcore_tp *tp) { @@ -1510,7 +1607,6 @@ void ubcore_report_tp_suspend(struct ubcore_device *dev, struct ubcore_tp *tp) kfree(req_msg); } -EXPORT_SYMBOL(ubcore_report_tp_suspend); /* restore target RM tp created by ubcore_advise_target_tp */ static struct ubcore_tp *ubcore_restore_advised_target_tp(struct ubcore_device *dev, diff --git a/drivers/ub/urma/ubcore/ubcore_tp.h b/drivers/ub/urma/ubcore/ubcore_tp.h index 2fb087ba6b03..450ee00f1477 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp.h +++ b/drivers/ub/urma/ubcore/ubcore_tp.h @@ -72,4 +72,5 @@ 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); #endif diff --git a/drivers/ub/urma/ubcore/ubcore_tp_table.c b/drivers/ub/urma/ubcore/ubcore_tp_table.c index a0b7014ca493..95917ea0f0f6 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp_table.c +++ b/drivers/ub/urma/ubcore/ubcore_tp_table.c @@ -42,7 +42,7 @@ void ubcore_remove_tp_node(struct ubcore_hash_table *ht, struct ubcore_tp_node * } /* Find and remove the tp from table only if it is unreferenced */ -struct ubcore_tp *ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, +void ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, const struct ubcore_tp_key *key) { struct ubcore_tp_node *tp_node; @@ -51,22 +51,21 @@ struct ubcore_tp *ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t h spin_lock(&ht->lock); if (ht->head == NULL) { spin_unlock(&ht->lock); - return NULL; + return; } tp_node = ubcore_hash_table_lookup_nolock(ht, hash, key); if (tp_node == NULL) { spin_unlock(&ht->lock); - return NULL; + 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); } spin_unlock(&ht->lock); - return tp; } struct ubcore_hash_table *ubcore_create_tptable(void) @@ -166,6 +165,7 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t spin_unlock(&ht->lock); mutex_destroy(&new_tp_node->lock); kfree(new_tp_node); + atomic_inc(&tp_node->tp->use_cnt); return tp_node; } @@ -173,6 +173,7 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t /* set private data for tp restore */ tp->priv = new_tp_node; spin_unlock(&ht->lock); + atomic_inc(&new_tp_node->tp->use_cnt); return new_tp_node; } @@ -202,12 +203,3 @@ struct ubcore_tp_node *ubcore_add_tp_with_tpn(struct ubcore_device *dev, struct return tp_node; } -struct ubcore_tp *ubcore_remove_tp_with_tpn(struct ubcore_device *dev, uint32_t tpn) -{ - struct ubcore_tp_key key; - - memset(&key, 0, sizeof(struct ubcore_tp_key)); - key.key_type = UBCORE_TP_KEY_TPN; - key.tpn = tpn; - return ubcore_find_remove_tp(&dev->ht[UBCORE_HT_TP], tpn, &key); -} diff --git a/drivers/ub/urma/ubcore/ubcore_tp_table.h b/drivers/ub/urma/ubcore/ubcore_tp_table.h index abf6e12c4fc6..8ef552f9ca2e 100644 --- a/drivers/ub/urma/ubcore/ubcore_tp_table.h +++ b/drivers/ub/urma/ubcore/ubcore_tp_table.h @@ -51,7 +51,7 @@ struct ubcore_tp_node *ubcore_add_tp_node(struct ubcore_hash_table *ht, uint32_t struct ubcore_ta *ta); void ubcore_remove_tp_node(struct ubcore_hash_table *ht, struct ubcore_tp_node *tp_node); /* Find and remove the tp from table only if it is unreferenced */ -struct ubcore_tp *ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, +void ubcore_find_remove_tp(struct ubcore_hash_table *ht, uint32_t hash, const struct ubcore_tp_key *key); /* TP table ops for devices that do not natively support RM */ @@ -61,5 +61,4 @@ 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); -struct ubcore_tp *ubcore_remove_tp_with_tpn(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 7c519cab6188..c2ec7ad67617 100644 --- a/drivers/ub/urma/ubcore/ubcore_umem.c +++ b/drivers/ub/urma/ubcore/ubcore_umem.c @@ -59,6 +59,7 @@ static int umem_pin_pages(uint64_t cur_base, uint64_t npages, uint32_t gup_flags min_t(unsigned long, (unsigned long)npages, PAGE_SIZE / sizeof(struct page *)), gup_flags | FOLL_LONGTERM, page_list); + return pinned; } @@ -67,6 +68,7 @@ static uint64_t umem_atomic_add(uint64_t npages, struct mm_struct *mm) uint64_t ret; ret = atomic64_add_return(npages, &mm->pinned_vm); + return ret; } diff --git a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c index 99159ef3fb3f..97bac1ef6cbb 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.c @@ -191,12 +191,6 @@ static int ubcore_copy_tpg_udrv_data(struct ubcore_cmd_hdr *hdr, struct ubcore_c if (ubcore_get_active_mtu(tp_node->tp->ub_dev, 0, &arg->local_mtu) != 0) return -1; - - if (arg->udrv_ext.out_len < tp_node->tp->tp_ext.len) { - ubcore_log_err("tp_ext memory is not long enough\n"); - return -1; - } - arg->udrv_ext.out_len = tp_node->tp->tp_ext.len; arg->out.tpn[0] = tp_node->tp->tpn; ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, @@ -204,10 +198,6 @@ static int ubcore_copy_tpg_udrv_data(struct ubcore_cmd_hdr *hdr, struct ubcore_c if (ret) return -1; - ret = (int)copy_to_user((void __user *)(uintptr_t)arg->udrv_ext.out_addr, - (char *)tp_node->tp->tp_ext.addr, - tp_node->tp->tp_ext.len); - return ret; } @@ -242,8 +232,9 @@ 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); } - atomic_inc(&tp_node->tp->use_cnt); return tp_node; } @@ -253,7 +244,6 @@ static int ubcore_cmd_create_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_cr struct ubcore_tp_cfg tp_cfg = { 0 }; struct ubcore_tp_node *tp_node = NULL; struct ubcore_device *dev = NULL; - struct ubcore_udata udata = { 0 }; int ret = 0; dev = ubcore_find_device(&arg->ta_data.jetty_id.eid, arg->ta_data.trans_type); @@ -267,28 +257,21 @@ 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]); - ubcore_set_udata(&udata, &advice, (struct ubcore_udrv_priv *)&arg->udata); - tp_node = ubcore_get_tp_node(dev, &advice, &tp_cfg, &udata); + tp_node = ubcore_hash_table_lookup(advice.meta.ht, advice.meta.hash, &advice.meta.key); if (!tp_node) - goto put_device; - - /* 1636 rm mode creates tp in the user context, but the tp parameter is not filled in. - * It needs to be obtained from uvs and filled in. - */ - if (tp_node->tp != NULL && tp_cfg.trans_mode == UBCORE_TP_RM) - ubcore_set_tp_init_cfg(tp_node->tp, &tp_cfg); + goto put_tptable; ret = ubcore_copy_tpg_udrv_data(hdr, arg, tp_node); if (ret) - goto remove_tp_node; + goto put_tptable; + ubcore_put_tptable(advice.meta.ht); ubcore_put_device(dev); return ret; -remove_tp_node: - ubcore_abort_tp(tp_node->tp, &advice.meta); +put_tptable: + ubcore_put_tptable(advice.meta.ht); put_device: ubcore_put_device(dev); return -1; @@ -539,17 +522,20 @@ static int ubcore_cmd_modify_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_mo 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_device; + goto put_tptable; } 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); if (ret) - goto put_device; + 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; @@ -720,16 +706,16 @@ static int ubcore_modify_target_tp_node(struct ubcore_tp_node *tp_node, struct ubcore_tp_attr *tp_attr, struct ubcore_udata *udata, struct ubcore_cmd_create_target_tpg *arg) { - if (ubcore_get_active_mtu(tp_node->tp->ub_dev, 0, &arg->local_mtu) != 0 && - (arg->local_mtu == 0 || arg->peer_mtu == 0)) - return -1; - tp_attr->mtu = min(arg->local_mtu, arg->peer_mtu); - /* 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) return 0; + if (ubcore_get_active_mtu(tp_node->tp->ub_dev, 0, &arg->local_mtu) != 0 && + (arg->local_mtu == 0 || arg->peer_mtu == 0)) + return -1; + tp_attr->mtu = min(arg->local_mtu, arg->peer_mtu); + udata->udrv_data->in_addr = arg->udrv_ext.in_addr; udata->udrv_data->in_len = arg->udrv_ext.in_len; if (ubcore_modify_tp(tp_node->tp->ub_dev, tp_node, tp_attr, *udata) != 0) { @@ -768,7 +754,7 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, 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) - goto put_device; + goto put_tptable; ret = ubcore_modify_target_tp_node(tp_node, tp_attr, &udata, arg); if (ret) @@ -778,11 +764,14 @@ static int ubcore_cmd_create_target_tp(struct ubcore_cmd_hdr *hdr, if (ret) goto remove_tp_node; + ubcore_put_tptable(advice.meta.ht); ubcore_put_device(dev); return ret; remove_tp_node: - ubcore_abort_tp(tp_node->tp, &advice.meta); + ubcore_find_remove_tp(advice.meta.ht, advice.meta.hash, &advice.meta.key); +put_tptable: + ubcore_put_tptable(advice.meta.ht); put_device: ubcore_put_device(dev); return -1; @@ -876,21 +865,25 @@ static int ubcore_cmd_modify_target_tp(struct ubcore_cmd_hdr *hdr, 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_device; + 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_device; + 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; @@ -1259,6 +1252,21 @@ static int ubcore_cmd_set_vport_cfg(struct ubcore_cmd_hdr *hdr) ubcore_log_err("find dev failed, arg_in: %s.\n", arg.in.vport_cfg.dev_name); return -EINVAL; } + + if (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; + } + + /* 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", + arg.in.vport_cfg.tp_cnt, dev->attr.dev_cap.max_tp_in_tpg); + ubcore_put_device(dev); + return -EINVAL; + } + ret = ubcore_set_vport_cfg(dev, &arg.in.vport_cfg); ubcore_put_device(dev); return ret; @@ -1267,6 +1275,7 @@ 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; int ret; @@ -1275,20 +1284,28 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; - tpf_dev = ubcore_find_device_with_name(arg.in.target_tpf_name); - if (tpf_dev == NULL) { - ubcore_log_err("failed to find tpf device"); + 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; } - ubcore_log_info("get tpf device name %s", tpf_dev->dev_name); - arg.out.port_is_active = true; - if (ubcore_check_port_state(tpf_dev, 0) != 0) { + if (ubcore_check_port_state(pf_dev, 0) != 0) { arg.out.port_is_active = false; - ubcore_log_warn("port status unactive on target side, tpf_dev: %s", - tpf_dev->dev_name); + 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); + if (tpf_dev == NULL) { + ubcore_log_err("failed to find tpf device"); + return -1; } + ubcore_log_info("get tpf device name %s", tpf_dev->dev_name); + + (void)strcpy(arg.out.target_tpf_name, tpf_dev->dev_name); ubcore_put_device(tpf_dev); if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, @@ -1298,40 +1315,26 @@ static int ubcore_cmd_get_dev_info(struct ubcore_cmd_hdr *hdr) return ret; } -static int ubcore_unmark_bind_jetty(struct ubcore_device *dev, struct ubcore_tp_advice *advice, - struct ubcore_ta_data *ta_data) +static int ubcore_unmark_bind_jetty(struct ubcore_tp_advice *advice, struct ubcore_ta_data *ta_data) { struct ubcore_tp_meta *meta; struct ubcore_jetty *jetty; - advice->ta.type = ta_data->ta_type; meta = &advice->meta; - - switch (ta_data->ta_type) { - case UBCORE_TA_JFS_TJFR: - break; - case UBCORE_TA_JETTY_TJETTY: - jetty = ubcore_find_jetty(dev, ta_data->jetty_id.id); - if (jetty != NULL && jetty->jetty_cfg.trans_mode == UBCORE_TP_RC) { - meta->ht = ubcore_get_tptable(jetty->tptable); - advice->ta.jetty = jetty; - advice->ta.tjetty_id = ta_data->tjetty_id; - if (meta->ht != NULL && memcmp(&meta->ht->rc_tjetty_id, &ta_data->tjetty_id, - sizeof(struct ubcore_jetty_id)) == 0) { - (void)memset(&meta->ht->rc_tjetty_id, - 0, sizeof(struct ubcore_jetty_id)); - } else { - ubcore_log_err("The jetty_id: %u is not bound tjetty_id: %u\n", - jetty->id, ta_data->tjetty_id.id); - return -1; - } + 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, + 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); + return -1; } - break; - case UBCORE_TA_NONE: - case UBCORE_TA_VIRT: - default: - return -1; } + spin_unlock(&meta->ht->lock); return 0; } @@ -1339,7 +1342,6 @@ static int ubcore_cmd_destroy_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_d { struct ubcore_tp_advice advice = {0}; struct ubcore_device *dev = NULL; - struct ubcore_tp *tp; int ret = 0; dev = ubcore_find_device(&arg->ta_data.jetty_id.eid, arg->ta_data.trans_type); @@ -1352,24 +1354,17 @@ static int ubcore_cmd_destroy_tp(struct ubcore_cmd_hdr *hdr, struct ubcore_cmd_d goto put_device; } else if (advice.meta.ht == NULL) { ubcore_log_err("tp table is already released"); - ret = 0; goto put_device; } if (arg->ta_data.is_target) { - ret = ubcore_unmark_bind_jetty(dev, &advice, &arg->ta_data); + ret = ubcore_unmark_bind_jetty(&advice, &arg->ta_data); if (ret != 0) - goto put_device; - } - tp = ubcore_find_remove_tp(advice.meta.ht, advice.meta.hash, &advice.meta.key); - if (tp == NULL) { - ubcore_log_warn("TP is not found, already removed or under use\n"); - ubcore_put_device(dev); - return 0; + goto put_tptable; } - ret = ubcore_destroy_tp(tp); - ubcore_put_device(dev); - return ret; + ubcore_find_remove_tp(advice.meta.ht, advice.meta.hash, &advice.meta.key); +put_tptable: + ubcore_put_tptable(advice.meta.ht); put_device: ubcore_put_device(dev); return ret; @@ -1562,6 +1557,51 @@ static int ubcore_cmd_create_utp(struct ubcore_cmd_hdr *hdr) return ret; } +static int ubcore_cmd_only_create_utp(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_create_utp *arg; + struct ubcore_device *dev; + struct ubcore_utp *utp = NULL; + int ret; + + arg = kzalloc(sizeof(struct ubcore_cmd_create_utp), GFP_KERNEL); + if (arg == NULL) + return -ENOMEM; + + ret = ubcore_copy_from_user(arg, + (void __user *)(uintptr_t)hdr->args_addr, sizeof(struct ubcore_cmd_create_utp)); + 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; + } + + utp = ubcore_create_utp(dev, &arg->in.utp_cfg); + if (utp == NULL) + goto put_device; + + /* fill output */ + arg->out.idx = utp->utpn; + + ret = ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, arg, + sizeof(struct ubcore_cmd_create_utp)); + if (ret) + goto destroy_utp; + else + goto put_device; + +destroy_utp: + (void)dev->ops->destroy_utp(utp); +put_device: + ubcore_put_device(dev); +free_arg: + kfree(arg); + return ret; +} + static int ubcore_cmd_destroy_utp(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_destroy_utp arg = {0}; @@ -1666,8 +1706,10 @@ static int ubcore_cmd_destroy_ctp(struct ubcore_cmd_hdr *hdr) return ret; dev = ubcore_find_tpf_device(&arg.in.tpf.netaddr, arg.in.tpf.trans_type); - if (dev == NULL) + if (dev == NULL) { + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg.in.tpf.netaddr.net_addr); return -ENODEV; + } ctp = ubcore_find_ctp(dev, arg.in.ctp_idx); if (ctp == NULL) { @@ -1699,10 +1741,16 @@ static int ubcore_cmd_restore_tp_error_op(struct ubcore_cmd_hdr *hdr, if (ret != 0) return ret; - /* Currently, 'netaddr' & 'type' are not necessary */ - dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); - if (dev == NULL || dev->ops == NULL || dev->ops->modify_tp == NULL) + 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); return -ENODEV; + } + + if (dev->ops == NULL || dev->ops->modify_tp == NULL) { + ret = -ENODEV; + goto put_device; + } tpg = ubcore_find_tpg(dev, arg.in.tpgn); if (tpg == NULL) { @@ -1755,6 +1803,22 @@ static int ubcore_cmd_restore_target_tp_error_ack(struct ubcore_cmd_hdr *hdr) return ubcore_cmd_restore_tp_error_op(hdr, false, true); } +static void ubcore_fill_attr_restore_tp_suspend(struct ubcore_cmd_restore_tp_suspend *arg, + union ubcore_tp_attr_mask *mask, struct ubcore_tp_attr *attr) +{ + mask->value = 0; + mask->bs.state = 1; + mask->bs.data_udp_start = 1; + mask->bs.ack_udp_start = 1; + attr->state = UBCORE_TP_STATE_RTS; + attr->data_udp_start = arg->in.data_udp_start; + attr->ack_udp_start = arg->in.ack_udp_start; + ubcore_log_info("restore tp suspend(mask): state: %u, data_udp_start: %u, ack_udp_start: %u", + mask->bs.state, mask->bs.data_udp_start, mask->bs.ack_udp_start); + ubcore_log_info("restore tp suspend(attr): state: %u, data_udp_start: %hu, ack_udp_start: %hu", + (uint32_t)attr->state, attr->data_udp_start, attr->ack_udp_start); +} + static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) { struct ubcore_cmd_restore_tp_suspend arg = {0}; @@ -1770,11 +1834,16 @@ static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; - /* Currently, 'netaddr' & 'type' are not necessary */ - dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); - if (dev == NULL || dev->ops == NULL || dev->ops->modify_tp == NULL) + 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); return -ENODEV; + } + if (dev->ops == NULL || dev->ops->modify_tp == NULL) { + ret = -ENODEV; + goto put_device; + } /* deal with RM first */ tpg = ubcore_find_tpg(dev, arg.in.tpgn); if (tpg == NULL) { @@ -1790,20 +1859,17 @@ static int ubcore_cmd_restore_tp_suspend(struct ubcore_cmd_hdr *hdr) goto put_device; } - mask.value = 0; - mask.bs.state = 1; - mask.bs.data_udp_start = 1; - mask.bs.ack_udp_start = 1; - attr.state = UBCORE_TP_STATE_RTS; - attr.data_udp_start = arg.in.data_udp_start; - attr.ack_udp_start = arg.in.ack_udp_start; - ubcore_log_info("restore tp suspend(mask): state: %u, data_udp_start: %u, ack_udp_start: %u", - mask.bs.state, mask.bs.data_udp_start, mask.bs.ack_udp_start); - ubcore_log_info("restore tp suspend(attr): state: %u, data_udp_start: %hu, ack_udp_start: %hu", - (uint32_t)attr.state, attr.data_udp_start, attr.ack_udp_start); + 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; + } + + ubcore_fill_attr_restore_tp_suspend(&arg, &mask, &attr); if (dev->ops->modify_tp(tp, &attr, mask) != 0) { ret = -1; - ubcore_log_err("Failed to modify tp"); + ubcore_log_err("Failed to modify tp to RTR from state %u and tpn = %u", + (uint32_t)tp->state, tp->tpn); goto put_device; } tp->state = UBCORE_TP_STATE_RTS; @@ -1836,6 +1902,7 @@ static int ubcore_cmd_get_dev_feature(struct ubcore_cmd_hdr *hdr) } arg.out.feature.value = dev->attr.dev_cap.feature.value; + arg.out.max_ueid_cnt = dev->attr.max_eid_cnt; ubcore_put_device(dev); if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, @@ -1858,11 +1925,16 @@ static int ubcore_cmd_change_tp_to_error(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; - /* Currently, 'netaddr' & 'type' are not necessary */ - dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); - if (dev == NULL || dev->ops == NULL || dev->ops->modify_tp == NULL) + 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); return -ENODEV; + } + if (dev->ops == NULL || dev->ops->modify_tp == NULL) { + ret = -ENODEV; + goto put_device; + } tpg = ubcore_find_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; @@ -1877,6 +1949,13 @@ static int ubcore_cmd_change_tp_to_error(struct ubcore_cmd_hdr *hdr) goto put_device; } + /* check tp's state, it cannot be change to ERR state when it's in RESET state */ + 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; + } + if (ubcore_change_tp_to_err(dev, tp) != 0) { ret = -EINVAL; ubcore_log_err("Failed to change tp to error"); @@ -1904,11 +1983,16 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) if (ret != 0) return ret; - /* Currently, 'netaddr' & 'type' are not necessary */ - dev = ubcore_find_tpf_device(NULL, UBCORE_TRANSPORT_UB); - if (dev == NULL || dev->ops == NULL || dev->ops->modify_tp == NULL) + 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); return -ENODEV; + } + if (dev->ops == NULL || dev->ops->modify_tp == NULL) { + ret = -ENODEV; + goto put_device; + } tpg = ubcore_find_tpg(dev, arg.in.tpgn); if (tpg == NULL) { ret = -EINVAL; @@ -1923,11 +2007,15 @@ static int ubcore_cmd_change_tpg_to_error(struct ubcore_cmd_hdr *hdr) continue; } - if (ubcore_change_tp_to_err(dev, tp) != 0) + 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); } - ubcore_log_info("Success to change tpg to error"); + ubcore_log_info("Success to finish cmd change tpg to error"); + + if (ubcore_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, + sizeof(struct ubcore_cmd_change_tpg_to_error)) != 0) + ret = -EPERM; put_device: ubcore_put_device(dev); @@ -2015,12 +2103,18 @@ static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) goto free_arg; dev = ubcore_find_tpf_device(&arg->in.tpf.netaddr, arg->in.tpf.trans_type); - if (dev == NULL || dev->ops == NULL || dev->ops->modify_vtp == NULL) { + if (dev == NULL) { + ubcore_log_err("Failed to find tpf by addr: %pI6c", &arg->in.tpf.netaddr.net_addr); ret = -ENODEV; - ubcore_log_err("fail to find tpf device"); goto free_arg; } + if (dev->ops == NULL || dev->ops->modify_vtp == NULL) { + ret = -ENODEV; + ubcore_log_err("fail to find tpf device"); + goto put_device; + } + for (i = 0; i < arg->in.cfg_cnt; i++) { ret = ubcore_init_modify_vtp(dev, &arg->in.vtp[i], &vtp_param, &vattr, &vattr_mask); @@ -2043,6 +2137,109 @@ static int ubcore_cmd_modify_vtp(struct ubcore_cmd_hdr *hdr) return ret; } +static int ubcore_cmd_opt_config_dscp_vl(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_opt_config_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_config_dscp_vl)); + if (ret != 0) + return ret; + 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->config_dscp_vl == NULL) { + ret = -ENODEV; + 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); + goto put_device; + } + +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; + struct ubcore_ueid_cfg cfg; + struct ubcore_device *dev; + int ret; + + ret = ubcore_copy_from_user(&arg, (void __user *)(uintptr_t)hdr->args_addr, + sizeof(struct ubcore_cmd_opt_eid)); + if (ret != 0) + return ret; + + dev = ubcore_find_device_with_name(arg.in.dev_name); + 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; + + if (hdr->command == UBCORE_CMD_ALLOC_EID) + ret = ubcore_add_ueid(dev, arg.in.fe_idx, &cfg); + else + ret = ubcore_delete_ueid(dev, arg.in.fe_idx, &cfg); + + ubcore_put_device(dev); + return ret; +} + +static int ubcore_cmd_opt_query_fe_idx(struct ubcore_cmd_hdr *hdr) +{ + struct ubcore_cmd_opt_query_fe_idx 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_fe_idx)); + if (ret != 0) + return ret; + + 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); + return -ENODEV; + } + + if (dev->ops->query_fe_idx == NULL) { + ret = -ENODEV; + goto put_device; + } + + ret = dev->ops->query_fe_idx(dev, &arg.in.devid, &arg.out.fe_idx); + if (ret != 0) { + ubcore_log_err("fail to query fe_idx, 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_fe_idx)); + +put_device: + ubcore_put_device(dev); + return ret; +} + typedef int (*ubcore_uvs_cmd_handler)(struct ubcore_cmd_hdr *hdr); static ubcore_uvs_cmd_handler g_ubcore_uvs_cmd_handlers[] = { @@ -2059,6 +2256,7 @@ static ubcore_uvs_cmd_handler g_ubcore_uvs_cmd_handlers[] = { [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, @@ -2076,6 +2274,10 @@ static ubcore_uvs_cmd_handler g_ubcore_uvs_cmd_handlers[] = { [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, }; 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 87a2094dbea8..c3d7426fc72c 100644 --- a/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h +++ b/drivers/ub/urma/ubcore/ubcore_uvs_cmd.h @@ -36,6 +36,7 @@ #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 /* only for uvs control ubcore device ioctl */ enum ubcore_uvs_cmd { @@ -51,6 +52,7 @@ enum ubcore_uvs_cmd { UBCORE_CMD_DEL_SIP, UBCORE_CMD_MAP_VTP, UBCORE_CMD_CREATE_UTP, + UBCORE_CMD_ONLY_CREATE_UTP, UBCORE_CMD_DESTROY_UTP, UBCORE_CMD_GET_DEV_FEATURE, UBCORE_CMD_RESTORE_TP_ERROR_RSP, @@ -68,9 +70,42 @@ enum ubcore_uvs_cmd { UBCORE_CMD_CREATE_CTP, UBCORE_CMD_DESTROY_CTP, UBCORE_CMD_CHANGE_TPG_TO_ERROR, + UBCORE_CMD_ALLOC_EID, + UBCORE_CMD_DEALLOC_EID, + UBCORE_CMD_QUERY_FE_IDX, + UBCORE_CMD_CONFIG_DSCP_VL, UBCORE_CMD_LAST }; +struct ubcore_cmd_opt_eid { + struct { + char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + uint32_t upi; + uint16_t fe_idx; + union ubcore_eid eid; + uint32_t eid_index; + } in; +}; + +struct ubcore_cmd_opt_query_fe_idx { + struct { + char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + struct ubcore_devid devid; + } in; + struct { + uint16_t fe_idx; + } out; +}; + +struct ubcore_cmd_opt_config_dscp_vl { + struct { + char dev_name[UBCORE_UVS_CMD_DEV_MAX]; + uint8_t dscp[UBCORE_MAX_DSCP_VL_NUM]; + uint8_t vl[UBCORE_MAX_DSCP_VL_NUM]; + uint8_t num; + } in; +}; + struct ubcore_cmd_channel_init { struct { char userspace_in[UBCORE_CMD_CHANNEL_INIT_SIZE]; @@ -127,8 +162,6 @@ struct ubcore_cmd_create_tpg { /* for alpha */ struct ubcore_ta_data ta_data; enum ubcore_mtu local_mtu; - struct ubcore_udrv_priv udata; - struct ubcore_udrv_ext udrv_ext; }; /* modify tps in the tp list of tpg to RTR, RTS, and then map vtpn to tpg */ @@ -306,6 +339,7 @@ struct ubcore_cmd_modify_vtp { /* restore tp error */ struct ubcore_cmd_restore_tp_error { struct { + struct ubcore_cmd_tpf tpf; uint32_t tpgn; uint32_t tpn; uint16_t data_udp_start; @@ -318,6 +352,7 @@ struct ubcore_cmd_restore_tp_error { /* restore tp suspend */ struct ubcore_cmd_restore_tp_suspend { struct { + struct ubcore_cmd_tpf tpf; uint32_t tpgn; uint32_t tpn; uint16_t data_udp_start; @@ -332,12 +367,14 @@ struct ubcore_cmd_get_dev_feature { } in; struct { union ubcore_device_feat feature; + uint32_t max_ueid_cnt; } out; }; /* change tp to error */ struct ubcore_cmd_change_tp_to_error { struct { + struct ubcore_cmd_tpf tpf; uint32_t tpgn; uint32_t tpn; } in; @@ -361,10 +398,12 @@ struct ubcore_cmd_show_upi { struct ubcore_cmd_get_dev_info { struct { - char target_tpf_name[UBCORE_UVS_CMD_DEV_MAX]; + char target_pf_name[UBCORE_UVS_CMD_DEV_MAX]; + struct ubcore_cmd_tpf tpf; } in; struct { bool port_is_active; + char target_tpf_name[UBCORE_UVS_CMD_DEV_MAX]; } out; }; diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.c b/drivers/ub/urma/ubcore/ubcore_vtp.c index e0396e96a795..387676a8214a 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.c +++ b/drivers/ub/urma/ubcore/ubcore_vtp.c @@ -75,8 +75,8 @@ static int ubcore_send_create_vtp_req(struct ubcore_device *dev, cb.callback = ubcore_handle_create_vtp_resp; cb.user_arg = vtpn; - ret = ubcore_send_fe2tpf_msg(dev, req, p->wait, &cb); - /* do not free req here */ + ret = ubcore_send_fe2tpf_msg(dev, req, &cb); + kfree(req); return ret; } @@ -122,8 +122,8 @@ static int ubcore_send_del_vtp_req(struct ubcore_vtpn *vtpn) cb.callback = ubcore_handle_del_vtp_resp; cb.user_arg = vtpn; - ret = ubcore_send_fe2tpf_msg(vtpn->ub_dev, req, true, &cb); - /* do not free req here */ + ret = ubcore_send_fe2tpf_msg(vtpn->ub_dev, req, &cb); + kfree(req); return ret; } @@ -136,6 +136,11 @@ static struct ubcore_vtpn *ubcore_alloc_vtpn(struct ubcore_device *dev, return NULL; vtpn = dev->ops->alloc_vtpn(dev); + if (vtpn == NULL) { + ubcore_log_err("failed to alloc vtpn!, dev_name:%s", dev->dev_name); + return NULL; + } + vtpn->ub_dev = dev; atomic_set(&vtpn->use_cnt, 1); atomic_set(&vtpn->state, (int)UBCORE_VTPS_CREATING); @@ -503,7 +508,6 @@ void ubcore_set_vtp_param(struct ubcore_device *dev, struct ubcore_jetty *jetty, vtp_param->peer_jetty = cfg->id.id; vtp_param->eid_index = cfg->eid_index; - vtp_param->wait = true; } int ubcore_config_function_migrate_state(struct ubcore_device *dev, uint16_t fe_idx, diff --git a/drivers/ub/urma/ubcore/ubcore_vtp.h b/drivers/ub/urma/ubcore/ubcore_vtp.h index 67b6fdfff38c..a6e0254d0001 100644 --- a/drivers/ub/urma/ubcore/ubcore_vtp.h +++ b/drivers/ub/urma/ubcore/ubcore_vtp.h @@ -36,7 +36,6 @@ struct ubcore_vtp_param { uint32_t local_jetty; uint32_t peer_jetty; uint32_t eid_index; - bool wait; /* wait blockingly or no wait */ /* for alpha */ struct ubcore_ta ta; }; @@ -55,8 +54,8 @@ struct ubcore_create_vtp_req { /* for alpha */ struct ubcore_ta_data ta_data; uint32_t udrv_in_len; - uint32_t udrv_out_len; - uint8_t udrv_data[0]; + uint32_t ext_len; + uint8_t udrv_ext[0]; /* struct ubcore_udrv_priv->in_len + struct ubcore_tp_ext->len*/ }; struct ubcore_create_vtp_resp { diff --git a/drivers/ub/urma/uburma/Makefile b/drivers/ub/urma/uburma/Makefile index c470b759146e..ad16b9596f03 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_cdev_file.o \ uburma_event.o \ - uburma_uobj.o + uburma_uobj.o \ + uburma_netlink.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 index a34613c1007a..e071300f5a4b 100644 --- a/drivers/ub/urma/uburma/uburma_cdev_file.c +++ b/drivers/ub/urma/uburma/uburma_cdev_file.c @@ -513,6 +513,19 @@ static ssize_t utp_cnt_show(struct device *dev, struct device_attribute *attr, c 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); @@ -622,6 +635,7 @@ static struct attribute *uburma_dev_attrs[] = { &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, @@ -956,7 +970,7 @@ static ssize_t show_eid_cb(struct ubcore_device *ubc_dev, char *buf, uint16_t id { union ubcore_eid eid; - if (ubc_dev->eid_table.eid_entries[idx].net == net) { + 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 { diff --git a/drivers/ub/urma/uburma/uburma_cmd.c b/drivers/ub/urma/uburma/uburma_cmd.c index 6645fb28cd3d..8f5aa50c668f 100644 --- a/drivers/ub/urma/uburma/uburma_cmd.c +++ b/drivers/ub/urma/uburma/uburma_cmd.c @@ -1642,6 +1642,7 @@ static int uburma_cmd_unadvise_jetty(struct ubcore_device *ubc_dev, static int uburma_cmd_bind_jetty(struct ubcore_device *ubc_dev, struct uburma_file *file, struct uburma_cmd_hdr *hdr) { + struct uburma_tjetty_uobj *uburma_tjetty; struct uburma_cmd_bind_jetty arg; struct uburma_uobj *tjetty_uobj; struct uburma_uobj *jetty_uobj; @@ -1675,6 +1676,8 @@ static int uburma_cmd_bind_jetty(struct ubcore_device *ubc_dev, else arg.out.tpn = UBURMA_INVALID_TPN; + uburma_tjetty = (struct uburma_tjetty_uobj *)(tjetty_uobj); + uburma_tjetty->jetty_uobj = (struct uburma_jetty_uobj *)jetty_uobj; ret = uburma_copy_to_user((void __user *)(uintptr_t)hdr->args_addr, &arg, sizeof(struct uburma_cmd_bind_jetty)); if (ret != 0) @@ -1687,6 +1690,7 @@ static int uburma_cmd_bind_jetty(struct ubcore_device *ubc_dev, static int uburma_cmd_unbind_jetty(struct ubcore_device *ubc_dev, struct uburma_file *file, struct uburma_cmd_hdr *hdr) { + struct uburma_tjetty_uobj *uburma_tjetty; struct uburma_cmd_unadvise_jetty arg; struct uburma_uobj *tjetty_uobj; struct uburma_uobj *jetty_uobj; @@ -1705,6 +1709,9 @@ static int uburma_cmd_unbind_jetty(struct ubcore_device *ubc_dev, if (ret != 0) uburma_log_err("failed to unbind jetty, ret: %d.\n", ret); + uburma_tjetty = (struct uburma_tjetty_uobj *)(tjetty_uobj); + uburma_tjetty->jetty_uobj = NULL; + uburma_put_jetty_tjetty_objs(jetty_uobj, tjetty_uobj); return ret; } diff --git a/drivers/ub/urma/uburma/uburma_dev_ops.c b/drivers/ub/urma/uburma/uburma_dev_ops.c index 102aa8f5cbb0..0f2655e774d2 100644 --- a/drivers/ub/urma/uburma/uburma_dev_ops.c +++ b/drivers/ub/urma/uburma/uburma_dev_ops.c @@ -29,6 +29,7 @@ #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) { @@ -97,8 +98,14 @@ int uburma_open(struct inode *inode, struct file *filp) mutex_lock(&ubu_dev->lists_mutex); ubc_dev = srcu_dereference(ubu_dev->ubc_dev, &ubu_dev->ubc_dev_srcu); if (ubc_dev == NULL || ubc_dev->dev_name == NULL) { - uburma_log_err("can not find ubcore device.\n"); ret = EIO; + uburma_log_err("can not find ubcore device.\n"); + 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; } diff --git a/drivers/ub/urma/uburma/uburma_event.c b/drivers/ub/urma/uburma/uburma_event.c index 1b630fcbb7ad..8078a37bd72f 100644 --- a/drivers/ub/urma/uburma/uburma_event.c +++ b/drivers/ub/urma/uburma/uburma_event.c @@ -127,11 +127,19 @@ void uburma_uninit_jfe(struct uburma_jfe *jfe) static int uburma_delete_jfce(struct inode *inode, struct file *filp) { struct uburma_uobj *uobj = filp->private_data; + struct uburma_file *ufile; + if (uobj == NULL || uobj->ufile == NULL) + return 0; + + ufile = uobj->ufile; + mutex_lock(&ufile->mutex); uobj_get(uobj); /* will call uburma_hot_unplug_jfce if clean up is not going on */ uburma_close_uobj_fd(filp); uobj_put(uobj); + mutex_unlock(&ufile->mutex); + return 0; } @@ -336,13 +344,20 @@ static int uburma_delete_jfae(struct inode *inode, struct file *filp) { struct uburma_uobj *uobj = filp->private_data; struct uburma_jfae_uobj *jfae = container_of(uobj, struct uburma_jfae_uobj, uobj); + struct uburma_file *ufile; - /* todonext: handle uobj == NULL */ + if (uobj == NULL || jfae == NULL || uobj->ufile == NULL) + return 0; + + ufile = uobj->ufile; + mutex_lock(&ufile->mutex); uobj_get(uobj); /* call uburma_hot_unplug_jfae when cleanup is not going on */ uburma_close_uobj_fd(filp); uburma_uninit_jfe(&jfae->jfe); uobj_put(uobj); + mutex_unlock(&ufile->mutex); + return 0; } diff --git a/drivers/ub/urma/uburma/uburma_main.c b/drivers/ub/urma/uburma/uburma_main.c index e348b5ccd728..e410828abdb5 100644 --- a/drivers/ub/urma/uburma/uburma_main.c +++ b/drivers/ub/urma/uburma/uburma_main.c @@ -37,6 +37,7 @@ #include "uburma_cdev_file.h" #include "uburma_uobj.h" #include "uburma_cmd.h" +#include "uburma_netlink.h" #define UBURMA_MAX_DEVICE 1024 #define UBURMA_DYNAMIC_MINOR_NUM UBURMA_MAX_DEVICE @@ -46,6 +47,7 @@ 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) { @@ -72,6 +74,7 @@ static const void *uburma_net_namespace(struct device *dev) return &init_net; } } + static char *uburma_devnode(struct device *dev, umode_t *mode) { if (mode) @@ -617,6 +620,133 @@ 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); @@ -638,6 +768,15 @@ static void uburma_net_exit(struct net *net) 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); @@ -666,6 +805,9 @@ static int uburma_net_init(struct net *net) 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); @@ -700,6 +842,7 @@ static int __init uburma_init(void) } uburma_register_client(); + uburma_netlink_init(); ret = register_pernet_device(&g_uburma_net_ops); if (ret != 0) { @@ -715,6 +858,7 @@ static int __init uburma_init(void) 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_main.h b/drivers/ub/urma/uburma/uburma_main.h new file mode 100644 index 000000000000..767c3a6ade4b --- /dev/null +++ b/drivers/ub/urma/uburma/uburma_main.h @@ -0,0 +1,29 @@ +/* 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 main header + * Author: Yan Fangfang + * Create: 2023-12-12 + * Note: + * History: 2023-12-12: Create file + */ + +#ifndef UBURMA_MAIN_H +#define UBURMA_MAIN_H + +#include "uburma_types.h" + +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/uburma/uburma_netlink.c b/drivers/ub/urma/uburma/uburma_netlink.c new file mode 100644 index 000000000000..21811c3d5125 --- /dev/null +++ b/drivers/ub/urma/uburma/uburma_netlink.c @@ -0,0 +1,133 @@ +// 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_netlink.h b/drivers/ub/urma/uburma/uburma_netlink.h new file mode 100644 index 000000000000..674982d491c6 --- /dev/null +++ b/drivers/ub/urma/uburma/uburma_netlink.h @@ -0,0 +1,48 @@ +/* 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 header + * Author: Yan Fangfang + * Create: 2023-12-06 + * Note: + * History: 2023-12-06: create file + */ + +#ifndef UBURMA_NETLINK_H +#define UBURMA_NETLINK_H + +#include +#include + +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 diff --git a/drivers/ub/urma/uburma/uburma_uobj.c b/drivers/ub/urma/uburma/uburma_uobj.c index b41abf52a7e0..582259890f0f 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.c +++ b/drivers/ub/urma/uburma/uburma_uobj.c @@ -192,6 +192,18 @@ static int __must_check uobj_remove_commit_internal(struct uburma_uobj *uobj, return ret; } +static int uobj_cg_try_charge(struct uburma_uobj *uobj) +{ + return ubcore_cgroup_try_charge(&uobj->cg_obj, uobj->ufile->ucontext->ub_dev, + UBCORE_RESOURCE_HCA_OBJECT); +} + +static void uboj_cg_uncharge(struct uburma_uobj *uobj) +{ + ubcore_cgroup_uncharge(&uobj->cg_obj, uobj->ufile->ucontext->ub_dev, + UBCORE_RESOURCE_HCA_OBJECT); +} + static struct uburma_uobj *uobj_idr_alloc_begin(const struct uobj_type *type, struct uburma_file *ufile) { @@ -203,12 +215,21 @@ static struct uburma_uobj *uobj_idr_alloc_begin(const struct uobj_type *type, return uobj; ret = uobj_alloc_idr(uobj); - if (ret) { - uobj_put(uobj); - return ERR_PTR(ret); - } + if (ret) + goto put_obj; + ret = uobj_cg_try_charge(uobj); + if (ret != 0) { + uburma_log_warn("cgroup charge failed"); + goto remove; + } return uobj; + +remove: + uobj_remove_idr(uobj); +put_obj: + uobj_put(uobj); + return ERR_PTR(ret); } static void uobj_idr_alloc_commit(struct uburma_uobj *uobj) @@ -220,6 +241,7 @@ static void uobj_idr_alloc_commit(struct uburma_uobj *uobj) static void uobj_idr_alloc_abort(struct uburma_uobj *uobj) { + uboj_cg_uncharge(uobj); uobj_remove_idr(uobj); uobj_put(uobj); } @@ -263,6 +285,7 @@ static int __must_check uobj_idr_remove_commit(struct uburma_uobj *uobj, if (why == UBURMA_REMOVE_DESTROY && ret) return ret; + uboj_cg_uncharge(uobj); uobj_remove_idr(uobj); return ret; } @@ -469,6 +492,29 @@ void uburma_init_uobj_context(struct uburma_file *ufile) init_rwsem(&ufile->cleanup_rwsem); } +static inline void do_clean_uobj(struct uburma_uobj *obj, unsigned int cur_order, + enum uburma_remove_reason why) +{ + int ret; + /* if we hit this WARN_ON, + * that means we are racing with a lookup_get. + */ + WARN_ON(uobj_try_lock(obj, true)); + ret = obj->type->type_class->remove_commit(obj, why); + if (ret) + pr_warn("uburma: failed to remove uobject id %d order %u\n", + obj->id, cur_order); + + list_del_init(&obj->list); + + /* uburma_close_uobj_fd will also try lock the uobj for write */ + if (uobj_type_is_fd(obj)) + uobj_unlock(obj, true); /* match with uobj_try_lock */ + + /* put the ref we took when we created the object */ + uobj_put(obj); +} + void uburma_cleanup_uobjs(struct uburma_file *ufile, enum uburma_remove_reason why) { unsigned int cur_order = 0; @@ -482,28 +528,10 @@ void uburma_cleanup_uobjs(struct uburma_file *ufile, enum uburma_remove_reason w mutex_lock(&ufile->uobjects_lock); list_for_each_entry_safe(obj, next_obj, &ufile->uobjects, list) { - if (obj->type->destroy_order == cur_order) { - int ret; - /* if we hit this WARN_ON, - * that means we are racing with a lookup_get. - */ - WARN_ON(uobj_try_lock(obj, true)); - ret = obj->type->type_class->remove_commit(obj, why); - if (ret) - pr_warn("uburma: failed to remove uobject id %d order %u\n", - obj->id, cur_order); - - list_del_init(&obj->list); - - /* uburma_close_uobj_fd will also try lock the uobj for write */ - if (uobj_type_is_fd(obj)) - uobj_unlock(obj, true); /* match with uobj_try_lock */ - - /* put the ref we took when we created the object */ - uobj_put(obj); - } else { + if (obj->type->destroy_order == cur_order) + do_clean_uobj(obj, cur_order, why); + else next_order = min(next_order, obj->type->destroy_order); - } } mutex_unlock(&ufile->uobjects_lock); cur_order = next_order; @@ -606,6 +634,14 @@ static int uburma_free_tjfr(struct uburma_uobj *uobj, enum uburma_remove_reason static int uburma_free_tjetty(struct uburma_uobj *uobj, enum uburma_remove_reason why) { + struct uburma_tjetty_uobj *uburma_tjetty; + + uburma_tjetty = (struct uburma_tjetty_uobj *)uobj; + if (uburma_tjetty->jetty_uobj != NULL) { + (void)ubcore_unbind_jetty(uburma_tjetty->jetty_uobj->uobj.object); + uburma_tjetty->jetty_uobj = NULL; + uburma_log_warn("unbind_jetty hasn't been done and it has been handled"); + } return ubcore_unimport_jetty((struct ubcore_tjetty *)uobj->object); } @@ -727,7 +763,7 @@ declare_uobj_class(UOBJ_CLASS_JETTY_GRP, &uobj_type_alloc_idr( sizeof(struct uburma_jetty_grp_uobj), 1, uburma_free_jetty_grp)); declare_uobj_class(UOBJ_CLASS_TARGET_JFR, &uobj_type_alloc_idr(sizeof(struct uburma_uobj), 0, uburma_free_tjfr)); -declare_uobj_class(UOBJ_CLASS_TARGET_JETTY, &uobj_type_alloc_idr(sizeof(struct uburma_uobj), 0, - uburma_free_tjetty)); +declare_uobj_class(UOBJ_CLASS_TARGET_JETTY, &uobj_type_alloc_idr(sizeof(struct uburma_tjetty_uobj), + 0, uburma_free_tjetty)); declare_uobj_class(UOBJ_CLASS_TARGET_SEG, &uobj_type_alloc_idr(sizeof(struct uburma_uobj), 0, uburma_free_tseg)); diff --git a/drivers/ub/urma/uburma/uburma_uobj.h b/drivers/ub/urma/uburma/uburma_uobj.h index 6565489036f0..f4f7617ae223 100644 --- a/drivers/ub/urma/uburma/uburma_uobj.h +++ b/drivers/ub/urma/uburma/uburma_uobj.h @@ -55,6 +55,7 @@ struct uburma_uobj { struct rcu_head rcu; /* kfree_rcu() overhead */ const struct uobj_type *type; + struct ubcore_cg_object cg_obj; /* cgroup control */ }; struct uobj_type { @@ -104,7 +105,7 @@ struct uburma_jfce_uobj { }; struct uburma_jfc_uobj { - struct uburma_uobj uobj; /* base uobj struct */ + struct uburma_uobj uobj; struct uburma_uobj *jfce; /* associated jfce uobj */ struct list_head comp_event_list; struct list_head async_event_list; @@ -113,29 +114,34 @@ struct uburma_jfc_uobj { }; struct uburma_jfs_uobj { - struct uburma_uobj uobj; /* base uobj struct */ + struct uburma_uobj uobj; struct list_head async_event_list; uint32_t async_events_reported; }; struct uburma_jfr_uobj { - struct uburma_uobj uobj; /* base uobj struct */ + struct uburma_uobj uobj; struct list_head async_event_list; uint32_t async_events_reported; }; struct uburma_jetty_uobj { - struct uburma_uobj uobj; /* base uobj struct */ + struct uburma_uobj uobj; struct list_head async_event_list; uint32_t async_events_reported; }; struct uburma_jetty_grp_uobj { - struct uburma_uobj uobj; /* base uobj struct */ + struct uburma_uobj uobj; struct list_head async_event_list; uint32_t async_events_reported; }; +struct uburma_tjetty_uobj { + struct uburma_uobj uobj; + struct uburma_jetty_uobj *jetty_uobj; +}; + struct uburma_jfae_uobj { struct uburma_uobj uobj; struct uburma_jfe jfe; diff --git a/include/urma/ubcore_api.h b/include/urma/ubcore_api.h index 23f705516824..be632cb7f8b6 100644 --- a/include/urma/ubcore_api.h +++ b/include/urma/ubcore_api.h @@ -21,7 +21,7 @@ #ifndef UBCORE_API_H #define UBCORE_API_H -#include "ubcore_types.h" +#include /** * Register a device to ubcore @@ -87,18 +87,18 @@ enum ubcore_mtu ubcore_get_mtu(int mtu); /** * TPF receives msg from VF or PF, called only by driver. * @param[in] dev: TPF device; - * @param[in] msg: received msg; + * @param[in] req: received msg; * @return: 0 on success, other value on error */ -int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *msg); +int ubcore_recv_req(struct ubcore_device *dev, struct ubcore_req_host *req); /** * VF or PF receives msg from TPF, called only by driver. * @param[in] dev: VF or PF device; - * @param[in] msg: received msg; + * @param[in] resp: received msg; * @return: 0 on success, other value on error */ -int ubcore_recv_resp(struct ubcore_device *dev, struct ubcore_resp *msg); +int ubcore_recv_resp(struct ubcore_device *dev, struct ubcore_resp *resp); /** * Invoke ndev bind port_id, called only by driver diff --git a/include/urma/ubcore_types.h b/include/urma/ubcore_types.h index ad020b7b56c1..6ee37273ab19 100644 --- a/include/urma/ubcore_types.h +++ b/include/urma/ubcore_types.h @@ -31,7 +31,8 @@ #include #include #include -#include "ubcore_opcode.h" +#include +#include #define UBCORE_GET_VERSION(a, b) (((a) << 16) + ((b) > 65535 ? 65535 : (b))) #define UBCORE_API_VERSION ((0 << 16) + 9) // Current Version: 0.9 @@ -46,6 +47,8 @@ #define UBCORE_MAX_ATTR_GROUP 3 #define UBCORE_EID_SIZE (16) #define UBCORE_EID_STR_LEN (39) +#define UBCORE_DEVID_SIZE (16) + #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" #define EID_UNPACK(...) __VA_ARGS__ @@ -69,6 +72,12 @@ enum ubcore_transport_type { UBCORE_TRANSPORT_MAX }; +enum ubcore_resource_type { + UBCORE_RESOURCE_HCA_HANDLE = 0, + UBCORE_RESOURCE_HCA_OBJECT, + UBCORE_RESOURCE_HCA_MAX +}; + #define UBCORE_ACCESS_LOCAL_WRITE 0x1 #define UBCORE_ACCESS_REMOTE_READ (0x1 << 1) #define UBCORE_ACCESS_REMOTE_WRITE (0x1 << 2) @@ -77,6 +86,18 @@ enum ubcore_transport_type { #define UBCORE_SEG_TOKEN_ID_INVALID UINT_MAX +struct ubcore_cg_device { +#ifdef CONFIG_CGROUP_RDMA + struct rdmacg_device dev; +#endif +}; + +struct ubcore_cg_object { +#ifdef CONFIG_CGROUP_RDMA + struct rdma_cgroup *cg; +#endif +}; + union ubcore_eid { uint8_t raw[UBCORE_EID_SIZE]; struct { @@ -101,6 +122,10 @@ struct ubcore_ueid_cfg { uint32_t eid_index; }; +struct ubcore_devid { + uint8_t raw[UBCORE_DEVID_SIZE]; +}; + struct ubcore_jetty_id { union ubcore_eid eid; uint32_t id; @@ -263,6 +288,7 @@ struct ubcore_ucontext { union ubcore_eid eid; uint32_t eid_index; void *jfae; /* jfae uobj */ + struct ubcore_cg_object cg_obj; atomic_t use_cnt; }; @@ -514,6 +540,7 @@ struct ubcore_device_cap { uint16_t trans_mode; /* one or more from ubcore_transport_mode_t */ 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_oor_cnt; /* max OOR window size by packet */ uint32_t mn; @@ -2230,6 +2257,25 @@ struct ubcore_ops { */ int (*modify_vtp)(struct ubcore_vtp *vtp, struct ubcore_vtp_attr *attr, union ubcore_vtp_attr_mask *mask); + /** + * query fe index. + * @param[in] dev: the ub device handle; + * @param[in] devid: vf devid to query + * @param[out] fe_idx: fe id; + * @return: 0 on success, other value on error + */ + int (*query_fe_idx)(struct ubcore_device *dev, struct ubcore_devid *devid, + uint16_t *fe_idx); + /** + * config dscp-vl mapping + * @param[in] dev:the ub dev handle; + * @param[in] dscp: the dscp value array + * @param[in] vl: the vl value array + * @param[in] num: array num + * @return: 0 on success, other value on error + */ + int (*config_dscp_vl)(struct ubcore_device *dev, uint8_t *dscp, uint8_t *vl, + uint8_t num); }; struct ubcore_bitmap { @@ -2300,6 +2346,7 @@ struct ubcore_device { struct completion comp; bool dynamic_eid; /* Assign eid dynamically with netdev notifier */ struct ubcore_eid_table eid_table; + struct ubcore_cg_device cg_device; }; struct ubcore_port { diff --git a/include/urma/ubcore_uapi.h b/include/urma/ubcore_uapi.h index a46f6607f934..80453b666166 100644 --- a/include/urma/ubcore_uapi.h +++ b/include/urma/ubcore_uapi.h @@ -23,7 +23,7 @@ #ifndef UBCORE_UAPI_H #define UBCORE_UAPI_H -#include "ubcore_types.h" +#include /** * Application specifies the device to allocate an context. * @param[in] dev: ubcore_device found by add ops in the client. @@ -508,6 +508,51 @@ int ubcore_post_jetty_recv_wr(struct ubcore_jetty *jetty, struct ubcore_jfr_wr * */ int ubcore_poll_jfc(struct ubcore_jfc *jfc, int cr_cnt, struct ubcore_cr *cr); + +// for system not support cgroup +#ifndef CONFIG_CGROUP_RDMA +static inline void ubcore_cgroup_reg_dev(struct ubcore_device *dev) {} + +static inline void ubcore_cgroup_unreg_dev(struct ubcore_device *dev) {} + +static inline int ubcore_cgroup_try_charge(struct ubcore_cg_object *cg_obj, + struct ubcore_device *dev, enum ubcore_resource_type type) { return 0; } + +static inline void ubcore_cgroup_uncharge(struct ubcore_cg_object *cg_obj, + struct ubcore_device *dev, enum ubcore_resource_type type) {} +#else +/** + * Client register cgroup dev + * @param[in] dev: the ubcore device handle; + */ +void ubcore_cgroup_reg_dev(struct ubcore_device *dev); + +/** + * Client unregister cgroup dev + * @param[in] dev: the ubcore device handle; + */ +void ubcore_cgroup_unreg_dev(struct ubcore_device *dev); + +/** + * Client try to charge cgroup count + * @param[in] cg_obj: the cgroup obj + * @param[in] dev: the ubcore device handle; + * @param[in] type: the cgroup resource type + * @return: 0 on success, other value on error + */ +int ubcore_cgroup_try_charge(struct ubcore_cg_object *cg_obj, struct ubcore_device *dev, + enum ubcore_resource_type type); + +/** + * Client uncharge cgroup count + * @param[in] cg_obj: the cgroup obj + * @param[in] dev: the ubcore device handle; + * @param[in] type: the cgroup resource type + */ +void ubcore_cgroup_uncharge(struct ubcore_cg_object *cg_obj, struct ubcore_device *dev, + 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); -- Gitee