18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright(c) 2015 - 2020 Intel Corporation. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license. When using or 58c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 158c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 168c2ecf20Sopenharmony_ci * General Public License for more details. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * BSD LICENSE 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 218c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 228c2ecf20Sopenharmony_ci * are met: 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above copyright 258c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 268c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above copyright 278c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 288c2ecf20Sopenharmony_ci * the documentation and/or other materials provided with the 298c2ecf20Sopenharmony_ci * distribution. 308c2ecf20Sopenharmony_ci * - Neither the name of Intel Corporation nor the names of its 318c2ecf20Sopenharmony_ci * contributors may be used to endorse or promote products derived 328c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 358c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 368c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 378c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 388c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 398c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 408c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 418c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 428c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 438c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 448c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include <linux/err.h> 498c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 508c2ecf20Sopenharmony_ci#include <linux/hash.h> 518c2ecf20Sopenharmony_ci#include <linux/module.h> 528c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 538c2ecf20Sopenharmony_ci#include <rdma/rdma_vt.h> 548c2ecf20Sopenharmony_ci#include <rdma/rdmavt_qp.h> 558c2ecf20Sopenharmony_ci#include <rdma/ib_verbs.h> 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#include "hfi.h" 588c2ecf20Sopenharmony_ci#include "qp.h" 598c2ecf20Sopenharmony_ci#include "trace.h" 608c2ecf20Sopenharmony_ci#include "verbs_txreq.h" 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciunsigned int hfi1_qp_table_size = 256; 638c2ecf20Sopenharmony_cimodule_param_named(qp_table_size, hfi1_qp_table_size, uint, S_IRUGO); 648c2ecf20Sopenharmony_ciMODULE_PARM_DESC(qp_table_size, "QP table size"); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic void flush_tx_list(struct rvt_qp *qp); 678c2ecf20Sopenharmony_cistatic int iowait_sleep( 688c2ecf20Sopenharmony_ci struct sdma_engine *sde, 698c2ecf20Sopenharmony_ci struct iowait_work *wait, 708c2ecf20Sopenharmony_ci struct sdma_txreq *stx, 718c2ecf20Sopenharmony_ci unsigned int seq, 728c2ecf20Sopenharmony_ci bool pkts_sent); 738c2ecf20Sopenharmony_cistatic void iowait_wakeup(struct iowait *wait, int reason); 748c2ecf20Sopenharmony_cistatic void iowait_sdma_drained(struct iowait *wait); 758c2ecf20Sopenharmony_cistatic void qp_pio_drain(struct rvt_qp *qp); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciconst struct rvt_operation_params hfi1_post_parms[RVT_OPERATION_MAX] = { 788c2ecf20Sopenharmony_ci[IB_WR_RDMA_WRITE] = { 798c2ecf20Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 808c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 818c2ecf20Sopenharmony_ci}, 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci[IB_WR_RDMA_READ] = { 848c2ecf20Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 858c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 868c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_ATOMIC, 878c2ecf20Sopenharmony_ci}, 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci[IB_WR_ATOMIC_CMP_AND_SWP] = { 908c2ecf20Sopenharmony_ci .length = sizeof(struct ib_atomic_wr), 918c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 928c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE, 938c2ecf20Sopenharmony_ci}, 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci[IB_WR_ATOMIC_FETCH_AND_ADD] = { 968c2ecf20Sopenharmony_ci .length = sizeof(struct ib_atomic_wr), 978c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 988c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE, 998c2ecf20Sopenharmony_ci}, 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci[IB_WR_RDMA_WRITE_WITH_IMM] = { 1028c2ecf20Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 1038c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 1048c2ecf20Sopenharmony_ci}, 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci[IB_WR_SEND] = { 1078c2ecf20Sopenharmony_ci .length = sizeof(struct ib_send_wr), 1088c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) | 1098c2ecf20Sopenharmony_ci BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 1108c2ecf20Sopenharmony_ci}, 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci[IB_WR_SEND_WITH_IMM] = { 1138c2ecf20Sopenharmony_ci .length = sizeof(struct ib_send_wr), 1148c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) | 1158c2ecf20Sopenharmony_ci BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 1168c2ecf20Sopenharmony_ci}, 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci[IB_WR_REG_MR] = { 1198c2ecf20Sopenharmony_ci .length = sizeof(struct ib_reg_wr), 1208c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 1218c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_LOCAL, 1228c2ecf20Sopenharmony_ci}, 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci[IB_WR_LOCAL_INV] = { 1258c2ecf20Sopenharmony_ci .length = sizeof(struct ib_send_wr), 1268c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC), 1278c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_LOCAL, 1288c2ecf20Sopenharmony_ci}, 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci[IB_WR_SEND_WITH_INV] = { 1318c2ecf20Sopenharmony_ci .length = sizeof(struct ib_send_wr), 1328c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 1338c2ecf20Sopenharmony_ci}, 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci[IB_WR_OPFN] = { 1368c2ecf20Sopenharmony_ci .length = sizeof(struct ib_atomic_wr), 1378c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 1388c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_USE_RESERVE, 1398c2ecf20Sopenharmony_ci}, 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci[IB_WR_TID_RDMA_WRITE] = { 1428c2ecf20Sopenharmony_ci .length = sizeof(struct ib_rdma_wr), 1438c2ecf20Sopenharmony_ci .qpt_support = BIT(IB_QPT_RC), 1448c2ecf20Sopenharmony_ci .flags = RVT_OPERATION_IGN_RNR_CNT, 1458c2ecf20Sopenharmony_ci}, 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void flush_list_head(struct list_head *l) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci while (!list_empty(l)) { 1528c2ecf20Sopenharmony_ci struct sdma_txreq *tx; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci tx = list_first_entry( 1558c2ecf20Sopenharmony_ci l, 1568c2ecf20Sopenharmony_ci struct sdma_txreq, 1578c2ecf20Sopenharmony_ci list); 1588c2ecf20Sopenharmony_ci list_del_init(&tx->list); 1598c2ecf20Sopenharmony_ci hfi1_put_txreq( 1608c2ecf20Sopenharmony_ci container_of(tx, struct verbs_txreq, txreq)); 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic void flush_tx_list(struct rvt_qp *qp) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci flush_list_head(&iowait_get_ib_work(&priv->s_iowait)->tx_head); 1698c2ecf20Sopenharmony_ci flush_list_head(&iowait_get_tid_work(&priv->s_iowait)->tx_head); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic void flush_iowait(struct rvt_qp *qp) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 1758c2ecf20Sopenharmony_ci unsigned long flags; 1768c2ecf20Sopenharmony_ci seqlock_t *lock = priv->s_iowait.lock; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!lock) 1798c2ecf20Sopenharmony_ci return; 1808c2ecf20Sopenharmony_ci write_seqlock_irqsave(lock, flags); 1818c2ecf20Sopenharmony_ci if (!list_empty(&priv->s_iowait.list)) { 1828c2ecf20Sopenharmony_ci list_del_init(&priv->s_iowait.list); 1838c2ecf20Sopenharmony_ci priv->s_iowait.lock = NULL; 1848c2ecf20Sopenharmony_ci rvt_put_qp(qp); 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci write_sequnlock_irqrestore(lock, flags); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci/** 1908c2ecf20Sopenharmony_ci * This function is what we would push to the core layer if we wanted to be a 1918c2ecf20Sopenharmony_ci * "first class citizen". Instead we hide this here and rely on Verbs ULPs 1928c2ecf20Sopenharmony_ci * to blindly pass the MTU enum value from the PathRecord to us. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_cistatic inline int verbs_mtu_enum_to_int(struct ib_device *dev, enum ib_mtu mtu) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci /* Constraining 10KB packets to 8KB packets */ 1978c2ecf20Sopenharmony_ci if (mtu == (enum ib_mtu)OPA_MTU_10240) 1988c2ecf20Sopenharmony_ci mtu = (enum ib_mtu)OPA_MTU_8192; 1998c2ecf20Sopenharmony_ci return opa_mtu_enum_to_int((enum opa_mtu)mtu); 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciint hfi1_check_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr, 2038c2ecf20Sopenharmony_ci int attr_mask, struct ib_udata *udata) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci struct ib_qp *ibqp = &qp->ibqp; 2068c2ecf20Sopenharmony_ci struct hfi1_ibdev *dev = to_idev(ibqp->device); 2078c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = dd_from_dev(dev); 2088c2ecf20Sopenharmony_ci u8 sc; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (attr_mask & IB_QP_AV) { 2118c2ecf20Sopenharmony_ci sc = ah_to_sc(ibqp->device, &attr->ah_attr); 2128c2ecf20Sopenharmony_ci if (sc == 0xf) 2138c2ecf20Sopenharmony_ci return -EINVAL; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (!qp_to_sdma_engine(qp, sc) && 2168c2ecf20Sopenharmony_ci dd->flags & HFI1_HAS_SEND_DMA) 2178c2ecf20Sopenharmony_ci return -EINVAL; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (!qp_to_send_context(qp, sc)) 2208c2ecf20Sopenharmony_ci return -EINVAL; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (attr_mask & IB_QP_ALT_PATH) { 2248c2ecf20Sopenharmony_ci sc = ah_to_sc(ibqp->device, &attr->alt_ah_attr); 2258c2ecf20Sopenharmony_ci if (sc == 0xf) 2268c2ecf20Sopenharmony_ci return -EINVAL; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (!qp_to_sdma_engine(qp, sc) && 2298c2ecf20Sopenharmony_ci dd->flags & HFI1_HAS_SEND_DMA) 2308c2ecf20Sopenharmony_ci return -EINVAL; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if (!qp_to_send_context(qp, sc)) 2338c2ecf20Sopenharmony_ci return -EINVAL; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci return 0; 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci/* 2408c2ecf20Sopenharmony_ci * qp_set_16b - Set the hdr_type based on whether the slid or the 2418c2ecf20Sopenharmony_ci * dlid in the connection is extended. Only applicable for RC and UC 2428c2ecf20Sopenharmony_ci * QPs. UD QPs determine this on the fly from the ah in the wqe 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_cistatic inline void qp_set_16b(struct rvt_qp *qp) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd; 2478c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp; 2488c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Update ah_attr to account for extended LIDs */ 2518c2ecf20Sopenharmony_ci hfi1_update_ah_attr(qp->ibqp.device, &qp->remote_ah_attr); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Create 32 bit LIDs */ 2548c2ecf20Sopenharmony_ci hfi1_make_opa_lid(&qp->remote_ah_attr); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (!(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH)) 2578c2ecf20Sopenharmony_ci return; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci ibp = to_iport(qp->ibqp.device, qp->port_num); 2608c2ecf20Sopenharmony_ci ppd = ppd_from_ibp(ibp); 2618c2ecf20Sopenharmony_ci priv->hdr_type = hfi1_get_hdr_type(ppd->lid, &qp->remote_ah_attr); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_civoid hfi1_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr, 2658c2ecf20Sopenharmony_ci int attr_mask, struct ib_udata *udata) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct ib_qp *ibqp = &qp->ibqp; 2688c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (attr_mask & IB_QP_AV) { 2718c2ecf20Sopenharmony_ci priv->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr); 2728c2ecf20Sopenharmony_ci priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc); 2738c2ecf20Sopenharmony_ci priv->s_sendcontext = qp_to_send_context(qp, priv->s_sc); 2748c2ecf20Sopenharmony_ci qp_set_16b(qp); 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (attr_mask & IB_QP_PATH_MIG_STATE && 2788c2ecf20Sopenharmony_ci attr->path_mig_state == IB_MIG_MIGRATED && 2798c2ecf20Sopenharmony_ci qp->s_mig_state == IB_MIG_ARMED) { 2808c2ecf20Sopenharmony_ci qp->s_flags |= HFI1_S_AHG_CLEAR; 2818c2ecf20Sopenharmony_ci priv->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr); 2828c2ecf20Sopenharmony_ci priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc); 2838c2ecf20Sopenharmony_ci priv->s_sendcontext = qp_to_send_context(qp, priv->s_sc); 2848c2ecf20Sopenharmony_ci qp_set_16b(qp); 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci opfn_qp_init(qp, attr, attr_mask); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/** 2918c2ecf20Sopenharmony_ci * hfi1_setup_wqe - set up the wqe 2928c2ecf20Sopenharmony_ci * @qp - The qp 2938c2ecf20Sopenharmony_ci * @wqe - The built wqe 2948c2ecf20Sopenharmony_ci * @call_send - Determine if the send should be posted or scheduled. 2958c2ecf20Sopenharmony_ci * 2968c2ecf20Sopenharmony_ci * Perform setup of the wqe. This is called 2978c2ecf20Sopenharmony_ci * prior to inserting the wqe into the ring but after 2988c2ecf20Sopenharmony_ci * the wqe has been setup by RDMAVT. This function 2998c2ecf20Sopenharmony_ci * allows the driver the opportunity to perform 3008c2ecf20Sopenharmony_ci * validation and additional setup of the wqe. 3018c2ecf20Sopenharmony_ci * 3028c2ecf20Sopenharmony_ci * Returns 0 on success, -EINVAL on failure 3038c2ecf20Sopenharmony_ci * 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_ciint hfi1_setup_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe, bool *call_send) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); 3088c2ecf20Sopenharmony_ci struct rvt_ah *ah; 3098c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd; 3108c2ecf20Sopenharmony_ci struct hfi1_devdata *dd; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci switch (qp->ibqp.qp_type) { 3138c2ecf20Sopenharmony_ci case IB_QPT_RC: 3148c2ecf20Sopenharmony_ci hfi1_setup_tid_rdma_wqe(qp, wqe); 3158c2ecf20Sopenharmony_ci fallthrough; 3168c2ecf20Sopenharmony_ci case IB_QPT_UC: 3178c2ecf20Sopenharmony_ci if (wqe->length > 0x80000000U) 3188c2ecf20Sopenharmony_ci return -EINVAL; 3198c2ecf20Sopenharmony_ci if (wqe->length > qp->pmtu) 3208c2ecf20Sopenharmony_ci *call_send = false; 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci case IB_QPT_SMI: 3238c2ecf20Sopenharmony_ci /* 3248c2ecf20Sopenharmony_ci * SM packets should exclusively use VL15 and their SL is 3258c2ecf20Sopenharmony_ci * ignored (IBTA v1.3, Section 3.5.8.2). Therefore, when ah 3268c2ecf20Sopenharmony_ci * is created, SL is 0 in most cases and as a result some 3278c2ecf20Sopenharmony_ci * fields (vl and pmtu) in ah may not be set correctly, 3288c2ecf20Sopenharmony_ci * depending on the SL2SC and SC2VL tables at the time. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci ppd = ppd_from_ibp(ibp); 3318c2ecf20Sopenharmony_ci dd = dd_from_ppd(ppd); 3328c2ecf20Sopenharmony_ci if (wqe->length > dd->vld[15].mtu) 3338c2ecf20Sopenharmony_ci return -EINVAL; 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci case IB_QPT_GSI: 3368c2ecf20Sopenharmony_ci case IB_QPT_UD: 3378c2ecf20Sopenharmony_ci ah = rvt_get_swqe_ah(wqe); 3388c2ecf20Sopenharmony_ci if (wqe->length > (1 << ah->log_pmtu)) 3398c2ecf20Sopenharmony_ci return -EINVAL; 3408c2ecf20Sopenharmony_ci if (ibp->sl_to_sc[rdma_ah_get_sl(&ah->attr)] == 0xf) 3418c2ecf20Sopenharmony_ci return -EINVAL; 3428c2ecf20Sopenharmony_ci default: 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* 3478c2ecf20Sopenharmony_ci * System latency between send and schedule is large enough that 3488c2ecf20Sopenharmony_ci * forcing call_send to true for piothreshold packets is necessary. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci if (wqe->length <= piothreshold) 3518c2ecf20Sopenharmony_ci *call_send = true; 3528c2ecf20Sopenharmony_ci return 0; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci/** 3568c2ecf20Sopenharmony_ci * _hfi1_schedule_send - schedule progress 3578c2ecf20Sopenharmony_ci * @qp: the QP 3588c2ecf20Sopenharmony_ci * 3598c2ecf20Sopenharmony_ci * This schedules qp progress w/o regard to the s_flags. 3608c2ecf20Sopenharmony_ci * 3618c2ecf20Sopenharmony_ci * It is only used in the post send, which doesn't hold 3628c2ecf20Sopenharmony_ci * the s_lock. 3638c2ecf20Sopenharmony_ci */ 3648c2ecf20Sopenharmony_cibool _hfi1_schedule_send(struct rvt_qp *qp) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 3678c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = 3688c2ecf20Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 3698c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 3708c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = ppd->dd; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (dd->flags & HFI1_SHUTDOWN) 3738c2ecf20Sopenharmony_ci return true; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci return iowait_schedule(&priv->s_iowait, ppd->hfi1_wq, 3768c2ecf20Sopenharmony_ci priv->s_sde ? 3778c2ecf20Sopenharmony_ci priv->s_sde->cpu : 3788c2ecf20Sopenharmony_ci cpumask_first(cpumask_of_node(dd->node))); 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic void qp_pio_drain(struct rvt_qp *qp) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (!priv->s_sendcontext) 3868c2ecf20Sopenharmony_ci return; 3878c2ecf20Sopenharmony_ci while (iowait_pio_pending(&priv->s_iowait)) { 3888c2ecf20Sopenharmony_ci write_seqlock_irq(&priv->s_sendcontext->waitlock); 3898c2ecf20Sopenharmony_ci hfi1_sc_wantpiobuf_intr(priv->s_sendcontext, 1); 3908c2ecf20Sopenharmony_ci write_sequnlock_irq(&priv->s_sendcontext->waitlock); 3918c2ecf20Sopenharmony_ci iowait_pio_drain(&priv->s_iowait); 3928c2ecf20Sopenharmony_ci write_seqlock_irq(&priv->s_sendcontext->waitlock); 3938c2ecf20Sopenharmony_ci hfi1_sc_wantpiobuf_intr(priv->s_sendcontext, 0); 3948c2ecf20Sopenharmony_ci write_sequnlock_irq(&priv->s_sendcontext->waitlock); 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci/** 3998c2ecf20Sopenharmony_ci * hfi1_schedule_send - schedule progress 4008c2ecf20Sopenharmony_ci * @qp: the QP 4018c2ecf20Sopenharmony_ci * 4028c2ecf20Sopenharmony_ci * This schedules qp progress and caller should hold 4038c2ecf20Sopenharmony_ci * the s_lock. 4048c2ecf20Sopenharmony_ci * @return true if the first leg is scheduled; 4058c2ecf20Sopenharmony_ci * false if the first leg is not scheduled. 4068c2ecf20Sopenharmony_ci */ 4078c2ecf20Sopenharmony_cibool hfi1_schedule_send(struct rvt_qp *qp) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 4108c2ecf20Sopenharmony_ci if (hfi1_send_ok(qp)) { 4118c2ecf20Sopenharmony_ci _hfi1_schedule_send(qp); 4128c2ecf20Sopenharmony_ci return true; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci if (qp->s_flags & HFI1_S_ANY_WAIT_IO) 4158c2ecf20Sopenharmony_ci iowait_set_flag(&((struct hfi1_qp_priv *)qp->priv)->s_iowait, 4168c2ecf20Sopenharmony_ci IOWAIT_PENDING_IB); 4178c2ecf20Sopenharmony_ci return false; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void hfi1_qp_schedule(struct rvt_qp *qp) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 4238c2ecf20Sopenharmony_ci bool ret; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (iowait_flag_set(&priv->s_iowait, IOWAIT_PENDING_IB)) { 4268c2ecf20Sopenharmony_ci ret = hfi1_schedule_send(qp); 4278c2ecf20Sopenharmony_ci if (ret) 4288c2ecf20Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_IB); 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci if (iowait_flag_set(&priv->s_iowait, IOWAIT_PENDING_TID)) { 4318c2ecf20Sopenharmony_ci ret = hfi1_schedule_tid_send(qp); 4328c2ecf20Sopenharmony_ci if (ret) 4338c2ecf20Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_TID); 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_civoid hfi1_qp_wakeup(struct rvt_qp *qp, u32 flag) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci unsigned long flags; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 4428c2ecf20Sopenharmony_ci if (qp->s_flags & flag) { 4438c2ecf20Sopenharmony_ci qp->s_flags &= ~flag; 4448c2ecf20Sopenharmony_ci trace_hfi1_qpwakeup(qp, flag); 4458c2ecf20Sopenharmony_ci hfi1_qp_schedule(qp); 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 4488c2ecf20Sopenharmony_ci /* Notify hfi1_destroy_qp() if it is waiting. */ 4498c2ecf20Sopenharmony_ci rvt_put_qp(qp); 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_civoid hfi1_qp_unbusy(struct rvt_qp *qp, struct iowait_work *wait) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (iowait_set_work_flag(wait) == IOWAIT_IB_SE) { 4578c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_BUSY; 4588c2ecf20Sopenharmony_ci /* 4598c2ecf20Sopenharmony_ci * If we are sending a first-leg packet from the second leg, 4608c2ecf20Sopenharmony_ci * we need to clear the busy flag from priv->s_flags to 4618c2ecf20Sopenharmony_ci * avoid a race condition when the qp wakes up before 4628c2ecf20Sopenharmony_ci * the call to hfi1_verbs_send() returns to the second 4638c2ecf20Sopenharmony_ci * leg. In that case, the second leg will terminate without 4648c2ecf20Sopenharmony_ci * being re-scheduled, resulting in failure to send TID RDMA 4658c2ecf20Sopenharmony_ci * WRITE DATA and TID RDMA ACK packets. 4668c2ecf20Sopenharmony_ci */ 4678c2ecf20Sopenharmony_ci if (priv->s_flags & HFI1_S_TID_BUSY_SET) { 4688c2ecf20Sopenharmony_ci priv->s_flags &= ~(HFI1_S_TID_BUSY_SET | 4698c2ecf20Sopenharmony_ci RVT_S_BUSY); 4708c2ecf20Sopenharmony_ci iowait_set_flag(&priv->s_iowait, IOWAIT_PENDING_TID); 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci } else { 4738c2ecf20Sopenharmony_ci priv->s_flags &= ~RVT_S_BUSY; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_cistatic int iowait_sleep( 4788c2ecf20Sopenharmony_ci struct sdma_engine *sde, 4798c2ecf20Sopenharmony_ci struct iowait_work *wait, 4808c2ecf20Sopenharmony_ci struct sdma_txreq *stx, 4818c2ecf20Sopenharmony_ci uint seq, 4828c2ecf20Sopenharmony_ci bool pkts_sent) 4838c2ecf20Sopenharmony_ci{ 4848c2ecf20Sopenharmony_ci struct verbs_txreq *tx = container_of(stx, struct verbs_txreq, txreq); 4858c2ecf20Sopenharmony_ci struct rvt_qp *qp; 4868c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv; 4878c2ecf20Sopenharmony_ci unsigned long flags; 4888c2ecf20Sopenharmony_ci int ret = 0; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci qp = tx->qp; 4918c2ecf20Sopenharmony_ci priv = qp->priv; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 4948c2ecf20Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 4958c2ecf20Sopenharmony_ci /* 4968c2ecf20Sopenharmony_ci * If we couldn't queue the DMA request, save the info 4978c2ecf20Sopenharmony_ci * and try again later rather than destroying the 4988c2ecf20Sopenharmony_ci * buffer and undoing the side effects of the copy. 4998c2ecf20Sopenharmony_ci */ 5008c2ecf20Sopenharmony_ci /* Make a common routine? */ 5018c2ecf20Sopenharmony_ci list_add_tail(&stx->list, &wait->tx_head); 5028c2ecf20Sopenharmony_ci write_seqlock(&sde->waitlock); 5038c2ecf20Sopenharmony_ci if (sdma_progress(sde, seq, stx)) 5048c2ecf20Sopenharmony_ci goto eagain; 5058c2ecf20Sopenharmony_ci if (list_empty(&priv->s_iowait.list)) { 5068c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = 5078c2ecf20Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci ibp->rvp.n_dmawait++; 5108c2ecf20Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_DMA_DESC; 5118c2ecf20Sopenharmony_ci iowait_get_priority(&priv->s_iowait); 5128c2ecf20Sopenharmony_ci iowait_queue(pkts_sent, &priv->s_iowait, 5138c2ecf20Sopenharmony_ci &sde->dmawait); 5148c2ecf20Sopenharmony_ci priv->s_iowait.lock = &sde->waitlock; 5158c2ecf20Sopenharmony_ci trace_hfi1_qpsleep(qp, RVT_S_WAIT_DMA_DESC); 5168c2ecf20Sopenharmony_ci rvt_get_qp(qp); 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci write_sequnlock(&sde->waitlock); 5198c2ecf20Sopenharmony_ci hfi1_qp_unbusy(qp, wait); 5208c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 5218c2ecf20Sopenharmony_ci ret = -EBUSY; 5228c2ecf20Sopenharmony_ci } else { 5238c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 5248c2ecf20Sopenharmony_ci hfi1_put_txreq(tx); 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci return ret; 5278c2ecf20Sopenharmony_cieagain: 5288c2ecf20Sopenharmony_ci write_sequnlock(&sde->waitlock); 5298c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 5308c2ecf20Sopenharmony_ci list_del_init(&stx->list); 5318c2ecf20Sopenharmony_ci return -EAGAIN; 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic void iowait_wakeup(struct iowait *wait, int reason) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci struct rvt_qp *qp = iowait_to_qp(wait); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci WARN_ON(reason != SDMA_AVAIL_REASON); 5398c2ecf20Sopenharmony_ci hfi1_qp_wakeup(qp, RVT_S_WAIT_DMA_DESC); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic void iowait_sdma_drained(struct iowait *wait) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci struct rvt_qp *qp = iowait_to_qp(wait); 5458c2ecf20Sopenharmony_ci unsigned long flags; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* 5488c2ecf20Sopenharmony_ci * This happens when the send engine notes 5498c2ecf20Sopenharmony_ci * a QP in the error state and cannot 5508c2ecf20Sopenharmony_ci * do the flush work until that QP's 5518c2ecf20Sopenharmony_ci * sdma work has finished. 5528c2ecf20Sopenharmony_ci */ 5538c2ecf20Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 5548c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_WAIT_DMA) { 5558c2ecf20Sopenharmony_ci qp->s_flags &= ~RVT_S_WAIT_DMA; 5568c2ecf20Sopenharmony_ci hfi1_schedule_send(qp); 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic void hfi1_init_priority(struct iowait *w) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct rvt_qp *qp = iowait_to_qp(w); 5648c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (qp->s_flags & RVT_S_ACK_PENDING) 5678c2ecf20Sopenharmony_ci w->priority++; 5688c2ecf20Sopenharmony_ci if (priv->s_flags & RVT_S_ACK_PENDING) 5698c2ecf20Sopenharmony_ci w->priority++; 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci/** 5738c2ecf20Sopenharmony_ci * qp_to_sdma_engine - map a qp to a send engine 5748c2ecf20Sopenharmony_ci * @qp: the QP 5758c2ecf20Sopenharmony_ci * @sc5: the 5 bit sc 5768c2ecf20Sopenharmony_ci * 5778c2ecf20Sopenharmony_ci * Return: 5788c2ecf20Sopenharmony_ci * A send engine for the qp or NULL for SMI type qp. 5798c2ecf20Sopenharmony_ci */ 5808c2ecf20Sopenharmony_cistruct sdma_engine *qp_to_sdma_engine(struct rvt_qp *qp, u8 sc5) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 5838c2ecf20Sopenharmony_ci struct sdma_engine *sde; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci if (!(dd->flags & HFI1_HAS_SEND_DMA)) 5868c2ecf20Sopenharmony_ci return NULL; 5878c2ecf20Sopenharmony_ci switch (qp->ibqp.qp_type) { 5888c2ecf20Sopenharmony_ci case IB_QPT_SMI: 5898c2ecf20Sopenharmony_ci return NULL; 5908c2ecf20Sopenharmony_ci default: 5918c2ecf20Sopenharmony_ci break; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci sde = sdma_select_engine_sc(dd, qp->ibqp.qp_num >> dd->qos_shift, sc5); 5948c2ecf20Sopenharmony_ci return sde; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci/* 5988c2ecf20Sopenharmony_ci * qp_to_send_context - map a qp to a send context 5998c2ecf20Sopenharmony_ci * @qp: the QP 6008c2ecf20Sopenharmony_ci * @sc5: the 5 bit sc 6018c2ecf20Sopenharmony_ci * 6028c2ecf20Sopenharmony_ci * Return: 6038c2ecf20Sopenharmony_ci * A send context for the qp 6048c2ecf20Sopenharmony_ci */ 6058c2ecf20Sopenharmony_cistruct send_context *qp_to_send_context(struct rvt_qp *qp, u8 sc5) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci switch (qp->ibqp.qp_type) { 6108c2ecf20Sopenharmony_ci case IB_QPT_SMI: 6118c2ecf20Sopenharmony_ci /* SMA packets to VL15 */ 6128c2ecf20Sopenharmony_ci return dd->vld[15].sc; 6138c2ecf20Sopenharmony_ci default: 6148c2ecf20Sopenharmony_ci break; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci return pio_select_send_context_sc(dd, qp->ibqp.qp_num >> dd->qos_shift, 6188c2ecf20Sopenharmony_ci sc5); 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic const char * const qp_type_str[] = { 6228c2ecf20Sopenharmony_ci "SMI", "GSI", "RC", "UC", "UD", 6238c2ecf20Sopenharmony_ci}; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cistatic int qp_idle(struct rvt_qp *qp) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci return 6288c2ecf20Sopenharmony_ci qp->s_last == qp->s_acked && 6298c2ecf20Sopenharmony_ci qp->s_acked == qp->s_cur && 6308c2ecf20Sopenharmony_ci qp->s_cur == qp->s_tail && 6318c2ecf20Sopenharmony_ci qp->s_tail == qp->s_head; 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci/** 6358c2ecf20Sopenharmony_ci * qp_iter_print - print the qp information to seq_file 6368c2ecf20Sopenharmony_ci * @s: the seq_file to emit the qp information on 6378c2ecf20Sopenharmony_ci * @iter: the iterator for the qp hash list 6388c2ecf20Sopenharmony_ci */ 6398c2ecf20Sopenharmony_civoid qp_iter_print(struct seq_file *s, struct rvt_qp_iter *iter) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci struct rvt_swqe *wqe; 6428c2ecf20Sopenharmony_ci struct rvt_qp *qp = iter->qp; 6438c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 6448c2ecf20Sopenharmony_ci struct sdma_engine *sde; 6458c2ecf20Sopenharmony_ci struct send_context *send_context; 6468c2ecf20Sopenharmony_ci struct rvt_ack_entry *e = NULL; 6478c2ecf20Sopenharmony_ci struct rvt_srq *srq = qp->ibqp.srq ? 6488c2ecf20Sopenharmony_ci ibsrq_to_rvtsrq(qp->ibqp.srq) : NULL; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci sde = qp_to_sdma_engine(qp, priv->s_sc); 6518c2ecf20Sopenharmony_ci wqe = rvt_get_swqe_ptr(qp, qp->s_last); 6528c2ecf20Sopenharmony_ci send_context = qp_to_send_context(qp, priv->s_sc); 6538c2ecf20Sopenharmony_ci if (qp->s_ack_queue) 6548c2ecf20Sopenharmony_ci e = &qp->s_ack_queue[qp->s_tail_ack_queue]; 6558c2ecf20Sopenharmony_ci seq_printf(s, 6568c2ecf20Sopenharmony_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", 6578c2ecf20Sopenharmony_ci iter->n, 6588c2ecf20Sopenharmony_ci qp_idle(qp) ? "I" : "B", 6598c2ecf20Sopenharmony_ci qp->ibqp.qp_num, 6608c2ecf20Sopenharmony_ci atomic_read(&qp->refcount), 6618c2ecf20Sopenharmony_ci qp_type_str[qp->ibqp.qp_type], 6628c2ecf20Sopenharmony_ci qp->state, 6638c2ecf20Sopenharmony_ci wqe ? wqe->wr.opcode : 0, 6648c2ecf20Sopenharmony_ci qp->s_flags, 6658c2ecf20Sopenharmony_ci iowait_sdma_pending(&priv->s_iowait), 6668c2ecf20Sopenharmony_ci iowait_pio_pending(&priv->s_iowait), 6678c2ecf20Sopenharmony_ci !list_empty(&priv->s_iowait.list), 6688c2ecf20Sopenharmony_ci qp->timeout, 6698c2ecf20Sopenharmony_ci wqe ? wqe->ssn : 0, 6708c2ecf20Sopenharmony_ci qp->s_lsn, 6718c2ecf20Sopenharmony_ci qp->s_last_psn, 6728c2ecf20Sopenharmony_ci qp->s_psn, qp->s_next_psn, 6738c2ecf20Sopenharmony_ci qp->s_sending_psn, qp->s_sending_hpsn, 6748c2ecf20Sopenharmony_ci qp->r_psn, 6758c2ecf20Sopenharmony_ci qp->s_last, qp->s_acked, qp->s_cur, 6768c2ecf20Sopenharmony_ci qp->s_tail, qp->s_head, qp->s_size, 6778c2ecf20Sopenharmony_ci qp->s_avail, 6788c2ecf20Sopenharmony_ci /* ack_queue ring pointers, size */ 6798c2ecf20Sopenharmony_ci qp->s_tail_ack_queue, qp->r_head_ack_queue, 6808c2ecf20Sopenharmony_ci rvt_max_atomic(&to_idev(qp->ibqp.device)->rdi), 6818c2ecf20Sopenharmony_ci /* remote QP info */ 6828c2ecf20Sopenharmony_ci qp->remote_qpn, 6838c2ecf20Sopenharmony_ci rdma_ah_get_dlid(&qp->remote_ah_attr), 6848c2ecf20Sopenharmony_ci rdma_ah_get_sl(&qp->remote_ah_attr), 6858c2ecf20Sopenharmony_ci qp->pmtu, 6868c2ecf20Sopenharmony_ci qp->s_retry, 6878c2ecf20Sopenharmony_ci qp->s_retry_cnt, 6888c2ecf20Sopenharmony_ci qp->s_rnr_retry_cnt, 6898c2ecf20Sopenharmony_ci qp->s_rnr_retry, 6908c2ecf20Sopenharmony_ci sde, 6918c2ecf20Sopenharmony_ci sde ? sde->this_idx : 0, 6928c2ecf20Sopenharmony_ci send_context, 6938c2ecf20Sopenharmony_ci send_context ? send_context->sw_index : 0, 6948c2ecf20Sopenharmony_ci ib_cq_head(qp->ibqp.send_cq), 6958c2ecf20Sopenharmony_ci ib_cq_tail(qp->ibqp.send_cq), 6968c2ecf20Sopenharmony_ci qp->pid, 6978c2ecf20Sopenharmony_ci qp->s_state, 6988c2ecf20Sopenharmony_ci qp->s_ack_state, 6998c2ecf20Sopenharmony_ci /* ack queue information */ 7008c2ecf20Sopenharmony_ci e ? e->opcode : 0, 7018c2ecf20Sopenharmony_ci e ? e->psn : 0, 7028c2ecf20Sopenharmony_ci e ? e->lpsn : 0, 7038c2ecf20Sopenharmony_ci qp->r_min_rnr_timer, 7048c2ecf20Sopenharmony_ci srq ? "SRQ" : "RQ", 7058c2ecf20Sopenharmony_ci srq ? srq->rq.size : qp->r_rq.size 7068c2ecf20Sopenharmony_ci ); 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_civoid *qp_priv_alloc(struct rvt_dev_info *rdi, struct rvt_qp *qp) 7108c2ecf20Sopenharmony_ci{ 7118c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci priv = kzalloc_node(sizeof(*priv), GFP_KERNEL, rdi->dparms.node); 7148c2ecf20Sopenharmony_ci if (!priv) 7158c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci priv->owner = qp; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci priv->s_ahg = kzalloc_node(sizeof(*priv->s_ahg), GFP_KERNEL, 7208c2ecf20Sopenharmony_ci rdi->dparms.node); 7218c2ecf20Sopenharmony_ci if (!priv->s_ahg) { 7228c2ecf20Sopenharmony_ci kfree(priv); 7238c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci iowait_init( 7268c2ecf20Sopenharmony_ci &priv->s_iowait, 7278c2ecf20Sopenharmony_ci 1, 7288c2ecf20Sopenharmony_ci _hfi1_do_send, 7298c2ecf20Sopenharmony_ci _hfi1_do_tid_send, 7308c2ecf20Sopenharmony_ci iowait_sleep, 7318c2ecf20Sopenharmony_ci iowait_wakeup, 7328c2ecf20Sopenharmony_ci iowait_sdma_drained, 7338c2ecf20Sopenharmony_ci hfi1_init_priority); 7348c2ecf20Sopenharmony_ci /* Init to a value to start the running average correctly */ 7358c2ecf20Sopenharmony_ci priv->s_running_pkt_size = piothreshold / 2; 7368c2ecf20Sopenharmony_ci return priv; 7378c2ecf20Sopenharmony_ci} 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_civoid qp_priv_free(struct rvt_dev_info *rdi, struct rvt_qp *qp) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci hfi1_qp_priv_tid_free(rdi, qp); 7448c2ecf20Sopenharmony_ci kfree(priv->s_ahg); 7458c2ecf20Sopenharmony_ci kfree(priv); 7468c2ecf20Sopenharmony_ci} 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ciunsigned free_all_qps(struct rvt_dev_info *rdi) 7498c2ecf20Sopenharmony_ci{ 7508c2ecf20Sopenharmony_ci struct hfi1_ibdev *verbs_dev = container_of(rdi, 7518c2ecf20Sopenharmony_ci struct hfi1_ibdev, 7528c2ecf20Sopenharmony_ci rdi); 7538c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = container_of(verbs_dev, 7548c2ecf20Sopenharmony_ci struct hfi1_devdata, 7558c2ecf20Sopenharmony_ci verbs_dev); 7568c2ecf20Sopenharmony_ci int n; 7578c2ecf20Sopenharmony_ci unsigned qp_inuse = 0; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci for (n = 0; n < dd->num_pports; n++) { 7608c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = &dd->pport[n].ibport_data; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci rcu_read_lock(); 7638c2ecf20Sopenharmony_ci if (rcu_dereference(ibp->rvp.qp[0])) 7648c2ecf20Sopenharmony_ci qp_inuse++; 7658c2ecf20Sopenharmony_ci if (rcu_dereference(ibp->rvp.qp[1])) 7668c2ecf20Sopenharmony_ci qp_inuse++; 7678c2ecf20Sopenharmony_ci rcu_read_unlock(); 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci return qp_inuse; 7718c2ecf20Sopenharmony_ci} 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_civoid flush_qp_waiters(struct rvt_qp *qp) 7748c2ecf20Sopenharmony_ci{ 7758c2ecf20Sopenharmony_ci lockdep_assert_held(&qp->s_lock); 7768c2ecf20Sopenharmony_ci flush_iowait(qp); 7778c2ecf20Sopenharmony_ci hfi1_tid_rdma_flush_wait(qp); 7788c2ecf20Sopenharmony_ci} 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_civoid stop_send_queue(struct rvt_qp *qp) 7818c2ecf20Sopenharmony_ci{ 7828c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci iowait_cancel_work(&priv->s_iowait); 7858c2ecf20Sopenharmony_ci if (cancel_work_sync(&priv->tid_rdma.trigger_work)) 7868c2ecf20Sopenharmony_ci rvt_put_qp(qp); 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_civoid quiesce_qp(struct rvt_qp *qp) 7908c2ecf20Sopenharmony_ci{ 7918c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci hfi1_del_tid_reap_timer(qp); 7948c2ecf20Sopenharmony_ci hfi1_del_tid_retry_timer(qp); 7958c2ecf20Sopenharmony_ci iowait_sdma_drain(&priv->s_iowait); 7968c2ecf20Sopenharmony_ci qp_pio_drain(qp); 7978c2ecf20Sopenharmony_ci flush_tx_list(qp); 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_civoid notify_qp_reset(struct rvt_qp *qp) 8018c2ecf20Sopenharmony_ci{ 8028c2ecf20Sopenharmony_ci hfi1_qp_kern_exp_rcv_clear_all(qp); 8038c2ecf20Sopenharmony_ci qp->r_adefered = 0; 8048c2ecf20Sopenharmony_ci clear_ahg(qp); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* Clear any OPFN state */ 8078c2ecf20Sopenharmony_ci if (qp->ibqp.qp_type == IB_QPT_RC) 8088c2ecf20Sopenharmony_ci opfn_conn_error(qp); 8098c2ecf20Sopenharmony_ci} 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci/* 8128c2ecf20Sopenharmony_ci * Switch to alternate path. 8138c2ecf20Sopenharmony_ci * The QP s_lock should be held and interrupts disabled. 8148c2ecf20Sopenharmony_ci */ 8158c2ecf20Sopenharmony_civoid hfi1_migrate_qp(struct rvt_qp *qp) 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 8188c2ecf20Sopenharmony_ci struct ib_event ev; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci qp->s_mig_state = IB_MIG_MIGRATED; 8218c2ecf20Sopenharmony_ci qp->remote_ah_attr = qp->alt_ah_attr; 8228c2ecf20Sopenharmony_ci qp->port_num = rdma_ah_get_port_num(&qp->alt_ah_attr); 8238c2ecf20Sopenharmony_ci qp->s_pkey_index = qp->s_alt_pkey_index; 8248c2ecf20Sopenharmony_ci qp->s_flags |= HFI1_S_AHG_CLEAR; 8258c2ecf20Sopenharmony_ci priv->s_sc = ah_to_sc(qp->ibqp.device, &qp->remote_ah_attr); 8268c2ecf20Sopenharmony_ci priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc); 8278c2ecf20Sopenharmony_ci qp_set_16b(qp); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci ev.device = qp->ibqp.device; 8308c2ecf20Sopenharmony_ci ev.element.qp = &qp->ibqp; 8318c2ecf20Sopenharmony_ci ev.event = IB_EVENT_PATH_MIG; 8328c2ecf20Sopenharmony_ci qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); 8338c2ecf20Sopenharmony_ci} 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ciint mtu_to_path_mtu(u32 mtu) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci return mtu_to_enum(mtu, OPA_MTU_8192); 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ciu32 mtu_from_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, u32 pmtu) 8418c2ecf20Sopenharmony_ci{ 8428c2ecf20Sopenharmony_ci u32 mtu; 8438c2ecf20Sopenharmony_ci struct hfi1_ibdev *verbs_dev = container_of(rdi, 8448c2ecf20Sopenharmony_ci struct hfi1_ibdev, 8458c2ecf20Sopenharmony_ci rdi); 8468c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = container_of(verbs_dev, 8478c2ecf20Sopenharmony_ci struct hfi1_devdata, 8488c2ecf20Sopenharmony_ci verbs_dev); 8498c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp; 8508c2ecf20Sopenharmony_ci u8 sc, vl; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci ibp = &dd->pport[qp->port_num - 1].ibport_data; 8538c2ecf20Sopenharmony_ci sc = ibp->sl_to_sc[rdma_ah_get_sl(&qp->remote_ah_attr)]; 8548c2ecf20Sopenharmony_ci vl = sc_to_vlt(dd, sc); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci mtu = verbs_mtu_enum_to_int(qp->ibqp.device, pmtu); 8578c2ecf20Sopenharmony_ci if (vl < PER_VL_SEND_CONTEXTS) 8588c2ecf20Sopenharmony_ci mtu = min_t(u32, mtu, dd->vld[vl].mtu); 8598c2ecf20Sopenharmony_ci return mtu; 8608c2ecf20Sopenharmony_ci} 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ciint get_pmtu_from_attr(struct rvt_dev_info *rdi, struct rvt_qp *qp, 8638c2ecf20Sopenharmony_ci struct ib_qp_attr *attr) 8648c2ecf20Sopenharmony_ci{ 8658c2ecf20Sopenharmony_ci int mtu, pidx = qp->port_num - 1; 8668c2ecf20Sopenharmony_ci struct hfi1_ibdev *verbs_dev = container_of(rdi, 8678c2ecf20Sopenharmony_ci struct hfi1_ibdev, 8688c2ecf20Sopenharmony_ci rdi); 8698c2ecf20Sopenharmony_ci struct hfi1_devdata *dd = container_of(verbs_dev, 8708c2ecf20Sopenharmony_ci struct hfi1_devdata, 8718c2ecf20Sopenharmony_ci verbs_dev); 8728c2ecf20Sopenharmony_ci mtu = verbs_mtu_enum_to_int(qp->ibqp.device, attr->path_mtu); 8738c2ecf20Sopenharmony_ci if (mtu == -1) 8748c2ecf20Sopenharmony_ci return -1; /* values less than 0 are error */ 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci if (mtu > dd->pport[pidx].ibmtu) 8778c2ecf20Sopenharmony_ci return mtu_to_enum(dd->pport[pidx].ibmtu, IB_MTU_2048); 8788c2ecf20Sopenharmony_ci else 8798c2ecf20Sopenharmony_ci return attr->path_mtu; 8808c2ecf20Sopenharmony_ci} 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_civoid notify_error_qp(struct rvt_qp *qp) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 8858c2ecf20Sopenharmony_ci seqlock_t *lock = priv->s_iowait.lock; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci if (lock) { 8888c2ecf20Sopenharmony_ci write_seqlock(lock); 8898c2ecf20Sopenharmony_ci if (!list_empty(&priv->s_iowait.list) && 8908c2ecf20Sopenharmony_ci !(qp->s_flags & RVT_S_BUSY) && 8918c2ecf20Sopenharmony_ci !(priv->s_flags & RVT_S_BUSY)) { 8928c2ecf20Sopenharmony_ci qp->s_flags &= ~HFI1_S_ANY_WAIT_IO; 8938c2ecf20Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_IB); 8948c2ecf20Sopenharmony_ci iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_TID); 8958c2ecf20Sopenharmony_ci list_del_init(&priv->s_iowait.list); 8968c2ecf20Sopenharmony_ci priv->s_iowait.lock = NULL; 8978c2ecf20Sopenharmony_ci rvt_put_qp(qp); 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci write_sequnlock(lock); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci if (!(qp->s_flags & RVT_S_BUSY) && !(priv->s_flags & RVT_S_BUSY)) { 9038c2ecf20Sopenharmony_ci qp->s_hdrwords = 0; 9048c2ecf20Sopenharmony_ci if (qp->s_rdma_mr) { 9058c2ecf20Sopenharmony_ci rvt_put_mr(qp->s_rdma_mr); 9068c2ecf20Sopenharmony_ci qp->s_rdma_mr = NULL; 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci flush_tx_list(qp); 9098c2ecf20Sopenharmony_ci } 9108c2ecf20Sopenharmony_ci} 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci/** 9138c2ecf20Sopenharmony_ci * hfi1_qp_iter_cb - callback for iterator 9148c2ecf20Sopenharmony_ci * @qp - the qp 9158c2ecf20Sopenharmony_ci * @v - the sl in low bits of v 9168c2ecf20Sopenharmony_ci * 9178c2ecf20Sopenharmony_ci * This is called from the iterator callback to work 9188c2ecf20Sopenharmony_ci * on an individual qp. 9198c2ecf20Sopenharmony_ci */ 9208c2ecf20Sopenharmony_cistatic void hfi1_qp_iter_cb(struct rvt_qp *qp, u64 v) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci int lastwqe; 9238c2ecf20Sopenharmony_ci struct ib_event ev; 9248c2ecf20Sopenharmony_ci struct hfi1_ibport *ibp = 9258c2ecf20Sopenharmony_ci to_iport(qp->ibqp.device, qp->port_num); 9268c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 9278c2ecf20Sopenharmony_ci u8 sl = (u8)v; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci if (qp->port_num != ppd->port || 9308c2ecf20Sopenharmony_ci (qp->ibqp.qp_type != IB_QPT_UC && 9318c2ecf20Sopenharmony_ci qp->ibqp.qp_type != IB_QPT_RC) || 9328c2ecf20Sopenharmony_ci rdma_ah_get_sl(&qp->remote_ah_attr) != sl || 9338c2ecf20Sopenharmony_ci !(ib_rvt_state_ops[qp->state] & RVT_POST_SEND_OK)) 9348c2ecf20Sopenharmony_ci return; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci spin_lock_irq(&qp->r_lock); 9378c2ecf20Sopenharmony_ci spin_lock(&qp->s_hlock); 9388c2ecf20Sopenharmony_ci spin_lock(&qp->s_lock); 9398c2ecf20Sopenharmony_ci lastwqe = rvt_error_qp(qp, IB_WC_WR_FLUSH_ERR); 9408c2ecf20Sopenharmony_ci spin_unlock(&qp->s_lock); 9418c2ecf20Sopenharmony_ci spin_unlock(&qp->s_hlock); 9428c2ecf20Sopenharmony_ci spin_unlock_irq(&qp->r_lock); 9438c2ecf20Sopenharmony_ci if (lastwqe) { 9448c2ecf20Sopenharmony_ci ev.device = qp->ibqp.device; 9458c2ecf20Sopenharmony_ci ev.element.qp = &qp->ibqp; 9468c2ecf20Sopenharmony_ci ev.event = IB_EVENT_QP_LAST_WQE_REACHED; 9478c2ecf20Sopenharmony_ci qp->ibqp.event_handler(&ev, qp->ibqp.qp_context); 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci/** 9528c2ecf20Sopenharmony_ci * hfi1_error_port_qps - put a port's RC/UC qps into error state 9538c2ecf20Sopenharmony_ci * @ibp: the ibport. 9548c2ecf20Sopenharmony_ci * @sl: the service level. 9558c2ecf20Sopenharmony_ci * 9568c2ecf20Sopenharmony_ci * This function places all RC/UC qps with a given service level into error 9578c2ecf20Sopenharmony_ci * state. It is generally called to force upper lay apps to abandon stale qps 9588c2ecf20Sopenharmony_ci * after an sl->sc mapping change. 9598c2ecf20Sopenharmony_ci */ 9608c2ecf20Sopenharmony_civoid hfi1_error_port_qps(struct hfi1_ibport *ibp, u8 sl) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 9638c2ecf20Sopenharmony_ci struct hfi1_ibdev *dev = &ppd->dd->verbs_dev; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci rvt_qp_iter(&dev->rdi, sl, hfi1_qp_iter_cb); 9668c2ecf20Sopenharmony_ci} 967