RDMA/erdma: Refactor the code of the modify_qp interface

The procedure for modifying QP is similar for both the iWARP and
RoCEv2 protocols. Therefore, we unify the code and provide the
erdma_modify_qp() interface for both protocols.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Link: https://patch.msgid.link/20241211020930.68833-7-boshiyu@linux.alibaba.com
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
Boshi Yu
2024-12-11 10:09:06 +08:00
committed by Leon Romanovsky
parent 9566cf6a77
commit de5b8008aa
6 changed files with 277 additions and 221 deletions

View File

@@ -567,7 +567,8 @@ static int erdma_proc_mpareq(struct erdma_cep *cep)
static int erdma_proc_mpareply(struct erdma_cep *cep)
{
struct erdma_qp_attrs qp_attrs;
enum erdma_qpa_mask_iwarp to_modify_attrs = 0;
struct erdma_mod_qp_params_iwarp params;
struct erdma_qp *qp = cep->qp;
struct mpa_rr *rep;
int ret;
@@ -597,26 +598,29 @@ static int erdma_proc_mpareply(struct erdma_cep *cep)
return -EINVAL;
}
memset(&qp_attrs, 0, sizeof(qp_attrs));
qp_attrs.irq_size = cep->ird;
qp_attrs.orq_size = cep->ord;
qp_attrs.state = ERDMA_QP_STATE_RTS;
memset(&params, 0, sizeof(params));
params.state = ERDMA_QPS_IWARP_RTS;
params.irq_size = cep->ird;
params.orq_size = cep->ord;
down_write(&qp->state_lock);
if (qp->attrs.state > ERDMA_QP_STATE_RTR) {
if (qp->attrs.iwarp.state > ERDMA_QPS_IWARP_RTR) {
ret = -EINVAL;
up_write(&qp->state_lock);
goto out_err;
}
qp->attrs.qp_type = ERDMA_QP_ACTIVE;
if (__mpa_ext_cc(cep->mpa.ext_data.bits) != qp->attrs.cc)
qp->attrs.cc = COMPROMISE_CC;
to_modify_attrs = ERDMA_QPA_IWARP_STATE | ERDMA_QPA_IWARP_LLP_HANDLE |
ERDMA_QPA_IWARP_MPA | ERDMA_QPA_IWARP_IRD |
ERDMA_QPA_IWARP_ORD;
ret = erdma_modify_qp_internal(qp, &qp_attrs,
ERDMA_QP_ATTR_STATE |
ERDMA_QP_ATTR_LLP_HANDLE |
ERDMA_QP_ATTR_MPA);
params.qp_type = ERDMA_QP_ACTIVE;
if (__mpa_ext_cc(cep->mpa.ext_data.bits) != qp->attrs.cc) {
to_modify_attrs |= ERDMA_QPA_IWARP_CC;
params.cc = COMPROMISE_CC;
}
ret = erdma_modify_qp_state_iwarp(qp, &params, to_modify_attrs);
up_write(&qp->state_lock);
@@ -722,7 +726,7 @@ static int erdma_newconn_connected(struct erdma_cep *cep)
__mpa_rr_set_revision(&cep->mpa.hdr.params.bits, MPA_REVISION_EXT_1);
memcpy(cep->mpa.hdr.key, MPA_KEY_REQ, MPA_KEY_SIZE);
cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.cookie);
cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.iwarp.cookie);
__mpa_ext_set_cc(&cep->mpa.ext_data.bits, cep->qp->attrs.cc);
ret = erdma_send_mpareqrep(cep, cep->private_data, cep->pd_len);
@@ -1126,10 +1130,11 @@ int erdma_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
{
struct erdma_dev *dev = to_edev(id->device);
struct erdma_cep *cep = (struct erdma_cep *)id->provider_data;
struct erdma_mod_qp_params_iwarp mod_qp_params;
enum erdma_qpa_mask_iwarp to_modify_attrs = 0;
struct erdma_dev *dev = to_edev(id->device);
struct erdma_qp *qp;
struct erdma_qp_attrs qp_attrs;
int ret;
erdma_cep_set_inuse(cep);
@@ -1156,7 +1161,7 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
erdma_qp_get(qp);
down_write(&qp->state_lock);
if (qp->attrs.state > ERDMA_QP_STATE_RTR) {
if (qp->attrs.iwarp.state > ERDMA_QPS_IWARP_RTR) {
ret = -EINVAL;
up_write(&qp->state_lock);
goto error;
@@ -1181,11 +1186,11 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
cep->cm_id = id;
id->add_ref(id);
memset(&qp_attrs, 0, sizeof(qp_attrs));
qp_attrs.orq_size = params->ord;
qp_attrs.irq_size = params->ird;
memset(&mod_qp_params, 0, sizeof(mod_qp_params));
qp_attrs.state = ERDMA_QP_STATE_RTS;
mod_qp_params.irq_size = params->ird;
mod_qp_params.orq_size = params->ord;
mod_qp_params.state = ERDMA_QPS_IWARP_RTS;
/* Associate QP with CEP */
erdma_cep_get(cep);
@@ -1194,19 +1199,21 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
cep->state = ERDMA_EPSTATE_RDMA_MODE;
qp->attrs.qp_type = ERDMA_QP_PASSIVE;
qp->attrs.pd_len = params->private_data_len;
mod_qp_params.qp_type = ERDMA_QP_PASSIVE;
mod_qp_params.pd_len = params->private_data_len;
if (qp->attrs.cc != __mpa_ext_cc(cep->mpa.ext_data.bits))
qp->attrs.cc = COMPROMISE_CC;
to_modify_attrs = ERDMA_QPA_IWARP_STATE | ERDMA_QPA_IWARP_ORD |
ERDMA_QPA_IWARP_LLP_HANDLE | ERDMA_QPA_IWARP_IRD |
ERDMA_QPA_IWARP_MPA;
if (qp->attrs.cc != __mpa_ext_cc(cep->mpa.ext_data.bits)) {
to_modify_attrs |= ERDMA_QPA_IWARP_CC;
mod_qp_params.cc = COMPROMISE_CC;
}
/* move to rts */
ret = erdma_modify_qp_internal(qp, &qp_attrs,
ERDMA_QP_ATTR_STATE |
ERDMA_QP_ATTR_ORD |
ERDMA_QP_ATTR_LLP_HANDLE |
ERDMA_QP_ATTR_IRD |
ERDMA_QP_ATTR_MPA);
ret = erdma_modify_qp_state_iwarp(qp, &mod_qp_params, to_modify_attrs);
up_write(&qp->state_lock);
if (ret)
@@ -1214,7 +1221,7 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
cep->mpa.ext_data.bits = 0;
__mpa_ext_set_cc(&cep->mpa.ext_data.bits, qp->attrs.cc);
cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.cookie);
cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.iwarp.cookie);
ret = erdma_send_mpareqrep(cep, params->private_data,
params->private_data_len);

View File

@@ -31,6 +31,7 @@
enum erdma_proto_type {
ERDMA_PROTO_IWARP = 0,
ERDMA_PROTO_ROCEV2 = 1,
ERDMA_PROTO_COUNT = 2,
};
/* PCIe Bar0 Registers. */

View File

@@ -486,7 +486,6 @@ static const struct ib_device_ops erdma_device_ops_rocev2 = {
.query_pkey = erdma_query_pkey,
.create_ah = erdma_create_ah,
.destroy_ah = erdma_destroy_ah,
.modify_qp = erdma_modify_qp_rocev2,
};
static const struct ib_device_ops erdma_device_ops_iwarp = {
@@ -498,7 +497,6 @@ static const struct ib_device_ops erdma_device_ops_iwarp = {
.iw_get_qp = erdma_get_ibqp,
.iw_reject = erdma_reject,
.iw_rem_ref = erdma_qp_put_ref,
.modify_qp = erdma_modify_qp,
};
static const struct ib_device_ops erdma_device_ops = {
@@ -533,6 +531,7 @@ static const struct ib_device_ops erdma_device_ops = {
.query_qp = erdma_query_qp,
.req_notify_cq = erdma_req_notify_cq,
.reg_user_mr = erdma_reg_user_mr,
.modify_qp = erdma_modify_qp,
INIT_RDMA_OBJ_SIZE(ib_cq, erdma_cq, ibcq),
INIT_RDMA_OBJ_SIZE(ib_pd, erdma_pd, ibpd),

View File

@@ -11,20 +11,20 @@
void erdma_qp_llp_close(struct erdma_qp *qp)
{
struct erdma_qp_attrs qp_attrs;
struct erdma_mod_qp_params_iwarp params;
down_write(&qp->state_lock);
switch (qp->attrs.state) {
case ERDMA_QP_STATE_RTS:
case ERDMA_QP_STATE_RTR:
case ERDMA_QP_STATE_IDLE:
case ERDMA_QP_STATE_TERMINATE:
qp_attrs.state = ERDMA_QP_STATE_CLOSING;
erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
switch (qp->attrs.iwarp.state) {
case ERDMA_QPS_IWARP_RTS:
case ERDMA_QPS_IWARP_RTR:
case ERDMA_QPS_IWARP_IDLE:
case ERDMA_QPS_IWARP_TERMINATE:
params.state = ERDMA_QPS_IWARP_CLOSING;
erdma_modify_qp_state_iwarp(qp, &params, ERDMA_QPA_IWARP_STATE);
break;
case ERDMA_QP_STATE_CLOSING:
qp->attrs.state = ERDMA_QP_STATE_IDLE;
case ERDMA_QPS_IWARP_CLOSING:
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_IDLE;
break;
default:
break;
@@ -48,9 +48,10 @@ struct ib_qp *erdma_get_ibqp(struct ib_device *ibdev, int id)
return NULL;
}
static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
struct erdma_qp_attrs *attrs,
enum erdma_qp_attr_mask mask)
static int
erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
struct erdma_mod_qp_params_iwarp *params,
enum erdma_qpa_mask_iwarp mask)
{
int ret;
struct erdma_dev *dev = qp->dev;
@@ -59,12 +60,15 @@ static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
struct erdma_cep *cep = qp->cep;
struct sockaddr_storage local_addr, remote_addr;
if (!(mask & ERDMA_QP_ATTR_LLP_HANDLE))
if (!(mask & ERDMA_QPA_IWARP_LLP_HANDLE))
return -EINVAL;
if (!(mask & ERDMA_QP_ATTR_MPA))
if (!(mask & ERDMA_QPA_IWARP_MPA))
return -EINVAL;
if (!(mask & ERDMA_QPA_IWARP_CC))
params->cc = qp->attrs.cc;
ret = getname_local(cep->sock, &local_addr);
if (ret < 0)
return ret;
@@ -73,18 +77,16 @@ static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
if (ret < 0)
return ret;
qp->attrs.state = ERDMA_QP_STATE_RTS;
tp = tcp_sk(qp->cep->sock->sk);
erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
CMDQ_OPCODE_MODIFY_QP);
req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, qp->attrs.state) |
FIELD_PREP(ERDMA_CMD_MODIFY_QP_CC_MASK, qp->attrs.cc) |
req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, params->state) |
FIELD_PREP(ERDMA_CMD_MODIFY_QP_CC_MASK, params->cc) |
FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
req.cookie = be32_to_cpu(qp->cep->mpa.ext_data.cookie);
req.cookie = be32_to_cpu(cep->mpa.ext_data.cookie);
req.dip = to_sockaddr_in(remote_addr).sin_addr.s_addr;
req.sip = to_sockaddr_in(local_addr).sin_addr.s_addr;
req.dport = to_sockaddr_in(remote_addr).sin_port;
@@ -92,33 +94,55 @@ static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
req.send_nxt = tp->snd_nxt;
/* rsvd tcp seq for mpa-rsp in server. */
if (qp->attrs.qp_type == ERDMA_QP_PASSIVE)
req.send_nxt += MPA_DEFAULT_HDR_LEN + qp->attrs.pd_len;
if (params->qp_type == ERDMA_QP_PASSIVE)
req.send_nxt += MPA_DEFAULT_HDR_LEN + params->pd_len;
req.recv_nxt = tp->rcv_nxt;
return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
if (ret)
return ret;
if (mask & ERDMA_QPA_IWARP_IRD)
qp->attrs.irq_size = params->irq_size;
if (mask & ERDMA_QPA_IWARP_ORD)
qp->attrs.orq_size = params->orq_size;
if (mask & ERDMA_QPA_IWARP_CC)
qp->attrs.cc = params->cc;
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_RTS;
return 0;
}
static int erdma_modify_qp_state_to_stop(struct erdma_qp *qp,
struct erdma_qp_attrs *attrs,
enum erdma_qp_attr_mask mask)
static int
erdma_modify_qp_state_to_stop(struct erdma_qp *qp,
struct erdma_mod_qp_params_iwarp *params,
enum erdma_qpa_mask_iwarp mask)
{
struct erdma_dev *dev = qp->dev;
struct erdma_cmdq_modify_qp_req req;
qp->attrs.state = attrs->state;
int ret;
erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
CMDQ_OPCODE_MODIFY_QP);
req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, attrs->state) |
req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, params->state) |
FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
if (ret)
return ret;
qp->attrs.iwarp.state = params->state;
return 0;
}
int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
enum erdma_qp_attr_mask mask)
int erdma_modify_qp_state_iwarp(struct erdma_qp *qp,
struct erdma_mod_qp_params_iwarp *params,
int mask)
{
bool need_reflush = false;
int drop_conn, ret = 0;
@@ -126,31 +150,31 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
if (!mask)
return 0;
if (!(mask & ERDMA_QP_ATTR_STATE))
if (!(mask & ERDMA_QPA_IWARP_STATE))
return 0;
switch (qp->attrs.state) {
case ERDMA_QP_STATE_IDLE:
case ERDMA_QP_STATE_RTR:
if (attrs->state == ERDMA_QP_STATE_RTS) {
ret = erdma_modify_qp_state_to_rts(qp, attrs, mask);
} else if (attrs->state == ERDMA_QP_STATE_ERROR) {
qp->attrs.state = ERDMA_QP_STATE_ERROR;
switch (qp->attrs.iwarp.state) {
case ERDMA_QPS_IWARP_IDLE:
case ERDMA_QPS_IWARP_RTR:
if (params->state == ERDMA_QPS_IWARP_RTS) {
ret = erdma_modify_qp_state_to_rts(qp, params, mask);
} else if (params->state == ERDMA_QPS_IWARP_ERROR) {
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_ERROR;
need_reflush = true;
if (qp->cep) {
erdma_cep_put(qp->cep);
qp->cep = NULL;
}
ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
ret = erdma_modify_qp_state_to_stop(qp, params, mask);
}
break;
case ERDMA_QP_STATE_RTS:
case ERDMA_QPS_IWARP_RTS:
drop_conn = 0;
if (attrs->state == ERDMA_QP_STATE_CLOSING ||
attrs->state == ERDMA_QP_STATE_TERMINATE ||
attrs->state == ERDMA_QP_STATE_ERROR) {
ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
if (params->state == ERDMA_QPS_IWARP_CLOSING ||
params->state == ERDMA_QPS_IWARP_TERMINATE ||
params->state == ERDMA_QPS_IWARP_ERROR) {
ret = erdma_modify_qp_state_to_stop(qp, params, mask);
drop_conn = 1;
need_reflush = true;
}
@@ -159,17 +183,17 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
erdma_qp_cm_drop(qp);
break;
case ERDMA_QP_STATE_TERMINATE:
if (attrs->state == ERDMA_QP_STATE_ERROR)
qp->attrs.state = ERDMA_QP_STATE_ERROR;
case ERDMA_QPS_IWARP_TERMINATE:
if (params->state == ERDMA_QPS_IWARP_ERROR)
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_ERROR;
break;
case ERDMA_QP_STATE_CLOSING:
if (attrs->state == ERDMA_QP_STATE_IDLE) {
qp->attrs.state = ERDMA_QP_STATE_IDLE;
} else if (attrs->state == ERDMA_QP_STATE_ERROR) {
ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
qp->attrs.state = ERDMA_QP_STATE_ERROR;
} else if (attrs->state != ERDMA_QP_STATE_CLOSING) {
case ERDMA_QPS_IWARP_CLOSING:
if (params->state == ERDMA_QPS_IWARP_IDLE) {
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_IDLE;
} else if (params->state == ERDMA_QPS_IWARP_ERROR) {
ret = erdma_modify_qp_state_to_stop(qp, params, mask);
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_ERROR;
} else if (params->state != ERDMA_QPS_IWARP_CLOSING) {
return -ECONNABORTED;
}
break;

View File

@@ -122,7 +122,7 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0,
&resp1);
if (!err && erdma_device_iwarp(dev))
qp->attrs.cookie =
qp->attrs.iwarp.cookie =
FIELD_GET(ERDMA_CMDQ_CREATE_QP_RESP_COOKIE_MASK, resp0);
return err;
@@ -1019,7 +1019,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
qp->attrs.max_recv_sge = attrs->cap.max_recv_sge;
if (erdma_device_iwarp(qp->dev))
qp->attrs.state = ERDMA_QP_STATE_IDLE;
qp->attrs.iwarp.state = ERDMA_QPS_IWARP_IDLE;
else
qp->attrs.rocev2.state = ERDMA_QPS_ROCEV2_RESET;
@@ -1296,18 +1296,18 @@ int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
struct erdma_dev *dev = to_edev(ibqp->device);
struct erdma_ucontext *ctx = rdma_udata_to_drv_context(
udata, struct erdma_ucontext, ibucontext);
struct erdma_mod_qp_params_rocev2 rocev2_params;
struct erdma_qp_attrs qp_attrs;
int err;
struct erdma_cmdq_destroy_qp_req req;
union erdma_mod_qp_params params;
int err;
down_write(&qp->state_lock);
if (erdma_device_iwarp(dev)) {
qp_attrs.state = ERDMA_QP_STATE_ERROR;
erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
params.iwarp.state = ERDMA_QPS_IWARP_ERROR;
erdma_modify_qp_state_iwarp(qp, &params.iwarp,
ERDMA_QPA_IWARP_STATE);
} else {
rocev2_params.state = ERDMA_QPS_ROCEV2_ERROR;
erdma_modify_qp_state_rocev2(qp, &rocev2_params,
params.rocev2.state = ERDMA_QPS_ROCEV2_ERROR;
erdma_modify_qp_state_rocev2(qp, &params.rocev2,
ERDMA_QPA_ROCEV2_STATE);
}
up_write(&qp->state_lock);
@@ -1563,38 +1563,69 @@ static void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr,
av->ntype = ERDMA_NETWORK_TYPE_IPV6;
}
static int ib_qp_state_to_erdma_qp_state[IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = ERDMA_QP_STATE_IDLE,
[IB_QPS_INIT] = ERDMA_QP_STATE_IDLE,
[IB_QPS_RTR] = ERDMA_QP_STATE_RTR,
[IB_QPS_RTS] = ERDMA_QP_STATE_RTS,
[IB_QPS_SQD] = ERDMA_QP_STATE_CLOSING,
[IB_QPS_SQE] = ERDMA_QP_STATE_TERMINATE,
[IB_QPS_ERR] = ERDMA_QP_STATE_ERROR
static int ib_qps_to_erdma_qps[ERDMA_PROTO_COUNT][IB_QPS_ERR + 1] = {
[ERDMA_PROTO_IWARP] = {
[IB_QPS_RESET] = ERDMA_QPS_IWARP_IDLE,
[IB_QPS_INIT] = ERDMA_QPS_IWARP_IDLE,
[IB_QPS_RTR] = ERDMA_QPS_IWARP_RTR,
[IB_QPS_RTS] = ERDMA_QPS_IWARP_RTS,
[IB_QPS_SQD] = ERDMA_QPS_IWARP_CLOSING,
[IB_QPS_SQE] = ERDMA_QPS_IWARP_TERMINATE,
[IB_QPS_ERR] = ERDMA_QPS_IWARP_ERROR,
},
[ERDMA_PROTO_ROCEV2] = {
[IB_QPS_RESET] = ERDMA_QPS_ROCEV2_RESET,
[IB_QPS_INIT] = ERDMA_QPS_ROCEV2_INIT,
[IB_QPS_RTR] = ERDMA_QPS_ROCEV2_RTR,
[IB_QPS_RTS] = ERDMA_QPS_ROCEV2_RTS,
[IB_QPS_SQD] = ERDMA_QPS_ROCEV2_SQD,
[IB_QPS_SQE] = ERDMA_QPS_ROCEV2_SQE,
[IB_QPS_ERR] = ERDMA_QPS_ROCEV2_ERROR,
},
};
static int ib_qps_to_erdma_qps_rocev2[IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = ERDMA_QPS_ROCEV2_RESET,
[IB_QPS_INIT] = ERDMA_QPS_ROCEV2_INIT,
[IB_QPS_RTR] = ERDMA_QPS_ROCEV2_RTR,
[IB_QPS_RTS] = ERDMA_QPS_ROCEV2_RTS,
[IB_QPS_SQD] = ERDMA_QPS_ROCEV2_SQD,
[IB_QPS_SQE] = ERDMA_QPS_ROCEV2_SQE,
[IB_QPS_ERR] = ERDMA_QPS_ROCEV2_ERROR,
static int erdma_qps_to_ib_qps[ERDMA_PROTO_COUNT][ERDMA_QPS_ROCEV2_COUNT] = {
[ERDMA_PROTO_IWARP] = {
[ERDMA_QPS_IWARP_IDLE] = IB_QPS_INIT,
[ERDMA_QPS_IWARP_RTR] = IB_QPS_RTR,
[ERDMA_QPS_IWARP_RTS] = IB_QPS_RTS,
[ERDMA_QPS_IWARP_CLOSING] = IB_QPS_ERR,
[ERDMA_QPS_IWARP_TERMINATE] = IB_QPS_ERR,
[ERDMA_QPS_IWARP_ERROR] = IB_QPS_ERR,
},
[ERDMA_PROTO_ROCEV2] = {
[ERDMA_QPS_ROCEV2_RESET] = IB_QPS_RESET,
[ERDMA_QPS_ROCEV2_INIT] = IB_QPS_INIT,
[ERDMA_QPS_ROCEV2_RTR] = IB_QPS_RTR,
[ERDMA_QPS_ROCEV2_RTS] = IB_QPS_RTS,
[ERDMA_QPS_ROCEV2_SQD] = IB_QPS_SQD,
[ERDMA_QPS_ROCEV2_SQE] = IB_QPS_SQE,
[ERDMA_QPS_ROCEV2_ERROR] = IB_QPS_ERR,
},
};
static int erdma_qps_to_ib_qps_rocev2[ERDMA_QPS_ROCEV2_COUNT] = {
[ERDMA_QPS_ROCEV2_RESET] = IB_QPS_RESET,
[ERDMA_QPS_ROCEV2_INIT] = IB_QPS_INIT,
[ERDMA_QPS_ROCEV2_RTR] = IB_QPS_RTR,
[ERDMA_QPS_ROCEV2_RTS] = IB_QPS_RTS,
[ERDMA_QPS_ROCEV2_SQD] = IB_QPS_SQD,
[ERDMA_QPS_ROCEV2_SQE] = IB_QPS_SQE,
[ERDMA_QPS_ROCEV2_ERROR] = IB_QPS_ERR,
};
static inline enum erdma_qps_iwarp ib_to_iwarp_qps(enum ib_qp_state state)
{
return ib_qps_to_erdma_qps[ERDMA_PROTO_IWARP][state];
}
static int erdma_check_qp_attr_rocev2(struct erdma_qp *qp,
struct ib_qp_attr *attr, int attr_mask)
static inline enum erdma_qps_rocev2 ib_to_rocev2_qps(enum ib_qp_state state)
{
return ib_qps_to_erdma_qps[ERDMA_PROTO_ROCEV2][state];
}
static inline enum ib_qp_state iwarp_to_ib_qps(enum erdma_qps_iwarp state)
{
return erdma_qps_to_ib_qps[ERDMA_PROTO_IWARP][state];
}
static inline enum ib_qp_state rocev2_to_ib_qps(enum erdma_qps_rocev2 state)
{
return erdma_qps_to_ib_qps[ERDMA_PROTO_ROCEV2][state];
}
static int erdma_check_qp_attrs(struct erdma_qp *qp, struct ib_qp_attr *attr,
int attr_mask)
{
enum ib_qp_state cur_state, nxt_state;
struct erdma_dev *dev = qp->dev;
@@ -1605,27 +1636,31 @@ static int erdma_check_qp_attr_rocev2(struct erdma_qp *qp,
goto out;
}
if ((attr_mask & IB_QP_PKEY_INDEX) &&
attr->pkey_index >= ERDMA_MAX_PKEYS)
goto out;
if ((attr_mask & IB_QP_PORT) &&
!rdma_is_port_valid(&dev->ibdev, attr->port_num))
goto out;
cur_state = (attr_mask & IB_QP_CUR_STATE) ?
attr->cur_qp_state :
erdma_qps_to_ib_qps_rocev2[qp->attrs.rocev2.state];
if (erdma_device_rocev2(dev)) {
cur_state = (attr_mask & IB_QP_CUR_STATE) ?
attr->cur_qp_state :
rocev2_to_ib_qps(qp->attrs.rocev2.state);
nxt_state = (attr_mask & IB_QP_STATE) ? attr->qp_state : cur_state;
nxt_state = (attr_mask & IB_QP_STATE) ? attr->qp_state :
cur_state;
if (!ib_modify_qp_is_ok(cur_state, nxt_state, qp->ibqp.qp_type,
attr_mask))
goto out;
if (!ib_modify_qp_is_ok(cur_state, nxt_state, qp->ibqp.qp_type,
attr_mask))
goto out;
if ((attr_mask & IB_QP_AV) &&
erdma_check_gid_attr(rdma_ah_read_grh(&attr->ah_attr)->sgid_attr))
goto out;
if ((attr_mask & IB_QP_AV) &&
erdma_check_gid_attr(
rdma_ah_read_grh(&attr->ah_attr)->sgid_attr))
goto out;
if ((attr_mask & IB_QP_PKEY_INDEX) &&
attr->pkey_index >= ERDMA_MAX_PKEYS)
goto out;
}
return 0;
@@ -1642,12 +1677,12 @@ static void erdma_init_mod_qp_params_rocev2(
u16 udp_sport;
if (ib_attr_mask & IB_QP_CUR_STATE)
cur_state = ib_qps_to_erdma_qps_rocev2[attr->cur_qp_state];
cur_state = ib_to_rocev2_qps(attr->cur_qp_state);
else
cur_state = qp->attrs.rocev2.state;
if (ib_attr_mask & IB_QP_STATE)
nxt_state = ib_qps_to_erdma_qps_rocev2[attr->qp_state];
nxt_state = ib_to_rocev2_qps(attr->qp_state);
else
nxt_state = cur_state;
@@ -1684,75 +1719,46 @@ static void erdma_init_mod_qp_params_rocev2(
*erdma_attr_mask = to_modify_attrs;
}
int erdma_modify_qp_rocev2(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata)
int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
struct ib_udata *udata)
{
struct erdma_mod_qp_params_rocev2 params;
struct erdma_qp *qp = to_eqp(ibqp);
union erdma_mod_qp_params params;
int ret = 0, erdma_attr_mask = 0;
down_write(&qp->state_lock);
ret = erdma_check_qp_attr_rocev2(qp, attr, attr_mask);
ret = erdma_check_qp_attrs(qp, attr, attr_mask);
if (ret)
goto out;
erdma_init_mod_qp_params_rocev2(qp, &params, &erdma_attr_mask, attr,
attr_mask);
if (erdma_device_iwarp(qp->dev)) {
if (attr_mask & IB_QP_STATE) {
erdma_attr_mask |= ERDMA_QPA_IWARP_STATE;
params.iwarp.state = ib_to_iwarp_qps(attr->qp_state);
}
ret = erdma_modify_qp_state_rocev2(qp, &params, erdma_attr_mask);
ret = erdma_modify_qp_state_iwarp(qp, &params.iwarp,
erdma_attr_mask);
} else {
erdma_init_mod_qp_params_rocev2(
qp, &params.rocev2, &erdma_attr_mask, attr, attr_mask);
ret = erdma_modify_qp_state_rocev2(qp, &params.rocev2,
erdma_attr_mask);
}
out:
up_write(&qp->state_lock);
return ret;
}
int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
struct ib_udata *udata)
{
struct erdma_qp_attrs new_attrs;
enum erdma_qp_attr_mask erdma_attr_mask = 0;
struct erdma_qp *qp = to_eqp(ibqp);
int ret = 0;
if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
return -EOPNOTSUPP;
memset(&new_attrs, 0, sizeof(new_attrs));
if (attr_mask & IB_QP_STATE) {
new_attrs.state = ib_qp_state_to_erdma_qp_state[attr->qp_state];
erdma_attr_mask |= ERDMA_QP_ATTR_STATE;
}
down_write(&qp->state_lock);
ret = erdma_modify_qp_internal(qp, &new_attrs, erdma_attr_mask);
up_write(&qp->state_lock);
return ret;
}
static enum ib_qp_state query_qp_state(struct erdma_qp *qp)
{
switch (qp->attrs.state) {
case ERDMA_QP_STATE_IDLE:
return IB_QPS_INIT;
case ERDMA_QP_STATE_RTR:
return IB_QPS_RTR;
case ERDMA_QP_STATE_RTS:
return IB_QPS_RTS;
case ERDMA_QP_STATE_CLOSING:
return IB_QPS_ERR;
case ERDMA_QP_STATE_TERMINATE:
return IB_QPS_ERR;
case ERDMA_QP_STATE_ERROR:
return IB_QPS_ERR;
default:
return IB_QPS_ERR;
}
if (erdma_device_iwarp(qp->dev))
return iwarp_to_ib_qps(qp->attrs.iwarp.state);
else
return rocev2_to_ib_qps(qp->attrs.rocev2.state);
}
int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,

View File

@@ -195,25 +195,26 @@ struct erdma_kqp {
u8 sig_all;
};
enum erdma_qp_state {
ERDMA_QP_STATE_IDLE = 0,
ERDMA_QP_STATE_RTR = 1,
ERDMA_QP_STATE_RTS = 2,
ERDMA_QP_STATE_CLOSING = 3,
ERDMA_QP_STATE_TERMINATE = 4,
ERDMA_QP_STATE_ERROR = 5,
ERDMA_QP_STATE_UNDEF = 7,
ERDMA_QP_STATE_COUNT = 8
enum erdma_qps_iwarp {
ERDMA_QPS_IWARP_IDLE = 0,
ERDMA_QPS_IWARP_RTR = 1,
ERDMA_QPS_IWARP_RTS = 2,
ERDMA_QPS_IWARP_CLOSING = 3,
ERDMA_QPS_IWARP_TERMINATE = 4,
ERDMA_QPS_IWARP_ERROR = 5,
ERDMA_QPS_IWARP_UNDEF = 6,
ERDMA_QPS_IWARP_COUNT = 7,
};
enum erdma_qp_attr_mask {
ERDMA_QP_ATTR_STATE = (1 << 0),
ERDMA_QP_ATTR_LLP_HANDLE = (1 << 2),
ERDMA_QP_ATTR_ORD = (1 << 3),
ERDMA_QP_ATTR_IRD = (1 << 4),
ERDMA_QP_ATTR_SQ_SIZE = (1 << 5),
ERDMA_QP_ATTR_RQ_SIZE = (1 << 6),
ERDMA_QP_ATTR_MPA = (1 << 7)
enum erdma_qpa_mask_iwarp {
ERDMA_QPA_IWARP_STATE = (1 << 0),
ERDMA_QPA_IWARP_LLP_HANDLE = (1 << 2),
ERDMA_QPA_IWARP_ORD = (1 << 3),
ERDMA_QPA_IWARP_IRD = (1 << 4),
ERDMA_QPA_IWARP_SQ_SIZE = (1 << 5),
ERDMA_QPA_IWARP_RQ_SIZE = (1 << 6),
ERDMA_QPA_IWARP_MPA = (1 << 7),
ERDMA_QPA_IWARP_CC = (1 << 8),
};
enum erdma_qps_rocev2 {
@@ -240,6 +241,23 @@ enum erdma_qp_flags {
ERDMA_QP_IN_FLUSHING = (1 << 0),
};
#define ERDMA_QP_ACTIVE 0
#define ERDMA_QP_PASSIVE 1
struct erdma_mod_qp_params_iwarp {
enum erdma_qps_iwarp state;
enum erdma_cc_alg cc;
u8 qp_type;
u8 pd_len;
u32 irq_size;
u32 orq_size;
};
struct erdma_qp_attrs_iwarp {
enum erdma_qps_iwarp state;
u32 cookie;
};
struct erdma_mod_qp_params_rocev2 {
enum erdma_qps_rocev2 state;
u32 qkey;
@@ -249,6 +267,11 @@ struct erdma_mod_qp_params_rocev2 {
struct erdma_av av;
};
union erdma_mod_qp_params {
struct erdma_mod_qp_params_iwarp iwarp;
struct erdma_mod_qp_params_rocev2 rocev2;
};
struct erdma_qp_attrs_rocev2 {
enum erdma_qps_rocev2 state;
u32 qkey;
@@ -257,7 +280,6 @@ struct erdma_qp_attrs_rocev2 {
};
struct erdma_qp_attrs {
enum erdma_qp_state state;
enum erdma_cc_alg cc; /* Congestion control algorithm */
u32 sq_size;
u32 rq_size;
@@ -265,12 +287,10 @@ struct erdma_qp_attrs {
u32 irq_size;
u32 max_send_sge;
u32 max_recv_sge;
u32 cookie;
#define ERDMA_QP_ACTIVE 0
#define ERDMA_QP_PASSIVE 1
u8 qp_type;
u8 pd_len;
struct erdma_qp_attrs_rocev2 rocev2;
union {
struct erdma_qp_attrs_iwarp iwarp;
struct erdma_qp_attrs_rocev2 rocev2;
};
};
struct erdma_qp {
@@ -342,8 +362,9 @@ static inline struct erdma_cq *find_cq_by_cqn(struct erdma_dev *dev, int id)
void erdma_qp_get(struct erdma_qp *qp);
void erdma_qp_put(struct erdma_qp *qp);
int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
enum erdma_qp_attr_mask mask);
int erdma_modify_qp_state_iwarp(struct erdma_qp *qp,
struct erdma_mod_qp_params_iwarp *params,
int mask);
int erdma_modify_qp_state_rocev2(struct erdma_qp *qp,
struct erdma_mod_qp_params_rocev2 *params,
int attr_mask);
@@ -426,8 +447,6 @@ int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
struct ib_qp_init_attr *init_attr);
int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
struct ib_udata *data);
int erdma_modify_qp_rocev2(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int mask, struct ib_udata *udata);
int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
int erdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
void erdma_disassociate_ucontext(struct ib_ucontext *ibcontext);