[PATCH for-next 3/3] RDMA/hns: Support setting GSI QP SL

From: hginjgerx

Date: Thu Jun 04 2026 - 07:49:05 EST


From: Chengchang Tang <tangchengchang@xxxxxxxxxx>

Add debugfs interface to set SL for GSI QP. The interface validates
that SL value does not exceed MAX_SERVICE_LEVEL.

The GSI QP uses the configured SL instead of the SL from AH when
posting UD SQ WQE.

Signed-off-by: Chengchang Tang <tangchengchang@xxxxxxxxxx>
Signed-off-by: Junxian Huang <huangjunxian6@xxxxxxxxxxxxx>
---
drivers/infiniband/hw/hns/hns_roce_debugfs.c | 30 ++++++++++++++++++++
drivers/infiniband/hw/hns/hns_roce_debugfs.h | 1 +
drivers/infiniband/hw/hns/hns_roce_device.h | 1 +
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 5 ++--
4 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_debugfs.c b/drivers/infiniband/hw/hns/hns_roce_debugfs.c
index 05630f7c9155..2f9410fdd0d7 100644
--- a/drivers/infiniband/hw/hns/hns_roce_debugfs.c
+++ b/drivers/infiniband/hw/hns/hns_roce_debugfs.c
@@ -339,6 +339,29 @@ static void create_cc_param_debugfs(struct hns_roce_dev *hr_dev,
}
}

+static int gsi_sl_debugfs_read(struct seq_file *seq, void *data)
+{
+ struct hns_roce_dev *hr_dev = data;
+
+ seq_printf(seq, "%u\n", hr_dev->gsi_sl);
+ return 0;
+}
+
+static ssize_t gsi_sl_debugfs_write(char *buf, size_t count, void *data)
+{
+ struct hns_roce_dev *hr_dev = data;
+ u32 val;
+
+ if (kstrtou32(buf, 0, &val))
+ return -EINVAL;
+
+ if (val > MAX_SERVICE_LEVEL)
+ return -EINVAL;
+
+ hr_dev->gsi_sl = val;
+ return count;
+}
+
/* debugfs for device */
void hns_roce_register_debugfs(struct hns_roce_dev *hr_dev)
{
@@ -349,6 +372,13 @@ void hns_roce_register_debugfs(struct hns_roce_dev *hr_dev)

create_sw_stat_debugfs(hr_dev, dbgfs->root);
create_cc_param_debugfs(hr_dev, dbgfs->root);
+
+ dbgfs->gsi_sl_seqfile.read = gsi_sl_debugfs_read;
+ dbgfs->gsi_sl_seqfile.write = gsi_sl_debugfs_write;
+ dbgfs->gsi_sl_seqfile.data = hr_dev;
+ debugfs_create_file("gsi_sl", 0600, dbgfs->root,
+ &dbgfs->gsi_sl_seqfile,
+ &hns_debugfs_seqfile_fops);
}

void hns_roce_unregister_debugfs(struct hns_roce_dev *hr_dev)
diff --git a/drivers/infiniband/hw/hns/hns_roce_debugfs.h b/drivers/infiniband/hw/hns/hns_roce_debugfs.h
index 116b1e8b6677..f04683900022 100644
--- a/drivers/infiniband/hw/hns/hns_roce_debugfs.h
+++ b/drivers/infiniband/hw/hns/hns_roce_debugfs.h
@@ -47,6 +47,7 @@ struct hns_roce_dev_debugfs {
struct dentry *root;
struct hns_sw_stat_debugfs sw_stat_root;
struct hns_cc_param_debugfs cc_param_root[CONG_TYPE_MAX_NUM];
+ struct hns_debugfs_seqfile gsi_sl_seqfile;
};

struct hns_roce_dev;
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 686610642c0a..8a5a116efd9e 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -1048,6 +1048,7 @@ struct hns_roce_dev {
struct hns_roce_dev_debugfs dbgfs;
atomic64_t *dfx_cnt;
struct hns_roce_scc_param *scc_param;
+ u8 gsi_sl;
};

enum hns_roce_trace_type {
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 6dd56a85d890..8d6444f44553 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -442,8 +442,9 @@ static int fill_ud_av(struct hns_roce_qp *qp,
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_HOPLIMIT, ah->av.hop_limit);
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_TCLASS, ah->av.tclass);
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_FLOW_LABEL, ah->av.flowlabel);
- if (!qp->ud_sl_set) {
- qp->sl = ah->av.sl;
+ if (!qp->ud_sl_set || qp->ibqp.qp_type == IB_QPT_GSI) {
+ qp->sl = qp->ibqp.qp_type == IB_QPT_GSI ?
+ hr_dev->gsi_sl : ah->av.sl;
qp->ud_sl_set = true;
}

--
2.33.0