162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2015 - 2020 Intel Corporation. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/err.h> 762306a36Sopenharmony_ci#include <linux/vmalloc.h> 862306a36Sopenharmony_ci#include <linux/hash.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/seq_file.h> 1162306a36Sopenharmony_ci#include <rdma/rdma_vt.h> 1262306a36Sopenharmony_ci#include <rdma/rdmavt_qp.h> 1362306a36Sopenharmony_ci#include <rdma/ib_verbs.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "hfi.h" 1662306a36Sopenharmony_ci#include "qp.h" 1762306a36Sopenharmony_ci#include "trace.h" 1862306a36Sopenharmony_ci#include "verbs_txreq.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciunsigned int hfi1_qp_table_size = 256; 2162306a36Sopenharmony_cimodule_param_named(qp_table_size, hfi1_qp_table_size, uint, S_IRUGO); 2262306a36Sopenharmony_ciMODULE_PARM_DESC(qp_table_size, "QP table size"); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic void flush_tx_list(struct rvt_qp *qp); 2562306a36Sopenharmony_cistatic int iowait_sleep( 2662306a36Sopenharmony_ci struct sdma_engine *sde, 2762306a36Sopenharmony_ci struct iowait_work *wait, 2862306a36Sopenharmony_ci struct sdma_txreq *stx, 2962306a36Sopenharmony_ci unsigned int seq, 3062306a36Sopenharmony_ci bool pkts_sent); 3162306a36Sopenharmony_cistatic void iowait_wakeup(struct iowait *wait, int reason); 3262306a36Sopenharmony_cistatic void iowait_sdma_drained(struct iowait *wait); 3362306a36Sopenharmony_cistatic void qp_pio_drain(struct rvt_qp *qp); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciconst struct rvt_operation_params hfi1_post_parms[RVT_OPERATION_MAX] = { 3662306a36Sopenharmony_ci[IB_WR_RDMA_WRITE] = { 3762306a36Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 3862306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 3962306a36Sopenharmony_ci}, 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci[IB_WR_RDMA_READ] = { 4262306a36Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 4362306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 4462306a36Sopenharmony_ci .flags = RVT_OPERATION_ATOMIC, 4562306a36Sopenharmony_ci}, 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci[IB_WR_ATOMIC_CMP_AND_SWP] = { 4862306a36Sopenharmony_ci .length = sizeof(struct ib_atomic_wr), 4962306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 5062306a36Sopenharmony_ci .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE, 5162306a36Sopenharmony_ci}, 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci[IB_WR_ATOMIC_FETCH_AND_ADD] = { 5462306a36Sopenharmony_ci .length = sizeof(struct ib_atomic_wr), 5562306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 5662306a36Sopenharmony_ci .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE, 5762306a36Sopenharmony_ci}, 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci[IB_WR_RDMA_WRITE_WITH_IMM] = { 6062306a36Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 6162306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 6262306a36Sopenharmony_ci}, 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci[IB_WR_SEND] = { 6562306a36Sopenharmony_ci .length = sizeof(struct ib_send_wr), 6662306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) | 6762306a36Sopenharmony_ci BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 6862306a36Sopenharmony_ci}, 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci[IB_WR_SEND_WITH_IMM] = { 7162306a36Sopenharmony_ci .length = sizeof(struct ib_send_wr), 7262306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) | 7362306a36Sopenharmony_ci BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 7462306a36Sopenharmony_ci}, 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci[IB_WR_REG_MR] = { 7762306a36Sopenharmony_ci .length = sizeof(struct ib_reg_wr), 7862306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 7962306a36Sopenharmony_ci .flags = RVT_OPERATION_LOCAL, 8062306a36Sopenharmony_ci}, 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci[IB_WR_LOCAL_INV] = { 8362306a36Sopenharmony_ci .length = sizeof(struct ib_send_wr), 8462306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 8562306a36Sopenharmony_ci .flags = RVT_OPERATION_LOCAL, 8662306a36Sopenharmony_ci}, 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci[IB_WR_SEND_WITH_INV] = { 8962306a36Sopenharmony_ci .length = sizeof(struct ib_send_wr), 9062306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 9162306a36Sopenharmony_ci}, 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci[IB_WR_OPFN] = { 9462306a36Sopenharmony_ci .length = sizeof(struct ib_atomic_wr), 9562306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 9662306a36Sopenharmony_ci .flags = RVT_OPERATION_USE_RESERVE, 9762306a36Sopenharmony_ci}, 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci[IB_WR_TID_RDMA_WRITE] = { 10062306a36Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 10162306a36Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 10262306a36Sopenharmony_ci .flags = RVT_OPERATION_IGN_RNR_CNT, 10362306a36Sopenharmony_ci}, 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void flush_list_head(struct list_head *l) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci while (!list_empty(l)) { 11062306a36Sopenharmony_ci struct sdma_txreq *tx; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci tx = list_first_entry( 11362306a36Sopenharmony_ci l, 11462306a36Sopenharmony_ci struct sdma_txreq, 11562306a36Sopenharmony_ci list); 11662306a36Sopenharmony_ci list_del_init(&tx->list); 11762306a36Sopenharmony_ci hfi1_put_txreq( 11862306a36Sopenharmony_ci container_of(tx, struct verbs_txreq, txreq)); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic void flush_tx_list(struct rvt_qp *qp) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci flush_list_head(&iowait_get_ib_work(&priv->s_iowait)->tx_head); 12762306a36Sopenharmony_ci flush_list_head(&iowait_get_tid_work(&priv->s_iowait)->tx_head); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic void flush_iowait(struct rvt_qp *qp) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 13362306a36Sopenharmony_ci unsigned long flags; 13462306a36Sopenharmony_ci seqlock_t *lock = priv->s_iowait.lock; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (!lock) 13762306a36Sopenharmony_ci return; 13862306a36Sopenharmony_ci write_seqlock_irqsave(lock, flags); 13962306a36Sopenharmony_ci if (!list_empty(&priv->s_iowait.list)) { 14062306a36Sopenharmony_ci list_del_init(&priv->s_iowait.list); 14162306a36Sopenharmony_ci priv->s_iowait.lock = NULL; 14262306a36Sopenharmony_ci rvt_put_qp(qp); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci write_sequnlock_irqrestore(lock, flags); 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/* 14862306a36Sopenharmony_ci * This function is what we would push to the core layer if we wanted to be a 14962306a36Sopenharmony_ci * "first class citizen". Instead we hide this here and rely on Verbs ULPs 15062306a36Sopenharmony_ci * to blindly pass the MTU enum value from the PathRecord to us. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_cistatic inline int verbs_mtu_enum_to_int(struct ib_device *dev, enum ib_mtu mtu) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci /* Constraining 10KB packets to 8KB packets */ 15562306a36Sopenharmony_ci if (mtu == (enum ib_mtu)OPA_MTU_10240) 15662306a36Sopenharmony_ci mtu = (enum ib_mtu)OPA_MTU_8192; 15762306a36Sopenharmony_ci return opa_mtu_enum_to_int((enum opa_mtu)mtu); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ciint hfi1_check_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr, 16162306a36Sopenharmony_ci int attr_mask, struct ib_udata *udata) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct ib_qp *ibqp = &qp->ibqp; 16462306a36Sopenharmony_ci struct hfi1_ibdev *dev = to_idev(ibqp->device); 16562306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_dev(dev); 16662306a36Sopenharmony_ci u8 sc; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (attr_mask & IB_QP_AV) { 16962306a36Sopenharmony_ci sc = ah_to_sc(ibqp->device, &attr->ah_attr); 17062306a36Sopenharmony_ci if (sc == 0xf) 17162306a36Sopenharmony_ci return -EINVAL; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (!qp_to_sdma_engine(qp, sc) && 17462306a36Sopenharmony_ci dd->flags & HFI1_HAS_SEND_DMA) 17562306a36Sopenharmony_ci return -EINVAL; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (!qp_to_send_context(qp, sc)) 17862306a36Sopenharmony_ci return -EINVAL; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci if (attr_mask & IB_QP_ALT_PATH) { 18262306a36Sopenharmony_ci sc = ah_to_sc(ibqp->device, &attr->alt_ah_attr); 18362306a36Sopenharmony_ci if (sc == 0xf) 18462306a36Sopenharmony_ci return -EINVAL; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (!qp_to_sdma_engine(qp, sc) && 18762306a36Sopenharmony_ci dd->flags & HFI1_HAS_SEND_DMA) 18862306a36Sopenharmony_ci return -EINVAL; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (!qp_to_send_context(qp, sc)) 19162306a36Sopenharmony_ci return -EINVAL; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci return 0; 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * qp_set_16b - Set the hdr_type based on whether the slid or the 19962306a36Sopenharmony_ci * dlid in the connection is extended. Only applicable for RC and UC 20062306a36Sopenharmony_ci * QPs. UD QPs determine this on the fly from the ah in the wqe 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_cistatic inline void qp_set_16b(struct rvt_qp *qp) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci struct hfi1_pportdata *ppd; 20562306a36Sopenharmony_ci struct hfi1_ibport *ibp; 20662306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Update ah_attr to account for extended LIDs */ 20962306a36Sopenharmony_ci hfi1_update_ah_attr(qp->ibqp.device, &qp->remote_ah_attr); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* Create 32 bit LIDs */ 21262306a36Sopenharmony_ci hfi1_make_opa_lid(&qp->remote_ah_attr); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (!(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) 21562306a36Sopenharmony_ci return; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 21862306a36Sopenharmony_ci ppd = ppd_from_ibp(ibp); 21962306a36Sopenharmony_ci priv->hdr_type = hfi1_get_hdr_type(ppd->lid, &qp->remote_ah_attr); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_civoid hfi1_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr, 22362306a36Sopenharmony_ci int attr_mask, struct ib_udata *udata) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci struct ib_qp *ibqp = &qp->ibqp; 22662306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (attr_mask & IB_QP_AV) { 22962306a36Sopenharmony_ci priv->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr); 23062306a36Sopenharmony_ci priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc); 23162306a36Sopenharmony_ci priv->s_sendcontext = qp_to_send_context(qp, priv->s_sc); 23262306a36Sopenharmony_ci qp_set_16b(qp); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (attr_mask & IB_QP_PATH_MIG_STATE && 23662306a36Sopenharmony_ci attr->path_mig_state == IB_MIG_MIGRATED && 23762306a36Sopenharmony_ci qp->s_mig_state == IB_MIG_ARMED) { 23862306a36Sopenharmony_ci qp->s_flags |= HFI1_S_AHG_CLEAR; 23962306a36Sopenharmony_ci priv->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr); 24062306a36Sopenharmony_ci priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc); 24162306a36Sopenharmony_ci priv->s_sendcontext = qp_to_send_context(qp, priv->s_sc); 24262306a36Sopenharmony_ci qp_set_16b(qp); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci opfn_qp_init(qp, attr, attr_mask); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/** 24962306a36Sopenharmony_ci * hfi1_setup_wqe - set up the wqe 25062306a36Sopenharmony_ci * @qp: The qp 25162306a36Sopenharmony_ci * @wqe: The built wqe 25262306a36Sopenharmony_ci * @call_send: Determine if the send should be posted or scheduled. 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * Perform setup of the wqe. This is called 25562306a36Sopenharmony_ci * prior to inserting the wqe into the ring but after 25662306a36Sopenharmony_ci * the wqe has been setup by RDMAVT. This function 25762306a36Sopenharmony_ci * allows the driver the opportunity to perform 25862306a36Sopenharmony_ci * validation and additional setup of the wqe. 25962306a36Sopenharmony_ci * 26062306a36Sopenharmony_ci * Returns 0 on success, -EINVAL on failure 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ciint hfi1_setup_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe, bool *call_send) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 26662306a36Sopenharmony_ci struct rvt_ah *ah; 26762306a36Sopenharmony_ci struct hfi1_pportdata *ppd; 26862306a36Sopenharmony_ci struct hfi1_devdata *dd; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci switch (qp->ibqp.qp_type) { 27162306a36Sopenharmony_ci case IB_QPT_RC: 27262306a36Sopenharmony_ci hfi1_setup_tid_rdma_wqe(qp, wqe); 27362306a36Sopenharmony_ci fallthrough; 27462306a36Sopenharmony_ci case IB_QPT_UC: 27562306a36Sopenharmony_ci if (wqe->length > 0x80000000U) 27662306a36Sopenharmony_ci return -EINVAL; 27762306a36Sopenharmony_ci if (wqe->length > qp->pmtu) 27862306a36Sopenharmony_ci *call_send = false; 27962306a36Sopenharmony_ci break; 28062306a36Sopenharmony_ci case IB_QPT_SMI: 28162306a36Sopenharmony_ci /* 28262306a36Sopenharmony_ci * SM packets should exclusively use VL15 and their SL is 28362306a36Sopenharmony_ci * ignored (IBTA v1.3, Section 3.5.8.2). Therefore, when ah 28462306a36Sopenharmony_ci * is created, SL is 0 in most cases and as a result some 28562306a36Sopenharmony_ci * fields (vl and pmtu) in ah may not be set correctly, 28662306a36Sopenharmony_ci * depending on the SL2SC and SC2VL tables at the time. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci ppd = ppd_from_ibp(ibp); 28962306a36Sopenharmony_ci dd = dd_from_ppd(ppd); 29062306a36Sopenharmony_ci if (wqe->length > dd->vld[15].mtu) 29162306a36Sopenharmony_ci return -EINVAL; 29262306a36Sopenharmony_ci break; 29362306a36Sopenharmony_ci case IB_QPT_GSI: 29462306a36Sopenharmony_ci case IB_QPT_UD: 29562306a36Sopenharmony_ci ah = rvt_get_swqe_ah(wqe); 29662306a36Sopenharmony_ci if (wqe->length > (1 << ah->log_pmtu)) 29762306a36Sopenharmony_ci return -EINVAL; 29862306a36Sopenharmony_ci if (ibp->sl_to_sc[rdma_ah_get_sl(&ah->attr)] == 0xf) 29962306a36Sopenharmony_ci return -EINVAL; 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci default: 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* 30662306a36Sopenharmony_ci * System latency between send and schedule is large enough that 30762306a36Sopenharmony_ci * forcing call_send to true for piothreshold packets is necessary. 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_ci if (wqe->length <= piothreshold) 31062306a36Sopenharmony_ci *call_send = true; 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci/** 31562306a36Sopenharmony_ci * _hfi1_schedule_send - schedule progress 31662306a36Sopenharmony_ci * @qp: the QP 31762306a36Sopenharmony_ci * 31862306a36Sopenharmony_ci * This schedules qp progress w/o regard to the s_flags. 31962306a36Sopenharmony_ci * 32062306a36Sopenharmony_ci * It is only used in the post send, which doesn't hold 32162306a36Sopenharmony_ci * the s_lock. 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_cibool _hfi1_schedule_send(struct rvt_qp *qp) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 32662306a36Sopenharmony_ci struct hfi1_ibport *ibp = 32762306a36Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 32862306a36Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 32962306a36Sopenharmony_ci struct hfi1_devdata *dd = ppd->dd; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci if (dd->flags & HFI1_SHUTDOWN) 33262306a36Sopenharmony_ci return true; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return iowait_schedule(&priv->s_iowait, ppd->hfi1_wq, 33562306a36Sopenharmony_ci priv->s_sde ? 33662306a36Sopenharmony_ci priv->s_sde->cpu : 33762306a36Sopenharmony_ci cpumask_first(cpumask_of_node(dd->node))); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic void qp_pio_drain(struct rvt_qp *qp) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (!priv->s_sendcontext) 34562306a36Sopenharmony_ci return; 34662306a36Sopenharmony_ci while (iowait_pio_pending(&priv->s_iowait)) { 34762306a36Sopenharmony_ci write_seqlock_irq(&priv->s_sendcontext->waitlock); 34862306a36Sopenharmony_ci hfi1_sc_wantpiobuf_intr(priv->s_sendcontext, 1); 34962306a36Sopenharmony_ci write_sequnlock_irq(&priv->s_sendcontext->waitlock); 35062306a36Sopenharmony_ci iowait_pio_drain(&priv->s_iowait); 35162306a36Sopenharmony_ci write_seqlock_irq(&priv->s_sendcontext->waitlock); 35262306a36Sopenharmony_ci hfi1_sc_wantpiobuf_intr(priv->s_sendcontext, 0); 35362306a36Sopenharmony_ci write_sequnlock_irq(&priv->s_sendcontext->waitlock); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci/** 35862306a36Sopenharmony_ci * hfi1_schedule_send - schedule progress 35962306a36Sopenharmony_ci * @qp: the QP 36062306a36Sopenharmony_ci * 36162306a36Sopenharmony_ci * This schedules qp progress and caller should hold 36262306a36Sopenharmony_ci * the s_lock. 36362306a36Sopenharmony_ci * @return true if the first leg is scheduled; 36462306a36Sopenharmony_ci * false if the first leg is not scheduled. 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_cibool hfi1_schedule_send(struct rvt_qp *qp) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 36962306a36Sopenharmony_ci if (hfi1_send_ok(qp)) { 37062306a36Sopenharmony_ci _hfi1_schedule_send(qp); 37162306a36Sopenharmony_ci return true; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci if (qp->s_flags & HFI1_S_ANY_WAIT_IO) 37462306a36Sopenharmony_ci iowait_set_flag(&((struct hfi1_qp_priv *)qp->priv)->s_iowait, 37562306a36Sopenharmony_ci IOWAIT_PENDING_IB); 37662306a36Sopenharmony_ci return false; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic void hfi1_qp_schedule(struct rvt_qp *qp) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 38262306a36Sopenharmony_ci bool ret; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci if (iowait_flag_set(&priv->s_iowait, IOWAIT_PENDING_IB)) { 38562306a36Sopenharmony_ci ret = hfi1_schedule_send(qp); 38662306a36Sopenharmony_ci if (ret) 38762306a36Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_IB); 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci if (iowait_flag_set(&priv->s_iowait, IOWAIT_PENDING_TID)) { 39062306a36Sopenharmony_ci ret = hfi1_schedule_tid_send(qp); 39162306a36Sopenharmony_ci if (ret) 39262306a36Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_TID); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_civoid hfi1_qp_wakeup(struct rvt_qp *qp, u32 flag) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci unsigned long flags; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 40162306a36Sopenharmony_ci if (qp->s_flags & flag) { 40262306a36Sopenharmony_ci qp->s_flags &= ~flag; 40362306a36Sopenharmony_ci trace_hfi1_qpwakeup(qp, flag); 40462306a36Sopenharmony_ci hfi1_qp_schedule(qp); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 40762306a36Sopenharmony_ci /* Notify hfi1_destroy_qp() if it is waiting. */ 40862306a36Sopenharmony_ci rvt_put_qp(qp); 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_civoid hfi1_qp_unbusy(struct rvt_qp *qp, struct iowait_work *wait) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci if (iowait_set_work_flag(wait) == IOWAIT_IB_SE) { 41662306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_BUSY; 41762306a36Sopenharmony_ci /* 41862306a36Sopenharmony_ci * If we are sending a first-leg packet from the second leg, 41962306a36Sopenharmony_ci * we need to clear the busy flag from priv->s_flags to 42062306a36Sopenharmony_ci * avoid a race condition when the qp wakes up before 42162306a36Sopenharmony_ci * the call to hfi1_verbs_send() returns to the second 42262306a36Sopenharmony_ci * leg. In that case, the second leg will terminate without 42362306a36Sopenharmony_ci * being re-scheduled, resulting in failure to send TID RDMA 42462306a36Sopenharmony_ci * WRITE DATA and TID RDMA ACK packets. 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci if (priv->s_flags & HFI1_S_TID_BUSY_SET) { 42762306a36Sopenharmony_ci priv->s_flags &= ~(HFI1_S_TID_BUSY_SET | 42862306a36Sopenharmony_ci RVT_S_BUSY); 42962306a36Sopenharmony_ci iowait_set_flag(&priv->s_iowait, IOWAIT_PENDING_TID); 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci } else { 43262306a36Sopenharmony_ci priv->s_flags &= ~RVT_S_BUSY; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int iowait_sleep( 43762306a36Sopenharmony_ci struct sdma_engine *sde, 43862306a36Sopenharmony_ci struct iowait_work *wait, 43962306a36Sopenharmony_ci struct sdma_txreq *stx, 44062306a36Sopenharmony_ci uint seq, 44162306a36Sopenharmony_ci bool pkts_sent) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci struct verbs_txreq *tx = container_of(stx, struct verbs_txreq, txreq); 44462306a36Sopenharmony_ci struct rvt_qp *qp; 44562306a36Sopenharmony_ci struct hfi1_qp_priv *priv; 44662306a36Sopenharmony_ci unsigned long flags; 44762306a36Sopenharmony_ci int ret = 0; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci qp = tx->qp; 45062306a36Sopenharmony_ci priv = qp->priv; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 45362306a36Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 45462306a36Sopenharmony_ci /* 45562306a36Sopenharmony_ci * If we couldn't queue the DMA request, save the info 45662306a36Sopenharmony_ci * and try again later rather than destroying the 45762306a36Sopenharmony_ci * buffer and undoing the side effects of the copy. 45862306a36Sopenharmony_ci */ 45962306a36Sopenharmony_ci /* Make a common routine? */ 46062306a36Sopenharmony_ci list_add_tail(&stx->list, &wait->tx_head); 46162306a36Sopenharmony_ci write_seqlock(&sde->waitlock); 46262306a36Sopenharmony_ci if (sdma_progress(sde, seq, stx)) 46362306a36Sopenharmony_ci goto eagain; 46462306a36Sopenharmony_ci if (list_empty(&priv->s_iowait.list)) { 46562306a36Sopenharmony_ci struct hfi1_ibport *ibp = 46662306a36Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci ibp->rvp.n_dmawait++; 46962306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_DMA_DESC; 47062306a36Sopenharmony_ci iowait_get_priority(&priv->s_iowait); 47162306a36Sopenharmony_ci iowait_queue(pkts_sent, &priv->s_iowait, 47262306a36Sopenharmony_ci &sde->dmawait); 47362306a36Sopenharmony_ci priv->s_iowait.lock = &sde->waitlock; 47462306a36Sopenharmony_ci trace_hfi1_qpsleep(qp, RVT_S_WAIT_DMA_DESC); 47562306a36Sopenharmony_ci rvt_get_qp(qp); 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci write_sequnlock(&sde->waitlock); 47862306a36Sopenharmony_ci hfi1_qp_unbusy(qp, wait); 47962306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 48062306a36Sopenharmony_ci ret = -EBUSY; 48162306a36Sopenharmony_ci } else { 48262306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 48362306a36Sopenharmony_ci hfi1_put_txreq(tx); 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci return ret; 48662306a36Sopenharmony_cieagain: 48762306a36Sopenharmony_ci write_sequnlock(&sde->waitlock); 48862306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 48962306a36Sopenharmony_ci list_del_init(&stx->list); 49062306a36Sopenharmony_ci return -EAGAIN; 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistatic void iowait_wakeup(struct iowait *wait, int reason) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci struct rvt_qp *qp = iowait_to_qp(wait); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci WARN_ON(reason != SDMA_AVAIL_REASON); 49862306a36Sopenharmony_ci hfi1_qp_wakeup(qp, RVT_S_WAIT_DMA_DESC); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic void iowait_sdma_drained(struct iowait *wait) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct rvt_qp *qp = iowait_to_qp(wait); 50462306a36Sopenharmony_ci unsigned long flags; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* 50762306a36Sopenharmony_ci * This happens when the send engine notes 50862306a36Sopenharmony_ci * a QP in the error state and cannot 50962306a36Sopenharmony_ci * do the flush work until that QP's 51062306a36Sopenharmony_ci * sdma work has finished. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 51362306a36Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_DMA) { 51462306a36Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_DMA; 51562306a36Sopenharmony_ci hfi1_schedule_send(qp); 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_cistatic void hfi1_init_priority(struct iowait *w) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci struct rvt_qp *qp = iowait_to_qp(w); 52362306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (qp->s_flags & RVT_S_ACK_PENDING) 52662306a36Sopenharmony_ci w->priority++; 52762306a36Sopenharmony_ci if (priv->s_flags & RVT_S_ACK_PENDING) 52862306a36Sopenharmony_ci w->priority++; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci/** 53262306a36Sopenharmony_ci * qp_to_sdma_engine - map a qp to a send engine 53362306a36Sopenharmony_ci * @qp: the QP 53462306a36Sopenharmony_ci * @sc5: the 5 bit sc 53562306a36Sopenharmony_ci * 53662306a36Sopenharmony_ci * Return: 53762306a36Sopenharmony_ci * A send engine for the qp or NULL for SMI type qp. 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_cistruct sdma_engine *qp_to_sdma_engine(struct rvt_qp *qp, u8 sc5) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 54262306a36Sopenharmony_ci struct sdma_engine *sde; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (!(dd->flags & HFI1_HAS_SEND_DMA)) 54562306a36Sopenharmony_ci return NULL; 54662306a36Sopenharmony_ci switch (qp->ibqp.qp_type) { 54762306a36Sopenharmony_ci case IB_QPT_SMI: 54862306a36Sopenharmony_ci return NULL; 54962306a36Sopenharmony_ci default: 55062306a36Sopenharmony_ci break; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci sde = sdma_select_engine_sc(dd, qp->ibqp.qp_num >> dd->qos_shift, sc5); 55362306a36Sopenharmony_ci return sde; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci/** 55762306a36Sopenharmony_ci * qp_to_send_context - map a qp to a send context 55862306a36Sopenharmony_ci * @qp: the QP 55962306a36Sopenharmony_ci * @sc5: the 5 bit sc 56062306a36Sopenharmony_ci * 56162306a36Sopenharmony_ci * Return: 56262306a36Sopenharmony_ci * A send context for the qp 56362306a36Sopenharmony_ci */ 56462306a36Sopenharmony_cistruct send_context *qp_to_send_context(struct rvt_qp *qp, u8 sc5) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci switch (qp->ibqp.qp_type) { 56962306a36Sopenharmony_ci case IB_QPT_SMI: 57062306a36Sopenharmony_ci /* SMA packets to VL15 */ 57162306a36Sopenharmony_ci return dd->vld[15].sc; 57262306a36Sopenharmony_ci default: 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci return pio_select_send_context_sc(dd, qp->ibqp.qp_num >> dd->qos_shift, 57762306a36Sopenharmony_ci sc5); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic const char * const qp_type_str[] = { 58162306a36Sopenharmony_ci "SMI", "GSI", "RC", "UC", "UD", 58262306a36Sopenharmony_ci}; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_cistatic int qp_idle(struct rvt_qp *qp) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci return 58762306a36Sopenharmony_ci qp->s_last == qp->s_acked && 58862306a36Sopenharmony_ci qp->s_acked == qp->s_cur && 58962306a36Sopenharmony_ci qp->s_cur == qp->s_tail && 59062306a36Sopenharmony_ci qp->s_tail == qp->s_head; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci/** 59462306a36Sopenharmony_ci * qp_iter_print - print the qp information to seq_file 59562306a36Sopenharmony_ci * @s: the seq_file to emit the qp information on 59662306a36Sopenharmony_ci * @iter: the iterator for the qp hash list 59762306a36Sopenharmony_ci */ 59862306a36Sopenharmony_civoid qp_iter_print(struct seq_file *s, struct rvt_qp_iter *iter) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci struct rvt_swqe *wqe; 60162306a36Sopenharmony_ci struct rvt_qp *qp = iter->qp; 60262306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 60362306a36Sopenharmony_ci struct sdma_engine *sde; 60462306a36Sopenharmony_ci struct send_context *send_context; 60562306a36Sopenharmony_ci struct rvt_ack_entry *e = NULL; 60662306a36Sopenharmony_ci struct rvt_srq *srq = qp->ibqp.srq ? 60762306a36Sopenharmony_ci ibsrq_to_rvtsrq(qp->ibqp.srq) : NULL; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci sde = qp_to_sdma_engine(qp, priv->s_sc); 61062306a36Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 61162306a36Sopenharmony_ci send_context = qp_to_send_context(qp, priv->s_sc); 61262306a36Sopenharmony_ci if (qp->s_ack_queue) 61362306a36Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 61462306a36Sopenharmony_ci seq_printf(s, 61562306a36Sopenharmony_ci "N %d %s QP %x R %u %s %u %u f=%x %u %u %u %u %u %u SPSN %x %x %x %x %x RPSN %x S(%u %u %u %u %u %u %u) R(%u %u %u) RQP %x LID %x SL %u MTU %u %u %u %u %u SDE %p,%u SC %p,%u SCQ %u %u PID %d OS %x %x E %x %x %x RNR %d %s %d\n", 61662306a36Sopenharmony_ci iter->n, 61762306a36Sopenharmony_ci qp_idle(qp) ? "I" : "B", 61862306a36Sopenharmony_ci qp->ibqp.qp_num, 61962306a36Sopenharmony_ci atomic_read(&qp->refcount), 62062306a36Sopenharmony_ci qp_type_str[qp->ibqp.qp_type], 62162306a36Sopenharmony_ci qp->state, 62262306a36Sopenharmony_ci wqe ? wqe->wr.opcode : 0, 62362306a36Sopenharmony_ci qp->s_flags, 62462306a36Sopenharmony_ci iowait_sdma_pending(&priv->s_iowait), 62562306a36Sopenharmony_ci iowait_pio_pending(&priv->s_iowait), 62662306a36Sopenharmony_ci !list_empty(&priv->s_iowait.list), 62762306a36Sopenharmony_ci qp->timeout, 62862306a36Sopenharmony_ci wqe ? wqe->ssn : 0, 62962306a36Sopenharmony_ci qp->s_lsn, 63062306a36Sopenharmony_ci qp->s_last_psn, 63162306a36Sopenharmony_ci qp->s_psn, qp->s_next_psn, 63262306a36Sopenharmony_ci qp->s_sending_psn, qp->s_sending_hpsn, 63362306a36Sopenharmony_ci qp->r_psn, 63462306a36Sopenharmony_ci qp->s_last, qp->s_acked, qp->s_cur, 63562306a36Sopenharmony_ci qp->s_tail, qp->s_head, qp->s_size, 63662306a36Sopenharmony_ci qp->s_avail, 63762306a36Sopenharmony_ci /* ack_queue ring pointers, size */ 63862306a36Sopenharmony_ci qp->s_tail_ack_queue, qp->r_head_ack_queue, 63962306a36Sopenharmony_ci rvt_max_atomic(&to_idev(qp->ibqp.device)->rdi), 64062306a36Sopenharmony_ci /* remote QP info */ 64162306a36Sopenharmony_ci qp->remote_qpn, 64262306a36Sopenharmony_ci rdma_ah_get_dlid(&qp->remote_ah_attr), 64362306a36Sopenharmony_ci rdma_ah_get_sl(&qp->remote_ah_attr), 64462306a36Sopenharmony_ci qp->pmtu, 64562306a36Sopenharmony_ci qp->s_retry, 64662306a36Sopenharmony_ci qp->s_retry_cnt, 64762306a36Sopenharmony_ci qp->s_rnr_retry_cnt, 64862306a36Sopenharmony_ci qp->s_rnr_retry, 64962306a36Sopenharmony_ci sde, 65062306a36Sopenharmony_ci sde ? sde->this_idx : 0, 65162306a36Sopenharmony_ci send_context, 65262306a36Sopenharmony_ci send_context ? send_context->sw_index : 0, 65362306a36Sopenharmony_ci ib_cq_head(qp->ibqp.send_cq), 65462306a36Sopenharmony_ci ib_cq_tail(qp->ibqp.send_cq), 65562306a36Sopenharmony_ci qp->pid, 65662306a36Sopenharmony_ci qp->s_state, 65762306a36Sopenharmony_ci qp->s_ack_state, 65862306a36Sopenharmony_ci /* ack queue information */ 65962306a36Sopenharmony_ci e ? e->opcode : 0, 66062306a36Sopenharmony_ci e ? e->psn : 0, 66162306a36Sopenharmony_ci e ? e->lpsn : 0, 66262306a36Sopenharmony_ci qp->r_min_rnr_timer, 66362306a36Sopenharmony_ci srq ? "SRQ" : "RQ", 66462306a36Sopenharmony_ci srq ? srq->rq.size : qp->r_rq.size 66562306a36Sopenharmony_ci ); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_civoid *qp_priv_alloc(struct rvt_dev_info *rdi, struct rvt_qp *qp) 66962306a36Sopenharmony_ci{ 67062306a36Sopenharmony_ci struct hfi1_qp_priv *priv; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci priv = kzalloc_node(sizeof(*priv), GFP_KERNEL, rdi->dparms.node); 67362306a36Sopenharmony_ci if (!priv) 67462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci priv->owner = qp; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci priv->s_ahg = kzalloc_node(sizeof(*priv->s_ahg), GFP_KERNEL, 67962306a36Sopenharmony_ci rdi->dparms.node); 68062306a36Sopenharmony_ci if (!priv->s_ahg) { 68162306a36Sopenharmony_ci kfree(priv); 68262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci iowait_init( 68562306a36Sopenharmony_ci &priv->s_iowait, 68662306a36Sopenharmony_ci 1, 68762306a36Sopenharmony_ci _hfi1_do_send, 68862306a36Sopenharmony_ci _hfi1_do_tid_send, 68962306a36Sopenharmony_ci iowait_sleep, 69062306a36Sopenharmony_ci iowait_wakeup, 69162306a36Sopenharmony_ci iowait_sdma_drained, 69262306a36Sopenharmony_ci hfi1_init_priority); 69362306a36Sopenharmony_ci /* Init to a value to start the running average correctly */ 69462306a36Sopenharmony_ci priv->s_running_pkt_size = piothreshold / 2; 69562306a36Sopenharmony_ci return priv; 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_civoid qp_priv_free(struct rvt_dev_info *rdi, struct rvt_qp *qp) 69962306a36Sopenharmony_ci{ 70062306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci hfi1_qp_priv_tid_free(rdi, qp); 70362306a36Sopenharmony_ci kfree(priv->s_ahg); 70462306a36Sopenharmony_ci kfree(priv); 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ciunsigned free_all_qps(struct rvt_dev_info *rdi) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci struct hfi1_ibdev *verbs_dev = container_of(rdi, 71062306a36Sopenharmony_ci struct hfi1_ibdev, 71162306a36Sopenharmony_ci rdi); 71262306a36Sopenharmony_ci struct hfi1_devdata *dd = container_of(verbs_dev, 71362306a36Sopenharmony_ci struct hfi1_devdata, 71462306a36Sopenharmony_ci verbs_dev); 71562306a36Sopenharmony_ci int n; 71662306a36Sopenharmony_ci unsigned qp_inuse = 0; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci for (n = 0; n < dd->num_pports; n++) { 71962306a36Sopenharmony_ci struct hfi1_ibport *ibp = &dd->pport[n].ibport_data; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci rcu_read_lock(); 72262306a36Sopenharmony_ci if (rcu_dereference(ibp->rvp.qp[0])) 72362306a36Sopenharmony_ci qp_inuse++; 72462306a36Sopenharmony_ci if (rcu_dereference(ibp->rvp.qp[1])) 72562306a36Sopenharmony_ci qp_inuse++; 72662306a36Sopenharmony_ci rcu_read_unlock(); 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci return qp_inuse; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_civoid flush_qp_waiters(struct rvt_qp *qp) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 73562306a36Sopenharmony_ci flush_iowait(qp); 73662306a36Sopenharmony_ci hfi1_tid_rdma_flush_wait(qp); 73762306a36Sopenharmony_ci} 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_civoid stop_send_queue(struct rvt_qp *qp) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci iowait_cancel_work(&priv->s_iowait); 74462306a36Sopenharmony_ci if (cancel_work_sync(&priv->tid_rdma.trigger_work)) 74562306a36Sopenharmony_ci rvt_put_qp(qp); 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_civoid quiesce_qp(struct rvt_qp *qp) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci hfi1_del_tid_reap_timer(qp); 75362306a36Sopenharmony_ci hfi1_del_tid_retry_timer(qp); 75462306a36Sopenharmony_ci iowait_sdma_drain(&priv->s_iowait); 75562306a36Sopenharmony_ci qp_pio_drain(qp); 75662306a36Sopenharmony_ci flush_tx_list(qp); 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_civoid notify_qp_reset(struct rvt_qp *qp) 76062306a36Sopenharmony_ci{ 76162306a36Sopenharmony_ci hfi1_qp_kern_exp_rcv_clear_all(qp); 76262306a36Sopenharmony_ci qp->r_adefered = 0; 76362306a36Sopenharmony_ci clear_ahg(qp); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci /* Clear any OPFN state */ 76662306a36Sopenharmony_ci if (qp->ibqp.qp_type == IB_QPT_RC) 76762306a36Sopenharmony_ci opfn_conn_error(qp); 76862306a36Sopenharmony_ci} 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci/* 77162306a36Sopenharmony_ci * Switch to alternate path. 77262306a36Sopenharmony_ci * The QP s_lock should be held and interrupts disabled. 77362306a36Sopenharmony_ci */ 77462306a36Sopenharmony_civoid hfi1_migrate_qp(struct rvt_qp *qp) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 77762306a36Sopenharmony_ci struct ib_event ev; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci qp->s_mig_state = IB_MIG_MIGRATED; 78062306a36Sopenharmony_ci qp->remote_ah_attr = qp->alt_ah_attr; 78162306a36Sopenharmony_ci qp->port_num = rdma_ah_get_port_num(&qp->alt_ah_attr); 78262306a36Sopenharmony_ci qp->s_pkey_index = qp->s_alt_pkey_index; 78362306a36Sopenharmony_ci qp->s_flags |= HFI1_S_AHG_CLEAR; 78462306a36Sopenharmony_ci priv->s_sc = ah_to_sc(qp->ibqp.device, &qp->remote_ah_attr); 78562306a36Sopenharmony_ci priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc); 78662306a36Sopenharmony_ci qp_set_16b(qp); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci ev.device = qp->ibqp.device; 78962306a36Sopenharmony_ci ev.element.qp = &qp->ibqp; 79062306a36Sopenharmony_ci ev.event = IB_EVENT_PATH_MIG; 79162306a36Sopenharmony_ci qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ciint mtu_to_path_mtu(u32 mtu) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci return mtu_to_enum(mtu, OPA_MTU_8192); 79762306a36Sopenharmony_ci} 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ciu32 mtu_from_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, u32 pmtu) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci u32 mtu; 80262306a36Sopenharmony_ci struct hfi1_ibdev *verbs_dev = container_of(rdi, 80362306a36Sopenharmony_ci struct hfi1_ibdev, 80462306a36Sopenharmony_ci rdi); 80562306a36Sopenharmony_ci struct hfi1_devdata *dd = container_of(verbs_dev, 80662306a36Sopenharmony_ci struct hfi1_devdata, 80762306a36Sopenharmony_ci verbs_dev); 80862306a36Sopenharmony_ci struct hfi1_ibport *ibp; 80962306a36Sopenharmony_ci u8 sc, vl; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci ibp = &dd->pport[qp->port_num - 1].ibport_data; 81262306a36Sopenharmony_ci sc = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)]; 81362306a36Sopenharmony_ci vl = sc_to_vlt(dd, sc); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci mtu = verbs_mtu_enum_to_int(qp->ibqp.device, pmtu); 81662306a36Sopenharmony_ci if (vl < PER_VL_SEND_CONTEXTS) 81762306a36Sopenharmony_ci mtu = min_t(u32, mtu, dd->vld[vl].mtu); 81862306a36Sopenharmony_ci return mtu; 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ciint get_pmtu_from_attr(struct rvt_dev_info *rdi, struct rvt_qp *qp, 82262306a36Sopenharmony_ci struct ib_qp_attr *attr) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci int mtu, pidx = qp->port_num - 1; 82562306a36Sopenharmony_ci struct hfi1_ibdev *verbs_dev = container_of(rdi, 82662306a36Sopenharmony_ci struct hfi1_ibdev, 82762306a36Sopenharmony_ci rdi); 82862306a36Sopenharmony_ci struct hfi1_devdata *dd = container_of(verbs_dev, 82962306a36Sopenharmony_ci struct hfi1_devdata, 83062306a36Sopenharmony_ci verbs_dev); 83162306a36Sopenharmony_ci mtu = verbs_mtu_enum_to_int(qp->ibqp.device, attr->path_mtu); 83262306a36Sopenharmony_ci if (mtu == -1) 83362306a36Sopenharmony_ci return -1; /* values less than 0 are error */ 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci if (mtu > dd->pport[pidx].ibmtu) 83662306a36Sopenharmony_ci return mtu_to_enum(dd->pport[pidx].ibmtu, IB_MTU_2048); 83762306a36Sopenharmony_ci else 83862306a36Sopenharmony_ci return attr->path_mtu; 83962306a36Sopenharmony_ci} 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_civoid notify_error_qp(struct rvt_qp *qp) 84262306a36Sopenharmony_ci{ 84362306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 84462306a36Sopenharmony_ci seqlock_t *lock = priv->s_iowait.lock; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci if (lock) { 84762306a36Sopenharmony_ci write_seqlock(lock); 84862306a36Sopenharmony_ci if (!list_empty(&priv->s_iowait.list) && 84962306a36Sopenharmony_ci !(qp->s_flags & RVT_S_BUSY) && 85062306a36Sopenharmony_ci !(priv->s_flags & RVT_S_BUSY)) { 85162306a36Sopenharmony_ci qp->s_flags &= ~HFI1_S_ANY_WAIT_IO; 85262306a36Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_IB); 85362306a36Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_TID); 85462306a36Sopenharmony_ci list_del_init(&priv->s_iowait.list); 85562306a36Sopenharmony_ci priv->s_iowait.lock = NULL; 85662306a36Sopenharmony_ci rvt_put_qp(qp); 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci write_sequnlock(lock); 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci if (!(qp->s_flags & RVT_S_BUSY) && !(priv->s_flags & RVT_S_BUSY)) { 86262306a36Sopenharmony_ci qp->s_hdrwords = 0; 86362306a36Sopenharmony_ci if (qp->s_rdma_mr) { 86462306a36Sopenharmony_ci rvt_put_mr(qp->s_rdma_mr); 86562306a36Sopenharmony_ci qp->s_rdma_mr = NULL; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci flush_tx_list(qp); 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci/** 87262306a36Sopenharmony_ci * hfi1_qp_iter_cb - callback for iterator 87362306a36Sopenharmony_ci * @qp: the qp 87462306a36Sopenharmony_ci * @v: the sl in low bits of v 87562306a36Sopenharmony_ci * 87662306a36Sopenharmony_ci * This is called from the iterator callback to work 87762306a36Sopenharmony_ci * on an individual qp. 87862306a36Sopenharmony_ci */ 87962306a36Sopenharmony_cistatic void hfi1_qp_iter_cb(struct rvt_qp *qp, u64 v) 88062306a36Sopenharmony_ci{ 88162306a36Sopenharmony_ci int lastwqe; 88262306a36Sopenharmony_ci struct ib_event ev; 88362306a36Sopenharmony_ci struct hfi1_ibport *ibp = 88462306a36Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 88562306a36Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 88662306a36Sopenharmony_ci u8 sl = (u8)v; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci if (qp->port_num != ppd->port || 88962306a36Sopenharmony_ci (qp->ibqp.qp_type != IB_QPT_UC && 89062306a36Sopenharmony_ci qp->ibqp.qp_type != IB_QPT_RC) || 89162306a36Sopenharmony_ci rdma_ah_get_sl(&qp->remote_ah_attr) != sl || 89262306a36Sopenharmony_ci !(ib_rvt_state_ops[qp->state] & RVT_POST_SEND_OK)) 89362306a36Sopenharmony_ci return; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci spin_lock_irq(&qp->r_lock); 89662306a36Sopenharmony_ci spin_lock(&qp->s_hlock); 89762306a36Sopenharmony_ci spin_lock(&qp->s_lock); 89862306a36Sopenharmony_ci lastwqe = rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 89962306a36Sopenharmony_ci spin_unlock(&qp->s_lock); 90062306a36Sopenharmony_ci spin_unlock(&qp->s_hlock); 90162306a36Sopenharmony_ci spin_unlock_irq(&qp->r_lock); 90262306a36Sopenharmony_ci if (lastwqe) { 90362306a36Sopenharmony_ci ev.device = qp->ibqp.device; 90462306a36Sopenharmony_ci ev.element.qp = &qp->ibqp; 90562306a36Sopenharmony_ci ev.event = IB_EVENT_QP_LAST_WQE_REACHED; 90662306a36Sopenharmony_ci qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci/** 91162306a36Sopenharmony_ci * hfi1_error_port_qps - put a port's RC/UC qps into error state 91262306a36Sopenharmony_ci * @ibp: the ibport. 91362306a36Sopenharmony_ci * @sl: the service level. 91462306a36Sopenharmony_ci * 91562306a36Sopenharmony_ci * This function places all RC/UC qps with a given service level into error 91662306a36Sopenharmony_ci * state. It is generally called to force upper lay apps to abandon stale qps 91762306a36Sopenharmony_ci * after an sl->sc mapping change. 91862306a36Sopenharmony_ci */ 91962306a36Sopenharmony_civoid hfi1_error_port_qps(struct hfi1_ibport *ibp, u8 sl) 92062306a36Sopenharmony_ci{ 92162306a36Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 92262306a36Sopenharmony_ci struct hfi1_ibdev *dev = &ppd->dd->verbs_dev; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci rvt_qp_iter(&dev->rdi, sl, hfi1_qp_iter_cb); 92562306a36Sopenharmony_ci} 926