1801 lines
54 KiB
C
1801 lines
54 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
// Copyright(c) 2024 Huawei Technologies Co., Ltd
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include "hinic3_hw.h"
|
|
#include "rdma_context_format.h"
|
|
#include "roce.h"
|
|
#include "roce_dfx.h"
|
|
#include "roce_cmd.h"
|
|
#include "roce_qp.h"
|
|
|
|
#include "roce_sysfs.h"
|
|
|
|
#define ROCE_DEFAULT_IP_EABLE_EN 1
|
|
#define ROCE_DEFAULT_IP_EABLE_DIS 0
|
|
#define ROCE_DEFAULT_MIN_CNP_PERIOD 16
|
|
#define ROCE_DEFAULT_ALPHA_DEC_PERIOD 160
|
|
#define ROCE_DEFAULT_RATE_DEC_PERIOD 32
|
|
#define ROCE_DEFAULT_RATE_INC_PERIOD 480
|
|
#define ROCE_DEFAULT_ALPHA_THRESHOLD 4 // 32, uint 8
|
|
#define ROCE_DEFAULT_CNP_CNT_THRESHOLD 6
|
|
#define ROCE_DEFAULT_PORT_MODE_25G 0
|
|
#define ROCE_DEFAULT_FACTOR_GITA 7
|
|
#define ROCE_DEFAULT_INITIAL_ALPHA 1023
|
|
#define ROCE_DEFAULT_RATE_INC_AI 2
|
|
#define ROCE_DEFAULT_RATE_INC_HAI 8
|
|
#define ROCE_DEFAULT_RATE_FIRST_SET 1024
|
|
#define ROCE_DEFAULT_RATE_TARGET_CLAMP 1
|
|
#define ROCE_DEFAULT_QUICK_AJ_ENABLE 0
|
|
#define ROCE_DEFAULT_CNP_PRIO_ENABLE 0
|
|
#define ROCE_DEFAULT_CNP_PRIO 0
|
|
#define ROCE_DEFAULT_TOKEN_PERIOD 16
|
|
#define ROCE_DEFAULT_MIN_RATE 1
|
|
#define ROCE_DEFAULT_WND_RESET_RATIO 0
|
|
#define ROCE_DEFAULT_WND_RESET_TIMEOUT 0
|
|
#define ROCE_PORT_MODE_MASK 0xfffffffe
|
|
#define ROCE_QUICK_AJ_EN_MASK 0xfffffffe
|
|
#define ROCE_CNP_PRIO_EN_MASK 0xfffffffe
|
|
#define ROCE_RT_CLAMP_MASK 0xfffffffe
|
|
#define ROCE_PRIO_EN_MASK 0xfffffffe
|
|
#define ROCE_MIN_RATE_INC_HAI 1
|
|
#define ROCE_MAX_RATE_INC_HAI 255
|
|
#define ROCE_MIN_RATE_INC_AI 1
|
|
#define ROCE_MAX_RATE_INC_AI 63
|
|
#define ROCE_MIN_INITIAL_ALPHA 127
|
|
#define ROCE_MAX_INITIAL_ALPHA 1023
|
|
#define ROCE_MIN_RATE_INC_PERIOD 1
|
|
#define ROCE_MAX_RATE_INC_PERIOD 1024
|
|
#define ROCE_MIN_ALPHA_DEC_PERIOD 1
|
|
#define ROCE_MAX_ALPHA_DEC_PERIOD 1024
|
|
#define ROCE_MIN_TOKEN_PERIOD 4
|
|
#define ROCE_MAX_TOKEN_PERIOD 255
|
|
#define ROCE_MIN_FLOW_MIN_RATE 1
|
|
#define ROCE_MAX_FLOW_MIN_RATE 64
|
|
#define ROCE_MIN_WND_RESET_RATIO 0
|
|
#define ROCE_MAX_WND_RESET_RATIO 0xf
|
|
#define ROCE_MIN_WND_RESET_TIMEOUT 0
|
|
#define ROCE_MAX_WND_RESET_TIMEOUT 0xf
|
|
#define ROCE_MIN_ALPHA_THRESHOLD 8
|
|
#define ROCE_MAX_ALPHA_THRESHOLD 248
|
|
#define ROCE_MIN_CNP_CNT_THRESHOLD 1
|
|
#define ROCE_MAX_CNP_CNT_THRESHOLD 15
|
|
#define ROCE_MIN_RATE_DEC_PERIOD 1
|
|
#define ROCE_MAX_RATE_DEC_PERIOD 255
|
|
#define ROCE_MIN_MIN_CNP_PERIOD 1
|
|
#define ROCE_MAX_MIN_CNP_PERIOD 255
|
|
#define ROCE_MIN_FACTOR_GITA 1
|
|
#define ROCE_MAX_FACTOR_GITA 15
|
|
#define ROCE_MIN_RATE_FIRST_SET 128
|
|
#define ROCE_MAX_RATE_FIRST_SET 8191
|
|
|
|
#define MAX_STRING_FORMAT_LEN 64
|
|
|
|
/* ECN VER */
|
|
#define ECN_VER_DCQCN 0
|
|
#define ECN_VER_PATHQCN 1
|
|
|
|
enum {
|
|
ROCE_DCQCN_NP = 0,
|
|
ROCE_DCQCN_RP = 1
|
|
};
|
|
|
|
#define to_roce3_ecn_ctx(_kobj) container_of(_kobj, struct roce3_ecn_ctx, ecn_root)
|
|
#define to_roce3_ecn_np_ctx(_kobj) container_of(_kobj, struct roce3_ecn_np_ctx, ecn_np_root)
|
|
#define to_roce3_ecn_rp_ctx(_kobj) container_of(_kobj, struct roce3_ecn_rp_ctx, ecn_rp_root)
|
|
|
|
#define INIT_ROCE_KOBJ_ATTR(_name, _mode, _show, _store) \
|
|
{ \
|
|
.attr = { .name = __stringify(_name), .mode = _mode }, \
|
|
.show = (_show), \
|
|
.store = (_store), \
|
|
}
|
|
|
|
#define ROCE_ATTR_RW(_name, _show, _store) \
|
|
static struct kobj_attribute roce_attr_##_name = \
|
|
INIT_ROCE_KOBJ_ATTR(_name, 0640, _show, _store)
|
|
|
|
#define ROCE_ATTR_PTR(_name) (&roce_attr_##_name.attr)
|
|
|
|
static int roce3_update_cfg_ccf_param(struct roce3_device *rdev,
|
|
const struct roce3_ecn_ctx *ecn_ctx)
|
|
{
|
|
const struct roce3_prio_enable_ctx *prio_enable_ctx = NULL;
|
|
const struct roce3_ip_prio_enable_ctx *ip_prio_enable_ctx = NULL;
|
|
struct roce_ccf_param ccf_param;
|
|
int ret, i;
|
|
|
|
memset(&ccf_param, 0, sizeof(ccf_param));
|
|
|
|
for (i = 0; i < PRI_ARRAY_LEN; i++) {
|
|
prio_enable_ctx = &ecn_ctx->np_ctx.enable_ctx.prio_enable[i];
|
|
ccf_param.dw0.bs.np_enable |= (prio_enable_ctx->prio_en << prio_enable_ctx->prio);
|
|
prio_enable_ctx = &ecn_ctx->rp_ctx.enable_ctx.prio_enable[i];
|
|
ccf_param.dw0.bs.rp_enable |= (prio_enable_ctx->prio_en << prio_enable_ctx->prio);
|
|
ip_prio_enable_ctx = &ecn_ctx->ip_enable_ctx.ip_prio_enable[i];
|
|
ccf_param.dw0.bs.ip_enable |=
|
|
(ip_prio_enable_ctx->prio_en << ip_prio_enable_ctx->prio);
|
|
}
|
|
|
|
ccf_param.dw0.bs.cnp_prio_enable = ecn_ctx->np_ctx.cnp_prio_enable;
|
|
ccf_param.dw0.bs.port_mode = ecn_ctx->np_ctx.port_mode;
|
|
ccf_param.dw1.bs.cnp_prio = ecn_ctx->np_ctx.cnp_prio;
|
|
ccf_param.dw1.bs.cnp_cos = roce3_get_db_cos_from_vlan_pri(rdev, ccf_param.dw1.bs.cnp_prio);
|
|
ccf_param.dw1.bs.ccf_appid = ecn_ctx->cc_algo;
|
|
|
|
ret = roce3_set_cfg_ccf_param(rdev->hwdev, rdev->glb_func_id, (u32 *)&ccf_param);
|
|
if (ret != 0) {
|
|
dev_err(rdev->hwdev_hdl,
|
|
"[ROCE, ERR] : Failed to set ccf param, func_id(%d) ret(%d)\n",
|
|
rdev->glb_func_id, ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int roce3_update_dcqcn_param(struct roce3_device *rdev, const struct roce3_ecn_ctx *ecn_ctx)
|
|
{
|
|
struct roce_dcqcn_param dcqcn_param;
|
|
int ret;
|
|
|
|
memset(&dcqcn_param, 0, sizeof(dcqcn_param));
|
|
|
|
dcqcn_param.dw0.bs.token_period = ecn_ctx->rp_ctx.token_period;
|
|
dcqcn_param.dw0.bs.flow_min_rate = ecn_ctx->rp_ctx.min_rate;
|
|
dcqcn_param.dw1.bs.rate_inc_period = ecn_ctx->rp_ctx.rate_inc_period;
|
|
dcqcn_param.dw1.bs.alpha_threshold = ecn_ctx->rp_ctx.alpha_threshold;
|
|
dcqcn_param.dw1.bs.cnp_cnt_threshold = ecn_ctx->rp_ctx.cnp_cnt_threshold;
|
|
dcqcn_param.dw1.bs.alpha_dec_period = ecn_ctx->rp_ctx.alpha_dec_period;
|
|
dcqcn_param.dw2.bs.rate_inc_ai = ecn_ctx->rp_ctx.rate_inc_ai;
|
|
dcqcn_param.dw2.bs.rate_inc_hai = ecn_ctx->rp_ctx.rate_inc_hai;
|
|
dcqcn_param.dw2.bs.rate_dec_period = ecn_ctx->rp_ctx.rate_dec_period;
|
|
dcqcn_param.dw2.bs.min_cnp_period = ecn_ctx->np_ctx.min_cnp_period;
|
|
dcqcn_param.dw3.bs.factor_gita = ecn_ctx->rp_ctx.factor_gita;
|
|
dcqcn_param.dw3.bs.rt_clamp = ecn_ctx->rp_ctx.rate_target_clamp;
|
|
dcqcn_param.dw3.bs.initial_alpha = ecn_ctx->rp_ctx.initial_alpha;
|
|
// adjust_en
|
|
dcqcn_param.dw3.bs.rate_first_set = ecn_ctx->rp_ctx.rate_first_set;
|
|
|
|
ret = roce3_set_cfg_dcqcn_param(rdev->hwdev, rdev->glb_func_id,
|
|
(u32 *)(void *)&dcqcn_param);
|
|
if (ret != 0) {
|
|
dev_err(rdev->hwdev_hdl,
|
|
"[ROCE, ERR] : Failed to set dcqcn param, func_id(%d), ret(%d)\n",
|
|
rdev->glb_func_id, ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int roce3_update_ipqcn_param(struct roce3_device *rdev, const struct roce3_ecn_ctx *ecn_ctx)
|
|
{
|
|
struct roce_ipqcn_param ipqcn_param;
|
|
int ret;
|
|
|
|
memset(&ipqcn_param, 0, sizeof(ipqcn_param));
|
|
|
|
ipqcn_param.dw0.bs.token_period = ecn_ctx->rp_ctx.token_period;
|
|
ipqcn_param.dw0.bs.flow_min_rate = ecn_ctx->rp_ctx.min_rate;
|
|
ipqcn_param.dw1.bs.rate_inc_period = ecn_ctx->rp_ctx.rate_inc_period;
|
|
ipqcn_param.dw1.bs.alpha_threshold = ecn_ctx->rp_ctx.alpha_threshold;
|
|
ipqcn_param.dw1.bs.cnp_cnt_threshold = ecn_ctx->rp_ctx.cnp_cnt_threshold;
|
|
ipqcn_param.dw1.bs.alpha_dec_period = ecn_ctx->rp_ctx.alpha_dec_period;
|
|
ipqcn_param.dw2.bs.rate_inc_ai = ecn_ctx->rp_ctx.rate_inc_ai;
|
|
ipqcn_param.dw2.bs.rate_inc_hai = ecn_ctx->rp_ctx.rate_inc_hai;
|
|
ipqcn_param.dw2.bs.rate_dec_period = ecn_ctx->rp_ctx.rate_dec_period;
|
|
ipqcn_param.dw2.bs.min_cnp_period = ecn_ctx->np_ctx.min_cnp_period;
|
|
ipqcn_param.dw3.bs.factor_gita = ecn_ctx->rp_ctx.factor_gita;
|
|
ipqcn_param.dw3.bs.rt_clamp = ecn_ctx->rp_ctx.rate_target_clamp;
|
|
ipqcn_param.dw3.bs.initial_alpha = ecn_ctx->rp_ctx.initial_alpha;
|
|
ipqcn_param.dw3.bs.rate_first_set = ecn_ctx->rp_ctx.rate_first_set;
|
|
|
|
ret = roce3_set_cfg_ipqcn_param(rdev->hwdev, rdev->glb_func_id,
|
|
(u32 *)(void *)&ipqcn_param);
|
|
if (ret != 0) {
|
|
dev_err(rdev->hwdev_hdl,
|
|
"[ROCE, ERR] : Failed to set ipqcn param, func_id(%d) ret(%d)\n",
|
|
rdev->glb_func_id, ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
typedef int (*roce3_update_param_t)(struct roce3_device *rdev, const struct roce3_ecn_ctx *ecn_ctx);
|
|
|
|
static roce3_update_param_t roce3_update_param_funcs[] = {
|
|
roce3_update_cfg_ccf_param,
|
|
roce3_update_dcqcn_param,
|
|
roce3_update_ipqcn_param,
|
|
};
|
|
|
|
int roce3_update_ecn_param(const struct roce3_ecn_ctx *ecn_ctx)
|
|
{
|
|
unsigned int i;
|
|
int ret = 0;
|
|
struct roce3_device *rdev = container_of(ecn_ctx, struct roce3_device, ecn_ctx);
|
|
|
|
for (i = 0; i < (sizeof(roce3_update_param_funcs) / sizeof(roce3_update_param_t)); i++) {
|
|
ret = roce3_update_param_funcs[i](rdev, ecn_ctx);
|
|
if (ret != 0)
|
|
ret = -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t roce3_show_cc_algo(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj);
|
|
|
|
if ((attr == NULL) || (buf == NULL)) {
|
|
pr_err("[ROCE] %s: attr or buf is null\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch ((int)ecn_ctx->cc_algo) {
|
|
case ROCE_CC_DISABLE:
|
|
return sprintf(buf, "%s\n", "disable");
|
|
case ROCE_CC_DCQCN_ALGO:
|
|
return sprintf(buf, "%s\n", "dcqcn");
|
|
case ROCE_CC_LDCP_ALGO:
|
|
return sprintf(buf, "%s\n", "ldcp");
|
|
case ROCE_CC_IPQCN_ALGO:
|
|
return sprintf(buf, "%s\n", "hc3_1/ipqcn");
|
|
default:
|
|
return sprintf(buf, "%s\n", "error_type");
|
|
}
|
|
}
|
|
|
|
static ssize_t roce3_store_cc_algo(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj);
|
|
u32 old_cc_algo = 0;
|
|
int cc_algo = 0;
|
|
ssize_t ret;
|
|
|
|
if ((attr == NULL) || (buf == NULL)) {
|
|
pr_err("[ROCE] %s: attr or buf is null\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* dcqcn -> 0x0, ldcp -> 0x2, hc3_1 -> 0x80 */
|
|
if (strncmp(buf, "disable", strlen("disable")) == 0) {
|
|
cc_algo = ROCE_CC_DISABLE;
|
|
} else if (strncmp(buf, "dcqcn", strlen("dcqcn")) == 0) {
|
|
cc_algo = ROCE_CC_DCQCN_ALGO;
|
|
} else if ((strncmp(buf, "ipqcn", strlen("ipqcn")) == 0) ||
|
|
(strncmp(buf, "hc3_1", strlen("hc3_1")) == 0)) {
|
|
cc_algo = ROCE_CC_IPQCN_ALGO;
|
|
} else if (strncmp(buf, "ldcp", strlen("ldcp")) == 0) {
|
|
cc_algo = ROCE_CC_LDCP_ALGO;
|
|
} else {
|
|
pr_err("[ROCE] %s: Invalid cc_algo(%d),buf(%s)\n", __func__, cc_algo, buf);
|
|
return -EIO;
|
|
}
|
|
|
|
if (ecn_ctx->cc_algo != (u32)cc_algo) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_cc_algo = ecn_ctx->cc_algo;
|
|
ecn_ctx->cc_algo = (u32)cc_algo;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to update cc_algo param, ret(%d)",
|
|
__func__, (int)ret);
|
|
ecn_ctx->cc_algo = old_cc_algo;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_ecn_prio_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_prio_enable_ctx *prio_enable_ctx =
|
|
container_of(attr, struct roce3_prio_enable_ctx, enable);
|
|
|
|
return sprintf(buf, "%d\n", (int)prio_enable_ctx->prio_en);
|
|
}
|
|
|
|
static ssize_t roce3_store_ecn_prio_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int prio_en = 0;
|
|
u32 old_prio_en = 0;
|
|
struct roce3_ecn_rp_ctx *rp_ctx = NULL;
|
|
struct roce3_ecn_np_ctx *np_ctx = NULL;
|
|
struct roce3_ecn_ctx *ecn_ctx = NULL;
|
|
struct roce3_prio_enable_ctx *prio_enable_ctx =
|
|
container_of(attr, struct roce3_prio_enable_ctx, enable);
|
|
struct roce3_ecn_enable_ctx *ecn_enable_ctx =
|
|
(struct roce3_ecn_enable_ctx *)prio_enable_ctx->ecn_enable_ctx;
|
|
|
|
if (ecn_enable_ctx->np_rp == ROCE_DCQCN_NP) {
|
|
np_ctx = container_of(ecn_enable_ctx, struct roce3_ecn_np_ctx, enable_ctx);
|
|
ecn_ctx = container_of(np_ctx, struct roce3_ecn_ctx, np_ctx);
|
|
} else {
|
|
rp_ctx = container_of(ecn_enable_ctx, struct roce3_ecn_rp_ctx, enable_ctx);
|
|
ecn_ctx = container_of(rp_ctx, struct roce3_ecn_ctx, rp_ctx);
|
|
}
|
|
|
|
ret = kstrtoint(buf, 10, &prio_en);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)prio_en & ROCE_PRIO_EN_MASK) != 0)
|
|
return -EIO;
|
|
|
|
if (prio_enable_ctx->prio_en != (u32)prio_en) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_prio_en = prio_enable_ctx->prio_en;
|
|
prio_enable_ctx->prio_en = (u32)prio_en;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
prio_enable_ctx->prio_en = old_prio_en;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_ecn_ip_prio_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ip_prio_enable_ctx *ip_prio_enable_ctx =
|
|
container_of(attr, struct roce3_ip_prio_enable_ctx, ip_enable);
|
|
|
|
return sprintf(buf, "%d\n", (int)ip_prio_enable_ctx->prio_en);
|
|
}
|
|
|
|
static ssize_t roce3_store_ecn_ip_prio_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int prio_en = 0;
|
|
u32 old_prio_en = 0;
|
|
struct roce3_ip_prio_enable_ctx *ip_prio_enable_ctx =
|
|
container_of(attr, struct roce3_ip_prio_enable_ctx, ip_enable);
|
|
struct roce3_ecn_ip_enable_ctx *ip_enable_ctx =
|
|
(struct roce3_ecn_ip_enable_ctx *)ip_prio_enable_ctx->ecn_ip_enable_ctx;
|
|
struct roce3_ecn_ctx *ecn_ctx = container_of(ip_enable_ctx,
|
|
struct roce3_ecn_ctx, ip_enable_ctx);
|
|
|
|
ret = kstrtoint(buf, 10, &prio_en);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)prio_en & ROCE_PRIO_EN_MASK) != 0)
|
|
return -EIO;
|
|
|
|
if (ip_prio_enable_ctx->prio_en != (u32)prio_en) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_prio_en = ip_prio_enable_ctx->prio_en;
|
|
ip_prio_enable_ctx->prio_en = (u32)prio_en;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ip_prio_enable_ctx->prio_en = old_prio_en;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_rate_inc_hai(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->rate_inc_hai);
|
|
}
|
|
|
|
static ssize_t roce3_store_rate_inc_hai(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int rate_inc_hai = 0;
|
|
u32 old_rate_inc_hai = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &rate_inc_hai);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((rate_inc_hai < ROCE_MIN_RATE_INC_HAI) || (rate_inc_hai > ROCE_MAX_RATE_INC_HAI))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->rate_inc_hai != (u32)rate_inc_hai) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_rate_inc_hai = ecn_rp_ctx->rate_inc_hai;
|
|
ecn_rp_ctx->rate_inc_hai = (u32)rate_inc_hai;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->rate_inc_hai = old_rate_inc_hai;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_rate_inc_ai(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->rate_inc_ai);
|
|
}
|
|
|
|
static ssize_t roce3_store_rate_inc_ai(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int rate_inc_ai = 0;
|
|
u32 old_rate_inc_ai = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &rate_inc_ai);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((rate_inc_ai < ROCE_MIN_RATE_INC_AI) || (rate_inc_ai > ROCE_MAX_RATE_INC_AI))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->rate_inc_ai != (u32)rate_inc_ai) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_rate_inc_ai = ecn_rp_ctx->rate_inc_ai;
|
|
ecn_rp_ctx->rate_inc_ai = (u32)rate_inc_ai;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->rate_inc_ai = old_rate_inc_ai;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_initial_alpha(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->initial_alpha);
|
|
}
|
|
|
|
static ssize_t roce3_store_initial_alpha(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int initial_alpha = 0;
|
|
u32 old_initial_alpha = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &initial_alpha);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((initial_alpha < ROCE_MIN_INITIAL_ALPHA) || (initial_alpha > ROCE_MAX_INITIAL_ALPHA))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->initial_alpha != (u32)initial_alpha) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_initial_alpha = ecn_rp_ctx->initial_alpha;
|
|
ecn_rp_ctx->initial_alpha = (u32)initial_alpha;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->initial_alpha = old_initial_alpha;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_factor_gita(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->factor_gita);
|
|
}
|
|
|
|
static ssize_t roce3_store_factor_gita(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int factor_gita = 0;
|
|
u32 old_factor_gita = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &factor_gita);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((factor_gita < ROCE_MIN_FACTOR_GITA) || (factor_gita > ROCE_MAX_FACTOR_GITA))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->factor_gita != (u32)factor_gita) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_factor_gita = ecn_rp_ctx->factor_gita;
|
|
ecn_rp_ctx->factor_gita = (u32)factor_gita;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->factor_gita = old_factor_gita;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_rate_inc_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->rate_inc_period);
|
|
}
|
|
|
|
static ssize_t roce3_store_rate_inc_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int rate_inc_period = 0;
|
|
u32 old_rate_inc_period = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &rate_inc_period);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((rate_inc_period < ROCE_MIN_RATE_INC_PERIOD) ||
|
|
(rate_inc_period > ROCE_MAX_RATE_INC_PERIOD))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->rate_inc_period != (u32)rate_inc_period) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_rate_inc_period = ecn_rp_ctx->rate_inc_period;
|
|
ecn_rp_ctx->rate_inc_period = (u32)rate_inc_period;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->rate_inc_period = old_rate_inc_period;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_cnp_cnt_threshold(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->cnp_cnt_threshold);
|
|
}
|
|
|
|
static ssize_t roce3_store_cnp_cnt_threshold(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int cnp_cnt_threshold = 0;
|
|
u32 old_cnp_cnt_threshold = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &cnp_cnt_threshold);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((cnp_cnt_threshold < ROCE_MIN_CNP_CNT_THRESHOLD) ||
|
|
(cnp_cnt_threshold > ROCE_MAX_CNP_CNT_THRESHOLD))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->cnp_cnt_threshold != (u32)cnp_cnt_threshold) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_cnp_cnt_threshold = ecn_rp_ctx->cnp_cnt_threshold;
|
|
ecn_rp_ctx->cnp_cnt_threshold = (u32)cnp_cnt_threshold;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->cnp_cnt_threshold = old_cnp_cnt_threshold;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_alpha_threshold(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n",
|
|
(int)(ecn_rp_ctx->alpha_threshold << ALPHA_THREADHOLD_UNIT_SHIFT));
|
|
}
|
|
|
|
static ssize_t roce3_store_alpha_threshold(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
u32 alpha_threshold = 0;
|
|
u32 old_alpha_threshold = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &alpha_threshold);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((alpha_threshold < ROCE_MIN_ALPHA_THRESHOLD) ||
|
|
(alpha_threshold > ROCE_MAX_ALPHA_THRESHOLD))
|
|
return -EIO;
|
|
alpha_threshold = ((u32)alpha_threshold >> ALPHA_THREADHOLD_UNIT_SHIFT);
|
|
|
|
if (ecn_rp_ctx->alpha_threshold != (u32)alpha_threshold) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_alpha_threshold = ecn_rp_ctx->alpha_threshold;
|
|
ecn_rp_ctx->alpha_threshold = (u32)alpha_threshold;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->alpha_threshold = old_alpha_threshold;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_rate_dec_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->rate_dec_period);
|
|
}
|
|
|
|
static ssize_t roce3_store_rate_dec_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int rate_dec_period = 0;
|
|
u32 old_rate_dec_period = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &rate_dec_period);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((rate_dec_period < ROCE_MIN_RATE_DEC_PERIOD) ||
|
|
(rate_dec_period > ROCE_MAX_RATE_DEC_PERIOD))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->rate_dec_period != (u32)rate_dec_period) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_rate_dec_period = ecn_rp_ctx->rate_dec_period;
|
|
ecn_rp_ctx->rate_dec_period = (u32)rate_dec_period;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->rate_dec_period = old_rate_dec_period;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_token_period(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->token_period);
|
|
}
|
|
|
|
static ssize_t roce3_store_token_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int token_period = 0;
|
|
u32 old_token_period = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &token_period);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((token_period < ROCE_MIN_TOKEN_PERIOD) ||
|
|
(token_period > ROCE_MAX_TOKEN_PERIOD))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->token_period != (u32)token_period) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_token_period = ecn_rp_ctx->token_period;
|
|
ecn_rp_ctx->token_period = (u32)token_period;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->token_period = old_token_period;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_min_rate(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->min_rate);
|
|
}
|
|
|
|
static ssize_t roce3_store_min_rate(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int min_rate = 0;
|
|
u32 old_min_rate = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &min_rate);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((min_rate < ROCE_MIN_FLOW_MIN_RATE) || (min_rate > ROCE_MAX_FLOW_MIN_RATE))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->token_period != (u32)min_rate) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_min_rate = ecn_rp_ctx->min_rate;
|
|
ecn_rp_ctx->min_rate = (u32)min_rate;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->min_rate = old_min_rate;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_alpha_dec_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->alpha_dec_period);
|
|
}
|
|
|
|
static ssize_t roce3_store_alpha_dec_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int alpha_dec_period = 0;
|
|
u32 old_alpha_dec_period = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &alpha_dec_period);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((alpha_dec_period < ROCE_MIN_ALPHA_DEC_PERIOD) ||
|
|
(alpha_dec_period > ROCE_MAX_ALPHA_DEC_PERIOD))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->alpha_dec_period != (u32)alpha_dec_period) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_alpha_dec_period = ecn_rp_ctx->alpha_dec_period;
|
|
ecn_rp_ctx->alpha_dec_period = (u32)alpha_dec_period;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->alpha_dec_period = old_alpha_dec_period;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_rate_first_set(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->rate_first_set);
|
|
}
|
|
|
|
static ssize_t roce3_store_rate_first_set(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int rate_first_set = 0;
|
|
u32 old_rate_first_set = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &rate_first_set);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((rate_first_set < ROCE_MIN_RATE_FIRST_SET) ||
|
|
(rate_first_set > ROCE_MAX_RATE_FIRST_SET))
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->rate_first_set != (u32)rate_first_set) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_rate_first_set = ecn_rp_ctx->rate_first_set;
|
|
ecn_rp_ctx->rate_first_set = (u32)rate_first_set;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->rate_first_set = old_rate_first_set;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_rate_target_clamp(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_rp_ctx->rate_target_clamp);
|
|
}
|
|
|
|
static ssize_t roce3_store_rate_target_clamp(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int rate_target_clamp = 0;
|
|
u32 old_rate_target_clamp = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_rp_ctx *ecn_rp_ctx = to_roce3_ecn_rp_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &rate_target_clamp);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)rate_target_clamp & ROCE_RT_CLAMP_MASK) != 0)
|
|
return -EIO;
|
|
|
|
if (ecn_rp_ctx->rate_target_clamp != (u32)rate_target_clamp) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_rate_target_clamp = ecn_rp_ctx->rate_target_clamp;
|
|
ecn_rp_ctx->rate_target_clamp = (u32)rate_target_clamp;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_rp_ctx->rate_target_clamp = old_rate_target_clamp;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_min_cnp_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_np_ctx->min_cnp_period);
|
|
}
|
|
|
|
static ssize_t roce3_store_min_cnp_period(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int min_cnp_period = 0;
|
|
u32 old_min_cnp_period = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &min_cnp_period);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((min_cnp_period < ROCE_MIN_MIN_CNP_PERIOD) ||
|
|
(min_cnp_period > ROCE_MAX_MIN_CNP_PERIOD))
|
|
return -EIO;
|
|
|
|
if (ecn_np_ctx->min_cnp_period != (u32)min_cnp_period) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_min_cnp_period = ecn_np_ctx->min_cnp_period;
|
|
ecn_np_ctx->min_cnp_period = (u32)min_cnp_period;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_np_ctx->min_cnp_period = old_min_cnp_period;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_port_mode(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_np_ctx->port_mode);
|
|
}
|
|
|
|
static ssize_t roce3_store_port_mode(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int port_mode = 0;
|
|
u32 old_port_mode = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &port_mode);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)port_mode & ROCE_PORT_MODE_MASK) != 0)
|
|
return -EIO;
|
|
|
|
if (ecn_np_ctx->port_mode != (u32)port_mode) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_port_mode = ecn_np_ctx->port_mode;
|
|
ecn_np_ctx->port_mode = (u32)port_mode;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_np_ctx->port_mode = old_port_mode;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_quick_adjust_en(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_np_ctx->quick_adjust_en);
|
|
}
|
|
|
|
static ssize_t roce3_store_quick_adjust_en(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int quick_adjust_en = 0;
|
|
u32 old_quick_adjust_en = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &quick_adjust_en);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)quick_adjust_en & ROCE_QUICK_AJ_EN_MASK) != 0)
|
|
return -EIO;
|
|
|
|
if (ecn_np_ctx->quick_adjust_en != (u32)quick_adjust_en) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_quick_adjust_en = ecn_np_ctx->quick_adjust_en;
|
|
ecn_np_ctx->quick_adjust_en = (u32)quick_adjust_en;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_np_ctx->quick_adjust_en = old_quick_adjust_en;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_cnp_prio_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_np_ctx->cnp_prio_enable);
|
|
}
|
|
|
|
static ssize_t roce3_store_cnp_prio_enable(struct kobject *kobj,
|
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int cnp_prio_enable = 0;
|
|
u32 old_cnp_prio_enable = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &cnp_prio_enable);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)cnp_prio_enable & ROCE_CNP_PRIO_EN_MASK) != 0)
|
|
return -EIO;
|
|
|
|
if (ecn_np_ctx->cnp_prio_enable != (u32)cnp_prio_enable) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_cnp_prio_enable = ecn_np_ctx->cnp_prio_enable;
|
|
ecn_np_ctx->cnp_prio_enable = (u32)cnp_prio_enable;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_np_ctx->cnp_prio_enable = old_cnp_prio_enable;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_show_cnp_prio(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_np_ctx->cnp_prio);
|
|
}
|
|
|
|
static ssize_t roce3_store_cnp_prio(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int cnp_prio = 0;
|
|
u32 old_cnp_prio = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj->parent);
|
|
struct roce3_ecn_np_ctx *ecn_np_ctx = to_roce3_ecn_np_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &cnp_prio);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if (((u32)cnp_prio) > (PRI_ARRAY_LEN - 1))
|
|
return -EIO;
|
|
|
|
if (ecn_np_ctx->cnp_prio != (u32)cnp_prio) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_cnp_prio = ecn_np_ctx->cnp_prio;
|
|
ecn_np_ctx->cnp_prio = (u32)cnp_prio;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_np_ctx->cnp_prio = old_cnp_prio;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static int roce3_init_ecn_enable_sysfs(struct kobject *kobj,
|
|
struct roce3_ecn_enable_ctx *ecn_enable_ctx)
|
|
{
|
|
int ret = 0;
|
|
int i = 0;
|
|
int j = 0;
|
|
const char *prio_arr[8] = {"0", "1", "2", "3", "4", "5", "6", "7"};
|
|
struct roce3_prio_enable_ctx *prio_enable = NULL;
|
|
|
|
ecn_enable_ctx->enable_root = kobject_create_and_add("enable", kobj);
|
|
if (ecn_enable_ctx->enable_root == NULL) {
|
|
pr_err("[ROCE, ERR] %s: Failed to create kobject for ecn enable.(ret:%d)\n",
|
|
__func__, ret);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
for (i = 0; i < PRI_ARRAY_LEN; i++) {
|
|
prio_enable = &ecn_enable_ctx->prio_enable[i];
|
|
prio_enable->ecn_enable_ctx = (void *)ecn_enable_ctx;
|
|
prio_enable->prio = (u32)i;
|
|
prio_enable->prio_en = 1;
|
|
sysfs_attr_init(&prio_enable->enable.attr);
|
|
prio_enable->enable.attr.name = prio_arr[i];
|
|
prio_enable->enable.attr.mode = 0640;
|
|
prio_enable->enable.show = roce3_show_ecn_prio_enable;
|
|
prio_enable->enable.store = roce3_store_ecn_prio_enable;
|
|
ret = sysfs_create_file(ecn_enable_ctx->enable_root, &prio_enable->enable.attr);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE, ERR] %s: Failed to create file for ecn enable.(ret:%d)\n",
|
|
__func__, ret);
|
|
goto err_create_file;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_create_file:
|
|
for (j = i - 1; j >= 0; j--) {
|
|
sysfs_remove_file(ecn_enable_ctx->enable_root,
|
|
&ecn_enable_ctx->prio_enable[i].enable.attr);
|
|
}
|
|
|
|
kobject_put(ecn_enable_ctx->enable_root);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void roce3_remove_ecn_enable_sysfs(struct kobject *kobj,
|
|
struct roce3_ecn_enable_ctx *ecn_enable_ctx)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < PRI_ARRAY_LEN; i++) {
|
|
sysfs_remove_file(ecn_enable_ctx->enable_root,
|
|
&ecn_enable_ctx->prio_enable[i].enable.attr);
|
|
}
|
|
|
|
kobject_put(ecn_enable_ctx->enable_root);
|
|
}
|
|
|
|
static int roce3_init_ecn_ip_enable_sysfs(struct kobject *kobj,
|
|
struct roce3_ecn_ip_enable_ctx *ip_enable_ctx)
|
|
{
|
|
int ret = 0;
|
|
int i = 0;
|
|
int j = 0;
|
|
const char *prio_arr[8] = {"0", "1", "2", "3", "4", "5", "6", "7"};
|
|
struct roce3_ip_prio_enable_ctx *ip_prio_enable = NULL;
|
|
|
|
ip_enable_ctx->ip_enable_root = kobject_create_and_add("ip_enable", kobj);
|
|
if (ip_enable_ctx->ip_enable_root == NULL) {
|
|
pr_err("[ROCE, ERR] %s: Failed to create kobject for ecn ip enable.(ret:%d)\n",
|
|
__func__, ret);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
for (i = 0; i < PRI_ARRAY_LEN; i++) {
|
|
ip_prio_enable = &ip_enable_ctx->ip_prio_enable[i];
|
|
ip_prio_enable->ecn_ip_enable_ctx = (void *)ip_enable_ctx;
|
|
ip_prio_enable->prio = (u32)i;
|
|
ip_prio_enable->prio_en = ROCE_DEFAULT_IP_EABLE_EN;
|
|
sysfs_attr_init(&ip_prio_enable->ip_enable.attr);
|
|
ip_prio_enable->ip_enable.attr.name = prio_arr[i];
|
|
ip_prio_enable->ip_enable.attr.mode = 0640;
|
|
ip_prio_enable->ip_enable.show = roce3_show_ecn_ip_prio_enable;
|
|
ip_prio_enable->ip_enable.store = roce3_store_ecn_ip_prio_enable;
|
|
ret = sysfs_create_file(ip_enable_ctx->ip_enable_root,
|
|
&ip_prio_enable->ip_enable.attr);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE, ERR] %s: Failed to create file for ecn ip enable.(ret:%d)\n",
|
|
__func__, ret);
|
|
goto err_create_file;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_create_file:
|
|
for (j = i - 1; j >= 0; j--) {
|
|
sysfs_remove_file(ip_enable_ctx->ip_enable_root,
|
|
&ip_enable_ctx->ip_prio_enable[i].ip_enable.attr);
|
|
}
|
|
|
|
kobject_put(ip_enable_ctx->ip_enable_root);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void roce3_remove_ecn_ip_enable_sysfs(struct kobject *kobj,
|
|
struct roce3_ecn_ip_enable_ctx *ip_enable_ctx)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < PRI_ARRAY_LEN; i++) {
|
|
sysfs_remove_file(ip_enable_ctx->ip_enable_root,
|
|
&ip_enable_ctx->ip_prio_enable[i].ip_enable.attr);
|
|
}
|
|
|
|
kobject_put(ip_enable_ctx->ip_enable_root);
|
|
}
|
|
|
|
ROCE_ATTR_RW(alpha_dec_period, roce3_show_alpha_dec_period, roce3_store_alpha_dec_period);
|
|
ROCE_ATTR_RW(rate_dec_period, roce3_show_rate_dec_period, roce3_store_rate_dec_period);
|
|
ROCE_ATTR_RW(rate_inc_period, roce3_show_rate_inc_period, roce3_store_rate_inc_period);
|
|
ROCE_ATTR_RW(cnp_cnt_threshold, roce3_show_cnp_cnt_threshold, roce3_store_cnp_cnt_threshold);
|
|
ROCE_ATTR_RW(alpha_threshold, roce3_show_alpha_threshold, roce3_store_alpha_threshold);
|
|
ROCE_ATTR_RW(factor_gita, roce3_show_factor_gita, roce3_store_factor_gita);
|
|
ROCE_ATTR_RW(initial_alpha, roce3_show_initial_alpha, roce3_store_initial_alpha);
|
|
ROCE_ATTR_RW(rate_inc_ai, roce3_show_rate_inc_ai, roce3_store_rate_inc_ai);
|
|
ROCE_ATTR_RW(rate_inc_hai, roce3_show_rate_inc_hai, roce3_store_rate_inc_hai);
|
|
ROCE_ATTR_RW(rate_first_set, roce3_show_rate_first_set, roce3_store_rate_first_set);
|
|
ROCE_ATTR_RW(rate_target_clamp, roce3_show_rate_target_clamp, roce3_store_rate_target_clamp);
|
|
ROCE_ATTR_RW(token_period, roce3_show_token_period, roce3_store_token_period);
|
|
ROCE_ATTR_RW(min_rate, roce3_show_min_rate, roce3_store_min_rate);
|
|
|
|
static struct attribute *ecn_rp_ctx_attrs[] = {
|
|
ROCE_ATTR_PTR(alpha_dec_period),
|
|
ROCE_ATTR_PTR(rate_dec_period),
|
|
ROCE_ATTR_PTR(rate_inc_period),
|
|
ROCE_ATTR_PTR(cnp_cnt_threshold),
|
|
ROCE_ATTR_PTR(alpha_threshold),
|
|
ROCE_ATTR_PTR(factor_gita),
|
|
ROCE_ATTR_PTR(initial_alpha),
|
|
ROCE_ATTR_PTR(rate_inc_ai),
|
|
ROCE_ATTR_PTR(rate_inc_hai),
|
|
ROCE_ATTR_PTR(rate_first_set),
|
|
ROCE_ATTR_PTR(rate_target_clamp),
|
|
ROCE_ATTR_PTR(token_period),
|
|
ROCE_ATTR_PTR(min_rate),
|
|
NULL,
|
|
};
|
|
ATTRIBUTE_GROUPS(ecn_rp_ctx);
|
|
|
|
static void roce_ecn_rp_sysfs_release(struct kobject *kobj) {}
|
|
|
|
static const struct kobj_type roce_ecn_rp_ktype = {
|
|
.sysfs_ops = &kobj_sysfs_ops,
|
|
.release = roce_ecn_rp_sysfs_release,
|
|
.default_groups = ecn_rp_ctx_groups,
|
|
};
|
|
|
|
static int roce3_init_ecn_rp_sysfs(struct kobject *kobj, struct roce3_ecn_rp_ctx *ecn_rp_ctx)
|
|
{
|
|
int ret = 0;
|
|
|
|
ecn_rp_ctx->alpha_dec_period = ROCE_DEFAULT_ALPHA_DEC_PERIOD;
|
|
ecn_rp_ctx->rate_dec_period = ROCE_DEFAULT_RATE_DEC_PERIOD;
|
|
ecn_rp_ctx->rate_inc_period = ROCE_DEFAULT_RATE_INC_PERIOD;
|
|
ecn_rp_ctx->alpha_threshold = ROCE_DEFAULT_ALPHA_THRESHOLD;
|
|
ecn_rp_ctx->cnp_cnt_threshold = ROCE_DEFAULT_CNP_CNT_THRESHOLD;
|
|
ecn_rp_ctx->factor_gita = ROCE_DEFAULT_FACTOR_GITA;
|
|
ecn_rp_ctx->initial_alpha = ROCE_DEFAULT_INITIAL_ALPHA;
|
|
ecn_rp_ctx->rate_inc_ai = ROCE_DEFAULT_RATE_INC_AI;
|
|
ecn_rp_ctx->rate_inc_hai = ROCE_DEFAULT_RATE_INC_HAI;
|
|
ecn_rp_ctx->rate_first_set = ROCE_DEFAULT_RATE_FIRST_SET;
|
|
ecn_rp_ctx->rate_target_clamp = ROCE_DEFAULT_RATE_TARGET_CLAMP;
|
|
ecn_rp_ctx->token_period = ROCE_DEFAULT_TOKEN_PERIOD;
|
|
ecn_rp_ctx->min_rate = ROCE_DEFAULT_MIN_RATE;
|
|
ret = kobject_init_and_add(&ecn_rp_ctx->ecn_rp_root, &roce_ecn_rp_ktype, kobj, "roce3_rp");
|
|
if (ret != 0) {
|
|
pr_err("[ROCE, ERR] %s: Failed to add kobject roce3_rp.(ret:%d)\n", __func__, ret);
|
|
kobject_put(&ecn_rp_ctx->ecn_rp_root);
|
|
return ret;
|
|
}
|
|
|
|
ecn_rp_ctx->enable_ctx.np_rp = ROCE_DCQCN_RP;
|
|
ret = roce3_init_ecn_enable_sysfs(&ecn_rp_ctx->ecn_rp_root, &ecn_rp_ctx->enable_ctx);
|
|
if (ret != 0)
|
|
goto err_init_prio_enable_sysfs;
|
|
|
|
return 0;
|
|
|
|
err_init_prio_enable_sysfs:
|
|
kobject_put(&ecn_rp_ctx->ecn_rp_root);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void roce3_remove_ecn_rp_sysfs(struct kobject *kobj, struct roce3_ecn_rp_ctx *ecn_rp_ctx)
|
|
{
|
|
roce3_remove_ecn_enable_sysfs(&ecn_rp_ctx->ecn_rp_root, &ecn_rp_ctx->enable_ctx);
|
|
|
|
kobject_put(&ecn_rp_ctx->ecn_rp_root);
|
|
}
|
|
|
|
ROCE_ATTR_RW(min_cnp_period, roce3_show_min_cnp_period, roce3_store_min_cnp_period);
|
|
ROCE_ATTR_RW(quick_adjust_en, roce3_show_quick_adjust_en, roce3_store_quick_adjust_en);
|
|
ROCE_ATTR_RW(port_mode, roce3_show_port_mode, roce3_store_port_mode);
|
|
ROCE_ATTR_RW(cnp_prio_enable, roce3_show_cnp_prio_enable, roce3_store_cnp_prio_enable);
|
|
ROCE_ATTR_RW(cnp_prio, roce3_show_cnp_prio, roce3_store_cnp_prio);
|
|
|
|
static struct attribute *ecn_np_ctx_attrs[] = {
|
|
ROCE_ATTR_PTR(min_cnp_period),
|
|
ROCE_ATTR_PTR(quick_adjust_en),
|
|
ROCE_ATTR_PTR(port_mode),
|
|
ROCE_ATTR_PTR(cnp_prio_enable),
|
|
ROCE_ATTR_PTR(cnp_prio),
|
|
NULL,
|
|
};
|
|
ATTRIBUTE_GROUPS(ecn_np_ctx);
|
|
|
|
static void roce_ecn_np_sysfs_release(struct kobject *kobj) {}
|
|
|
|
static const struct kobj_type roce_ecn_np_ktype = {
|
|
.sysfs_ops = &kobj_sysfs_ops,
|
|
.release = roce_ecn_np_sysfs_release,
|
|
.default_groups = ecn_np_ctx_groups,
|
|
};
|
|
|
|
static int roce3_init_ecn_np_sysfs(struct kobject *kobj, struct roce3_ecn_np_ctx *ecn_np_ctx)
|
|
{
|
|
int ret = 0;
|
|
|
|
ecn_np_ctx->min_cnp_period = ROCE_DEFAULT_MIN_CNP_PERIOD;
|
|
ecn_np_ctx->quick_adjust_en = ROCE_DEFAULT_QUICK_AJ_ENABLE;
|
|
ecn_np_ctx->port_mode = ROCE_DEFAULT_PORT_MODE_25G;
|
|
ecn_np_ctx->cnp_prio_enable = ROCE_DEFAULT_CNP_PRIO_ENABLE;
|
|
ecn_np_ctx->cnp_prio = ROCE_DEFAULT_CNP_PRIO;
|
|
ret = kobject_init_and_add(&ecn_np_ctx->ecn_np_root, &roce_ecn_np_ktype, kobj, "roce3_np");
|
|
if (ret != 0) {
|
|
pr_err("[ROCE, ERR] %s: Failed to add kobject roce3_np.(ret:%d)\n", __func__, ret);
|
|
kobject_put(&ecn_np_ctx->ecn_np_root);
|
|
return ret;
|
|
}
|
|
|
|
ecn_np_ctx->enable_ctx.np_rp = ROCE_DCQCN_NP;
|
|
ret = roce3_init_ecn_enable_sysfs(&ecn_np_ctx->ecn_np_root, &ecn_np_ctx->enable_ctx);
|
|
if (ret != 0)
|
|
goto err_init_prio_enable_sysfs;
|
|
|
|
return 0;
|
|
|
|
err_init_prio_enable_sysfs:
|
|
kobject_put(&ecn_np_ctx->ecn_np_root);
|
|
return ret;
|
|
}
|
|
|
|
static void roce3_remove_ecn_np_sysfs(struct kobject *kobj, struct roce3_ecn_np_ctx *ecn_np_ctx)
|
|
{
|
|
roce3_remove_ecn_enable_sysfs(&ecn_np_ctx->ecn_np_root, &ecn_np_ctx->enable_ctx);
|
|
|
|
kobject_put(&ecn_np_ctx->ecn_np_root);
|
|
}
|
|
|
|
static ssize_t roce3_show_ecn_ver(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
|
{
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj);
|
|
|
|
return sprintf(buf, "%d\n", (int)ecn_ctx->ecn_ver);
|
|
}
|
|
|
|
static ssize_t roce3_store_ecn_ver(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
ssize_t ret = 0;
|
|
int ecn_ver = 0;
|
|
u32 old_ecn_ver = 0;
|
|
struct roce3_ecn_ctx *ecn_ctx = to_roce3_ecn_ctx(kobj);
|
|
|
|
ret = kstrtoint(buf, 10, &ecn_ver);
|
|
if (ret != 0)
|
|
return -EIO;
|
|
|
|
if ((ecn_ver < ECN_VER_DCQCN) || (ecn_ver > ECN_VER_PATHQCN))
|
|
return -EIO;
|
|
|
|
if (ecn_ctx->ecn_ver != (u32)ecn_ver) {
|
|
mutex_lock(&ecn_ctx->ecn_mutex);
|
|
old_ecn_ver = ecn_ctx->ecn_ver;
|
|
ecn_ctx->ecn_ver = (u32)ecn_ver;
|
|
ret = (ssize_t)roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0) {
|
|
ecn_ctx->ecn_ver = old_ecn_ver;
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
return -EIO;
|
|
}
|
|
mutex_unlock(&ecn_ctx->ecn_mutex);
|
|
}
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
ROCE_ATTR_RW(ecn_ver, roce3_show_ecn_ver, roce3_store_ecn_ver);
|
|
ROCE_ATTR_RW(cc_algo, roce3_show_cc_algo, roce3_store_cc_algo);
|
|
|
|
static struct attribute *ecn_ctx_attrs[] = {
|
|
ROCE_ATTR_PTR(ecn_ver),
|
|
ROCE_ATTR_PTR(cc_algo),
|
|
NULL,
|
|
};
|
|
ATTRIBUTE_GROUPS(ecn_ctx);
|
|
|
|
static void roce_ecn_sysfs_release(struct kobject *kobj) {}
|
|
|
|
static const struct kobj_type roce_ecn_ktype = {
|
|
.sysfs_ops = &kobj_sysfs_ops,
|
|
.release = roce_ecn_sysfs_release,
|
|
.default_groups = ecn_ctx_groups,
|
|
};
|
|
|
|
static int roce3_init_ecn_sysfs(struct net_device *ndev, struct roce3_ecn_ctx *ecn_ctx)
|
|
{
|
|
int ret = 0;
|
|
|
|
memset(ecn_ctx, 0, sizeof(*ecn_ctx));
|
|
|
|
mutex_init(&ecn_ctx->ecn_mutex);
|
|
|
|
ecn_ctx->ecn_ver = ECN_VER_DCQCN;
|
|
#ifdef ROCE_COMPUTE
|
|
#ifdef EULER_2_10_OFED_4_18
|
|
ecn_ctx->cc_algo = ROCE_CC_LDCP_ALGO;
|
|
#else
|
|
ecn_ctx->cc_algo = ROCE_CC_DCQCN_ALGO;
|
|
#endif
|
|
#elif defined(ROCE_VBS_EN) || defined(ROCE_STANDARD)
|
|
ecn_ctx->cc_algo = ROCE_CC_LDCP_ALGO;
|
|
#else
|
|
ecn_ctx->cc_algo = ROCE_CC_DISABLE;
|
|
#endif
|
|
|
|
ret = kobject_init_and_add(&ecn_ctx->ecn_root, &roce_ecn_ktype, &ndev->dev.kobj, "ecn");
|
|
if (ret != 0) {
|
|
pr_err("[ROCE, ERR] %s: Failed to add kobject ecn.(ret:%d)\n", __func__, ret);
|
|
kobject_put(&ecn_ctx->ecn_root);
|
|
return ret;
|
|
}
|
|
|
|
ret = roce3_init_ecn_np_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->np_ctx);
|
|
if (ret != 0)
|
|
goto err_init_np_sysfs;
|
|
|
|
ret = roce3_init_ecn_rp_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->rp_ctx);
|
|
if (ret != 0)
|
|
goto err_init_rp_sysfs;
|
|
|
|
ret = roce3_init_ecn_ip_enable_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->ip_enable_ctx);
|
|
if (ret != 0)
|
|
goto err_init_ip_enable_sysfs;
|
|
|
|
ret = roce3_update_ecn_param(ecn_ctx);
|
|
if (ret != 0)
|
|
goto err_update;
|
|
|
|
return 0;
|
|
|
|
err_update:
|
|
roce3_remove_ecn_ip_enable_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->ip_enable_ctx);
|
|
err_init_ip_enable_sysfs:
|
|
roce3_remove_ecn_rp_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->rp_ctx);
|
|
err_init_rp_sysfs:
|
|
roce3_remove_ecn_np_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->np_ctx);
|
|
err_init_np_sysfs:
|
|
kobject_put(&ecn_ctx->ecn_root);
|
|
return ret;
|
|
}
|
|
|
|
static void roce3_prase_qpc(struct roce_qp_context *qpc)
|
|
{
|
|
qpc->chip_seg.sqc.dw2.value = be32_to_cpu(qpc->chip_seg.sqc.dw2.value);
|
|
qpc->chip_seg.sqc.dw3.value = be32_to_cpu(qpc->chip_seg.sqc.dw3.value);
|
|
qpc->chip_seg.sqac.dw3.value = be32_to_cpu(qpc->chip_seg.sqac.dw3.value);
|
|
qpc->chip_seg.sqac.dw7.value = be32_to_cpu(qpc->chip_seg.sqac.dw7.value);
|
|
qpc->chip_seg.rqc.dw3.value = be32_to_cpu(qpc->chip_seg.rqc.dw3.value);
|
|
qpc->chip_seg.rqc.dw7.value = be32_to_cpu(qpc->chip_seg.rqc.dw7.value);
|
|
qpc->sw_seg.ucode_seg.common.dw3.value =
|
|
be32_to_cpu(qpc->sw_seg.ucode_seg.common.dw3.value);
|
|
qpc->sw_seg.ucode_seg.sq_ctx.dw9.value =
|
|
be32_to_cpu(qpc->sw_seg.ucode_seg.sq_ctx.dw9.value);
|
|
qpc->sw_seg.ucode_seg.sq_ctx.ack_ctx.dw15.value =
|
|
be32_to_cpu(qpc->sw_seg.ucode_seg.sq_ctx.ack_ctx.dw15.value);
|
|
qpc->sw_seg.ucode_seg.rq_ctx.dw22.value =
|
|
be32_to_cpu(qpc->sw_seg.ucode_seg.rq_ctx.dw22.value);
|
|
qpc->sw_seg.ucode_seg.rq_ctx.ack_ctx.dw27.value =
|
|
be32_to_cpu(qpc->sw_seg.ucode_seg.rq_ctx.ack_ctx.dw27.value);
|
|
}
|
|
|
|
static ssize_t roce3_store_dfx_qpc(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
u32 qpn;
|
|
struct roce3_dfx_qpc_ctx *qpc_ctx = NULL;
|
|
struct roce3_dfx_ctx *dfx_ctx = NULL;
|
|
struct roce3_device *rdev = NULL;
|
|
struct roce_qp_context qpc;
|
|
struct rdma_service_cap *rdma_cap = NULL;
|
|
|
|
if (kobj == NULL || attr == NULL || buf == NULL || count == 0) {
|
|
pr_err("[ROCE] %s: Invalid input para\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
qpc_ctx = container_of(attr, struct roce3_dfx_qpc_ctx, kattr);
|
|
dfx_ctx = container_of(qpc_ctx, struct roce3_dfx_ctx, qpc_ctx);
|
|
rdev = container_of(dfx_ctx, struct roce3_device, dfx_ctx);
|
|
|
|
memset(&qpc, 0, sizeof(struct roce_qp_context));
|
|
|
|
ret = (int)kstrtou32(buf, 10, &qpn);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to do sscanf_s, ret(%d)\n", __func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
rdma_cap = &rdev->rdma_cap;
|
|
if ((qpn >= rdma_cap->dev_rdma_cap.roce_own_cap.max_qps) || (qpn < ROCE_MIN_QPN)) {
|
|
pr_err("[ROCE] %s: Invalid qpn(%u), max_qps(%u)\n",
|
|
__func__, qpn, rdma_cap->dev_rdma_cap.roce_own_cap.max_qps);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = roce3_dfx_cmd_query_qp(rdev, qpn, &qpc);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to query qpc, ret(%d)\n", __func__, ret);
|
|
return (ssize_t)ret;
|
|
}
|
|
|
|
roce3_prase_qpc(&qpc);
|
|
|
|
roce3_dfx_print("qpn(0x%x): sqc pi(0x%x), sqc ci(0x%x), ccf_appid(0x%x)\n",
|
|
qpn, qpc.chip_seg.sqc.dw2.bs.sq_pi, qpc.chip_seg.sqc.dw3.bs.sq_ci,
|
|
qpc.sw_seg.ucode_seg.common.dw0.bs.ccf_appid);
|
|
roce3_dfx_print("sqac ci(0x%x), sqac wqe_prefetch_ci(0x%x), rqc pi(0x%x), rqc ci(0x%x)\n",
|
|
qpc.chip_seg.sqac.dw3.bs.sqa_ci, qpc.chip_seg.sqac.dw7.bs.sqa_wqe_prefetch_ci,
|
|
qpc.chip_seg.rqc.dw7.bs.rq_pi, qpc.chip_seg.rqc.dw3.bs.rq_ci);
|
|
roce3_dfx_print("sq_ssn(0x%x), sq_rcv_msn(0x%x), rq_last_msn(0x%x), rqa_msn(0x%x)\n",
|
|
qpc.sw_seg.ucode_seg.sq_ctx.dw9.bs.ssn,
|
|
qpc.sw_seg.ucode_seg.sq_ctx.ack_ctx.dw15.bs.sq_rcv_msn,
|
|
qpc.sw_seg.ucode_seg.rq_ctx.dw22.bs.last_msn,
|
|
qpc.sw_seg.ucode_seg.rq_ctx.ack_ctx.dw27.bs.msn);
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_store_dfx_cqc(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
u32 cqn;
|
|
struct roce3_dfx_cqc_ctx *cqc_ctx = NULL;
|
|
struct roce3_dfx_ctx *dfx_ctx = NULL;
|
|
struct roce3_device *rdev = NULL;
|
|
struct roce_cq_context cqc;
|
|
struct rdma_service_cap *rdma_cap = NULL;
|
|
|
|
if (kobj == NULL || attr == NULL || buf == NULL || count == 0) {
|
|
pr_err("[ROCE] %s: Invalid input para\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
cqc_ctx = container_of(attr, struct roce3_dfx_cqc_ctx, kattr);
|
|
dfx_ctx = container_of(cqc_ctx, struct roce3_dfx_ctx, cqc_ctx);
|
|
rdev = container_of(dfx_ctx, struct roce3_device, dfx_ctx);
|
|
|
|
memset(&cqc, 0, sizeof(struct roce_cq_context));
|
|
|
|
ret = (int)kstrtou32(buf, 10, &cqn);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to do sscanf_s, ret(%d)\n", __func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
rdma_cap = &rdev->rdma_cap;
|
|
if (cqn >= rdma_cap->dev_rdma_cap.roce_own_cap.max_cqs) {
|
|
pr_err("[ROCE] %s: Invalid cqn(%u), max_cqs(%u)\n", __func__, cqn,
|
|
rdma_cap->dev_rdma_cap.roce_own_cap.max_cqs);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = roce3_dfx_cmd_query_cq(rdev, cqn, &cqc);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to query cqc, ret(%d)\n", __func__, ret);
|
|
return (ssize_t)ret;
|
|
}
|
|
|
|
cqc.dw2.value = be32_to_cpu(cqc.dw2.value);
|
|
cqc.dw1.value = be32_to_cpu(cqc.dw1.value);
|
|
|
|
roce3_dfx_print("cqn(0x%x): pi(0x%x), ci(0x%x)\n", cqn, cqc.dw2.bs.pi, cqc.dw1.bs.ci);
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static ssize_t roce3_store_dfx_srqc(struct kobject *kobj, struct kobj_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
u32 srqn;
|
|
struct roce3_dfx_srqc_ctx *srqc_ctx = NULL;
|
|
struct roce3_dfx_ctx *dfx_ctx = NULL;
|
|
struct roce3_device *rdev = NULL;
|
|
struct roce_srq_context srqc;
|
|
struct rdma_service_cap *rdma_cap = NULL;
|
|
|
|
if (kobj == NULL || attr == NULL || buf == NULL || count == 0) {
|
|
pr_err("[ROCE] %s: Invalid input para\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
srqc_ctx = container_of(attr, struct roce3_dfx_srqc_ctx, kattr);
|
|
dfx_ctx = container_of(srqc_ctx, struct roce3_dfx_ctx, srqc_ctx);
|
|
rdev = container_of(dfx_ctx, struct roce3_device, dfx_ctx);
|
|
|
|
memset(&srqc, 0, sizeof(struct roce_srq_context));
|
|
|
|
ret = (int)kstrtou32(buf, 10, &srqn);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to do sscanf_s, ret(%d)\n", __func__, ret);
|
|
return -EIO;
|
|
}
|
|
|
|
rdma_cap = &rdev->rdma_cap;
|
|
if (srqn >= rdma_cap->dev_rdma_cap.roce_own_cap.max_srqs) {
|
|
pr_err("[ROCE] %s: Invalid srqn(%u), max_srqs(%u)\n", __func__, srqn,
|
|
rdma_cap->dev_rdma_cap.roce_own_cap.max_srqs);
|
|
return -EIO;
|
|
}
|
|
|
|
ret = roce3_dfx_cmd_query_srq(rdev, srqn, &srqc);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to query srqc, ret(%d)\n", __func__, ret);
|
|
return (ssize_t)ret;
|
|
}
|
|
|
|
srqc.dw4.value = be32_to_cpu(srqc.dw4.value);
|
|
|
|
roce3_dfx_print("srqn(0x%x): pcnt(0x%x), ccnt(0x%x)\n",
|
|
srqn, srqc.dw4.bs.pcnt, srqc.dw4.bs.ccnt);
|
|
|
|
return (ssize_t)count;
|
|
}
|
|
|
|
static int roce3_init_dfx_sub_ctx_sysfs(struct kobject *kobj, struct roce3_dfx_ctx *dfx_ctx)
|
|
{
|
|
int ret;
|
|
struct kobj_attribute *qpc_kattr = NULL;
|
|
struct kobj_attribute *cqc_kattr = NULL;
|
|
struct kobj_attribute *srqc_kattr = NULL;
|
|
|
|
if (kobj == NULL || dfx_ctx == NULL) {
|
|
pr_err("[ROCE] %s: Invalid kobj or dfx_ctx\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
qpc_kattr = &dfx_ctx->qpc_ctx.kattr;
|
|
cqc_kattr = &dfx_ctx->cqc_ctx.kattr;
|
|
srqc_kattr = &dfx_ctx->srqc_ctx.kattr;
|
|
|
|
sysfs_attr_init(&qpc_kattr->attr);
|
|
qpc_kattr->attr.name = "qpc";
|
|
qpc_kattr->attr.mode = 0640;
|
|
qpc_kattr->store = roce3_store_dfx_qpc;
|
|
ret = sysfs_create_file(kobj, &qpc_kattr->attr);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: QPC failed to do sysfs_create_file, ret(%d)\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
sysfs_attr_init(&cqc_kattr->attr);
|
|
cqc_kattr->attr.name = "cqc";
|
|
cqc_kattr->attr.mode = 0640;
|
|
cqc_kattr->store = roce3_store_dfx_cqc;
|
|
ret = sysfs_create_file(kobj, &cqc_kattr->attr);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: CQC failed to do sysfs_create_file, ret(%d)\n", __func__, ret);
|
|
goto err_create_cqc_sysfs;
|
|
}
|
|
|
|
sysfs_attr_init(&srqc_kattr->attr);
|
|
srqc_kattr->attr.name = "srqc";
|
|
srqc_kattr->attr.mode = 0640;
|
|
srqc_kattr->store = roce3_store_dfx_srqc;
|
|
ret = sysfs_create_file(kobj, &srqc_kattr->attr);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: SRQC failed to do sysfs_create_file, ret(%d)\n", __func__, ret);
|
|
goto err_create_srqc_sysfs;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_create_srqc_sysfs:
|
|
sysfs_remove_file(kobj, &cqc_kattr->attr);
|
|
|
|
err_create_cqc_sysfs:
|
|
sysfs_remove_file(kobj, &qpc_kattr->attr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int roce3_init_dfx_sysfs(struct net_device *ndev, struct roce3_dfx_ctx *dfx_ctx)
|
|
{
|
|
int ret;
|
|
|
|
memset(dfx_ctx, 0, sizeof(*dfx_ctx));
|
|
|
|
dfx_ctx->dfx_root = kobject_create_and_add("roce3_dfx", &ndev->dev.kobj);
|
|
if (dfx_ctx->dfx_root == NULL) {
|
|
pr_err("[ROCE] %s: Failed to do kobject_create_and_add\n", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = roce3_init_dfx_sub_ctx_sysfs(dfx_ctx->dfx_root, dfx_ctx);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to init dfx sub ctx sysfs, ret(%d)\n", __func__, ret);
|
|
kobject_put(dfx_ctx->dfx_root);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void roce3_remove_ecn_sysfs(struct roce3_ecn_ctx *ecn_ctx)
|
|
{
|
|
roce3_remove_ecn_ip_enable_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->ip_enable_ctx);
|
|
|
|
roce3_remove_ecn_rp_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->rp_ctx);
|
|
|
|
roce3_remove_ecn_np_sysfs(&ecn_ctx->ecn_root, &ecn_ctx->np_ctx);
|
|
|
|
kobject_put(&ecn_ctx->ecn_root);
|
|
}
|
|
|
|
int roce3_init_sysfs(struct roce3_device *rdev)
|
|
{
|
|
int ret;
|
|
|
|
ret = roce3_init_ecn_sysfs(rdev->ndev, &rdev->ecn_ctx);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to init ecn sysfs, ret(%d)\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = roce3_init_dfx_sysfs(rdev->ndev, &rdev->dfx_ctx);
|
|
if (ret != 0) {
|
|
pr_err("[ROCE] %s: Failed to init dfx sysfs, ret(%d)\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void roce3_remove_dfx_sub_sysfs(struct roce3_dfx_ctx *dfx_ctx)
|
|
{
|
|
if (dfx_ctx->dfx_root != NULL) {
|
|
sysfs_remove_file(dfx_ctx->dfx_root, &dfx_ctx->srqc_ctx.kattr.attr);
|
|
|
|
sysfs_remove_file(dfx_ctx->dfx_root, &dfx_ctx->cqc_ctx.kattr.attr);
|
|
|
|
sysfs_remove_file(dfx_ctx->dfx_root, &dfx_ctx->qpc_ctx.kattr.attr);
|
|
|
|
kobject_put(dfx_ctx->dfx_root);
|
|
|
|
dfx_ctx->dfx_root = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void roce3_remove_sysfs(struct roce3_device *rdev)
|
|
{
|
|
roce3_remove_dfx_sub_sysfs(&rdev->dfx_ctx);
|
|
roce3_remove_ecn_sysfs(&rdev->ecn_ctx);
|
|
}
|