Re: [PATCH for-next v3 06/12] RDMA/erdma: Add event queue implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 2/22/22 3:53 PM, dust.li wrote:
On Thu, Feb 17, 2022 at 11:01:10AM +0800, Cheng Xu wrote:
From: Cheng Xu <chengyou@xxxxxxxxxxxxxxxxx>

Event queue (EQ) is the main notifcaition way from erdma hardware to its
driver. Each erdma device contains 2 kinds EQs: asynchronous EQ (AEQ) and
completion EQ (CEQ). Per device has 1 AEQ, which used for RDMA async event
report, and max to 32 CEQs (numbered for CEQ0 to CEQ31). CEQ0 is used for
cmdq completion event report, and the reset CEQs are used for RDMA

reset --> rest ?


Yes, will fix it.

completion event report.

Signed-off-by: Cheng Xu <chengyou@xxxxxxxxxxxxxxxxx>
---
drivers/infiniband/hw/erdma/erdma_eq.c | 366 +++++++++++++++++++++++++
1 file changed, 366 insertions(+)
create mode 100644 drivers/infiniband/hw/erdma/erdma_eq.c

diff --git a/drivers/infiniband/hw/erdma/erdma_eq.c b/drivers/infiniband/hw/erdma/erdma_eq.c
new file mode 100644
index 000000000000..2a2215710e94
--- /dev/null
+++ b/drivers/infiniband/hw/erdma/erdma_eq.c
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+
+/* Authors: Cheng Xu <chengyou@xxxxxxxxxxxxxxxxx> */
+/*          Kai Shen <kaishen@xxxxxxxxxxxxxxxxx> */
+/* Copyright (c) 2020-2022, Alibaba Group. */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <rdma/iw_cm.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+
+#include "erdma.h"
+#include "erdma_cm.h"
+#include "erdma_hw.h"
+#include "erdma_verbs.h"
+
+void notify_eq(struct erdma_eq *eq)
+{
+	u64 db_data = FIELD_PREP(ERDMA_EQDB_CI_MASK, eq->ci) |
+		      FIELD_PREP(ERDMA_EQDB_ARM_MASK, 1);
+
+	*eq->db_record = db_data;
+	writeq(db_data, eq->db_addr);
+
+	atomic64_inc(&eq->notify_num);
+}
+
+static void *get_eq_entry(struct erdma_eq *eq, u16 idx)
+{
+	idx &= (eq->depth - 1);
+
+	return eq->qbuf + (idx << EQE_SHIFT);
+}
+
+static void *get_valid_eqe(struct erdma_eq *eq)
+{
+	u64 *eqe = (u64 *)get_eq_entry(eq, eq->ci);
+	u64 val = READ_ONCE(*eqe);
+
+	if (FIELD_GET(ERDMA_CEQE_HDR_O_MASK, val) == eq->owner) {
+		dma_rmb();
+		eq->ci++;
+		if ((eq->ci & (eq->depth - 1)) == 0)
+			eq->owner = !eq->owner;
+
+		atomic64_inc(&eq->event_num);
+		return eqe;
+	}
+
+	return NULL;
+}
+
+static int erdma_poll_aeq_event(struct erdma_eq *aeq, void *out)
+{
+	struct erdma_aeqe *aeqe;
+
+	aeqe = (struct erdma_aeqe *)get_valid_eqe(aeq);
+	if (aeqe && out) {
+		memcpy(out, aeqe, EQE_SIZE);
+		return 1;
+	}
+
+	return 0;
+}
+
+int erdma_poll_ceq_event(struct erdma_eq *ceq)
+{
+	u64 *ceqe;
+	u64 val;
+
+	ceqe = (u64 *)get_valid_eqe(ceq);
+	if (ceqe) {
+		val = READ_ONCE(*ceqe);
+		return FIELD_GET(ERDMA_CEQE_HDR_CQN_MASK, val);
+	}
+
+	return -1;
+}

Probably not a real issue. Just wonder why not use the same function
format (i.e. return value, argument) for the above 2 erdma_poll_xxx_event()s ?


Will consider this.

Thanks,
Cheng Xu



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux