Skip to content

Commit ee20cc1

Browse files
Junxian Huangrleon
authored andcommitted
RDMA/hns: Support DSCP
Add support for DSCP configuration. For DSCP, get dscp-prio mapping via hns3 nic driver api .get_dscp_prio() and fill the SL (in WQE for UD or in QPC for RC) with the priority value. The prio-tc mapping is configured to HW by hns3 nic driver. HW will select a corresponding TC according to SL and the prio-tc mapping. Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> Link: https://lore.kernel.org/r/20240315093551.1650088-1-huangjunxian6@hisilicon.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 2ca7e93 commit ee20cc1

File tree

5 files changed

+116
-30
lines changed

5 files changed

+116
-30
lines changed

drivers/infiniband/hw/hns/hns_roce_ah.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
5959
struct hns_roce_dev *hr_dev = to_hr_dev(ibah->device);
6060
struct hns_roce_ib_create_ah_resp resp = {};
6161
struct hns_roce_ah *ah = to_hr_ah(ibah);
62-
int ret = 0;
63-
u32 max_sl;
62+
u8 tclass = get_tclass(grh);
63+
u8 priority = 0;
64+
u8 tc_mode = 0;
65+
int ret;
6466

6567
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata)
6668
return -EOPNOTSUPP;
@@ -74,16 +76,23 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
7476
ah->av.hop_limit = grh->hop_limit;
7577
ah->av.flowlabel = grh->flow_label;
7678
ah->av.udp_sport = get_ah_udp_sport(ah_attr);
77-
ah->av.tclass = get_tclass(grh);
78-
79-
ah->av.sl = rdma_ah_get_sl(ah_attr);
80-
max_sl = min_t(u32, MAX_SERVICE_LEVEL, hr_dev->caps.sl_num - 1);
81-
if (unlikely(ah->av.sl > max_sl)) {
82-
ibdev_err_ratelimited(&hr_dev->ib_dev,
83-
"failed to set sl, sl (%u) shouldn't be larger than %u.\n",
84-
ah->av.sl, max_sl);
79+
ah->av.tclass = tclass;
80+
81+
ret = hr_dev->hw->get_dscp(hr_dev, tclass, &tc_mode, &priority);
82+
if (ret == -EOPNOTSUPP)
83+
ret = 0;
84+
85+
if (ret && grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
86+
return ret;
87+
88+
if (tc_mode == HNAE3_TC_MAP_MODE_DSCP &&
89+
grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
90+
ah->av.sl = priority;
91+
else
92+
ah->av.sl = rdma_ah_get_sl(ah_attr);
93+
94+
if (!check_sl_valid(hr_dev, ah->av.sl))
8595
return -EINVAL;
86-
}
8796

8897
memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE);
8998
memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
@@ -99,6 +108,8 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
99108
}
100109

101110
if (udata) {
111+
resp.priority = ah->av.sl;
112+
resp.tc_mode = tc_mode;
102113
memcpy(resp.dmac, ah_attr->roce.dmac, ETH_ALEN);
103114
ret = ib_copy_to_udata(udata, &resp,
104115
min(udata->outlen, sizeof(resp)));

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@ struct hns_roce_qp {
645645
struct hns_user_mmap_entry *dwqe_mmap_entry;
646646
u32 config;
647647
enum hns_roce_cong_type cong_type;
648+
u8 tc_mode;
649+
u8 priority;
648650
};
649651

650652
struct hns_roce_ib_iboe {
@@ -950,6 +952,8 @@ struct hns_roce_hw {
950952
int (*query_sccc)(struct hns_roce_dev *hr_dev, u32 qpn, void *buffer);
951953
int (*query_hw_counter)(struct hns_roce_dev *hr_dev,
952954
u64 *stats, u32 port, int *hw_counters);
955+
int (*get_dscp)(struct hns_roce_dev *hr_dev, u8 dscp,
956+
u8 *tc_mode, u8 *priority);
953957
const struct ib_device_ops *hns_roce_dev_ops;
954958
const struct ib_device_ops *hns_roce_dev_srq_ops;
955959
};
@@ -1292,4 +1296,6 @@ struct hns_user_mmap_entry *
12921296
hns_roce_user_mmap_entry_insert(struct ib_ucontext *ucontext, u64 address,
12931297
size_t length,
12941298
enum hns_roce_mmap_type mmap_type);
1299+
bool check_sl_valid(struct hns_roce_dev *hr_dev, u8 sl);
1300+
12951301
#endif /* _HNS_ROCE_DEVICE_H */

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,6 @@ static int fill_ud_av(struct hns_roce_v2_ud_send_wqe *ud_sq_wqe,
443443
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_HOPLIMIT, ah->av.hop_limit);
444444
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_TCLASS, ah->av.tclass);
445445
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_FLOW_LABEL, ah->av.flowlabel);
446-
447-
if (WARN_ON(ah->av.sl > MAX_SERVICE_LEVEL))
448-
return -EINVAL;
449-
450446
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_SL, ah->av.sl);
451447

