📄 ehca_qp.c
字号:
ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p", qp_num, bad_send_wqe_p); /* convert wqe pointer to vadr */ bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p); if (ehca_debug_level) ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num); squeue = &my_qp->ipz_squeue; if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) { ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x" " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p); return -EFAULT; } /* loop sets wqe's purge bit */ wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs); *bad_wqe_cnt = 0; while (wqe->optype != 0xff && wqe->wqef != 0xff) { if (ehca_debug_level) ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num); wqe->nr_of_data_seg = 0; /* suppress data access */ wqe->wqef = WQEF_PURGE; /* WQE to be purged */ q_ofs = ipz_queue_advance_offset(squeue, q_ofs); wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs); *bad_wqe_cnt = (*bad_wqe_cnt)+1; } /* * bad wqe will be reprocessed and ignored when pol_cq() is called, * i.e. nr of wqes with flush error status is one less */ ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x", qp_num, (*bad_wqe_cnt)-1); wqe->wqef = 0; return 0;}/* * internal_modify_qp with circumvention to handle aqp0 properly * smi_reset2init indicates if this is an internal reset-to-init-call for * smi. This flag must always be zero if called from ehca_modify_qp()! * This internal func was intorduced to avoid recursion of ehca_modify_qp()! */static int internal_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, int smi_reset2init){ enum ib_qp_state qp_cur_state, qp_new_state; int cnt, qp_attr_idx, ret = 0; enum ib_qp_statetrans statetrans; struct hcp_modify_qp_control_block *mqpcb; struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); struct ehca_shca *shca = container_of(ibqp->pd->device, struct ehca_shca, ib_device); u64 update_mask; u64 h_ret; int bad_wqe_cnt = 0; int squeue_locked = 0; unsigned long flags = 0; /* do query_qp to obtain current attr values */ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); if (!mqpcb) { ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); return -ENOMEM; } h_ret = hipz_h_query_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle, &my_qp->pf, mqpcb, my_qp->galpas.kernel); if (h_ret != H_SUCCESS) { ehca_err(ibqp->device, "hipz_h_query_qp() failed " "ehca_qp=%p qp_num=%x h_ret=%li", my_qp, ibqp->qp_num, h_ret); ret = ehca2ib_return_code(h_ret); goto modify_qp_exit1; } qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state); if (qp_cur_state == -EINVAL) { /* invalid qp state */ ret = -EINVAL; ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x " "ehca_qp=%p qp_num=%x", mqpcb->qp_state, my_qp, ibqp->qp_num); goto modify_qp_exit1; } /* * circumvention to set aqp0 initial state to init * as expected by IB spec */ if (smi_reset2init == 0 && ibqp->qp_type == IB_QPT_SMI && qp_cur_state == IB_QPS_RESET && (attr_mask & IB_QP_STATE) && attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */ struct ib_qp_attr smiqp_attr = { .qp_state = IB_QPS_INIT, .port_num = my_qp->init_attr.port_num, .pkey_index = 0, .qkey = 0 }; int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT | IB_QP_PKEY_INDEX | IB_QP_QKEY; int smirc = internal_modify_qp( ibqp, &smiqp_attr, smiqp_attr_mask, 1); if (smirc) { ehca_err(ibqp->device, "SMI RESET -> INIT failed. " "ehca_modify_qp() rc=%i", smirc); ret = H_PARAMETER; goto modify_qp_exit1; } qp_cur_state = IB_QPS_INIT; ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded"); } /* is transmitted current state equal to "real" current state */ if ((attr_mask & IB_QP_CUR_STATE) && qp_cur_state != attr->cur_qp_state) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>" " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x", attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num); goto modify_qp_exit1; } ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x current qp_state=%x " "new qp_state=%x attribute_mask=%x", my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask); qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state; if (!smi_reset2init && !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type, attr_mask)) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid qp transition new_state=%x cur_state=%x " "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state, qp_cur_state, my_qp, ibqp->qp_num, attr_mask); goto modify_qp_exit1; } mqpcb->qp_state = ib2ehca_qp_state(qp_new_state); if (mqpcb->qp_state) update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1); else { ret = -EINVAL; ehca_err(ibqp->device, "Invalid new qp state=%x " "ehca_qp=%p qp_num=%x", qp_new_state, my_qp, ibqp->qp_num); goto modify_qp_exit1; } /* retrieve state transition struct to get req and opt attrs */ statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state); if (statetrans < 0) { ret = -EINVAL; ehca_err(ibqp->device, "<INVALID STATE CHANGE> qp_cur_state=%x " "new_qp_state=%x State_xsition=%x ehca_qp=%p " "qp_num=%x", qp_cur_state, qp_new_state, statetrans, my_qp, ibqp->qp_num); goto modify_qp_exit1; } qp_attr_idx = ib2ehcaqptype(ibqp->qp_type); if (qp_attr_idx < 0) { ret = qp_attr_idx; ehca_err(ibqp->device, "Invalid QP type=%x ehca_qp=%p qp_num=%x", ibqp->qp_type, my_qp, ibqp->qp_num); goto modify_qp_exit1; } ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x", my_qp, ibqp->qp_num, statetrans); /* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set * in non-LL UD QPs. */ if ((my_qp->qp_type == IB_QPT_UD) && (my_qp->ext_type != EQPT_LLQP) && (statetrans == IB_QPST_INIT2RTR) && (shca->hw_level >= 0x22)) { update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); mqpcb->send_grh_flag = 1; } /* sqe -> rts: set purge bit of bad wqe before actual trans */ if ((my_qp->qp_type == IB_QPT_UD || my_qp->qp_type == IB_QPT_GSI || my_qp->qp_type == IB_QPT_SMI) && statetrans == IB_QPST_SQE2RTS) { /* mark next free wqe if kernel */ if (!ibqp->uobject) { struct ehca_wqe *wqe; /* lock send queue */ spin_lock_irqsave(&my_qp->spinlock_s, flags); squeue_locked = 1; /* mark next free wqe */ wqe = (struct ehca_wqe *) ipz_qeit_get(&my_qp->ipz_squeue); wqe->optype = wqe->wqef = 0xff; ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p", ibqp->qp_num, wqe); } ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt); if (ret) { ehca_err(ibqp->device, "prepare_sqe_rts() failed " "ehca_qp=%p qp_num=%x ret=%i", my_qp, ibqp->qp_num, ret); goto modify_qp_exit2; } } /* * enable RDMA_Atomic_Control if reset->init und reliable con * this is necessary since gen2 does not provide that flag, * but pHyp requires it */ if (statetrans == IB_QPST_RESET2INIT && (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) { mqpcb->rdma_atomic_ctrl = 3; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1); } /* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */ if (statetrans == IB_QPST_INIT2RTR && (ibqp->qp_type == IB_QPT_UC) && !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) { mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */ update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); } if (attr_mask & IB_QP_PKEY_INDEX) { if (attr->pkey_index >= 16) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid pkey_index=%x. " "ehca_qp=%p qp_num=%x max_pkey_index=f", attr->pkey_index, my_qp, ibqp->qp_num); goto modify_qp_exit2; } mqpcb->prim_p_key_idx = attr->pkey_index; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1); } if (attr_mask & IB_QP_PORT) { if (attr->port_num < 1 || attr->port_num > shca->num_ports) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid port=%x. " "ehca_qp=%p qp_num=%x num_ports=%x", attr->port_num, my_qp, ibqp->qp_num, shca->num_ports); goto modify_qp_exit2; } mqpcb->prim_phys_port = attr->port_num; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1); } if (attr_mask & IB_QP_QKEY) { mqpcb->qkey = attr->qkey; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1); } if (attr_mask & IB_QP_AV) { mqpcb->dlid = attr->ah_attr.dlid; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1); mqpcb->source_path_bits = attr->ah_attr.src_path_bits; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1); mqpcb->service_level = attr->ah_attr.sl; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1); if (ehca_calc_ipd(shca, mqpcb->prim_phys_port, attr->ah_attr.static_rate, &mqpcb->max_static_rate)) { ret = -EINVAL; goto modify_qp_exit2; } update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); /* * Always supply the GRH flag, even if it's zero, to give the * hypervisor a clear "yes" or "no" instead of a "perhaps" */ update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); /* * only if GRH is TRUE we might consider SOURCE_GID_IDX * and DEST_GID otherwise phype will return H_ATTR_PARM!!! */ if (attr->ah_attr.ah_flags == IB_AH_GRH) { mqpcb->send_grh_flag = 1; mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1); for (cnt = 0; cnt < 16; cnt++) mqpcb->dest_gid.byte[cnt] = attr->ah_attr.grh.dgid.raw[cnt]; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1); mqpcb->flow_label = attr->ah_attr.grh.flow_label; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1); mqpcb->hop_limit = attr->ah_attr.grh.hop_limit; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1); mqpcb->traffic_class = attr->ah_attr.grh.traffic_class; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1); } } if (attr_mask & IB_QP_PATH_MTU) { mqpcb->path_mtu = attr->path_mtu; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1); } if (attr_mask & IB_QP_TIMEOUT) { mqpcb->timeout = attr->timeout; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1); } if (attr_mask & IB_QP_RETRY_CNT) { mqpcb->retry_count = attr->retry_cnt; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1); } if (attr_mask & IB_QP_RNR_RETRY) { mqpcb->rnr_retry_count = attr->rnr_retry; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1); } if (attr_mask & IB_QP_RQ_PSN) { mqpcb->receive_psn = attr->rq_psn; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1); } if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ? attr->max_dest_rd_atomic : 2; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); } if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ? attr->max_rd_atomic : 2; update_mask |= EHCA_BMASK_SET (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1); } if (attr_mask & IB_QP_ALT_PATH) { if (attr->alt_port_num < 1 || attr->alt_port_num > shca->num_ports) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid alt_port=%x. " "ehca_qp=%p qp_num=%x num_ports=%x", attr->alt_port_num, my_qp, ibqp->qp_num, shca->num_ports); goto modify_qp_exit2; } mqpcb->alt_phys_port = attr->alt_port_num; if (attr->alt_pkey_index >= 16) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid alt_pkey_index=%x. " "ehca_qp=%p qp_num=%x max_pkey_index=f", attr->pkey_index, my_qp, ibqp->qp_num); goto modify_qp_exit2; } mqpcb->alt_p_key_idx = attr->alt_pkey_index; mqpcb->timeout_al = attr->alt_timeout; mqpcb->dlid_al = attr->alt_ah_attr.dlid; mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits; mqpcb->service_level_al = attr->alt_ah_attr.sl; if (ehca_calc_ipd(shca, mqpcb->alt_phys_port, attr->alt_ah_attr.static_rate, &mqpcb->max_static_rate_al)) { ret = -EINVAL; goto modify_qp_exit2; } /* OpenIB doesn't support alternate retry counts - copy them */ mqpcb->retry_count_al = mqpcb->retry_count; mqpcb->rnr_retry_count_al = mqpcb->rnr_retry_count; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_ALT_PHYS_PORT, 1) | EHCA_BMASK_SET(MQPCB_MASK_ALT_P_KEY_IDX, 1) | EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT_AL, 1); /* * Always supply the GRH flag, even if it's zero, to give the * hypervisor a clear "yes" or "no" instead of a "perhaps" */ update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1); /* * only if GRH is TRUE we might consider SOURCE_GID_IDX * and DEST_GID otherwise phype will return H_ATTR_PARM!!! */ if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) { mqpcb->send_grh_flag_al = 1; for (cnt = 0; cnt < 16; cnt++) mqpcb->dest_gid_al.byte[cnt] = attr->alt_ah_attr.grh.dgid.raw[cnt]; mqpcb->source_gid_idx_al = attr->alt_ah_attr.grh.sgid_index; mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label; mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit; mqpcb->traffic_class_al = attr->alt_ah_attr.grh.traffic_class; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1) | EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1); } } if (attr_mask & IB_QP_MIN_RNR_TIMER) { mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1); } if (attr_mask & IB_QP_SQ_PSN) { mqpcb->send_psn = attr->sq_psn; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1); } if (attr_mask & IB_QP_DEST_QPN) { mqpcb->dest_qp_nr = attr->dest_qp_num; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1); } if (attr_mask & IB_QP_PATH_MIG_STATE) { if (attr->path_mig_state != IB_MIG_REARM && attr->path_mig_state != IB_MIG_MIGRATED) { ret = -EINVAL; ehca_err(ibqp->device, "Invalid mig_state=%x", attr->path_mig_state); goto modify_qp_exit2; } mqpcb->path_migration_state = attr->path_mig_state + 1; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1); } if (attr_mask & IB_QP_CAP) { mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1); mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1); /* no support for max_send/recv_sge yet */ } if (ehca_debug_level) ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num); h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -