This patch adds support for the write with notify operation. Including support for configuring cq to enable write with notify, and qp to enable write with notify.
At the same time, a pair of APIs are added in the kernel side, rdma_register_notify_addr()/rdma_unregister_notify_addr().
Users need to use this API to register the notify address.
Signed-off-by: Chengchang Tang tangchengchang@huawei.com --- drivers/infiniband/hw/hns/hns_roce_common.h | 3 ++ drivers/infiniband/hw/hns/hns_roce_cq.c | 60 ++++++++++++++++++++++++++++- drivers/infiniband/hw/hns/hns_roce_device.h | 30 +++++++++++++++ drivers/infiniband/hw/hns/hns_roce_ext.c | 52 ++++++++++++++++++++++++- drivers/infiniband/hw/hns/hns_roce_ext.h | 23 +++++++++++ drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 55 ++++++++++++++++++++++++-- drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 25 ++++++++++++ drivers/infiniband/hw/hns/hns_roce_main.c | 2 + drivers/infiniband/hw/hns/hns_roce_qp.c | 16 ++++++++ include/uapi/rdma/hns-abi.h | 7 +++- 10 files changed, 265 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_common.h b/drivers/infiniband/hw/hns/hns_roce_common.h index 465d1f9..c2470b5 100644 --- a/drivers/infiniband/hw/hns/hns_roce_common.h +++ b/drivers/infiniband/hw/hns/hns_roce_common.h @@ -42,6 +42,9 @@ #define roce_get_field(origin, mask, shift) \ ((le32_to_cpu(origin) & (mask)) >> (u32)(shift))
+#define roce_get_field64(origin, mask, shift) \ + ((le64_to_cpu(origin) & (mask)) >> (u32)(shift)) + #define roce_get_bit(origin, shift) \ roce_get_field((origin), (1ul << (shift)), (shift))
diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c index 3bc029c..1858b07 100644 --- a/drivers/infiniband/hw/hns/hns_roce_cq.c +++ b/drivers/infiniband/hw/hns/hns_roce_cq.c @@ -332,6 +332,58 @@ static int set_poe_param(struct hns_roce_dev *hr_dev, return 0; }
+static bool is_notify_support(struct hns_roce_dev *hr_dev, + enum hns_roce_notify_mode notify_mode, + enum hns_roce_notify_device_en device_en) +{ + if (!is_write_notify_supported(hr_dev)) + return false; + + /* some configuration is not supported in HIP10 */ + if (hr_dev->pci_dev->revision != PCI_REVISION_ID_HIP10) + return true; + + if (notify_mode == HNS_ROCE_NOTIFY_MODE_64B_ALIGN || + device_en == HNS_ROCE_NOTIFY_DDR) { + ibdev_err(&hr_dev->ib_dev, "Unsupported notify_mode.\n"); + return false; + } + + return true; +} + +static int set_write_notify_param(struct hns_roce_dev *hr_dev, + struct hns_roce_cq *hr_cq, + struct hns_roce_ib_create_cq *ucmd) +{ +#define NOTIFY_MODE_MASK 0x3 + const struct { + u8 mode; + u8 mem_type; + } notify_attr[] = { + {HNS_ROCE_NOTIFY_MODE_64B_ALIGN, HNS_ROCE_NOTIFY_DEV}, + {HNS_ROCE_NOTIFY_MODE_4B_ALIGN, HNS_ROCE_NOTIFY_DEV}, + {HNS_ROCE_NOTIFY_MODE_64B_ALIGN, HNS_ROCE_NOTIFY_DDR}, + {HNS_ROCE_NOTIFY_MODE_4B_ALIGN, HNS_ROCE_NOTIFY_DDR}, + }; + u8 attr = ucmd->notify_mode & NOTIFY_MODE_MASK; + + if (!(ucmd->create_flags & HNS_ROCE_CREATE_CQ_FLAGS_WRITE_WITH_NOTIFY)) + return 0; + + if (!is_notify_support(hr_dev, notify_attr[attr].mode, + notify_attr[attr].mem_type)) + return -EOPNOTSUPP; + + hr_cq->flags |= HNS_ROCE_CQ_FLAG_NOTIFY_EN; + hr_cq->write_notify.notify_addr = + hr_dev->notify_tbl[ucmd->notify_idx].base_addr; + hr_cq->write_notify.notify_mode = notify_attr[attr].mode; + hr_cq->write_notify.notify_device_en = notify_attr[attr].mem_type; + + return 0; +} + static int set_cq_param(struct hns_roce_cq *hr_cq, u32 cq_entries, int vector, struct hns_roce_ib_create_cq *ucmd) { @@ -348,14 +400,18 @@ static int set_cq_param(struct hns_roce_cq *hr_cq, u32 cq_entries, int vector, INIT_LIST_HEAD(&hr_cq->sq_list); INIT_LIST_HEAD(&hr_cq->rq_list);
- if (!(ucmd->create_flags)) + if (!ucmd->create_flags) return 0;
+ if ((ucmd->create_flags & HNS_ROCE_CREATE_CQ_FLAGS_POE_MODE) && + (ucmd->create_flags & HNS_ROCE_CREATE_CQ_FLAGS_WRITE_WITH_NOTIFY)) + return -EINVAL; + ret = set_poe_param(hr_dev, hr_cq, ucmd); if (ret) return ret;
- return 0; + return set_write_notify_param(hr_dev, hr_cq, ucmd); }
static int set_cqe_size(struct hns_roce_cq *hr_cq, struct ib_udata *udata, diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 7b07f8c5..f808985 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -37,9 +37,11 @@ #include <rdma/ib_verbs.h> #include <rdma/hns-abi.h> #include "hns_roce_bond.h" +#include "hns_roce_ext.h"
#define PCI_REVISION_ID_HIP08 0x21 #define PCI_REVISION_ID_HIP09 0x30 +#define PCI_REVISION_ID_HIP10 0x32
#define HNS_ROCE_MAX_MSG_LEN 0x80000000
@@ -104,6 +106,8 @@ #define CQ_BANKID_SHIFT 2 #define CQ_BANKID_MASK GENMASK(1, 0)
+#define MAX_NOTIFY_MEM_SIZE BIT(24) + #define HNS_ROCE_MEM_BAR 2
enum { @@ -162,6 +166,7 @@ enum { HNS_ROCE_CAP_FLAG_SVE_DIRECT_WQE = BIT(13), HNS_ROCE_CAP_FLAG_SDI_MODE = BIT(14), HNS_ROCE_CAP_FLAG_DCA_MODE = BIT(15), + HNS_ROCE_CAP_FLAG_WRITE_NOTIFY = BIT(16), HNS_ROCE_CAP_FLAG_STASH = BIT(17), HNS_ROCE_CAP_FLAG_CQE_INLINE = BIT(19), HNS_ROCE_CAP_FLAG_BOND = BIT(21), @@ -488,6 +493,22 @@ struct hns_roce_db { unsigned long order; };
+enum hns_roce_notify_mode { + HNS_ROCE_NOTIFY_MODE_64B_ALIGN = 0, + HNS_ROCE_NOTIFY_MODE_4B_ALIGN = 1, +}; + +enum hns_roce_notify_device_en { + HNS_ROCE_NOTIFY_DEV = 0, + HNS_ROCE_NOTIFY_DDR = 1, +}; + +struct hns_roce_notify_conf { + u64 notify_addr; /* should be aligned to 4k */ + u8 notify_mode; /* use enum hns_roce_notify_mode */ + u8 notify_device_en; /* use enum hns_roce_notify_device_en */ +}; + struct hns_roce_cq { struct ib_cq ib_cq; struct hns_roce_mtr mtr; @@ -509,6 +530,7 @@ struct hns_roce_cq { int is_armed; /* cq is armed */ struct list_head node; /* all armed cqs are on a list */ u8 poe_channel; + struct hns_roce_notify_conf write_notify; };
struct hns_roce_idx_que { @@ -1153,6 +1175,9 @@ struct hns_roce_dev { struct hns_roce_port port_data[HNS_ROCE_MAX_PORTS]; atomic64_t *dfx_cnt; struct hns_roce_poe_ctx poe_ctx; /* poe ch array */ + + struct rdma_notify_mem *notify_tbl; + size_t notify_num; };
static inline struct hns_roce_dev *to_hr_dev(struct ib_device *ib_dev) @@ -1315,6 +1340,11 @@ static inline bool poe_is_supported(struct hns_roce_dev *hr_dev) return !!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_POE); }
+static inline bool is_write_notify_supported(struct hns_roce_dev *dev) +{ + return !!(dev->caps.flags & HNS_ROCE_CAP_FLAG_WRITE_NOTIFY); +} + void hns_roce_init_uar_table(struct hns_roce_dev *dev); int hns_roce_uar_alloc(struct hns_roce_dev *dev, struct hns_roce_uar *uar);
diff --git a/drivers/infiniband/hw/hns/hns_roce_ext.c b/drivers/infiniband/hw/hns/hns_roce_ext.c index 826f34e..63d0a48 100644 --- a/drivers/infiniband/hw/hns/hns_roce_ext.c +++ b/drivers/infiniband/hw/hns/hns_roce_ext.c @@ -26,7 +26,7 @@ bool rdma_support_stars(struct ib_device *ib_dev) if (!is_hns_roce(ib_dev) || is_hns_roce_vf(hr_dev)) return false;
- if (poe_is_supported(hr_dev)) + if (poe_is_supported(hr_dev) && is_write_notify_supported(hr_dev)) return true;
return false; @@ -91,3 +91,53 @@ int rdma_query_hw_id(struct ib_device *ib_dev, u32 *chip_id, } EXPORT_SYMBOL(rdma_query_hw_id);
+int rdma_register_notify_addr(struct ib_device *ib_dev, + size_t num, struct rdma_notify_mem *notify_mem) +{ + struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev); + size_t i; + + if (!is_hns_roce(ib_dev) || !is_write_notify_supported(hr_dev)) + return -EOPNOTSUPP; + + if (hr_dev->notify_tbl) + return -EBUSY; + + if (!num || !notify_mem) + return -EINVAL; + + for (i = 0; i < num; i++) { + if (!notify_mem[i].size || + notify_mem[i].size > MAX_NOTIFY_MEM_SIZE) + return -EINVAL; + if (!notify_mem[i].base_addr) + return -EINVAL; + } + + hr_dev->notify_tbl = kvmalloc_array(num, sizeof(*notify_mem), + GFP_KERNEL); + if (!hr_dev->notify_tbl) + return -ENOMEM; + + hr_dev->notify_num = num; + memcpy(hr_dev->notify_tbl, notify_mem, sizeof(*notify_mem) * num); + + return 0; +} +EXPORT_SYMBOL(rdma_register_notify_addr); + +int rdma_unregister_notify_addr(struct ib_device *ib_dev) +{ + struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev); + + if (!is_hns_roce(ib_dev) || !is_write_notify_supported(hr_dev)) + return -EOPNOTSUPP; + + if (hr_dev->notify_tbl) + kvfree(hr_dev->notify_tbl); + + hr_dev->notify_tbl = NULL; + + return 0; +} +EXPORT_SYMBOL(rdma_unregister_notify_addr); diff --git a/drivers/infiniband/hw/hns/hns_roce_ext.h b/drivers/infiniband/hw/hns/hns_roce_ext.h index d80fdfc..11a2d3c 100644 --- a/drivers/infiniband/hw/hns/hns_roce_ext.h +++ b/drivers/infiniband/hw/hns/hns_roce_ext.h @@ -40,4 +40,27 @@ u64 rdma_query_qp_db(struct ib_device *ib_dev, int qp_index); */ int rdma_query_hw_id(struct ib_device *ib_dev, u32 *chip_id, u32 *die_id, u32 *func_id); +/** + * struct rdma_notify_mem + * @base_addr - The memory region base addr for write with notify operation. + * @size - size of the notify memory region + */ +struct rdma_notify_mem { + u64 base_addr; + u32 size; +}; + +/** + * rdma_register_notify_addr - Register an memory region which will be used by + * write with notify operation. + * @num - How many elements in array + * @notify_mem - Notify memory array. + * + * If notify_mem has already been registered, re-registration + * will not be allowed. + */ +int rdma_register_notify_addr(struct ib_device *ib_dev, + size_t num, struct rdma_notify_mem *notify_mem); +int rdma_unregister_notify_addr(struct ib_device *ib_dev); + #endif diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 3d35d7c..45988eb 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -3850,6 +3850,44 @@ static void hns_roce_v2_cq_clean(struct hns_roce_cq *hr_cq, u32 qpn, spin_unlock_irq(&hr_cq->lock); }
+static void enable_write_notify(struct hns_roce_cq *hr_cq, + struct hns_roce_v2_cq_context *cq_context) +{ + hr_reg_enable(cq_context, CQC_NOTIFY_EN); + hr_reg_write(cq_context, CQC_NOTIFY_DEVICE_EN, + hr_cq->write_notify.notify_device_en); + hr_reg_write(cq_context, CQC_NOTIFY_MODE, + hr_cq->write_notify.notify_mode); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_0, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_0_M, + CQC_NOTIFY_ADDR_0_S)); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_1, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_1_M, + CQC_NOTIFY_ADDR_1_S)); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_2, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_2_M, + CQC_NOTIFY_ADDR_2_S)); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_3, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_3_M, + CQC_NOTIFY_ADDR_3_S)); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_4, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_4_M, + CQC_NOTIFY_ADDR_4_S)); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_5, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_5_M, + CQC_NOTIFY_ADDR_5_S)); + hr_reg_write(cq_context, CQC_NOTIFY_ADDR_6, + (u32)roce_get_field64(hr_cq->write_notify.notify_addr, + CQC_NOTIFY_ADDR_6_M, + CQC_NOTIFY_ADDR_6_S)); +} + static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts, dma_addr_t dma_handle) @@ -3870,12 +3908,14 @@ static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev, hr_reg_write(cq_context, CQC_POE_NUM, hr_cq->poe_channel); }
+ if (hr_cq->flags & HNS_ROCE_CQ_FLAG_NOTIFY_EN) + enable_write_notify(hr_cq, cq_context); + else if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_STASH) + hr_reg_enable(cq_context, CQC_STASH); + if (hr_cq->cqe_size == HNS_ROCE_V3_CQE_SIZE) hr_reg_write(cq_context, CQC_CQE_SIZE, CQE_SIZE_64B);
- if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_STASH) - hr_reg_enable(cq_context, CQC_STASH); - hr_reg_write(cq_context, CQC_CQE_CUR_BLK_ADDR_L, to_hr_hw_page_addr(mtts[0])); hr_reg_write(cq_context, CQC_CQE_CUR_BLK_ADDR_H, @@ -4541,6 +4581,12 @@ static void set_access_flags(struct hns_roce_qp *hr_qp, hr_reg_write_bool(context, QPC_EXT_ATE, access_flags & IB_ACCESS_REMOTE_ATOMIC); hr_reg_clear(qpc_mask, QPC_EXT_ATE); + + if ((hr_qp->en_flags & HNS_ROCE_QP_CAP_WRITE_WITH_NOTIFY) && + (access_flags & IB_ACCESS_REMOTE_WRITE)) { + hr_reg_enable(context, QPC_WN_EN); + hr_reg_clear(qpc_mask, QPC_WN_EN); + } }
static void set_qpc_wqe_cnt(struct hns_roce_qp *hr_qp, @@ -4623,7 +4669,8 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp, if (hr_dev->caps.qpc_sz < HNS_ROCE_V3_QPC_SZ) return;
- if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_STASH) + if (!(hr_qp->en_flags & HNS_ROCE_QP_CAP_WRITE_WITH_NOTIFY) && + (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_STASH)) hr_reg_enable(&context->ext, QPCEX_STASH); }
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index d3b0fa1..6fa920b 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -291,32 +291,54 @@ struct hns_roce_v2_cq_context { #define HNS_ROCE_V2_CQ_DEFAULT_BURST_NUM 0x0 #define HNS_ROCE_V2_CQ_DEFAULT_INTERVAL 0x0
+#define CQC_NOTIFY_ADDR_0_S 12 +#define CQC_NOTIFY_ADDR_0_M GENMASK(19, 12) +#define CQC_NOTIFY_ADDR_1_S 20 +#define CQC_NOTIFY_ADDR_1_M GENMASK(29, 20) +#define CQC_NOTIFY_ADDR_2_S 30 +#define CQC_NOTIFY_ADDR_2_M GENMASK(33, 30) +#define CQC_NOTIFY_ADDR_3_S 34 +#define CQC_NOTIFY_ADDR_3_M GENMASK(41, 34) +#define CQC_NOTIFY_ADDR_4_S 42 +#define CQC_NOTIFY_ADDR_4_M GENMASK(49, 42) +#define CQC_NOTIFY_ADDR_5_S 50 +#define CQC_NOTIFY_ADDR_5_M GENMASK(57, 50) +#define CQC_NOTIFY_ADDR_6_S 58 +#define CQC_NOTIFY_ADDR_6_M GENMASK(63, 58) + #define CQC_FIELD_LOC(h, l) FIELD_LOC(struct hns_roce_v2_cq_context, h, l)
#define CQC_CQ_ST CQC_FIELD_LOC(1, 0) #define CQC_POLL CQC_FIELD_LOC(2, 2) #define CQC_SE CQC_FIELD_LOC(3, 3) #define CQC_OVER_IGNORE CQC_FIELD_LOC(4, 4) +#define CQC_NOTIFY_MODE CQC_FIELD_LOC(4, 4) #define CQC_ARM_ST CQC_FIELD_LOC(7, 6) #define CQC_SHIFT CQC_FIELD_LOC(12, 8) #define CQC_CMD_SN CQC_FIELD_LOC(14, 13) #define CQC_CEQN CQC_FIELD_LOC(23, 15) +#define CQC_NOTIFY_ADDR_0 CQC_FIELD_LOC(31, 24) #define CQC_CQN CQC_FIELD_LOC(55, 32) #define CQC_POE_EN CQC_FIELD_LOC(56, 56) #define CQC_POE_NUM CQC_FIELD_LOC(58, 57) #define CQC_CQE_SIZE CQC_FIELD_LOC(60, 59) #define CQC_CQ_CNT_MODE CQC_FIELD_LOC(61, 61) +#define CQC_NOTIFY_DEVICE_EN CQC_FIELD_LOC(62, 62) #define CQC_STASH CQC_FIELD_LOC(63, 63) #define CQC_CQE_CUR_BLK_ADDR_L CQC_FIELD_LOC(95, 64) #define CQC_CQE_CUR_BLK_ADDR_H CQC_FIELD_LOC(115, 96) #define CQC_POE_QID CQC_FIELD_LOC(125, 116) +#define CQC_NOTIFY_ADDR_1 CQC_FIELD_LOC(125, 116) #define CQC_CQE_HOP_NUM CQC_FIELD_LOC(127, 126) #define CQC_CQE_NEX_BLK_ADDR_L CQC_FIELD_LOC(159, 128) #define CQC_CQE_NEX_BLK_ADDR_H CQC_FIELD_LOC(179, 160) +#define CQC_NOTIFY_ADDR_2 CQC_FIELD_LOC(183, 180) #define CQC_CQE_BAR_PG_SZ CQC_FIELD_LOC(187, 184) #define CQC_CQE_BUF_PG_SZ CQC_FIELD_LOC(191, 188) #define CQC_CQ_PRODUCER_IDX CQC_FIELD_LOC(215, 192) +#define CQC_NOTIFY_ADDR_3 CQC_FIELD_LOC(223, 216) #define CQC_CQ_CONSUMER_IDX CQC_FIELD_LOC(247, 224) +#define CQC_NOTIFY_ADDR_4 CQC_FIELD_LOC(255, 248) #define CQC_CQE_BA_L CQC_FIELD_LOC(287, 256) #define CQC_CQE_BA_H CQC_FIELD_LOC(316, 288) #define CQC_POE_QID_H_0 CQC_FIELD_LOC(319, 317) @@ -324,11 +346,14 @@ struct hns_roce_v2_cq_context { #define CQC_CQE_DB_RECORD_ADDR_L CQC_FIELD_LOC(351, 321) #define CQC_CQE_DB_RECORD_ADDR_H CQC_FIELD_LOC(383, 352) #define CQC_CQE_CNT CQC_FIELD_LOC(407, 384) +#define CQC_NOTIFY_ADDR_5 CQC_FIELD_LOC(415, 408) #define CQC_CQ_MAX_CNT CQC_FIELD_LOC(431, 416) #define CQC_CQ_PERIOD CQC_FIELD_LOC(447, 432) #define CQC_CQE_REPORT_TIMER CQC_FIELD_LOC(471, 448) #define CQC_WR_CQE_IDX CQC_FIELD_LOC(479, 472) #define CQC_SE_CQE_IDX CQC_FIELD_LOC(503, 480) +#define CQC_NOTIFY_ADDR_6 CQC_FIELD_LOC(509, 504) +#define CQC_NOTIFY_EN CQC_FIELD_LOC(510, 510) #define CQC_POE_QID_H_1 CQC_FIELD_LOC(511, 511)
struct hns_roce_srq_context { diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index af9d054..239e08a 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -1594,6 +1594,8 @@ void hns_roce_exit(struct hns_roce_dev *hr_dev, bool bond_cleanup) if (hr_dev->hw->cmq_exit) hr_dev->hw->cmq_exit(hr_dev); hns_roce_dealloc_dfx_cnt(hr_dev); + if (hr_dev->notify_tbl) + kvfree(hr_dev->notify_tbl); }
MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index fcb5e95..287523f 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -1133,6 +1133,20 @@ static void set_congest_param(struct hns_roce_dev *hr_dev, default_congest_type(hr_dev, hr_qp); }
+static void set_qp_notify_param(struct hns_roce_qp *hr_qp, + struct ib_cq *ib_cq) +{ + struct hns_roce_cq *hr_cq = ib_cq ? to_hr_cq(ib_cq) : NULL; + + /* + * Always enable write with notify for XRC TGT since no flag + * could be passed to kernel for this type of QP + */ + if ((hr_cq && hr_cq->flags & HNS_ROCE_CQ_FLAG_NOTIFY_EN) || + (hr_qp->ibqp.qp_type == IB_QPT_XRC_TGT)) + hr_qp->en_flags |= HNS_ROCE_QP_CAP_WRITE_WITH_NOTIFY; +} + static bool check_cq_poe_en(struct ib_cq *ib_cq) { struct hns_roce_cq *hr_cq = ib_cq ? to_hr_cq(ib_cq) : NULL; @@ -1199,6 +1213,8 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, if (init_attr->qp_type == IB_QPT_XRC_TGT) default_congest_type(hr_dev, hr_qp);
+ set_qp_notify_param(hr_qp, init_attr->recv_cq); + if (udata) { ret = ib_copy_from_udata(ucmd, udata, min(udata->inlen, sizeof(*ucmd))); diff --git a/include/uapi/rdma/hns-abi.h b/include/uapi/rdma/hns-abi.h index eeee57f..7223135 100644 --- a/include/uapi/rdma/hns-abi.h +++ b/include/uapi/rdma/hns-abi.h @@ -38,6 +38,7 @@
enum hns_roce_create_cq_create_flags { HNS_ROCE_CREATE_CQ_FLAGS_POE_MODE = 1 << 0, + HNS_ROCE_CREATE_CQ_FLAGS_WRITE_WITH_NOTIFY = 1 << 1, };
struct hns_roce_ib_create_cq { @@ -47,12 +48,15 @@ struct hns_roce_ib_create_cq { __u32 reserved; __aligned_u64 create_flags; /* Use enum hns_roce_create_cq_create_flags */ __u8 poe_channel; - __u8 rsv[7]; + __u8 notify_mode; + __u16 notify_idx; + __u16 rsv[2]; };
enum hns_roce_cq_cap_flags { HNS_ROCE_CQ_FLAG_RECORD_DB = 1 << 0, HNS_ROCE_CQ_FLAG_POE_EN = 1 << 2, + HNS_ROCE_CQ_FLAG_NOTIFY_EN = 1 << 3, };
struct hns_roce_ib_create_cq_resp { @@ -120,6 +124,7 @@ enum hns_roce_qp_cap_flags { HNS_ROCE_QP_CAP_DIRECT_WQE = 1 << 5, HNS_ROCE_QP_CAP_DYNAMIC_CTX_DETACH = 1 << 6, HNS_ROCE_QP_CAP_STARS_SQ_MODE = 1 << 7, + HNS_ROCE_QP_CAP_WRITE_WITH_NOTIFY = 1 << 8, };
struct hns_roce_ib_create_qp_resp {