static struct ib_ah *rxe_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr) { int err; struct rxe_dev *rxe = to_rdev(ibpd->device); struct rxe_pd *pd = to_rpd(ibpd); struct rxe_ah *ah; err = rxe_av_chk_attr(rxe, attr); if (err) goto err1; ah = rxe_alloc(&rxe->ah_pool); if (!ah) { err = -ENOMEM; goto err1; } rxe_add_ref(pd); ah->pd = pd; err = rxe_init_av(rxe, attr, &ah->av); if (err) goto err2; return &ah->ibah; err2: rxe_drop_ref(pd); rxe_drop_ref(ah); err1: return ERR_PTR(err); }
static int rxe_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr) { int err; struct rxe_dev *rxe = to_rdev(ibah->device); struct rxe_ah *ah = to_rah(ibah); err = rxe_av_chk_attr(rxe, attr); if (err) return err; rxe_init_av(attr, &ah->av); return 0; }
static int rxe_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr, u32 flags, struct ib_udata *udata) { int err; struct rxe_dev *rxe = to_rdev(ibah->device); struct rxe_ah *ah = to_rah(ibah); err = rxe_av_chk_attr(rxe, attr); if (err) return err; err = rxe_add_to_pool(&rxe->ah_pool, &ah->pelem); if (err) return err; rxe_init_av(attr, &ah->av); return 0; }
/* called by the modify qp verb, this routine checks all the parameters before * making any changes */ int rxe_qp_chk_attr(struct rxe_dev *rxe, struct rxe_qp *qp, struct ib_qp_attr *attr, int mask) { enum ib_qp_state cur_state = (mask & IB_QP_CUR_STATE) ? attr->cur_qp_state : qp->attr.qp_state; enum ib_qp_state new_state = (mask & IB_QP_STATE) ? attr->qp_state : cur_state; if (!ib_modify_qp_is_ok(cur_state, new_state, qp_type(qp), mask, IB_LINK_LAYER_ETHERNET)) { pr_warn("invalid mask or state for qp\n"); goto err1; } if (mask & IB_QP_STATE) { if (cur_state == IB_QPS_SQD) { if (qp->req.state == QP_STATE_DRAIN && new_state != IB_QPS_ERR) goto err1; } } if (mask & IB_QP_PORT) { if (attr->port_num != 1) { pr_warn("invalid port %d\n", attr->port_num); goto err1; } } if (mask & IB_QP_CAP && rxe_qp_chk_cap(rxe, &attr->cap, !!qp->srq)) goto err1; if (mask & IB_QP_AV && rxe_av_chk_attr(rxe, &attr->ah_attr)) goto err1; if (mask & IB_QP_ALT_PATH) { if (rxe_av_chk_attr(rxe, &attr->alt_ah_attr)) goto err1; if (attr->alt_port_num != 1) { pr_warn("invalid alt port %d\n", attr->alt_port_num); goto err1; } if (attr->alt_timeout > 31) { pr_warn("invalid QP alt timeout %d > 31\n", attr->alt_timeout); goto err1; } } if (mask & IB_QP_PATH_MTU) { struct rxe_port *port = &rxe->port; enum ib_mtu max_mtu = port->attr.max_mtu; enum ib_mtu mtu = attr->path_mtu; if (mtu > max_mtu) { pr_debug("invalid mtu (%d) > (%d)\n", ib_mtu_enum_to_int(mtu), ib_mtu_enum_to_int(max_mtu)); goto err1; } } if (mask & IB_QP_MAX_QP_RD_ATOMIC) { if (attr->max_rd_atomic > rxe->attr.max_qp_rd_atom) { pr_warn("invalid max_rd_atomic %d > %d\n", attr->max_rd_atomic, rxe->attr.max_qp_rd_atom); goto err1; } } if (mask & IB_QP_TIMEOUT) { if (attr->timeout > 31) { pr_warn("invalid QP timeout %d > 31\n", attr->timeout); goto err1; } } return 0; err1: return -EINVAL; }