-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Broken up commit to add the Soft iWarp RDMA driver. Signed-off-by: Bernard Metzler <bmt@zurich.ibm.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
- Loading branch information
Bernard Metzler
authored and
Jason Gunthorpe
committed
Jul 2, 2019
1 parent
8b6a361
commit b0fff73
Showing
1 changed file
with
101 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause | ||
|
||
/* Authors: Bernard Metzler <bmt@zurich.ibm.com> */ | ||
/* Copyright (c) 2008-2019, IBM Corporation */ | ||
|
||
#include <linux/errno.h> | ||
#include <linux/types.h> | ||
|
||
#include <rdma/ib_verbs.h> | ||
|
||
#include "siw.h" | ||
|
||
static int map_wc_opcode[SIW_NUM_OPCODES] = { | ||
[SIW_OP_WRITE] = IB_WC_RDMA_WRITE, | ||
[SIW_OP_SEND] = IB_WC_SEND, | ||
[SIW_OP_SEND_WITH_IMM] = IB_WC_SEND, | ||
[SIW_OP_READ] = IB_WC_RDMA_READ, | ||
[SIW_OP_READ_LOCAL_INV] = IB_WC_RDMA_READ, | ||
[SIW_OP_COMP_AND_SWAP] = IB_WC_COMP_SWAP, | ||
[SIW_OP_FETCH_AND_ADD] = IB_WC_FETCH_ADD, | ||
[SIW_OP_INVAL_STAG] = IB_WC_LOCAL_INV, | ||
[SIW_OP_REG_MR] = IB_WC_REG_MR, | ||
[SIW_OP_RECEIVE] = IB_WC_RECV, | ||
[SIW_OP_READ_RESPONSE] = -1 /* not used */ | ||
}; | ||
|
||
static struct { | ||
enum siw_opcode siw; | ||
enum ib_wc_status ib; | ||
} map_cqe_status[SIW_NUM_WC_STATUS] = { | ||
{ SIW_WC_SUCCESS, IB_WC_SUCCESS }, | ||
{ SIW_WC_LOC_LEN_ERR, IB_WC_LOC_LEN_ERR }, | ||
{ SIW_WC_LOC_PROT_ERR, IB_WC_LOC_PROT_ERR }, | ||
{ SIW_WC_LOC_QP_OP_ERR, IB_WC_LOC_QP_OP_ERR }, | ||
{ SIW_WC_WR_FLUSH_ERR, IB_WC_WR_FLUSH_ERR }, | ||
{ SIW_WC_BAD_RESP_ERR, IB_WC_BAD_RESP_ERR }, | ||
{ SIW_WC_LOC_ACCESS_ERR, IB_WC_LOC_ACCESS_ERR }, | ||
{ SIW_WC_REM_ACCESS_ERR, IB_WC_REM_ACCESS_ERR }, | ||
{ SIW_WC_REM_INV_REQ_ERR, IB_WC_REM_INV_REQ_ERR }, | ||
{ SIW_WC_GENERAL_ERR, IB_WC_GENERAL_ERR } | ||
}; | ||
|
||
/* | ||
* Reap one CQE from the CQ. Only used by kernel clients | ||
* during CQ normal operation. Might be called during CQ | ||
* flush for user mapped CQE array as well. | ||
*/ | ||
int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc) | ||
{ | ||
struct siw_cqe *cqe; | ||
unsigned long flags; | ||
|
||
spin_lock_irqsave(&cq->lock, flags); | ||
|
||
cqe = &cq->queue[cq->cq_get % cq->num_cqe]; | ||
if (READ_ONCE(cqe->flags) & SIW_WQE_VALID) { | ||
memset(wc, 0, sizeof(*wc)); | ||
wc->wr_id = cqe->id; | ||
wc->status = map_cqe_status[cqe->status].ib; | ||
wc->opcode = map_wc_opcode[cqe->opcode]; | ||
wc->byte_len = cqe->bytes; | ||
|
||
/* | ||
* During CQ flush, also user land CQE's may get | ||
* reaped here, which do not hold a QP reference | ||
* and do not qualify for memory extension verbs. | ||
*/ | ||
if (likely(cq->kernel_verbs)) { | ||
if (cqe->flags & SIW_WQE_REM_INVAL) { | ||
wc->ex.invalidate_rkey = cqe->inval_stag; | ||
wc->wc_flags = IB_WC_WITH_INVALIDATE; | ||
} | ||
wc->qp = cqe->base_qp; | ||
siw_dbg_cq(cq, "idx %u, type %d, flags %2x, id 0x%p\n", | ||
cq->cq_get % cq->num_cqe, cqe->opcode, | ||
cqe->flags, (void *)cqe->id); | ||
} | ||
WRITE_ONCE(cqe->flags, 0); | ||
cq->cq_get++; | ||
|
||
spin_unlock_irqrestore(&cq->lock, flags); | ||
|
||
return 1; | ||
} | ||
spin_unlock_irqrestore(&cq->lock, flags); | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* siw_cq_flush() | ||
* | ||
* Flush all CQ elements. | ||
*/ | ||
void siw_cq_flush(struct siw_cq *cq) | ||
{ | ||
struct ib_wc wc; | ||
|
||
while (siw_reap_cqe(cq, &wc)) | ||
; | ||
} |