1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 /* Authors: Cheng Xu <chengyou@linux.alibaba.com> */
4 /* Kai Shen <kaishen@linux.alibaba.com> */
5 /* Copyright (c) 2020-2022, Alibaba Group. */
7 #include "erdma_verbs.h"
9 static void *get_next_valid_cqe(struct erdma_cq
*cq
)
11 __be32
*cqe
= get_queue_entry(cq
->kern_cq
.qbuf
, cq
->kern_cq
.ci
,
12 cq
->depth
, CQE_SHIFT
);
13 u32 owner
= FIELD_GET(ERDMA_CQE_HDR_OWNER_MASK
,
14 be32_to_cpu(READ_ONCE(*cqe
)));
16 return owner
^ !!(cq
->kern_cq
.ci
& cq
->depth
) ? cqe
: NULL
;
19 static void notify_cq(struct erdma_cq
*cq
, u8 solcitied
)
22 FIELD_PREP(ERDMA_CQDB_IDX_MASK
, (cq
->kern_cq
.notify_cnt
)) |
23 FIELD_PREP(ERDMA_CQDB_CQN_MASK
, cq
->cqn
) |
24 FIELD_PREP(ERDMA_CQDB_ARM_MASK
, 1) |
25 FIELD_PREP(ERDMA_CQDB_SOL_MASK
, solcitied
) |
26 FIELD_PREP(ERDMA_CQDB_CMDSN_MASK
, cq
->kern_cq
.cmdsn
) |
27 FIELD_PREP(ERDMA_CQDB_CI_MASK
, cq
->kern_cq
.ci
);
29 *cq
->kern_cq
.dbrec
= db_data
;
30 writeq(db_data
, cq
->kern_cq
.db
);
33 int erdma_req_notify_cq(struct ib_cq
*ibcq
, enum ib_cq_notify_flags flags
)
35 struct erdma_cq
*cq
= to_ecq(ibcq
);
36 unsigned long irq_flags
;
39 spin_lock_irqsave(&cq
->kern_cq
.lock
, irq_flags
);
41 notify_cq(cq
, (flags
& IB_CQ_SOLICITED_MASK
) == IB_CQ_SOLICITED
);
43 if ((flags
& IB_CQ_REPORT_MISSED_EVENTS
) && get_next_valid_cqe(cq
))
46 cq
->kern_cq
.notify_cnt
++;
48 spin_unlock_irqrestore(&cq
->kern_cq
.lock
, irq_flags
);
53 static const enum ib_wc_opcode wc_mapping_table
[ERDMA_NUM_OPCODES
] = {
54 [ERDMA_OP_WRITE
] = IB_WC_RDMA_WRITE
,
55 [ERDMA_OP_READ
] = IB_WC_RDMA_READ
,
56 [ERDMA_OP_SEND
] = IB_WC_SEND
,
57 [ERDMA_OP_SEND_WITH_IMM
] = IB_WC_SEND
,
58 [ERDMA_OP_RECEIVE
] = IB_WC_RECV
,
59 [ERDMA_OP_RECV_IMM
] = IB_WC_RECV_RDMA_WITH_IMM
,
60 [ERDMA_OP_RECV_INV
] = IB_WC_RECV
,
61 [ERDMA_OP_WRITE_WITH_IMM
] = IB_WC_RDMA_WRITE
,
62 [ERDMA_OP_RSP_SEND_IMM
] = IB_WC_RECV
,
63 [ERDMA_OP_SEND_WITH_INV
] = IB_WC_SEND
,
64 [ERDMA_OP_REG_MR
] = IB_WC_REG_MR
,
65 [ERDMA_OP_LOCAL_INV
] = IB_WC_LOCAL_INV
,
66 [ERDMA_OP_READ_WITH_INV
] = IB_WC_RDMA_READ
,
67 [ERDMA_OP_ATOMIC_CAS
] = IB_WC_COMP_SWAP
,
68 [ERDMA_OP_ATOMIC_FAA
] = IB_WC_FETCH_ADD
,
72 enum erdma_wc_status erdma
;
73 enum ib_wc_status base
;
74 enum erdma_vendor_err vendor
;
75 } map_cqe_status
[ERDMA_NUM_WC_STATUS
] = {
76 { ERDMA_WC_SUCCESS
, IB_WC_SUCCESS
, ERDMA_WC_VENDOR_NO_ERR
},
77 { ERDMA_WC_GENERAL_ERR
, IB_WC_GENERAL_ERR
, ERDMA_WC_VENDOR_NO_ERR
},
78 { ERDMA_WC_RECV_WQE_FORMAT_ERR
, IB_WC_GENERAL_ERR
,
79 ERDMA_WC_VENDOR_INVALID_RQE
},
80 { ERDMA_WC_RECV_STAG_INVALID_ERR
, IB_WC_REM_ACCESS_ERR
,
81 ERDMA_WC_VENDOR_RQE_INVALID_STAG
},
82 { ERDMA_WC_RECV_ADDR_VIOLATION_ERR
, IB_WC_REM_ACCESS_ERR
,
83 ERDMA_WC_VENDOR_RQE_ADDR_VIOLATION
},
84 { ERDMA_WC_RECV_RIGHT_VIOLATION_ERR
, IB_WC_REM_ACCESS_ERR
,
85 ERDMA_WC_VENDOR_RQE_ACCESS_RIGHT_ERR
},
86 { ERDMA_WC_RECV_PDID_ERR
, IB_WC_REM_ACCESS_ERR
,
87 ERDMA_WC_VENDOR_RQE_INVALID_PD
},
88 { ERDMA_WC_RECV_WARRPING_ERR
, IB_WC_REM_ACCESS_ERR
,
89 ERDMA_WC_VENDOR_RQE_WRAP_ERR
},
90 { ERDMA_WC_SEND_WQE_FORMAT_ERR
, IB_WC_LOC_QP_OP_ERR
,
91 ERDMA_WC_VENDOR_INVALID_SQE
},
92 { ERDMA_WC_SEND_WQE_ORD_EXCEED
, IB_WC_GENERAL_ERR
,
93 ERDMA_WC_VENDOR_ZERO_ORD
},
94 { ERDMA_WC_SEND_STAG_INVALID_ERR
, IB_WC_LOC_ACCESS_ERR
,
95 ERDMA_WC_VENDOR_SQE_INVALID_STAG
},
96 { ERDMA_WC_SEND_ADDR_VIOLATION_ERR
, IB_WC_LOC_ACCESS_ERR
,
97 ERDMA_WC_VENDOR_SQE_ADDR_VIOLATION
},
98 { ERDMA_WC_SEND_RIGHT_VIOLATION_ERR
, IB_WC_LOC_ACCESS_ERR
,
99 ERDMA_WC_VENDOR_SQE_ACCESS_ERR
},
100 { ERDMA_WC_SEND_PDID_ERR
, IB_WC_LOC_ACCESS_ERR
,
101 ERDMA_WC_VENDOR_SQE_INVALID_PD
},
102 { ERDMA_WC_SEND_WARRPING_ERR
, IB_WC_LOC_ACCESS_ERR
,
103 ERDMA_WC_VENDOR_SQE_WARP_ERR
},
104 { ERDMA_WC_FLUSH_ERR
, IB_WC_WR_FLUSH_ERR
, ERDMA_WC_VENDOR_NO_ERR
},
105 { ERDMA_WC_RETRY_EXC_ERR
, IB_WC_RETRY_EXC_ERR
, ERDMA_WC_VENDOR_NO_ERR
},
108 #define ERDMA_POLLCQ_NO_QP 1
110 static int erdma_poll_one_cqe(struct erdma_cq
*cq
, struct ib_wc
*wc
)
112 struct erdma_dev
*dev
= to_edev(cq
->ibcq
.device
);
113 u8 opcode
, syndrome
, qtype
;
114 struct erdma_kqp
*kern_qp
;
115 struct erdma_cqe
*cqe
;
122 cqe
= get_next_valid_cqe(cq
);
128 /* cqbuf should be ready when we poll */
131 qpn
= be32_to_cpu(cqe
->qpn
);
132 wqe_idx
= be32_to_cpu(cqe
->qe_idx
);
133 cqe_hdr
= be32_to_cpu(cqe
->hdr
);
135 qp
= find_qp_by_qpn(dev
, qpn
);
137 return ERDMA_POLLCQ_NO_QP
;
139 kern_qp
= &qp
->kern_qp
;
141 qtype
= FIELD_GET(ERDMA_CQE_HDR_QTYPE_MASK
, cqe_hdr
);
142 syndrome
= FIELD_GET(ERDMA_CQE_HDR_SYNDROME_MASK
, cqe_hdr
);
143 opcode
= FIELD_GET(ERDMA_CQE_HDR_OPCODE_MASK
, cqe_hdr
);
145 if (qtype
== ERDMA_CQE_QTYPE_SQ
) {
146 id_table
= kern_qp
->swr_tbl
;
147 depth
= qp
->attrs
.sq_size
;
148 wqe_hdr
= get_queue_entry(qp
->kern_qp
.sq_buf
, wqe_idx
,
149 qp
->attrs
.sq_size
, SQEBB_SHIFT
);
151 FIELD_GET(ERDMA_SQE_HDR_WQEBB_CNT_MASK
, *wqe_hdr
) +
154 id_table
= kern_qp
->rwr_tbl
;
155 depth
= qp
->attrs
.rq_size
;
157 wc
->wr_id
= id_table
[wqe_idx
& (depth
- 1)];
158 wc
->byte_len
= be32_to_cpu(cqe
->size
);
162 wc
->opcode
= wc_mapping_table
[opcode
];
163 if (opcode
== ERDMA_OP_RECV_IMM
|| opcode
== ERDMA_OP_RSP_SEND_IMM
) {
164 wc
->ex
.imm_data
= cpu_to_be32(le32_to_cpu(cqe
->imm_data
));
165 wc
->wc_flags
|= IB_WC_WITH_IMM
;
166 } else if (opcode
== ERDMA_OP_RECV_INV
) {
167 wc
->ex
.invalidate_rkey
= be32_to_cpu(cqe
->inv_rkey
);
168 wc
->wc_flags
|= IB_WC_WITH_INVALIDATE
;
171 if (syndrome
>= ERDMA_NUM_WC_STATUS
)
172 syndrome
= ERDMA_WC_GENERAL_ERR
;
174 wc
->status
= map_cqe_status
[syndrome
].base
;
175 wc
->vendor_err
= map_cqe_status
[syndrome
].vendor
;
181 int erdma_poll_cq(struct ib_cq
*ibcq
, int num_entries
, struct ib_wc
*wc
)
183 struct erdma_cq
*cq
= to_ecq(ibcq
);
187 spin_lock_irqsave(&cq
->kern_cq
.lock
, flags
);
189 for (npolled
= 0; npolled
< num_entries
;) {
190 ret
= erdma_poll_one_cqe(cq
, wc
+ npolled
);
192 if (ret
== -EAGAIN
) /* no received new CQEs. */
194 else if (ret
) /* ignore invalid CQEs. */
200 spin_unlock_irqrestore(&cq
->kern_cq
.lock
, flags
);