452448
ud_sq_wqe->sgid_index = ah->av.gid_index;
@@ -4828,6 +4824,69 @@ static int fill_cong_field(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
48284824
return 0;
48294825
}
48304826

4827+
static int hns_roce_hw_v2_get_dscp(struct hns_roce_dev *hr_dev, u8 dscp,
4828+
u8 *tc_mode, u8 *priority)
4829+
{
4830+
struct hns_roce_v2_priv *priv = hr_dev->priv;
4831+
struct hnae3_handle *handle = priv->handle;
4832+
const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
4833+
4834+
if (!ops->get_dscp_prio)
4835+
return -EOPNOTSUPP;
4836+
4837+
return ops->get_dscp_prio(handle, dscp, tc_mode, priority);
4838+
}
4839+
4840+
bool check_sl_valid(struct hns_roce_dev *hr_dev, u8 sl)
4841+
{
4842+
u32 max_sl;
4843+
4844+
max_sl = min_t(u32, MAX_SERVICE_LEVEL, hr_dev->caps.sl_num - 1);
4845+
if (unlikely(sl > max_sl)) {
4846+
ibdev_err_ratelimited(&hr_dev->ib_dev,
4847+
"failed to set SL(%u). Shouldn't be larger than %u.\n",
4848+
sl, max_sl);
4849+
return false;
4850+
}
4851+
4852+
return true;
4853+
}
4854+
4855+
static int hns_roce_set_sl(struct ib_qp *ibqp,
4856+
const struct ib_qp_attr *attr,
4857+
struct hns_roce_v2_qp_context *context,
4858+
struct hns_roce_v2_qp_context *qpc_mask)
4859+
{
4860+
const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr);
4861+
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
4862+
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
4863+
struct ib_device *ibdev = &hr_dev->ib_dev;
4864+
int ret;
4865+
4866+
ret = hns_roce_hw_v2_get_dscp(hr_dev, get_tclass(&attr->ah_attr.grh),
4867+
&hr_qp->tc_mode, &hr_qp->priority);
4868+
if (ret && ret != -EOPNOTSUPP &&
4869+
grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
4870+
ibdev_err_ratelimited(ibdev,
4871+
"failed to get dscp, ret = %d.\n", ret);
4872+
return ret;
4873+
}
4874+
4875+
if (hr_qp->tc_mode == HNAE3_TC_MAP_MODE_DSCP &&
4876+
grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
4877+
hr_qp->sl = hr_qp->priority;
4878+
else
4879+
hr_qp->sl = rdma_ah_get_sl(&attr->ah_attr);
4880+
4881+
if (!check_sl_valid(hr_dev, hr_qp->sl))
4882+
return -EINVAL;
4883+
4884+
hr_reg_write(context, QPC_SL, hr_qp->sl);
4885+
hr_reg_clear(qpc_mask, QPC_SL);
4886+
4887+
return 0;
4888+
}
4889+
48314890
static int hns_roce_v2_set_path(struct ib_qp *ibqp,
48324891
const struct ib_qp_attr *attr,
48334892
int attr_mask,
@@ -4843,25 +4902,18 @@ static int hns_roce_v2_set_path(struct ib_qp *ibqp,
48434902
int is_roce_protocol;
48444903
u16 vlan_id = 0xffff;
48454904
bool is_udp = false;
4846-
u32 max_sl;
48474905
u8 ib_port;
48484906
u8 hr_port;
48494907
int ret;
48504908

4851-
max_sl = min_t(u32, MAX_SERVICE_LEVEL, hr_dev->caps.sl_num - 1);
4852-
if (unlikely(sl > max_sl)) {
4853-
ibdev_err_ratelimited(ibdev,
4854-
"failed to fill QPC, sl (%u) shouldn't be larger than %u.\n",
4855-
sl, max_sl);
4856-
return -EINVAL;
4857-
}
4858-
48594909
/*
48604910
* If free_mr_en of qp is set, it means that this qp comes from
48614911
* free mr. This qp will perform the loopback operation.
48624912
* In the loopback scenario, only sl needs to be set.
48634913
*/
48644914
if (hr_qp->free_mr_en) {
4915+
if (!check_sl_valid(hr_dev, sl))
4916+
return -EINVAL;
48654917
hr_reg_write(context, QPC_SL, sl);
48664918
hr_reg_clear(qpc_mask, QPC_SL);
48674919
hr_qp->sl = sl;
@@ -4931,11 +4983,7 @@ static int hns_roce_v2_set_path(struct ib_qp *ibqp,
49314983
memcpy(context->dgid, grh->dgid.raw, sizeof(grh->dgid.raw));
49324984
memset(qpc_mask->dgid, 0, sizeof(grh->dgid.raw));
49334985

4934-
hr_qp->sl = sl;
4935-
hr_reg_write(context, QPC_SL, hr_qp->sl);
4936-
hr_reg_clear(qpc_mask, QPC_SL);
4937-
4938-
return 0;
4986+
return hns_roce_set_sl(ibqp, attr, context, qpc_mask);
49394987
}
49404988

49414989
static bool check_qp_state(enum ib_qp_state cur_state,
@@ -6735,6 +6783,7 @@ static const struct hns_roce_hw hns_roce_hw_v2 = {
67356783
.query_srqc = hns_roce_v2_query_srqc,
67366784
.query_sccc = hns_roce_v2_query_sccc,
67376785
.query_hw_counter = hns_roce_hw_v2_query_counter,
6786+
.get_dscp = hns_roce_hw_v2_get_dscp,
67386787
.hns_roce_dev_ops = &hns_roce_v2_dev_ops,
67396788
.hns_roce_dev_srq_ops = &hns_roce_v2_dev_srq_ops,
67406789
};

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,7 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
13861386
int attr_mask, struct ib_udata *udata)
13871387
{
13881388
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
1389+
struct hns_roce_ib_modify_qp_resp resp = {};
13891390
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
13901391
enum ib_qp_state cur_state, new_state;
13911392
int ret = -EINVAL;
@@ -1427,6 +1428,18 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
14271428

14281429
ret = hr_dev->hw->modify_qp(ibqp, attr, attr_mask, cur_state,
14291430
new_state, udata);
1431+
if (ret)
1432+
goto out;
1433+
1434+
if (udata && udata->outlen) {
1435+
resp.tc_mode = hr_qp->tc_mode;
1436+
resp.priority = hr_qp->sl;
1437+
ret = ib_copy_to_udata(udata, &resp,
1438+
min(udata->outlen, sizeof(resp)));
1439+
if (ret)
1440+
ibdev_err_ratelimited(&hr_dev->ib_dev,
1441+
"failed to copy modify qp resp.\n");
1442+
}
14301443

14311444
out:
14321445
mutex_unlock(&hr_qp->mutex);

include/uapi/rdma/hns-abi.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ struct hns_roce_ib_create_qp_resp {
109109
__aligned_u64 dwqe_mmap_key;
110110
};
111111

112+
struct hns_roce_ib_modify_qp_resp {
113+
__u8 tc_mode;
114+
__u8 priority;
115+
__u8 reserved[6];
116+
};
117+
112118
enum {
113119
HNS_ROCE_EXSGE_FLAGS = 1 << 0,
114120
HNS_ROCE_RQ_INLINE_FLAGS = 1 << 1,
@@ -143,7 +149,8 @@ struct hns_roce_ib_alloc_pd_resp {
143149

144150
struct hns_roce_ib_create_ah_resp {
145151
__u8 dmac[6];
146-
__u8 reserved[2];
152+
__u8 priority;
153+
__u8 tc_mode;
147154
};
148155

149156
#endif /* HNS_ABI_USER_H */

0 commit comments

Comments
 (0)