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 <rdma/ib_mad.h> 762306a36Sopenharmony_ci#include <rdma/ib_user_verbs.h> 862306a36Sopenharmony_ci#include <linux/io.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/utsname.h> 1162306a36Sopenharmony_ci#include <linux/rculist.h> 1262306a36Sopenharmony_ci#include <linux/mm.h> 1362306a36Sopenharmony_ci#include <linux/vmalloc.h> 1462306a36Sopenharmony_ci#include <rdma/opa_addr.h> 1562306a36Sopenharmony_ci#include <linux/nospec.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "hfi.h" 1862306a36Sopenharmony_ci#include "common.h" 1962306a36Sopenharmony_ci#include "device.h" 2062306a36Sopenharmony_ci#include "trace.h" 2162306a36Sopenharmony_ci#include "qp.h" 2262306a36Sopenharmony_ci#include "verbs_txreq.h" 2362306a36Sopenharmony_ci#include "debugfs.h" 2462306a36Sopenharmony_ci#include "vnic.h" 2562306a36Sopenharmony_ci#include "fault.h" 2662306a36Sopenharmony_ci#include "affinity.h" 2762306a36Sopenharmony_ci#include "ipoib.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic unsigned int hfi1_lkey_table_size = 16; 3062306a36Sopenharmony_cimodule_param_named(lkey_table_size, hfi1_lkey_table_size, uint, 3162306a36Sopenharmony_ci S_IRUGO); 3262306a36Sopenharmony_ciMODULE_PARM_DESC(lkey_table_size, 3362306a36Sopenharmony_ci "LKEY table size in bits (2^n, 1 <= n <= 23)"); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic unsigned int hfi1_max_pds = 0xFFFF; 3662306a36Sopenharmony_cimodule_param_named(max_pds, hfi1_max_pds, uint, S_IRUGO); 3762306a36Sopenharmony_ciMODULE_PARM_DESC(max_pds, 3862306a36Sopenharmony_ci "Maximum number of protection domains to support"); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic unsigned int hfi1_max_ahs = 0xFFFF; 4162306a36Sopenharmony_cimodule_param_named(max_ahs, hfi1_max_ahs, uint, S_IRUGO); 4262306a36Sopenharmony_ciMODULE_PARM_DESC(max_ahs, "Maximum number of address handles to support"); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciunsigned int hfi1_max_cqes = 0x2FFFFF; 4562306a36Sopenharmony_cimodule_param_named(max_cqes, hfi1_max_cqes, uint, S_IRUGO); 4662306a36Sopenharmony_ciMODULE_PARM_DESC(max_cqes, 4762306a36Sopenharmony_ci "Maximum number of completion queue entries to support"); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciunsigned int hfi1_max_cqs = 0x1FFFF; 5062306a36Sopenharmony_cimodule_param_named(max_cqs, hfi1_max_cqs, uint, S_IRUGO); 5162306a36Sopenharmony_ciMODULE_PARM_DESC(max_cqs, "Maximum number of completion queues to support"); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciunsigned int hfi1_max_qp_wrs = 0x3FFF; 5462306a36Sopenharmony_cimodule_param_named(max_qp_wrs, hfi1_max_qp_wrs, uint, S_IRUGO); 5562306a36Sopenharmony_ciMODULE_PARM_DESC(max_qp_wrs, "Maximum number of QP WRs to support"); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciunsigned int hfi1_max_qps = 32768; 5862306a36Sopenharmony_cimodule_param_named(max_qps, hfi1_max_qps, uint, S_IRUGO); 5962306a36Sopenharmony_ciMODULE_PARM_DESC(max_qps, "Maximum number of QPs to support"); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciunsigned int hfi1_max_sges = 0x60; 6262306a36Sopenharmony_cimodule_param_named(max_sges, hfi1_max_sges, uint, S_IRUGO); 6362306a36Sopenharmony_ciMODULE_PARM_DESC(max_sges, "Maximum number of SGEs to support"); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciunsigned int hfi1_max_mcast_grps = 16384; 6662306a36Sopenharmony_cimodule_param_named(max_mcast_grps, hfi1_max_mcast_grps, uint, S_IRUGO); 6762306a36Sopenharmony_ciMODULE_PARM_DESC(max_mcast_grps, 6862306a36Sopenharmony_ci "Maximum number of multicast groups to support"); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciunsigned int hfi1_max_mcast_qp_attached = 16; 7162306a36Sopenharmony_cimodule_param_named(max_mcast_qp_attached, hfi1_max_mcast_qp_attached, 7262306a36Sopenharmony_ci uint, S_IRUGO); 7362306a36Sopenharmony_ciMODULE_PARM_DESC(max_mcast_qp_attached, 7462306a36Sopenharmony_ci "Maximum number of attached QPs to support"); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciunsigned int hfi1_max_srqs = 1024; 7762306a36Sopenharmony_cimodule_param_named(max_srqs, hfi1_max_srqs, uint, S_IRUGO); 7862306a36Sopenharmony_ciMODULE_PARM_DESC(max_srqs, "Maximum number of SRQs to support"); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciunsigned int hfi1_max_srq_sges = 128; 8162306a36Sopenharmony_cimodule_param_named(max_srq_sges, hfi1_max_srq_sges, uint, S_IRUGO); 8262306a36Sopenharmony_ciMODULE_PARM_DESC(max_srq_sges, "Maximum number of SRQ SGEs to support"); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ciunsigned int hfi1_max_srq_wrs = 0x1FFFF; 8562306a36Sopenharmony_cimodule_param_named(max_srq_wrs, hfi1_max_srq_wrs, uint, S_IRUGO); 8662306a36Sopenharmony_ciMODULE_PARM_DESC(max_srq_wrs, "Maximum number of SRQ WRs support"); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciunsigned short piothreshold = 256; 8962306a36Sopenharmony_cimodule_param(piothreshold, ushort, S_IRUGO); 9062306a36Sopenharmony_ciMODULE_PARM_DESC(piothreshold, "size used to determine sdma vs. pio"); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic unsigned int sge_copy_mode; 9362306a36Sopenharmony_cimodule_param(sge_copy_mode, uint, S_IRUGO); 9462306a36Sopenharmony_ciMODULE_PARM_DESC(sge_copy_mode, 9562306a36Sopenharmony_ci "Verbs copy mode: 0 use memcpy, 1 use cacheless copy, 2 adapt based on WSS"); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void verbs_sdma_complete( 9862306a36Sopenharmony_ci struct sdma_txreq *cookie, 9962306a36Sopenharmony_ci int status); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic int pio_wait(struct rvt_qp *qp, 10262306a36Sopenharmony_ci struct send_context *sc, 10362306a36Sopenharmony_ci struct hfi1_pkt_state *ps, 10462306a36Sopenharmony_ci u32 flag); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* Length of buffer to create verbs txreq cache name */ 10762306a36Sopenharmony_ci#define TXREQ_NAME_LEN 24 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic uint wss_threshold = 80; 11062306a36Sopenharmony_cimodule_param(wss_threshold, uint, S_IRUGO); 11162306a36Sopenharmony_ciMODULE_PARM_DESC(wss_threshold, "Percentage (1-100) of LLC to use as a threshold for a cacheless copy"); 11262306a36Sopenharmony_cistatic uint wss_clean_period = 256; 11362306a36Sopenharmony_cimodule_param(wss_clean_period, uint, S_IRUGO); 11462306a36Sopenharmony_ciMODULE_PARM_DESC(wss_clean_period, "Count of verbs copies before an entry in the page copy table is cleaned"); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* 11762306a36Sopenharmony_ci * Translate ib_wr_opcode into ib_wc_opcode. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ciconst enum ib_wc_opcode ib_hfi1_wc_opcode[] = { 12062306a36Sopenharmony_ci [IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE, 12162306a36Sopenharmony_ci [IB_WR_TID_RDMA_WRITE] = IB_WC_RDMA_WRITE, 12262306a36Sopenharmony_ci [IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE, 12362306a36Sopenharmony_ci [IB_WR_SEND] = IB_WC_SEND, 12462306a36Sopenharmony_ci [IB_WR_SEND_WITH_IMM] = IB_WC_SEND, 12562306a36Sopenharmony_ci [IB_WR_RDMA_READ] = IB_WC_RDMA_READ, 12662306a36Sopenharmony_ci [IB_WR_TID_RDMA_READ] = IB_WC_RDMA_READ, 12762306a36Sopenharmony_ci [IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP, 12862306a36Sopenharmony_ci [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD, 12962306a36Sopenharmony_ci [IB_WR_SEND_WITH_INV] = IB_WC_SEND, 13062306a36Sopenharmony_ci [IB_WR_LOCAL_INV] = IB_WC_LOCAL_INV, 13162306a36Sopenharmony_ci [IB_WR_REG_MR] = IB_WC_REG_MR 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/* 13562306a36Sopenharmony_ci * Length of header by opcode, 0 --> not supported 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ciconst u8 hdr_len_by_opcode[256] = { 13862306a36Sopenharmony_ci /* RC */ 13962306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_FIRST] = 12 + 8, 14062306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_MIDDLE] = 12 + 8, 14162306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_LAST] = 12 + 8, 14262306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE] = 12 + 8 + 4, 14362306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_ONLY] = 12 + 8, 14462306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_ONLY_WITH_IMMEDIATE] = 12 + 8 + 4, 14562306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_FIRST] = 12 + 8 + 16, 14662306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_MIDDLE] = 12 + 8, 14762306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_LAST] = 12 + 8, 14862306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE] = 12 + 8 + 4, 14962306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_ONLY] = 12 + 8 + 16, 15062306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = 12 + 8 + 20, 15162306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_REQUEST] = 12 + 8 + 16, 15262306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST] = 12 + 8 + 4, 15362306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE] = 12 + 8, 15462306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST] = 12 + 8 + 4, 15562306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY] = 12 + 8 + 4, 15662306a36Sopenharmony_ci [IB_OPCODE_RC_ACKNOWLEDGE] = 12 + 8 + 4, 15762306a36Sopenharmony_ci [IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE] = 12 + 8 + 4 + 8, 15862306a36Sopenharmony_ci [IB_OPCODE_RC_COMPARE_SWAP] = 12 + 8 + 28, 15962306a36Sopenharmony_ci [IB_OPCODE_RC_FETCH_ADD] = 12 + 8 + 28, 16062306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE] = 12 + 8 + 4, 16162306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_ONLY_WITH_INVALIDATE] = 12 + 8 + 4, 16262306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_READ_REQ] = 12 + 8 + 36, 16362306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_READ_RESP] = 12 + 8 + 36, 16462306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_REQ] = 12 + 8 + 36, 16562306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_RESP] = 12 + 8 + 36, 16662306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_DATA] = 12 + 8 + 36, 16762306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_DATA_LAST] = 12 + 8 + 36, 16862306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_ACK] = 12 + 8 + 36, 16962306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_RESYNC] = 12 + 8 + 36, 17062306a36Sopenharmony_ci /* UC */ 17162306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_FIRST] = 12 + 8, 17262306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_MIDDLE] = 12 + 8, 17362306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_LAST] = 12 + 8, 17462306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE] = 12 + 8 + 4, 17562306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_ONLY] = 12 + 8, 17662306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_ONLY_WITH_IMMEDIATE] = 12 + 8 + 4, 17762306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_FIRST] = 12 + 8 + 16, 17862306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_MIDDLE] = 12 + 8, 17962306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_LAST] = 12 + 8, 18062306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE] = 12 + 8 + 4, 18162306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_ONLY] = 12 + 8 + 16, 18262306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = 12 + 8 + 20, 18362306a36Sopenharmony_ci /* UD */ 18462306a36Sopenharmony_ci [IB_OPCODE_UD_SEND_ONLY] = 12 + 8 + 8, 18562306a36Sopenharmony_ci [IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE] = 12 + 8 + 12 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic const opcode_handler opcode_handler_tbl[256] = { 18962306a36Sopenharmony_ci /* RC */ 19062306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_FIRST] = &hfi1_rc_rcv, 19162306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_MIDDLE] = &hfi1_rc_rcv, 19262306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_LAST] = &hfi1_rc_rcv, 19362306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE] = &hfi1_rc_rcv, 19462306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_ONLY] = &hfi1_rc_rcv, 19562306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_ONLY_WITH_IMMEDIATE] = &hfi1_rc_rcv, 19662306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_FIRST] = &hfi1_rc_rcv, 19762306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_MIDDLE] = &hfi1_rc_rcv, 19862306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_LAST] = &hfi1_rc_rcv, 19962306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE] = &hfi1_rc_rcv, 20062306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_ONLY] = &hfi1_rc_rcv, 20162306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = &hfi1_rc_rcv, 20262306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_REQUEST] = &hfi1_rc_rcv, 20362306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST] = &hfi1_rc_rcv, 20462306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE] = &hfi1_rc_rcv, 20562306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST] = &hfi1_rc_rcv, 20662306a36Sopenharmony_ci [IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY] = &hfi1_rc_rcv, 20762306a36Sopenharmony_ci [IB_OPCODE_RC_ACKNOWLEDGE] = &hfi1_rc_rcv, 20862306a36Sopenharmony_ci [IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE] = &hfi1_rc_rcv, 20962306a36Sopenharmony_ci [IB_OPCODE_RC_COMPARE_SWAP] = &hfi1_rc_rcv, 21062306a36Sopenharmony_ci [IB_OPCODE_RC_FETCH_ADD] = &hfi1_rc_rcv, 21162306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE] = &hfi1_rc_rcv, 21262306a36Sopenharmony_ci [IB_OPCODE_RC_SEND_ONLY_WITH_INVALIDATE] = &hfi1_rc_rcv, 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* TID RDMA has separate handlers for different opcodes.*/ 21562306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_REQ] = &hfi1_rc_rcv_tid_rdma_write_req, 21662306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_RESP] = &hfi1_rc_rcv_tid_rdma_write_resp, 21762306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_DATA] = &hfi1_rc_rcv_tid_rdma_write_data, 21862306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_WRITE_DATA_LAST] = &hfi1_rc_rcv_tid_rdma_write_data, 21962306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_READ_REQ] = &hfi1_rc_rcv_tid_rdma_read_req, 22062306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_READ_RESP] = &hfi1_rc_rcv_tid_rdma_read_resp, 22162306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_RESYNC] = &hfi1_rc_rcv_tid_rdma_resync, 22262306a36Sopenharmony_ci [IB_OPCODE_TID_RDMA_ACK] = &hfi1_rc_rcv_tid_rdma_ack, 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci /* UC */ 22562306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_FIRST] = &hfi1_uc_rcv, 22662306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_MIDDLE] = &hfi1_uc_rcv, 22762306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_LAST] = &hfi1_uc_rcv, 22862306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE] = &hfi1_uc_rcv, 22962306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_ONLY] = &hfi1_uc_rcv, 23062306a36Sopenharmony_ci [IB_OPCODE_UC_SEND_ONLY_WITH_IMMEDIATE] = &hfi1_uc_rcv, 23162306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_FIRST] = &hfi1_uc_rcv, 23262306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_MIDDLE] = &hfi1_uc_rcv, 23362306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_LAST] = &hfi1_uc_rcv, 23462306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE] = &hfi1_uc_rcv, 23562306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_ONLY] = &hfi1_uc_rcv, 23662306a36Sopenharmony_ci [IB_OPCODE_UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = &hfi1_uc_rcv, 23762306a36Sopenharmony_ci /* UD */ 23862306a36Sopenharmony_ci [IB_OPCODE_UD_SEND_ONLY] = &hfi1_ud_rcv, 23962306a36Sopenharmony_ci [IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE] = &hfi1_ud_rcv, 24062306a36Sopenharmony_ci /* CNP */ 24162306a36Sopenharmony_ci [IB_OPCODE_CNP] = &hfi1_cnp_rcv 24262306a36Sopenharmony_ci}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#define OPMASK 0x1f 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic const u32 pio_opmask[BIT(3)] = { 24762306a36Sopenharmony_ci /* RC */ 24862306a36Sopenharmony_ci [IB_OPCODE_RC >> 5] = 24962306a36Sopenharmony_ci BIT(RC_OP(SEND_ONLY) & OPMASK) | 25062306a36Sopenharmony_ci BIT(RC_OP(SEND_ONLY_WITH_IMMEDIATE) & OPMASK) | 25162306a36Sopenharmony_ci BIT(RC_OP(RDMA_WRITE_ONLY) & OPMASK) | 25262306a36Sopenharmony_ci BIT(RC_OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE) & OPMASK) | 25362306a36Sopenharmony_ci BIT(RC_OP(RDMA_READ_REQUEST) & OPMASK) | 25462306a36Sopenharmony_ci BIT(RC_OP(ACKNOWLEDGE) & OPMASK) | 25562306a36Sopenharmony_ci BIT(RC_OP(ATOMIC_ACKNOWLEDGE) & OPMASK) | 25662306a36Sopenharmony_ci BIT(RC_OP(COMPARE_SWAP) & OPMASK) | 25762306a36Sopenharmony_ci BIT(RC_OP(FETCH_ADD) & OPMASK), 25862306a36Sopenharmony_ci /* UC */ 25962306a36Sopenharmony_ci [IB_OPCODE_UC >> 5] = 26062306a36Sopenharmony_ci BIT(UC_OP(SEND_ONLY) & OPMASK) | 26162306a36Sopenharmony_ci BIT(UC_OP(SEND_ONLY_WITH_IMMEDIATE) & OPMASK) | 26262306a36Sopenharmony_ci BIT(UC_OP(RDMA_WRITE_ONLY) & OPMASK) | 26362306a36Sopenharmony_ci BIT(UC_OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE) & OPMASK), 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/* 26762306a36Sopenharmony_ci * System image GUID. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci__be64 ib_hfi1_sys_image_guid; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/* 27262306a36Sopenharmony_ci * Make sure the QP is ready and able to accept the given opcode. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_cistatic inline opcode_handler qp_ok(struct hfi1_packet *packet) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci if (!(ib_rvt_state_ops[packet->qp->state] & RVT_PROCESS_RECV_OK)) 27762306a36Sopenharmony_ci return NULL; 27862306a36Sopenharmony_ci if (((packet->opcode & RVT_OPCODE_QP_MASK) == 27962306a36Sopenharmony_ci packet->qp->allowed_ops) || 28062306a36Sopenharmony_ci (packet->opcode == IB_OPCODE_CNP)) 28162306a36Sopenharmony_ci return opcode_handler_tbl[packet->opcode]; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci return NULL; 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic u64 hfi1_fault_tx(struct rvt_qp *qp, u8 opcode, u64 pbc) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci#ifdef CONFIG_FAULT_INJECTION 28962306a36Sopenharmony_ci if ((opcode & IB_OPCODE_MSP) == IB_OPCODE_MSP) { 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * In order to drop non-IB traffic we 29262306a36Sopenharmony_ci * set PbcInsertHrc to NONE (0x2). 29362306a36Sopenharmony_ci * The packet will still be delivered 29462306a36Sopenharmony_ci * to the receiving node but a 29562306a36Sopenharmony_ci * KHdrHCRCErr (KDETH packet with a bad 29662306a36Sopenharmony_ci * HCRC) will be triggered and the 29762306a36Sopenharmony_ci * packet will not be delivered to the 29862306a36Sopenharmony_ci * correct context. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci pbc &= ~PBC_INSERT_HCRC_SMASK; 30162306a36Sopenharmony_ci pbc |= (u64)PBC_IHCRC_NONE << PBC_INSERT_HCRC_SHIFT; 30262306a36Sopenharmony_ci } else { 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * In order to drop regular verbs 30562306a36Sopenharmony_ci * traffic we set the PbcTestEbp 30662306a36Sopenharmony_ci * flag. The packet will still be 30762306a36Sopenharmony_ci * delivered to the receiving node but 30862306a36Sopenharmony_ci * a 'late ebp error' will be 30962306a36Sopenharmony_ci * triggered and will be dropped. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_ci pbc |= PBC_TEST_EBP; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci#endif 31462306a36Sopenharmony_ci return pbc; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic opcode_handler tid_qp_ok(int opcode, struct hfi1_packet *packet) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci if (packet->qp->ibqp.qp_type != IB_QPT_RC || 32062306a36Sopenharmony_ci !(ib_rvt_state_ops[packet->qp->state] & RVT_PROCESS_RECV_OK)) 32162306a36Sopenharmony_ci return NULL; 32262306a36Sopenharmony_ci if ((opcode & RVT_OPCODE_QP_MASK) == IB_OPCODE_TID_RDMA) 32362306a36Sopenharmony_ci return opcode_handler_tbl[opcode]; 32462306a36Sopenharmony_ci return NULL; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_civoid hfi1_kdeth_eager_rcv(struct hfi1_packet *packet) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 33062306a36Sopenharmony_ci struct ib_header *hdr = packet->hdr; 33162306a36Sopenharmony_ci u32 tlen = packet->tlen; 33262306a36Sopenharmony_ci struct hfi1_pportdata *ppd = rcd->ppd; 33362306a36Sopenharmony_ci struct hfi1_ibport *ibp = &ppd->ibport_data; 33462306a36Sopenharmony_ci struct rvt_dev_info *rdi = &ppd->dd->verbs_dev.rdi; 33562306a36Sopenharmony_ci opcode_handler opcode_handler; 33662306a36Sopenharmony_ci unsigned long flags; 33762306a36Sopenharmony_ci u32 qp_num; 33862306a36Sopenharmony_ci int lnh; 33962306a36Sopenharmony_ci u8 opcode; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* DW == LRH (2) + BTH (3) + KDETH (9) + CRC (1) */ 34262306a36Sopenharmony_ci if (unlikely(tlen < 15 * sizeof(u32))) 34362306a36Sopenharmony_ci goto drop; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci lnh = be16_to_cpu(hdr->lrh[0]) & 3; 34662306a36Sopenharmony_ci if (lnh != HFI1_LRH_BTH) 34762306a36Sopenharmony_ci goto drop; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci packet->ohdr = &hdr->u.oth; 35062306a36Sopenharmony_ci trace_input_ibhdr(rcd->dd, packet, !!(rhf_dc_info(packet->rhf))); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci opcode = (be32_to_cpu(packet->ohdr->bth[0]) >> 24); 35362306a36Sopenharmony_ci inc_opstats(tlen, &rcd->opstats->stats[opcode]); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci /* verbs_qp can be picked up from any tid_rdma header struct */ 35662306a36Sopenharmony_ci qp_num = be32_to_cpu(packet->ohdr->u.tid_rdma.r_req.verbs_qp) & 35762306a36Sopenharmony_ci RVT_QPN_MASK; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci rcu_read_lock(); 36062306a36Sopenharmony_ci packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num); 36162306a36Sopenharmony_ci if (!packet->qp) 36262306a36Sopenharmony_ci goto drop_rcu; 36362306a36Sopenharmony_ci spin_lock_irqsave(&packet->qp->r_lock, flags); 36462306a36Sopenharmony_ci opcode_handler = tid_qp_ok(opcode, packet); 36562306a36Sopenharmony_ci if (likely(opcode_handler)) 36662306a36Sopenharmony_ci opcode_handler(packet); 36762306a36Sopenharmony_ci else 36862306a36Sopenharmony_ci goto drop_unlock; 36962306a36Sopenharmony_ci spin_unlock_irqrestore(&packet->qp->r_lock, flags); 37062306a36Sopenharmony_ci rcu_read_unlock(); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci return; 37362306a36Sopenharmony_cidrop_unlock: 37462306a36Sopenharmony_ci spin_unlock_irqrestore(&packet->qp->r_lock, flags); 37562306a36Sopenharmony_cidrop_rcu: 37662306a36Sopenharmony_ci rcu_read_unlock(); 37762306a36Sopenharmony_cidrop: 37862306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_civoid hfi1_kdeth_expected_rcv(struct hfi1_packet *packet) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 38462306a36Sopenharmony_ci struct ib_header *hdr = packet->hdr; 38562306a36Sopenharmony_ci u32 tlen = packet->tlen; 38662306a36Sopenharmony_ci struct hfi1_pportdata *ppd = rcd->ppd; 38762306a36Sopenharmony_ci struct hfi1_ibport *ibp = &ppd->ibport_data; 38862306a36Sopenharmony_ci struct rvt_dev_info *rdi = &ppd->dd->verbs_dev.rdi; 38962306a36Sopenharmony_ci opcode_handler opcode_handler; 39062306a36Sopenharmony_ci unsigned long flags; 39162306a36Sopenharmony_ci u32 qp_num; 39262306a36Sopenharmony_ci int lnh; 39362306a36Sopenharmony_ci u8 opcode; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* DW == LRH (2) + BTH (3) + KDETH (9) + CRC (1) */ 39662306a36Sopenharmony_ci if (unlikely(tlen < 15 * sizeof(u32))) 39762306a36Sopenharmony_ci goto drop; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci lnh = be16_to_cpu(hdr->lrh[0]) & 3; 40062306a36Sopenharmony_ci if (lnh != HFI1_LRH_BTH) 40162306a36Sopenharmony_ci goto drop; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci packet->ohdr = &hdr->u.oth; 40462306a36Sopenharmony_ci trace_input_ibhdr(rcd->dd, packet, !!(rhf_dc_info(packet->rhf))); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci opcode = (be32_to_cpu(packet->ohdr->bth[0]) >> 24); 40762306a36Sopenharmony_ci inc_opstats(tlen, &rcd->opstats->stats[opcode]); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* verbs_qp can be picked up from any tid_rdma header struct */ 41062306a36Sopenharmony_ci qp_num = be32_to_cpu(packet->ohdr->u.tid_rdma.r_rsp.verbs_qp) & 41162306a36Sopenharmony_ci RVT_QPN_MASK; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci rcu_read_lock(); 41462306a36Sopenharmony_ci packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num); 41562306a36Sopenharmony_ci if (!packet->qp) 41662306a36Sopenharmony_ci goto drop_rcu; 41762306a36Sopenharmony_ci spin_lock_irqsave(&packet->qp->r_lock, flags); 41862306a36Sopenharmony_ci opcode_handler = tid_qp_ok(opcode, packet); 41962306a36Sopenharmony_ci if (likely(opcode_handler)) 42062306a36Sopenharmony_ci opcode_handler(packet); 42162306a36Sopenharmony_ci else 42262306a36Sopenharmony_ci goto drop_unlock; 42362306a36Sopenharmony_ci spin_unlock_irqrestore(&packet->qp->r_lock, flags); 42462306a36Sopenharmony_ci rcu_read_unlock(); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci return; 42762306a36Sopenharmony_cidrop_unlock: 42862306a36Sopenharmony_ci spin_unlock_irqrestore(&packet->qp->r_lock, flags); 42962306a36Sopenharmony_cidrop_rcu: 43062306a36Sopenharmony_ci rcu_read_unlock(); 43162306a36Sopenharmony_cidrop: 43262306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int hfi1_do_pkey_check(struct hfi1_packet *packet) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 43862306a36Sopenharmony_ci struct hfi1_pportdata *ppd = rcd->ppd; 43962306a36Sopenharmony_ci struct hfi1_16b_header *hdr = packet->hdr; 44062306a36Sopenharmony_ci u16 pkey; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci /* Pkey check needed only for bypass packets */ 44362306a36Sopenharmony_ci if (packet->etype != RHF_RCV_TYPE_BYPASS) 44462306a36Sopenharmony_ci return 0; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci /* Perform pkey check */ 44762306a36Sopenharmony_ci pkey = hfi1_16B_get_pkey(hdr); 44862306a36Sopenharmony_ci return ingress_pkey_check(ppd, pkey, packet->sc, 44962306a36Sopenharmony_ci packet->qp->s_pkey_index, 45062306a36Sopenharmony_ci packet->slid, true); 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic inline void hfi1_handle_packet(struct hfi1_packet *packet, 45462306a36Sopenharmony_ci bool is_mcast) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci u32 qp_num; 45762306a36Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 45862306a36Sopenharmony_ci struct hfi1_pportdata *ppd = rcd->ppd; 45962306a36Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(rcd); 46062306a36Sopenharmony_ci struct rvt_dev_info *rdi = &ppd->dd->verbs_dev.rdi; 46162306a36Sopenharmony_ci opcode_handler packet_handler; 46262306a36Sopenharmony_ci unsigned long flags; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci inc_opstats(packet->tlen, &rcd->opstats->stats[packet->opcode]); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (unlikely(is_mcast)) { 46762306a36Sopenharmony_ci struct rvt_mcast *mcast; 46862306a36Sopenharmony_ci struct rvt_mcast_qp *p; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci if (!packet->grh) 47162306a36Sopenharmony_ci goto drop; 47262306a36Sopenharmony_ci mcast = rvt_mcast_find(&ibp->rvp, 47362306a36Sopenharmony_ci &packet->grh->dgid, 47462306a36Sopenharmony_ci opa_get_lid(packet->dlid, 9B)); 47562306a36Sopenharmony_ci if (!mcast) 47662306a36Sopenharmony_ci goto drop; 47762306a36Sopenharmony_ci rcu_read_lock(); 47862306a36Sopenharmony_ci list_for_each_entry_rcu(p, &mcast->qp_list, list) { 47962306a36Sopenharmony_ci packet->qp = p->qp; 48062306a36Sopenharmony_ci if (hfi1_do_pkey_check(packet)) 48162306a36Sopenharmony_ci goto unlock_drop; 48262306a36Sopenharmony_ci spin_lock_irqsave(&packet->qp->r_lock, flags); 48362306a36Sopenharmony_ci packet_handler = qp_ok(packet); 48462306a36Sopenharmony_ci if (likely(packet_handler)) 48562306a36Sopenharmony_ci packet_handler(packet); 48662306a36Sopenharmony_ci else 48762306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 48862306a36Sopenharmony_ci spin_unlock_irqrestore(&packet->qp->r_lock, flags); 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci rcu_read_unlock(); 49162306a36Sopenharmony_ci /* 49262306a36Sopenharmony_ci * Notify rvt_multicast_detach() if it is waiting for us 49362306a36Sopenharmony_ci * to finish. 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ci if (atomic_dec_return(&mcast->refcount) <= 1) 49662306a36Sopenharmony_ci wake_up(&mcast->wait); 49762306a36Sopenharmony_ci } else { 49862306a36Sopenharmony_ci /* Get the destination QP number. */ 49962306a36Sopenharmony_ci if (packet->etype == RHF_RCV_TYPE_BYPASS && 50062306a36Sopenharmony_ci hfi1_16B_get_l4(packet->hdr) == OPA_16B_L4_FM) 50162306a36Sopenharmony_ci qp_num = hfi1_16B_get_dest_qpn(packet->mgmt); 50262306a36Sopenharmony_ci else 50362306a36Sopenharmony_ci qp_num = ib_bth_get_qpn(packet->ohdr); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci rcu_read_lock(); 50662306a36Sopenharmony_ci packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num); 50762306a36Sopenharmony_ci if (!packet->qp) 50862306a36Sopenharmony_ci goto unlock_drop; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci if (hfi1_do_pkey_check(packet)) 51162306a36Sopenharmony_ci goto unlock_drop; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci spin_lock_irqsave(&packet->qp->r_lock, flags); 51462306a36Sopenharmony_ci packet_handler = qp_ok(packet); 51562306a36Sopenharmony_ci if (likely(packet_handler)) 51662306a36Sopenharmony_ci packet_handler(packet); 51762306a36Sopenharmony_ci else 51862306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 51962306a36Sopenharmony_ci spin_unlock_irqrestore(&packet->qp->r_lock, flags); 52062306a36Sopenharmony_ci rcu_read_unlock(); 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci return; 52362306a36Sopenharmony_ciunlock_drop: 52462306a36Sopenharmony_ci rcu_read_unlock(); 52562306a36Sopenharmony_cidrop: 52662306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci/** 53062306a36Sopenharmony_ci * hfi1_ib_rcv - process an incoming packet 53162306a36Sopenharmony_ci * @packet: data packet information 53262306a36Sopenharmony_ci * 53362306a36Sopenharmony_ci * This is called to process an incoming packet at interrupt level. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_civoid hfi1_ib_rcv(struct hfi1_packet *packet) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci trace_input_ibhdr(rcd->dd, packet, !!(rhf_dc_info(packet->rhf))); 54062306a36Sopenharmony_ci hfi1_handle_packet(packet, hfi1_check_mcast(packet->dlid)); 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_civoid hfi1_16B_rcv(struct hfi1_packet *packet) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci struct hfi1_ctxtdata *rcd = packet->rcd; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci trace_input_ibhdr(rcd->dd, packet, false); 54862306a36Sopenharmony_ci hfi1_handle_packet(packet, hfi1_check_mcast(packet->dlid)); 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci/* 55262306a36Sopenharmony_ci * This is called from a timer to check for QPs 55362306a36Sopenharmony_ci * which need kernel memory in order to send a packet. 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_cistatic void mem_timer(struct timer_list *t) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci struct hfi1_ibdev *dev = from_timer(dev, t, mem_timer); 55862306a36Sopenharmony_ci struct list_head *list = &dev->memwait; 55962306a36Sopenharmony_ci struct rvt_qp *qp = NULL; 56062306a36Sopenharmony_ci struct iowait *wait; 56162306a36Sopenharmony_ci unsigned long flags; 56262306a36Sopenharmony_ci struct hfi1_qp_priv *priv; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci write_seqlock_irqsave(&dev->iowait_lock, flags); 56562306a36Sopenharmony_ci if (!list_empty(list)) { 56662306a36Sopenharmony_ci wait = list_first_entry(list, struct iowait, list); 56762306a36Sopenharmony_ci qp = iowait_to_qp(wait); 56862306a36Sopenharmony_ci priv = qp->priv; 56962306a36Sopenharmony_ci list_del_init(&priv->s_iowait.list); 57062306a36Sopenharmony_ci priv->s_iowait.lock = NULL; 57162306a36Sopenharmony_ci /* refcount held until actual wake up */ 57262306a36Sopenharmony_ci if (!list_empty(list)) 57362306a36Sopenharmony_ci mod_timer(&dev->mem_timer, jiffies + 1); 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci write_sequnlock_irqrestore(&dev->iowait_lock, flags); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci if (qp) 57862306a36Sopenharmony_ci hfi1_qp_wakeup(qp, RVT_S_WAIT_KMEM); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci/* 58262306a36Sopenharmony_ci * This is called with progress side lock held. 58362306a36Sopenharmony_ci */ 58462306a36Sopenharmony_ci/* New API */ 58562306a36Sopenharmony_cistatic void verbs_sdma_complete( 58662306a36Sopenharmony_ci struct sdma_txreq *cookie, 58762306a36Sopenharmony_ci int status) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci struct verbs_txreq *tx = 59062306a36Sopenharmony_ci container_of(cookie, struct verbs_txreq, txreq); 59162306a36Sopenharmony_ci struct rvt_qp *qp = tx->qp; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci spin_lock(&qp->s_lock); 59462306a36Sopenharmony_ci if (tx->wqe) { 59562306a36Sopenharmony_ci rvt_send_complete(qp, tx->wqe, IB_WC_SUCCESS); 59662306a36Sopenharmony_ci } else if (qp->ibqp.qp_type == IB_QPT_RC) { 59762306a36Sopenharmony_ci struct hfi1_opa_header *hdr; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci hdr = &tx->phdr.hdr; 60062306a36Sopenharmony_ci if (unlikely(status == SDMA_TXREQ_S_ABORTED)) 60162306a36Sopenharmony_ci hfi1_rc_verbs_aborted(qp, hdr); 60262306a36Sopenharmony_ci hfi1_rc_send_complete(qp, hdr); 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci spin_unlock(&qp->s_lock); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci hfi1_put_txreq(tx); 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_civoid hfi1_wait_kmem(struct rvt_qp *qp) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 61262306a36Sopenharmony_ci struct ib_qp *ibqp = &qp->ibqp; 61362306a36Sopenharmony_ci struct ib_device *ibdev = ibqp->device; 61462306a36Sopenharmony_ci struct hfi1_ibdev *dev = to_idev(ibdev); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (list_empty(&priv->s_iowait.list)) { 61762306a36Sopenharmony_ci if (list_empty(&dev->memwait)) 61862306a36Sopenharmony_ci mod_timer(&dev->mem_timer, jiffies + 1); 61962306a36Sopenharmony_ci qp->s_flags |= RVT_S_WAIT_KMEM; 62062306a36Sopenharmony_ci list_add_tail(&priv->s_iowait.list, &dev->memwait); 62162306a36Sopenharmony_ci priv->s_iowait.lock = &dev->iowait_lock; 62262306a36Sopenharmony_ci trace_hfi1_qpsleep(qp, RVT_S_WAIT_KMEM); 62362306a36Sopenharmony_ci rvt_get_qp(qp); 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_cistatic int wait_kmem(struct hfi1_ibdev *dev, 62862306a36Sopenharmony_ci struct rvt_qp *qp, 62962306a36Sopenharmony_ci struct hfi1_pkt_state *ps) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci unsigned long flags; 63262306a36Sopenharmony_ci int ret = 0; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 63562306a36Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 63662306a36Sopenharmony_ci write_seqlock(&dev->iowait_lock); 63762306a36Sopenharmony_ci list_add_tail(&ps->s_txreq->txreq.list, 63862306a36Sopenharmony_ci &ps->wait->tx_head); 63962306a36Sopenharmony_ci hfi1_wait_kmem(qp); 64062306a36Sopenharmony_ci write_sequnlock(&dev->iowait_lock); 64162306a36Sopenharmony_ci hfi1_qp_unbusy(qp, ps->wait); 64262306a36Sopenharmony_ci ret = -EBUSY; 64362306a36Sopenharmony_ci } 64462306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci return ret; 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci/* 65062306a36Sopenharmony_ci * This routine calls txadds for each sg entry. 65162306a36Sopenharmony_ci * 65262306a36Sopenharmony_ci * Add failures will revert the sge cursor 65362306a36Sopenharmony_ci */ 65462306a36Sopenharmony_cistatic noinline int build_verbs_ulp_payload( 65562306a36Sopenharmony_ci struct sdma_engine *sde, 65662306a36Sopenharmony_ci u32 length, 65762306a36Sopenharmony_ci struct verbs_txreq *tx) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci struct rvt_sge_state *ss = tx->ss; 66062306a36Sopenharmony_ci struct rvt_sge *sg_list = ss->sg_list; 66162306a36Sopenharmony_ci struct rvt_sge sge = ss->sge; 66262306a36Sopenharmony_ci u8 num_sge = ss->num_sge; 66362306a36Sopenharmony_ci u32 len; 66462306a36Sopenharmony_ci int ret = 0; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci while (length) { 66762306a36Sopenharmony_ci len = rvt_get_sge_length(&ss->sge, length); 66862306a36Sopenharmony_ci WARN_ON_ONCE(len == 0); 66962306a36Sopenharmony_ci ret = sdma_txadd_kvaddr( 67062306a36Sopenharmony_ci sde->dd, 67162306a36Sopenharmony_ci &tx->txreq, 67262306a36Sopenharmony_ci ss->sge.vaddr, 67362306a36Sopenharmony_ci len); 67462306a36Sopenharmony_ci if (ret) 67562306a36Sopenharmony_ci goto bail_txadd; 67662306a36Sopenharmony_ci rvt_update_sge(ss, len, false); 67762306a36Sopenharmony_ci length -= len; 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci return ret; 68062306a36Sopenharmony_cibail_txadd: 68162306a36Sopenharmony_ci /* unwind cursor */ 68262306a36Sopenharmony_ci ss->sge = sge; 68362306a36Sopenharmony_ci ss->num_sge = num_sge; 68462306a36Sopenharmony_ci ss->sg_list = sg_list; 68562306a36Sopenharmony_ci return ret; 68662306a36Sopenharmony_ci} 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci/** 68962306a36Sopenharmony_ci * update_tx_opstats - record stats by opcode 69062306a36Sopenharmony_ci * @qp: the qp 69162306a36Sopenharmony_ci * @ps: transmit packet state 69262306a36Sopenharmony_ci * @plen: the plen in dwords 69362306a36Sopenharmony_ci * 69462306a36Sopenharmony_ci * This is a routine to record the tx opstats after a 69562306a36Sopenharmony_ci * packet has been presented to the egress mechanism. 69662306a36Sopenharmony_ci */ 69762306a36Sopenharmony_cistatic void update_tx_opstats(struct rvt_qp *qp, struct hfi1_pkt_state *ps, 69862306a36Sopenharmony_ci u32 plen) 69962306a36Sopenharmony_ci{ 70062306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 70162306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 70262306a36Sopenharmony_ci struct hfi1_opcode_stats_perctx *s = get_cpu_ptr(dd->tx_opstats); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci inc_opstats(plen * 4, &s->stats[ps->opcode]); 70562306a36Sopenharmony_ci put_cpu_ptr(s); 70662306a36Sopenharmony_ci#endif 70762306a36Sopenharmony_ci} 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci/* 71062306a36Sopenharmony_ci * Build the number of DMA descriptors needed to send length bytes of data. 71162306a36Sopenharmony_ci * 71262306a36Sopenharmony_ci * NOTE: DMA mapping is held in the tx until completed in the ring or 71362306a36Sopenharmony_ci * the tx desc is freed without having been submitted to the ring 71462306a36Sopenharmony_ci * 71562306a36Sopenharmony_ci * This routine ensures all the helper routine calls succeed. 71662306a36Sopenharmony_ci */ 71762306a36Sopenharmony_ci/* New API */ 71862306a36Sopenharmony_cistatic int build_verbs_tx_desc( 71962306a36Sopenharmony_ci struct sdma_engine *sde, 72062306a36Sopenharmony_ci u32 length, 72162306a36Sopenharmony_ci struct verbs_txreq *tx, 72262306a36Sopenharmony_ci struct hfi1_ahg_info *ahg_info, 72362306a36Sopenharmony_ci u64 pbc) 72462306a36Sopenharmony_ci{ 72562306a36Sopenharmony_ci int ret = 0; 72662306a36Sopenharmony_ci struct hfi1_sdma_header *phdr = &tx->phdr; 72762306a36Sopenharmony_ci u16 hdrbytes = (tx->hdr_dwords + sizeof(pbc) / 4) << 2; 72862306a36Sopenharmony_ci u8 extra_bytes = 0; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (tx->phdr.hdr.hdr_type) { 73162306a36Sopenharmony_ci /* 73262306a36Sopenharmony_ci * hdrbytes accounts for PBC. Need to subtract 8 bytes 73362306a36Sopenharmony_ci * before calculating padding. 73462306a36Sopenharmony_ci */ 73562306a36Sopenharmony_ci extra_bytes = hfi1_get_16b_padding(hdrbytes - 8, length) + 73662306a36Sopenharmony_ci (SIZE_OF_CRC << 2) + SIZE_OF_LT; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci if (!ahg_info->ahgcount) { 73962306a36Sopenharmony_ci ret = sdma_txinit_ahg( 74062306a36Sopenharmony_ci &tx->txreq, 74162306a36Sopenharmony_ci ahg_info->tx_flags, 74262306a36Sopenharmony_ci hdrbytes + length + 74362306a36Sopenharmony_ci extra_bytes, 74462306a36Sopenharmony_ci ahg_info->ahgidx, 74562306a36Sopenharmony_ci 0, 74662306a36Sopenharmony_ci NULL, 74762306a36Sopenharmony_ci 0, 74862306a36Sopenharmony_ci verbs_sdma_complete); 74962306a36Sopenharmony_ci if (ret) 75062306a36Sopenharmony_ci goto bail_txadd; 75162306a36Sopenharmony_ci phdr->pbc = cpu_to_le64(pbc); 75262306a36Sopenharmony_ci ret = sdma_txadd_kvaddr( 75362306a36Sopenharmony_ci sde->dd, 75462306a36Sopenharmony_ci &tx->txreq, 75562306a36Sopenharmony_ci phdr, 75662306a36Sopenharmony_ci hdrbytes); 75762306a36Sopenharmony_ci if (ret) 75862306a36Sopenharmony_ci goto bail_txadd; 75962306a36Sopenharmony_ci } else { 76062306a36Sopenharmony_ci ret = sdma_txinit_ahg( 76162306a36Sopenharmony_ci &tx->txreq, 76262306a36Sopenharmony_ci ahg_info->tx_flags, 76362306a36Sopenharmony_ci length, 76462306a36Sopenharmony_ci ahg_info->ahgidx, 76562306a36Sopenharmony_ci ahg_info->ahgcount, 76662306a36Sopenharmony_ci ahg_info->ahgdesc, 76762306a36Sopenharmony_ci hdrbytes, 76862306a36Sopenharmony_ci verbs_sdma_complete); 76962306a36Sopenharmony_ci if (ret) 77062306a36Sopenharmony_ci goto bail_txadd; 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci /* add the ulp payload - if any. tx->ss can be NULL for acks */ 77362306a36Sopenharmony_ci if (tx->ss) { 77462306a36Sopenharmony_ci ret = build_verbs_ulp_payload(sde, length, tx); 77562306a36Sopenharmony_ci if (ret) 77662306a36Sopenharmony_ci goto bail_txadd; 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* add icrc, lt byte, and padding to flit */ 78062306a36Sopenharmony_ci if (extra_bytes) 78162306a36Sopenharmony_ci ret = sdma_txadd_daddr(sde->dd, &tx->txreq, sde->dd->sdma_pad_phys, 78262306a36Sopenharmony_ci extra_bytes); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cibail_txadd: 78562306a36Sopenharmony_ci return ret; 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cistatic u64 update_hcrc(u8 opcode, u64 pbc) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci if ((opcode & IB_OPCODE_TID_RDMA) == IB_OPCODE_TID_RDMA) { 79162306a36Sopenharmony_ci pbc &= ~PBC_INSERT_HCRC_SMASK; 79262306a36Sopenharmony_ci pbc |= (u64)PBC_IHCRC_LKDETH << PBC_INSERT_HCRC_SHIFT; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci return pbc; 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ciint hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps, 79862306a36Sopenharmony_ci u64 pbc) 79962306a36Sopenharmony_ci{ 80062306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 80162306a36Sopenharmony_ci struct hfi1_ahg_info *ahg_info = priv->s_ahg; 80262306a36Sopenharmony_ci u32 hdrwords = ps->s_txreq->hdr_dwords; 80362306a36Sopenharmony_ci u32 len = ps->s_txreq->s_cur_size; 80462306a36Sopenharmony_ci u32 plen; 80562306a36Sopenharmony_ci struct hfi1_ibdev *dev = ps->dev; 80662306a36Sopenharmony_ci struct hfi1_pportdata *ppd = ps->ppd; 80762306a36Sopenharmony_ci struct verbs_txreq *tx; 80862306a36Sopenharmony_ci u8 sc5 = priv->s_sc; 80962306a36Sopenharmony_ci int ret; 81062306a36Sopenharmony_ci u32 dwords; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci if (ps->s_txreq->phdr.hdr.hdr_type) { 81362306a36Sopenharmony_ci u8 extra_bytes = hfi1_get_16b_padding((hdrwords << 2), len); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci dwords = (len + extra_bytes + (SIZE_OF_CRC << 2) + 81662306a36Sopenharmony_ci SIZE_OF_LT) >> 2; 81762306a36Sopenharmony_ci } else { 81862306a36Sopenharmony_ci dwords = (len + 3) >> 2; 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci plen = hdrwords + dwords + sizeof(pbc) / 4; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci tx = ps->s_txreq; 82362306a36Sopenharmony_ci if (!sdma_txreq_built(&tx->txreq)) { 82462306a36Sopenharmony_ci if (likely(pbc == 0)) { 82562306a36Sopenharmony_ci u32 vl = sc_to_vlt(dd_from_ibdev(qp->ibqp.device), sc5); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci /* No vl15 here */ 82862306a36Sopenharmony_ci /* set PBC_DC_INFO bit (aka SC[4]) in pbc */ 82962306a36Sopenharmony_ci if (ps->s_txreq->phdr.hdr.hdr_type) 83062306a36Sopenharmony_ci pbc |= PBC_PACKET_BYPASS | 83162306a36Sopenharmony_ci PBC_INSERT_BYPASS_ICRC; 83262306a36Sopenharmony_ci else 83362306a36Sopenharmony_ci pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci pbc = create_pbc(ppd, 83662306a36Sopenharmony_ci pbc, 83762306a36Sopenharmony_ci qp->srate_mbps, 83862306a36Sopenharmony_ci vl, 83962306a36Sopenharmony_ci plen); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (unlikely(hfi1_dbg_should_fault_tx(qp, ps->opcode))) 84262306a36Sopenharmony_ci pbc = hfi1_fault_tx(qp, ps->opcode, pbc); 84362306a36Sopenharmony_ci else 84462306a36Sopenharmony_ci /* Update HCRC based on packet opcode */ 84562306a36Sopenharmony_ci pbc = update_hcrc(ps->opcode, pbc); 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci tx->wqe = qp->s_wqe; 84862306a36Sopenharmony_ci ret = build_verbs_tx_desc(tx->sde, len, tx, ahg_info, pbc); 84962306a36Sopenharmony_ci if (unlikely(ret)) 85062306a36Sopenharmony_ci goto bail_build; 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci ret = sdma_send_txreq(tx->sde, ps->wait, &tx->txreq, ps->pkts_sent); 85362306a36Sopenharmony_ci if (unlikely(ret < 0)) { 85462306a36Sopenharmony_ci if (ret == -ECOMM) 85562306a36Sopenharmony_ci goto bail_ecomm; 85662306a36Sopenharmony_ci return ret; 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci update_tx_opstats(qp, ps, plen); 86062306a36Sopenharmony_ci trace_sdma_output_ibhdr(dd_from_ibdev(qp->ibqp.device), 86162306a36Sopenharmony_ci &ps->s_txreq->phdr.hdr, ib_is_sc5(sc5)); 86262306a36Sopenharmony_ci return ret; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cibail_ecomm: 86562306a36Sopenharmony_ci /* The current one got "sent" */ 86662306a36Sopenharmony_ci return 0; 86762306a36Sopenharmony_cibail_build: 86862306a36Sopenharmony_ci ret = wait_kmem(dev, qp, ps); 86962306a36Sopenharmony_ci if (!ret) { 87062306a36Sopenharmony_ci /* free txreq - bad state */ 87162306a36Sopenharmony_ci hfi1_put_txreq(ps->s_txreq); 87262306a36Sopenharmony_ci ps->s_txreq = NULL; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci return ret; 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci/* 87862306a36Sopenharmony_ci * If we are now in the error state, return zero to flush the 87962306a36Sopenharmony_ci * send work request. 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_cistatic int pio_wait(struct rvt_qp *qp, 88262306a36Sopenharmony_ci struct send_context *sc, 88362306a36Sopenharmony_ci struct hfi1_pkt_state *ps, 88462306a36Sopenharmony_ci u32 flag) 88562306a36Sopenharmony_ci{ 88662306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 88762306a36Sopenharmony_ci struct hfi1_devdata *dd = sc->dd; 88862306a36Sopenharmony_ci unsigned long flags; 88962306a36Sopenharmony_ci int ret = 0; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci /* 89262306a36Sopenharmony_ci * Note that as soon as want_buffer() is called and 89362306a36Sopenharmony_ci * possibly before it returns, sc_piobufavail() 89462306a36Sopenharmony_ci * could be called. Therefore, put QP on the I/O wait list before 89562306a36Sopenharmony_ci * enabling the PIO avail interrupt. 89662306a36Sopenharmony_ci */ 89762306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 89862306a36Sopenharmony_ci if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { 89962306a36Sopenharmony_ci write_seqlock(&sc->waitlock); 90062306a36Sopenharmony_ci list_add_tail(&ps->s_txreq->txreq.list, 90162306a36Sopenharmony_ci &ps->wait->tx_head); 90262306a36Sopenharmony_ci if (list_empty(&priv->s_iowait.list)) { 90362306a36Sopenharmony_ci struct hfi1_ibdev *dev = &dd->verbs_dev; 90462306a36Sopenharmony_ci int was_empty; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci dev->n_piowait += !!(flag & RVT_S_WAIT_PIO); 90762306a36Sopenharmony_ci dev->n_piodrain += !!(flag & HFI1_S_WAIT_PIO_DRAIN); 90862306a36Sopenharmony_ci qp->s_flags |= flag; 90962306a36Sopenharmony_ci was_empty = list_empty(&sc->piowait); 91062306a36Sopenharmony_ci iowait_get_priority(&priv->s_iowait); 91162306a36Sopenharmony_ci iowait_queue(ps->pkts_sent, &priv->s_iowait, 91262306a36Sopenharmony_ci &sc->piowait); 91362306a36Sopenharmony_ci priv->s_iowait.lock = &sc->waitlock; 91462306a36Sopenharmony_ci trace_hfi1_qpsleep(qp, RVT_S_WAIT_PIO); 91562306a36Sopenharmony_ci rvt_get_qp(qp); 91662306a36Sopenharmony_ci /* counting: only call wantpiobuf_intr if first user */ 91762306a36Sopenharmony_ci if (was_empty) 91862306a36Sopenharmony_ci hfi1_sc_wantpiobuf_intr(sc, 1); 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci write_sequnlock(&sc->waitlock); 92162306a36Sopenharmony_ci hfi1_qp_unbusy(qp, ps->wait); 92262306a36Sopenharmony_ci ret = -EBUSY; 92362306a36Sopenharmony_ci } 92462306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 92562306a36Sopenharmony_ci return ret; 92662306a36Sopenharmony_ci} 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic void verbs_pio_complete(void *arg, int code) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci struct rvt_qp *qp = (struct rvt_qp *)arg; 93162306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci if (iowait_pio_dec(&priv->s_iowait)) 93462306a36Sopenharmony_ci iowait_drain_wakeup(&priv->s_iowait); 93562306a36Sopenharmony_ci} 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ciint hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps, 93862306a36Sopenharmony_ci u64 pbc) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 94162306a36Sopenharmony_ci u32 hdrwords = ps->s_txreq->hdr_dwords; 94262306a36Sopenharmony_ci struct rvt_sge_state *ss = ps->s_txreq->ss; 94362306a36Sopenharmony_ci u32 len = ps->s_txreq->s_cur_size; 94462306a36Sopenharmony_ci u32 dwords; 94562306a36Sopenharmony_ci u32 plen; 94662306a36Sopenharmony_ci struct hfi1_pportdata *ppd = ps->ppd; 94762306a36Sopenharmony_ci u32 *hdr; 94862306a36Sopenharmony_ci u8 sc5; 94962306a36Sopenharmony_ci unsigned long flags = 0; 95062306a36Sopenharmony_ci struct send_context *sc; 95162306a36Sopenharmony_ci struct pio_buf *pbuf; 95262306a36Sopenharmony_ci int wc_status = IB_WC_SUCCESS; 95362306a36Sopenharmony_ci int ret = 0; 95462306a36Sopenharmony_ci pio_release_cb cb = NULL; 95562306a36Sopenharmony_ci u8 extra_bytes = 0; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci if (ps->s_txreq->phdr.hdr.hdr_type) { 95862306a36Sopenharmony_ci u8 pad_size = hfi1_get_16b_padding((hdrwords << 2), len); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci extra_bytes = pad_size + (SIZE_OF_CRC << 2) + SIZE_OF_LT; 96162306a36Sopenharmony_ci dwords = (len + extra_bytes) >> 2; 96262306a36Sopenharmony_ci hdr = (u32 *)&ps->s_txreq->phdr.hdr.opah; 96362306a36Sopenharmony_ci } else { 96462306a36Sopenharmony_ci dwords = (len + 3) >> 2; 96562306a36Sopenharmony_ci hdr = (u32 *)&ps->s_txreq->phdr.hdr.ibh; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci plen = hdrwords + dwords + sizeof(pbc) / 4; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* only RC/UC use complete */ 97062306a36Sopenharmony_ci switch (qp->ibqp.qp_type) { 97162306a36Sopenharmony_ci case IB_QPT_RC: 97262306a36Sopenharmony_ci case IB_QPT_UC: 97362306a36Sopenharmony_ci cb = verbs_pio_complete; 97462306a36Sopenharmony_ci break; 97562306a36Sopenharmony_ci default: 97662306a36Sopenharmony_ci break; 97762306a36Sopenharmony_ci } 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* vl15 special case taken care of in ud.c */ 98062306a36Sopenharmony_ci sc5 = priv->s_sc; 98162306a36Sopenharmony_ci sc = ps->s_txreq->psc; 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci if (likely(pbc == 0)) { 98462306a36Sopenharmony_ci u8 vl = sc_to_vlt(dd_from_ibdev(qp->ibqp.device), sc5); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci /* set PBC_DC_INFO bit (aka SC[4]) in pbc */ 98762306a36Sopenharmony_ci if (ps->s_txreq->phdr.hdr.hdr_type) 98862306a36Sopenharmony_ci pbc |= PBC_PACKET_BYPASS | PBC_INSERT_BYPASS_ICRC; 98962306a36Sopenharmony_ci else 99062306a36Sopenharmony_ci pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci pbc = create_pbc(ppd, pbc, qp->srate_mbps, vl, plen); 99362306a36Sopenharmony_ci if (unlikely(hfi1_dbg_should_fault_tx(qp, ps->opcode))) 99462306a36Sopenharmony_ci pbc = hfi1_fault_tx(qp, ps->opcode, pbc); 99562306a36Sopenharmony_ci else 99662306a36Sopenharmony_ci /* Update HCRC based on packet opcode */ 99762306a36Sopenharmony_ci pbc = update_hcrc(ps->opcode, pbc); 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci if (cb) 100062306a36Sopenharmony_ci iowait_pio_inc(&priv->s_iowait); 100162306a36Sopenharmony_ci pbuf = sc_buffer_alloc(sc, plen, cb, qp); 100262306a36Sopenharmony_ci if (IS_ERR_OR_NULL(pbuf)) { 100362306a36Sopenharmony_ci if (cb) 100462306a36Sopenharmony_ci verbs_pio_complete(qp, 0); 100562306a36Sopenharmony_ci if (IS_ERR(pbuf)) { 100662306a36Sopenharmony_ci /* 100762306a36Sopenharmony_ci * If we have filled the PIO buffers to capacity and are 100862306a36Sopenharmony_ci * not in an active state this request is not going to 100962306a36Sopenharmony_ci * go out to so just complete it with an error or else a 101062306a36Sopenharmony_ci * ULP or the core may be stuck waiting. 101162306a36Sopenharmony_ci */ 101262306a36Sopenharmony_ci hfi1_cdbg( 101362306a36Sopenharmony_ci PIO, 101462306a36Sopenharmony_ci "alloc failed. state not active, completing"); 101562306a36Sopenharmony_ci wc_status = IB_WC_GENERAL_ERR; 101662306a36Sopenharmony_ci goto pio_bail; 101762306a36Sopenharmony_ci } else { 101862306a36Sopenharmony_ci /* 101962306a36Sopenharmony_ci * This is a normal occurrence. The PIO buffs are full 102062306a36Sopenharmony_ci * up but we are still happily sending, well we could be 102162306a36Sopenharmony_ci * so lets continue to queue the request. 102262306a36Sopenharmony_ci */ 102362306a36Sopenharmony_ci hfi1_cdbg(PIO, "alloc failed. state active, queuing"); 102462306a36Sopenharmony_ci ret = pio_wait(qp, sc, ps, RVT_S_WAIT_PIO); 102562306a36Sopenharmony_ci if (!ret) 102662306a36Sopenharmony_ci /* txreq not queued - free */ 102762306a36Sopenharmony_ci goto bail; 102862306a36Sopenharmony_ci /* tx consumed in wait */ 102962306a36Sopenharmony_ci return ret; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci } 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci if (dwords == 0) { 103462306a36Sopenharmony_ci pio_copy(ppd->dd, pbuf, pbc, hdr, hdrwords); 103562306a36Sopenharmony_ci } else { 103662306a36Sopenharmony_ci seg_pio_copy_start(pbuf, pbc, 103762306a36Sopenharmony_ci hdr, hdrwords * 4); 103862306a36Sopenharmony_ci if (ss) { 103962306a36Sopenharmony_ci while (len) { 104062306a36Sopenharmony_ci void *addr = ss->sge.vaddr; 104162306a36Sopenharmony_ci u32 slen = rvt_get_sge_length(&ss->sge, len); 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci rvt_update_sge(ss, slen, false); 104462306a36Sopenharmony_ci seg_pio_copy_mid(pbuf, addr, slen); 104562306a36Sopenharmony_ci len -= slen; 104662306a36Sopenharmony_ci } 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci /* add icrc, lt byte, and padding to flit */ 104962306a36Sopenharmony_ci if (extra_bytes) 105062306a36Sopenharmony_ci seg_pio_copy_mid(pbuf, ppd->dd->sdma_pad_dma, 105162306a36Sopenharmony_ci extra_bytes); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci seg_pio_copy_end(pbuf); 105462306a36Sopenharmony_ci } 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci update_tx_opstats(qp, ps, plen); 105762306a36Sopenharmony_ci trace_pio_output_ibhdr(dd_from_ibdev(qp->ibqp.device), 105862306a36Sopenharmony_ci &ps->s_txreq->phdr.hdr, ib_is_sc5(sc5)); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_cipio_bail: 106162306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 106262306a36Sopenharmony_ci if (qp->s_wqe) { 106362306a36Sopenharmony_ci rvt_send_complete(qp, qp->s_wqe, wc_status); 106462306a36Sopenharmony_ci } else if (qp->ibqp.qp_type == IB_QPT_RC) { 106562306a36Sopenharmony_ci if (unlikely(wc_status == IB_WC_GENERAL_ERR)) 106662306a36Sopenharmony_ci hfi1_rc_verbs_aborted(qp, &ps->s_txreq->phdr.hdr); 106762306a36Sopenharmony_ci hfi1_rc_send_complete(qp, &ps->s_txreq->phdr.hdr); 106862306a36Sopenharmony_ci } 106962306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci ret = 0; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_cibail: 107462306a36Sopenharmony_ci hfi1_put_txreq(ps->s_txreq); 107562306a36Sopenharmony_ci return ret; 107662306a36Sopenharmony_ci} 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci/* 107962306a36Sopenharmony_ci * egress_pkey_matches_entry - return 1 if the pkey matches ent (ent 108062306a36Sopenharmony_ci * being an entry from the partition key table), return 0 108162306a36Sopenharmony_ci * otherwise. Use the matching criteria for egress partition keys 108262306a36Sopenharmony_ci * specified in the OPAv1 spec., section 9.1l.7. 108362306a36Sopenharmony_ci */ 108462306a36Sopenharmony_cistatic inline int egress_pkey_matches_entry(u16 pkey, u16 ent) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci u16 mkey = pkey & PKEY_LOW_15_MASK; 108762306a36Sopenharmony_ci u16 mentry = ent & PKEY_LOW_15_MASK; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci if (mkey == mentry) { 109062306a36Sopenharmony_ci /* 109162306a36Sopenharmony_ci * If pkey[15] is set (full partition member), 109262306a36Sopenharmony_ci * is bit 15 in the corresponding table element 109362306a36Sopenharmony_ci * clear (limited member)? 109462306a36Sopenharmony_ci */ 109562306a36Sopenharmony_ci if (pkey & PKEY_MEMBER_MASK) 109662306a36Sopenharmony_ci return !!(ent & PKEY_MEMBER_MASK); 109762306a36Sopenharmony_ci return 1; 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci return 0; 110062306a36Sopenharmony_ci} 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci/** 110362306a36Sopenharmony_ci * egress_pkey_check - check P_KEY of a packet 110462306a36Sopenharmony_ci * @ppd: Physical IB port data 110562306a36Sopenharmony_ci * @slid: SLID for packet 110662306a36Sopenharmony_ci * @pkey: PKEY for header 110762306a36Sopenharmony_ci * @sc5: SC for packet 110862306a36Sopenharmony_ci * @s_pkey_index: It will be used for look up optimization for kernel contexts 110962306a36Sopenharmony_ci * only. If it is negative value, then it means user contexts is calling this 111062306a36Sopenharmony_ci * function. 111162306a36Sopenharmony_ci * 111262306a36Sopenharmony_ci * It checks if hdr's pkey is valid. 111362306a36Sopenharmony_ci * 111462306a36Sopenharmony_ci * Return: 0 on success, otherwise, 1 111562306a36Sopenharmony_ci */ 111662306a36Sopenharmony_ciint egress_pkey_check(struct hfi1_pportdata *ppd, u32 slid, u16 pkey, 111762306a36Sopenharmony_ci u8 sc5, int8_t s_pkey_index) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci struct hfi1_devdata *dd; 112062306a36Sopenharmony_ci int i; 112162306a36Sopenharmony_ci int is_user_ctxt_mechanism = (s_pkey_index < 0); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci if (!(ppd->part_enforce & HFI1_PART_ENFORCE_OUT)) 112462306a36Sopenharmony_ci return 0; 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci /* If SC15, pkey[0:14] must be 0x7fff */ 112762306a36Sopenharmony_ci if ((sc5 == 0xf) && ((pkey & PKEY_LOW_15_MASK) != PKEY_LOW_15_MASK)) 112862306a36Sopenharmony_ci goto bad; 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci /* Is the pkey = 0x0, or 0x8000? */ 113162306a36Sopenharmony_ci if ((pkey & PKEY_LOW_15_MASK) == 0) 113262306a36Sopenharmony_ci goto bad; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci /* 113562306a36Sopenharmony_ci * For the kernel contexts only, if a qp is passed into the function, 113662306a36Sopenharmony_ci * the most likely matching pkey has index qp->s_pkey_index 113762306a36Sopenharmony_ci */ 113862306a36Sopenharmony_ci if (!is_user_ctxt_mechanism && 113962306a36Sopenharmony_ci egress_pkey_matches_entry(pkey, ppd->pkeys[s_pkey_index])) { 114062306a36Sopenharmony_ci return 0; 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci for (i = 0; i < MAX_PKEY_VALUES; i++) { 114462306a36Sopenharmony_ci if (egress_pkey_matches_entry(pkey, ppd->pkeys[i])) 114562306a36Sopenharmony_ci return 0; 114662306a36Sopenharmony_ci } 114762306a36Sopenharmony_cibad: 114862306a36Sopenharmony_ci /* 114962306a36Sopenharmony_ci * For the user-context mechanism, the P_KEY check would only happen 115062306a36Sopenharmony_ci * once per SDMA request, not once per packet. Therefore, there's no 115162306a36Sopenharmony_ci * need to increment the counter for the user-context mechanism. 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_ci if (!is_user_ctxt_mechanism) { 115462306a36Sopenharmony_ci incr_cntr64(&ppd->port_xmit_constraint_errors); 115562306a36Sopenharmony_ci dd = ppd->dd; 115662306a36Sopenharmony_ci if (!(dd->err_info_xmit_constraint.status & 115762306a36Sopenharmony_ci OPA_EI_STATUS_SMASK)) { 115862306a36Sopenharmony_ci dd->err_info_xmit_constraint.status |= 115962306a36Sopenharmony_ci OPA_EI_STATUS_SMASK; 116062306a36Sopenharmony_ci dd->err_info_xmit_constraint.slid = slid; 116162306a36Sopenharmony_ci dd->err_info_xmit_constraint.pkey = pkey; 116262306a36Sopenharmony_ci } 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci return 1; 116562306a36Sopenharmony_ci} 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci/* 116862306a36Sopenharmony_ci * get_send_routine - choose an egress routine 116962306a36Sopenharmony_ci * 117062306a36Sopenharmony_ci * Choose an egress routine based on QP type 117162306a36Sopenharmony_ci * and size 117262306a36Sopenharmony_ci */ 117362306a36Sopenharmony_cistatic inline send_routine get_send_routine(struct rvt_qp *qp, 117462306a36Sopenharmony_ci struct hfi1_pkt_state *ps) 117562306a36Sopenharmony_ci{ 117662306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 117762306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 117862306a36Sopenharmony_ci struct verbs_txreq *tx = ps->s_txreq; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (unlikely(!(dd->flags & HFI1_HAS_SEND_DMA))) 118162306a36Sopenharmony_ci return dd->process_pio_send; 118262306a36Sopenharmony_ci switch (qp->ibqp.qp_type) { 118362306a36Sopenharmony_ci case IB_QPT_SMI: 118462306a36Sopenharmony_ci return dd->process_pio_send; 118562306a36Sopenharmony_ci case IB_QPT_GSI: 118662306a36Sopenharmony_ci case IB_QPT_UD: 118762306a36Sopenharmony_ci break; 118862306a36Sopenharmony_ci case IB_QPT_UC: 118962306a36Sopenharmony_ci case IB_QPT_RC: 119062306a36Sopenharmony_ci priv->s_running_pkt_size = 119162306a36Sopenharmony_ci (tx->s_cur_size + priv->s_running_pkt_size) / 2; 119262306a36Sopenharmony_ci if (piothreshold && 119362306a36Sopenharmony_ci priv->s_running_pkt_size <= min(piothreshold, qp->pmtu) && 119462306a36Sopenharmony_ci (BIT(ps->opcode & OPMASK) & pio_opmask[ps->opcode >> 5]) && 119562306a36Sopenharmony_ci iowait_sdma_pending(&priv->s_iowait) == 0 && 119662306a36Sopenharmony_ci !sdma_txreq_built(&tx->txreq)) 119762306a36Sopenharmony_ci return dd->process_pio_send; 119862306a36Sopenharmony_ci break; 119962306a36Sopenharmony_ci default: 120062306a36Sopenharmony_ci break; 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci return dd->process_dma_send; 120362306a36Sopenharmony_ci} 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci/** 120662306a36Sopenharmony_ci * hfi1_verbs_send - send a packet 120762306a36Sopenharmony_ci * @qp: the QP to send on 120862306a36Sopenharmony_ci * @ps: the state of the packet to send 120962306a36Sopenharmony_ci * 121062306a36Sopenharmony_ci * Return zero if packet is sent or queued OK. 121162306a36Sopenharmony_ci * Return non-zero and clear qp->s_flags RVT_S_BUSY otherwise. 121262306a36Sopenharmony_ci */ 121362306a36Sopenharmony_ciint hfi1_verbs_send(struct rvt_qp *qp, struct hfi1_pkt_state *ps) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device); 121662306a36Sopenharmony_ci struct hfi1_qp_priv *priv = qp->priv; 121762306a36Sopenharmony_ci struct ib_other_headers *ohdr = NULL; 121862306a36Sopenharmony_ci send_routine sr; 121962306a36Sopenharmony_ci int ret; 122062306a36Sopenharmony_ci u16 pkey; 122162306a36Sopenharmony_ci u32 slid; 122262306a36Sopenharmony_ci u8 l4 = 0; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci /* locate the pkey within the headers */ 122562306a36Sopenharmony_ci if (ps->s_txreq->phdr.hdr.hdr_type) { 122662306a36Sopenharmony_ci struct hfi1_16b_header *hdr = &ps->s_txreq->phdr.hdr.opah; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci l4 = hfi1_16B_get_l4(hdr); 122962306a36Sopenharmony_ci if (l4 == OPA_16B_L4_IB_LOCAL) 123062306a36Sopenharmony_ci ohdr = &hdr->u.oth; 123162306a36Sopenharmony_ci else if (l4 == OPA_16B_L4_IB_GLOBAL) 123262306a36Sopenharmony_ci ohdr = &hdr->u.l.oth; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci slid = hfi1_16B_get_slid(hdr); 123562306a36Sopenharmony_ci pkey = hfi1_16B_get_pkey(hdr); 123662306a36Sopenharmony_ci } else { 123762306a36Sopenharmony_ci struct ib_header *hdr = &ps->s_txreq->phdr.hdr.ibh; 123862306a36Sopenharmony_ci u8 lnh = ib_get_lnh(hdr); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci if (lnh == HFI1_LRH_GRH) 124162306a36Sopenharmony_ci ohdr = &hdr->u.l.oth; 124262306a36Sopenharmony_ci else 124362306a36Sopenharmony_ci ohdr = &hdr->u.oth; 124462306a36Sopenharmony_ci slid = ib_get_slid(hdr); 124562306a36Sopenharmony_ci pkey = ib_bth_get_pkey(ohdr); 124662306a36Sopenharmony_ci } 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci if (likely(l4 != OPA_16B_L4_FM)) 124962306a36Sopenharmony_ci ps->opcode = ib_bth_get_opcode(ohdr); 125062306a36Sopenharmony_ci else 125162306a36Sopenharmony_ci ps->opcode = IB_OPCODE_UD_SEND_ONLY; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci sr = get_send_routine(qp, ps); 125462306a36Sopenharmony_ci ret = egress_pkey_check(dd->pport, slid, pkey, 125562306a36Sopenharmony_ci priv->s_sc, qp->s_pkey_index); 125662306a36Sopenharmony_ci if (unlikely(ret)) { 125762306a36Sopenharmony_ci /* 125862306a36Sopenharmony_ci * The value we are returning here does not get propagated to 125962306a36Sopenharmony_ci * the verbs caller. Thus we need to complete the request with 126062306a36Sopenharmony_ci * error otherwise the caller could be sitting waiting on the 126162306a36Sopenharmony_ci * completion event. Only do this for PIO. SDMA has its own 126262306a36Sopenharmony_ci * mechanism for handling the errors. So for SDMA we can just 126362306a36Sopenharmony_ci * return. 126462306a36Sopenharmony_ci */ 126562306a36Sopenharmony_ci if (sr == dd->process_pio_send) { 126662306a36Sopenharmony_ci unsigned long flags; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci hfi1_cdbg(PIO, "%s() Failed. Completing with err", 126962306a36Sopenharmony_ci __func__); 127062306a36Sopenharmony_ci spin_lock_irqsave(&qp->s_lock, flags); 127162306a36Sopenharmony_ci rvt_send_complete(qp, qp->s_wqe, IB_WC_GENERAL_ERR); 127262306a36Sopenharmony_ci spin_unlock_irqrestore(&qp->s_lock, flags); 127362306a36Sopenharmony_ci } 127462306a36Sopenharmony_ci return -EINVAL; 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci if (sr == dd->process_dma_send && iowait_pio_pending(&priv->s_iowait)) 127762306a36Sopenharmony_ci return pio_wait(qp, 127862306a36Sopenharmony_ci ps->s_txreq->psc, 127962306a36Sopenharmony_ci ps, 128062306a36Sopenharmony_ci HFI1_S_WAIT_PIO_DRAIN); 128162306a36Sopenharmony_ci return sr(qp, ps, 0); 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci/** 128562306a36Sopenharmony_ci * hfi1_fill_device_attr - Fill in rvt dev info device attributes. 128662306a36Sopenharmony_ci * @dd: the device data structure 128762306a36Sopenharmony_ci */ 128862306a36Sopenharmony_cistatic void hfi1_fill_device_attr(struct hfi1_devdata *dd) 128962306a36Sopenharmony_ci{ 129062306a36Sopenharmony_ci struct rvt_dev_info *rdi = &dd->verbs_dev.rdi; 129162306a36Sopenharmony_ci u32 ver = dd->dc8051_ver; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci memset(&rdi->dparms.props, 0, sizeof(rdi->dparms.props)); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci rdi->dparms.props.fw_ver = ((u64)(dc8051_ver_maj(ver)) << 32) | 129662306a36Sopenharmony_ci ((u64)(dc8051_ver_min(ver)) << 16) | 129762306a36Sopenharmony_ci (u64)dc8051_ver_patch(ver); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci rdi->dparms.props.device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR | 130062306a36Sopenharmony_ci IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | 130162306a36Sopenharmony_ci IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN | 130262306a36Sopenharmony_ci IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE | 130362306a36Sopenharmony_ci IB_DEVICE_MEM_MGT_EXTENSIONS; 130462306a36Sopenharmony_ci rdi->dparms.props.kernel_cap_flags = IBK_RDMA_NETDEV_OPA; 130562306a36Sopenharmony_ci rdi->dparms.props.page_size_cap = PAGE_SIZE; 130662306a36Sopenharmony_ci rdi->dparms.props.vendor_id = dd->oui1 << 16 | dd->oui2 << 8 | dd->oui3; 130762306a36Sopenharmony_ci rdi->dparms.props.vendor_part_id = dd->pcidev->device; 130862306a36Sopenharmony_ci rdi->dparms.props.hw_ver = dd->minrev; 130962306a36Sopenharmony_ci rdi->dparms.props.sys_image_guid = ib_hfi1_sys_image_guid; 131062306a36Sopenharmony_ci rdi->dparms.props.max_mr_size = U64_MAX; 131162306a36Sopenharmony_ci rdi->dparms.props.max_fast_reg_page_list_len = UINT_MAX; 131262306a36Sopenharmony_ci rdi->dparms.props.max_qp = hfi1_max_qps; 131362306a36Sopenharmony_ci rdi->dparms.props.max_qp_wr = 131462306a36Sopenharmony_ci (hfi1_max_qp_wrs >= HFI1_QP_WQE_INVALID ? 131562306a36Sopenharmony_ci HFI1_QP_WQE_INVALID - 1 : hfi1_max_qp_wrs); 131662306a36Sopenharmony_ci rdi->dparms.props.max_send_sge = hfi1_max_sges; 131762306a36Sopenharmony_ci rdi->dparms.props.max_recv_sge = hfi1_max_sges; 131862306a36Sopenharmony_ci rdi->dparms.props.max_sge_rd = hfi1_max_sges; 131962306a36Sopenharmony_ci rdi->dparms.props.max_cq = hfi1_max_cqs; 132062306a36Sopenharmony_ci rdi->dparms.props.max_ah = hfi1_max_ahs; 132162306a36Sopenharmony_ci rdi->dparms.props.max_cqe = hfi1_max_cqes; 132262306a36Sopenharmony_ci rdi->dparms.props.max_pd = hfi1_max_pds; 132362306a36Sopenharmony_ci rdi->dparms.props.max_qp_rd_atom = HFI1_MAX_RDMA_ATOMIC; 132462306a36Sopenharmony_ci rdi->dparms.props.max_qp_init_rd_atom = 255; 132562306a36Sopenharmony_ci rdi->dparms.props.max_srq = hfi1_max_srqs; 132662306a36Sopenharmony_ci rdi->dparms.props.max_srq_wr = hfi1_max_srq_wrs; 132762306a36Sopenharmony_ci rdi->dparms.props.max_srq_sge = hfi1_max_srq_sges; 132862306a36Sopenharmony_ci rdi->dparms.props.atomic_cap = IB_ATOMIC_GLOB; 132962306a36Sopenharmony_ci rdi->dparms.props.max_pkeys = hfi1_get_npkeys(dd); 133062306a36Sopenharmony_ci rdi->dparms.props.max_mcast_grp = hfi1_max_mcast_grps; 133162306a36Sopenharmony_ci rdi->dparms.props.max_mcast_qp_attach = hfi1_max_mcast_qp_attached; 133262306a36Sopenharmony_ci rdi->dparms.props.max_total_mcast_qp_attach = 133362306a36Sopenharmony_ci rdi->dparms.props.max_mcast_qp_attach * 133462306a36Sopenharmony_ci rdi->dparms.props.max_mcast_grp; 133562306a36Sopenharmony_ci} 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic inline u16 opa_speed_to_ib(u16 in) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci u16 out = 0; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci if (in & OPA_LINK_SPEED_25G) 134262306a36Sopenharmony_ci out |= IB_SPEED_EDR; 134362306a36Sopenharmony_ci if (in & OPA_LINK_SPEED_12_5G) 134462306a36Sopenharmony_ci out |= IB_SPEED_FDR; 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci return out; 134762306a36Sopenharmony_ci} 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci/* 135062306a36Sopenharmony_ci * Convert a single OPA link width (no multiple flags) to an IB value. 135162306a36Sopenharmony_ci * A zero OPA link width means link down, which means the IB width value 135262306a36Sopenharmony_ci * is a don't care. 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_cistatic inline u16 opa_width_to_ib(u16 in) 135562306a36Sopenharmony_ci{ 135662306a36Sopenharmony_ci switch (in) { 135762306a36Sopenharmony_ci case OPA_LINK_WIDTH_1X: 135862306a36Sopenharmony_ci /* map 2x and 3x to 1x as they don't exist in IB */ 135962306a36Sopenharmony_ci case OPA_LINK_WIDTH_2X: 136062306a36Sopenharmony_ci case OPA_LINK_WIDTH_3X: 136162306a36Sopenharmony_ci return IB_WIDTH_1X; 136262306a36Sopenharmony_ci default: /* link down or unknown, return our largest width */ 136362306a36Sopenharmony_ci case OPA_LINK_WIDTH_4X: 136462306a36Sopenharmony_ci return IB_WIDTH_4X; 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci} 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_cistatic int query_port(struct rvt_dev_info *rdi, u32 port_num, 136962306a36Sopenharmony_ci struct ib_port_attr *props) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci struct hfi1_ibdev *verbs_dev = dev_from_rdi(rdi); 137262306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_dev(verbs_dev); 137362306a36Sopenharmony_ci struct hfi1_pportdata *ppd = &dd->pport[port_num - 1]; 137462306a36Sopenharmony_ci u32 lid = ppd->lid; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci /* props being zeroed by the caller, avoid zeroing it here */ 137762306a36Sopenharmony_ci props->lid = lid ? lid : 0; 137862306a36Sopenharmony_ci props->lmc = ppd->lmc; 137962306a36Sopenharmony_ci /* OPA logical states match IB logical states */ 138062306a36Sopenharmony_ci props->state = driver_lstate(ppd); 138162306a36Sopenharmony_ci props->phys_state = driver_pstate(ppd); 138262306a36Sopenharmony_ci props->gid_tbl_len = HFI1_GUIDS_PER_PORT; 138362306a36Sopenharmony_ci props->active_width = (u8)opa_width_to_ib(ppd->link_width_active); 138462306a36Sopenharmony_ci /* see rate_show() in ib core/sysfs.c */ 138562306a36Sopenharmony_ci props->active_speed = opa_speed_to_ib(ppd->link_speed_active); 138662306a36Sopenharmony_ci props->max_vl_num = ppd->vls_supported; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci /* Once we are a "first class" citizen and have added the OPA MTUs to 138962306a36Sopenharmony_ci * the core we can advertise the larger MTU enum to the ULPs, for now 139062306a36Sopenharmony_ci * advertise only 4K. 139162306a36Sopenharmony_ci * 139262306a36Sopenharmony_ci * Those applications which are either OPA aware or pass the MTU enum 139362306a36Sopenharmony_ci * from the Path Records to us will get the new 8k MTU. Those that 139462306a36Sopenharmony_ci * attempt to process the MTU enum may fail in various ways. 139562306a36Sopenharmony_ci */ 139662306a36Sopenharmony_ci props->max_mtu = mtu_to_enum((!valid_ib_mtu(hfi1_max_mtu) ? 139762306a36Sopenharmony_ci 4096 : hfi1_max_mtu), IB_MTU_4096); 139862306a36Sopenharmony_ci props->active_mtu = !valid_ib_mtu(ppd->ibmtu) ? props->max_mtu : 139962306a36Sopenharmony_ci mtu_to_enum(ppd->ibmtu, IB_MTU_4096); 140062306a36Sopenharmony_ci props->phys_mtu = hfi1_max_mtu; 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci return 0; 140362306a36Sopenharmony_ci} 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_cistatic int modify_device(struct ib_device *device, 140662306a36Sopenharmony_ci int device_modify_mask, 140762306a36Sopenharmony_ci struct ib_device_modify *device_modify) 140862306a36Sopenharmony_ci{ 140962306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(device); 141062306a36Sopenharmony_ci unsigned i; 141162306a36Sopenharmony_ci int ret; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID | 141462306a36Sopenharmony_ci IB_DEVICE_MODIFY_NODE_DESC)) { 141562306a36Sopenharmony_ci ret = -EOPNOTSUPP; 141662306a36Sopenharmony_ci goto bail; 141762306a36Sopenharmony_ci } 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC) { 142062306a36Sopenharmony_ci memcpy(device->node_desc, device_modify->node_desc, 142162306a36Sopenharmony_ci IB_DEVICE_NODE_DESC_MAX); 142262306a36Sopenharmony_ci for (i = 0; i < dd->num_pports; i++) { 142362306a36Sopenharmony_ci struct hfi1_ibport *ibp = &dd->pport[i].ibport_data; 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci hfi1_node_desc_chg(ibp); 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID) { 143062306a36Sopenharmony_ci ib_hfi1_sys_image_guid = 143162306a36Sopenharmony_ci cpu_to_be64(device_modify->sys_image_guid); 143262306a36Sopenharmony_ci for (i = 0; i < dd->num_pports; i++) { 143362306a36Sopenharmony_ci struct hfi1_ibport *ibp = &dd->pport[i].ibport_data; 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci hfi1_sys_guid_chg(ibp); 143662306a36Sopenharmony_ci } 143762306a36Sopenharmony_ci } 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci ret = 0; 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_cibail: 144262306a36Sopenharmony_ci return ret; 144362306a36Sopenharmony_ci} 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_cistatic int shut_down_port(struct rvt_dev_info *rdi, u32 port_num) 144662306a36Sopenharmony_ci{ 144762306a36Sopenharmony_ci struct hfi1_ibdev *verbs_dev = dev_from_rdi(rdi); 144862306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_dev(verbs_dev); 144962306a36Sopenharmony_ci struct hfi1_pportdata *ppd = &dd->pport[port_num - 1]; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci set_link_down_reason(ppd, OPA_LINKDOWN_REASON_UNKNOWN, 0, 145262306a36Sopenharmony_ci OPA_LINKDOWN_REASON_UNKNOWN); 145362306a36Sopenharmony_ci return set_link_state(ppd, HLS_DN_DOWNDEF); 145462306a36Sopenharmony_ci} 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_cistatic int hfi1_get_guid_be(struct rvt_dev_info *rdi, struct rvt_ibport *rvp, 145762306a36Sopenharmony_ci int guid_index, __be64 *guid) 145862306a36Sopenharmony_ci{ 145962306a36Sopenharmony_ci struct hfi1_ibport *ibp = container_of(rvp, struct hfi1_ibport, rvp); 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci if (guid_index >= HFI1_GUIDS_PER_PORT) 146262306a36Sopenharmony_ci return -EINVAL; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci *guid = get_sguid(ibp, guid_index); 146562306a36Sopenharmony_ci return 0; 146662306a36Sopenharmony_ci} 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci/* 146962306a36Sopenharmony_ci * convert ah port,sl to sc 147062306a36Sopenharmony_ci */ 147162306a36Sopenharmony_ciu8 ah_to_sc(struct ib_device *ibdev, struct rdma_ah_attr *ah) 147262306a36Sopenharmony_ci{ 147362306a36Sopenharmony_ci struct hfi1_ibport *ibp = to_iport(ibdev, rdma_ah_get_port_num(ah)); 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci return ibp->sl_to_sc[rdma_ah_get_sl(ah)]; 147662306a36Sopenharmony_ci} 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_cistatic int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr) 147962306a36Sopenharmony_ci{ 148062306a36Sopenharmony_ci struct hfi1_ibport *ibp; 148162306a36Sopenharmony_ci struct hfi1_pportdata *ppd; 148262306a36Sopenharmony_ci struct hfi1_devdata *dd; 148362306a36Sopenharmony_ci u8 sc5; 148462306a36Sopenharmony_ci u8 sl; 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci if (hfi1_check_mcast(rdma_ah_get_dlid(ah_attr)) && 148762306a36Sopenharmony_ci !(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) 148862306a36Sopenharmony_ci return -EINVAL; 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci /* test the mapping for validity */ 149162306a36Sopenharmony_ci ibp = to_iport(ibdev, rdma_ah_get_port_num(ah_attr)); 149262306a36Sopenharmony_ci ppd = ppd_from_ibp(ibp); 149362306a36Sopenharmony_ci dd = dd_from_ppd(ppd); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci sl = rdma_ah_get_sl(ah_attr); 149662306a36Sopenharmony_ci if (sl >= ARRAY_SIZE(ibp->sl_to_sc)) 149762306a36Sopenharmony_ci return -EINVAL; 149862306a36Sopenharmony_ci sl = array_index_nospec(sl, ARRAY_SIZE(ibp->sl_to_sc)); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci sc5 = ibp->sl_to_sc[sl]; 150162306a36Sopenharmony_ci if (sc_to_vlt(dd, sc5) > num_vls && sc_to_vlt(dd, sc5) != 0xf) 150262306a36Sopenharmony_ci return -EINVAL; 150362306a36Sopenharmony_ci return 0; 150462306a36Sopenharmony_ci} 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_cistatic void hfi1_notify_new_ah(struct ib_device *ibdev, 150762306a36Sopenharmony_ci struct rdma_ah_attr *ah_attr, 150862306a36Sopenharmony_ci struct rvt_ah *ah) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci struct hfi1_ibport *ibp; 151162306a36Sopenharmony_ci struct hfi1_pportdata *ppd; 151262306a36Sopenharmony_ci struct hfi1_devdata *dd; 151362306a36Sopenharmony_ci u8 sc5; 151462306a36Sopenharmony_ci struct rdma_ah_attr *attr = &ah->attr; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* 151762306a36Sopenharmony_ci * Do not trust reading anything from rvt_ah at this point as it is not 151862306a36Sopenharmony_ci * done being setup. We can however modify things which we need to set. 151962306a36Sopenharmony_ci */ 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci ibp = to_iport(ibdev, rdma_ah_get_port_num(ah_attr)); 152262306a36Sopenharmony_ci ppd = ppd_from_ibp(ibp); 152362306a36Sopenharmony_ci sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&ah->attr)]; 152462306a36Sopenharmony_ci hfi1_update_ah_attr(ibdev, attr); 152562306a36Sopenharmony_ci hfi1_make_opa_lid(attr); 152662306a36Sopenharmony_ci dd = dd_from_ppd(ppd); 152762306a36Sopenharmony_ci ah->vl = sc_to_vlt(dd, sc5); 152862306a36Sopenharmony_ci if (ah->vl < num_vls || ah->vl == 15) 152962306a36Sopenharmony_ci ah->log_pmtu = ilog2(dd->vld[ah->vl].mtu); 153062306a36Sopenharmony_ci} 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci/** 153362306a36Sopenharmony_ci * hfi1_get_npkeys - return the size of the PKEY table for context 0 153462306a36Sopenharmony_ci * @dd: the hfi1_ib device 153562306a36Sopenharmony_ci */ 153662306a36Sopenharmony_ciunsigned hfi1_get_npkeys(struct hfi1_devdata *dd) 153762306a36Sopenharmony_ci{ 153862306a36Sopenharmony_ci return ARRAY_SIZE(dd->pport[0].pkeys); 153962306a36Sopenharmony_ci} 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_cistatic void init_ibport(struct hfi1_pportdata *ppd) 154262306a36Sopenharmony_ci{ 154362306a36Sopenharmony_ci struct hfi1_ibport *ibp = &ppd->ibport_data; 154462306a36Sopenharmony_ci size_t sz = ARRAY_SIZE(ibp->sl_to_sc); 154562306a36Sopenharmony_ci int i; 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci for (i = 0; i < sz; i++) { 154862306a36Sopenharmony_ci ibp->sl_to_sc[i] = i; 154962306a36Sopenharmony_ci ibp->sc_to_sl[i] = i; 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci for (i = 0; i < RVT_MAX_TRAP_LISTS ; i++) 155362306a36Sopenharmony_ci INIT_LIST_HEAD(&ibp->rvp.trap_lists[i].list); 155462306a36Sopenharmony_ci timer_setup(&ibp->rvp.trap_timer, hfi1_handle_trap_timer, 0); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci spin_lock_init(&ibp->rvp.lock); 155762306a36Sopenharmony_ci /* Set the prefix to the default value (see ch. 4.1.1) */ 155862306a36Sopenharmony_ci ibp->rvp.gid_prefix = IB_DEFAULT_GID_PREFIX; 155962306a36Sopenharmony_ci ibp->rvp.sm_lid = 0; 156062306a36Sopenharmony_ci /* 156162306a36Sopenharmony_ci * Below should only set bits defined in OPA PortInfo.CapabilityMask 156262306a36Sopenharmony_ci * and PortInfo.CapabilityMask3 156362306a36Sopenharmony_ci */ 156462306a36Sopenharmony_ci ibp->rvp.port_cap_flags = IB_PORT_AUTO_MIGR_SUP | 156562306a36Sopenharmony_ci IB_PORT_CAP_MASK_NOTICE_SUP; 156662306a36Sopenharmony_ci ibp->rvp.port_cap3_flags = OPA_CAP_MASK3_IsSharedSpaceSupported; 156762306a36Sopenharmony_ci ibp->rvp.pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA; 156862306a36Sopenharmony_ci ibp->rvp.pma_counter_select[1] = IB_PMA_PORT_RCV_DATA; 156962306a36Sopenharmony_ci ibp->rvp.pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS; 157062306a36Sopenharmony_ci ibp->rvp.pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS; 157162306a36Sopenharmony_ci ibp->rvp.pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT; 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci RCU_INIT_POINTER(ibp->rvp.qp[0], NULL); 157462306a36Sopenharmony_ci RCU_INIT_POINTER(ibp->rvp.qp[1], NULL); 157562306a36Sopenharmony_ci} 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_cistatic void hfi1_get_dev_fw_str(struct ib_device *ibdev, char *str) 157862306a36Sopenharmony_ci{ 157962306a36Sopenharmony_ci struct rvt_dev_info *rdi = ib_to_rvt(ibdev); 158062306a36Sopenharmony_ci struct hfi1_ibdev *dev = dev_from_rdi(rdi); 158162306a36Sopenharmony_ci u32 ver = dd_from_dev(dev)->dc8051_ver; 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci snprintf(str, IB_FW_VERSION_NAME_MAX, "%u.%u.%u", dc8051_ver_maj(ver), 158462306a36Sopenharmony_ci dc8051_ver_min(ver), dc8051_ver_patch(ver)); 158562306a36Sopenharmony_ci} 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_cistatic const char * const driver_cntr_names[] = { 158862306a36Sopenharmony_ci /* must be element 0*/ 158962306a36Sopenharmony_ci "DRIVER_KernIntr", 159062306a36Sopenharmony_ci "DRIVER_ErrorIntr", 159162306a36Sopenharmony_ci "DRIVER_Tx_Errs", 159262306a36Sopenharmony_ci "DRIVER_Rcv_Errs", 159362306a36Sopenharmony_ci "DRIVER_HW_Errs", 159462306a36Sopenharmony_ci "DRIVER_NoPIOBufs", 159562306a36Sopenharmony_ci "DRIVER_CtxtsOpen", 159662306a36Sopenharmony_ci "DRIVER_RcvLen_Errs", 159762306a36Sopenharmony_ci "DRIVER_EgrBufFull", 159862306a36Sopenharmony_ci "DRIVER_EgrHdrFull" 159962306a36Sopenharmony_ci}; 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_cistatic struct rdma_stat_desc *dev_cntr_descs; 160262306a36Sopenharmony_cistatic struct rdma_stat_desc *port_cntr_descs; 160362306a36Sopenharmony_ciint num_driver_cntrs = ARRAY_SIZE(driver_cntr_names); 160462306a36Sopenharmony_cistatic int num_dev_cntrs; 160562306a36Sopenharmony_cistatic int num_port_cntrs; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci/* 160862306a36Sopenharmony_ci * Convert a list of names separated by '\n' into an array of NULL terminated 160962306a36Sopenharmony_ci * strings. Optionally some entries can be reserved in the array to hold extra 161062306a36Sopenharmony_ci * external strings. 161162306a36Sopenharmony_ci */ 161262306a36Sopenharmony_cistatic int init_cntr_names(const char *names_in, const size_t names_len, 161362306a36Sopenharmony_ci int num_extra_names, int *num_cntrs, 161462306a36Sopenharmony_ci struct rdma_stat_desc **cntr_descs) 161562306a36Sopenharmony_ci{ 161662306a36Sopenharmony_ci struct rdma_stat_desc *names_out; 161762306a36Sopenharmony_ci char *p; 161862306a36Sopenharmony_ci int i, n; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci n = 0; 162162306a36Sopenharmony_ci for (i = 0; i < names_len; i++) 162262306a36Sopenharmony_ci if (names_in[i] == '\n') 162362306a36Sopenharmony_ci n++; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci names_out = kzalloc((n + num_extra_names) * sizeof(*names_out) 162662306a36Sopenharmony_ci + names_len, 162762306a36Sopenharmony_ci GFP_KERNEL); 162862306a36Sopenharmony_ci if (!names_out) { 162962306a36Sopenharmony_ci *num_cntrs = 0; 163062306a36Sopenharmony_ci *cntr_descs = NULL; 163162306a36Sopenharmony_ci return -ENOMEM; 163262306a36Sopenharmony_ci } 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci p = (char *)&names_out[n + num_extra_names]; 163562306a36Sopenharmony_ci memcpy(p, names_in, names_len); 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci for (i = 0; i < n; i++) { 163862306a36Sopenharmony_ci names_out[i].name = p; 163962306a36Sopenharmony_ci p = strchr(p, '\n'); 164062306a36Sopenharmony_ci *p++ = '\0'; 164162306a36Sopenharmony_ci } 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci *num_cntrs = n; 164462306a36Sopenharmony_ci *cntr_descs = names_out; 164562306a36Sopenharmony_ci return 0; 164662306a36Sopenharmony_ci} 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_cistatic struct rdma_hw_stats *hfi1_alloc_hw_device_stats(struct ib_device *ibdev) 164962306a36Sopenharmony_ci{ 165062306a36Sopenharmony_ci if (!dev_cntr_descs) { 165162306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(ibdev); 165262306a36Sopenharmony_ci int i, err; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci err = init_cntr_names(dd->cntrnames, dd->cntrnameslen, 165562306a36Sopenharmony_ci num_driver_cntrs, 165662306a36Sopenharmony_ci &num_dev_cntrs, &dev_cntr_descs); 165762306a36Sopenharmony_ci if (err) 165862306a36Sopenharmony_ci return NULL; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci for (i = 0; i < num_driver_cntrs; i++) 166162306a36Sopenharmony_ci dev_cntr_descs[num_dev_cntrs + i].name = 166262306a36Sopenharmony_ci driver_cntr_names[i]; 166362306a36Sopenharmony_ci } 166462306a36Sopenharmony_ci return rdma_alloc_hw_stats_struct(dev_cntr_descs, 166562306a36Sopenharmony_ci num_dev_cntrs + num_driver_cntrs, 166662306a36Sopenharmony_ci RDMA_HW_STATS_DEFAULT_LIFESPAN); 166762306a36Sopenharmony_ci} 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_cistatic struct rdma_hw_stats *hfi_alloc_hw_port_stats(struct ib_device *ibdev, 167062306a36Sopenharmony_ci u32 port_num) 167162306a36Sopenharmony_ci{ 167262306a36Sopenharmony_ci if (!port_cntr_descs) { 167362306a36Sopenharmony_ci struct hfi1_devdata *dd = dd_from_ibdev(ibdev); 167462306a36Sopenharmony_ci int err; 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci err = init_cntr_names(dd->portcntrnames, dd->portcntrnameslen, 167762306a36Sopenharmony_ci 0, 167862306a36Sopenharmony_ci &num_port_cntrs, &port_cntr_descs); 167962306a36Sopenharmony_ci if (err) 168062306a36Sopenharmony_ci return NULL; 168162306a36Sopenharmony_ci } 168262306a36Sopenharmony_ci return rdma_alloc_hw_stats_struct(port_cntr_descs, num_port_cntrs, 168362306a36Sopenharmony_ci RDMA_HW_STATS_DEFAULT_LIFESPAN); 168462306a36Sopenharmony_ci} 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_cistatic u64 hfi1_sps_ints(void) 168762306a36Sopenharmony_ci{ 168862306a36Sopenharmony_ci unsigned long index, flags; 168962306a36Sopenharmony_ci struct hfi1_devdata *dd; 169062306a36Sopenharmony_ci u64 sps_ints = 0; 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci xa_lock_irqsave(&hfi1_dev_table, flags); 169362306a36Sopenharmony_ci xa_for_each(&hfi1_dev_table, index, dd) { 169462306a36Sopenharmony_ci sps_ints += get_all_cpu_total(dd->int_counter); 169562306a36Sopenharmony_ci } 169662306a36Sopenharmony_ci xa_unlock_irqrestore(&hfi1_dev_table, flags); 169762306a36Sopenharmony_ci return sps_ints; 169862306a36Sopenharmony_ci} 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_cistatic int get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats, 170162306a36Sopenharmony_ci u32 port, int index) 170262306a36Sopenharmony_ci{ 170362306a36Sopenharmony_ci u64 *values; 170462306a36Sopenharmony_ci int count; 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci if (!port) { 170762306a36Sopenharmony_ci u64 *stats = (u64 *)&hfi1_stats; 170862306a36Sopenharmony_ci int i; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci hfi1_read_cntrs(dd_from_ibdev(ibdev), NULL, &values); 171162306a36Sopenharmony_ci values[num_dev_cntrs] = hfi1_sps_ints(); 171262306a36Sopenharmony_ci for (i = 1; i < num_driver_cntrs; i++) 171362306a36Sopenharmony_ci values[num_dev_cntrs + i] = stats[i]; 171462306a36Sopenharmony_ci count = num_dev_cntrs + num_driver_cntrs; 171562306a36Sopenharmony_ci } else { 171662306a36Sopenharmony_ci struct hfi1_ibport *ibp = to_iport(ibdev, port); 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci hfi1_read_portcntrs(ppd_from_ibp(ibp), NULL, &values); 171962306a36Sopenharmony_ci count = num_port_cntrs; 172062306a36Sopenharmony_ci } 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci memcpy(stats->value, values, count * sizeof(u64)); 172362306a36Sopenharmony_ci return count; 172462306a36Sopenharmony_ci} 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_cistatic const struct ib_device_ops hfi1_dev_ops = { 172762306a36Sopenharmony_ci .owner = THIS_MODULE, 172862306a36Sopenharmony_ci .driver_id = RDMA_DRIVER_HFI1, 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci .alloc_hw_device_stats = hfi1_alloc_hw_device_stats, 173162306a36Sopenharmony_ci .alloc_hw_port_stats = hfi_alloc_hw_port_stats, 173262306a36Sopenharmony_ci .alloc_rdma_netdev = hfi1_vnic_alloc_rn, 173362306a36Sopenharmony_ci .device_group = &ib_hfi1_attr_group, 173462306a36Sopenharmony_ci .get_dev_fw_str = hfi1_get_dev_fw_str, 173562306a36Sopenharmony_ci .get_hw_stats = get_hw_stats, 173662306a36Sopenharmony_ci .modify_device = modify_device, 173762306a36Sopenharmony_ci .port_groups = hfi1_attr_port_groups, 173862306a36Sopenharmony_ci /* keep process mad in the driver */ 173962306a36Sopenharmony_ci .process_mad = hfi1_process_mad, 174062306a36Sopenharmony_ci .rdma_netdev_get_params = hfi1_ipoib_rn_get_params, 174162306a36Sopenharmony_ci}; 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci/** 174462306a36Sopenharmony_ci * hfi1_register_ib_device - register our device with the infiniband core 174562306a36Sopenharmony_ci * @dd: the device data structure 174662306a36Sopenharmony_ci * Return 0 if successful, errno if unsuccessful. 174762306a36Sopenharmony_ci */ 174862306a36Sopenharmony_ciint hfi1_register_ib_device(struct hfi1_devdata *dd) 174962306a36Sopenharmony_ci{ 175062306a36Sopenharmony_ci struct hfi1_ibdev *dev = &dd->verbs_dev; 175162306a36Sopenharmony_ci struct ib_device *ibdev = &dev->rdi.ibdev; 175262306a36Sopenharmony_ci struct hfi1_pportdata *ppd = dd->pport; 175362306a36Sopenharmony_ci struct hfi1_ibport *ibp = &ppd->ibport_data; 175462306a36Sopenharmony_ci unsigned i; 175562306a36Sopenharmony_ci int ret; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci for (i = 0; i < dd->num_pports; i++) 175862306a36Sopenharmony_ci init_ibport(ppd + i); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci /* Only need to initialize non-zero fields. */ 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci timer_setup(&dev->mem_timer, mem_timer, 0); 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci seqlock_init(&dev->iowait_lock); 176562306a36Sopenharmony_ci seqlock_init(&dev->txwait_lock); 176662306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->txwait); 176762306a36Sopenharmony_ci INIT_LIST_HEAD(&dev->memwait); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci ret = verbs_txreq_init(dev); 177062306a36Sopenharmony_ci if (ret) 177162306a36Sopenharmony_ci goto err_verbs_txreq; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci /* Use first-port GUID as node guid */ 177462306a36Sopenharmony_ci ibdev->node_guid = get_sguid(ibp, HFI1_PORT_GUID_INDEX); 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci /* 177762306a36Sopenharmony_ci * The system image GUID is supposed to be the same for all 177862306a36Sopenharmony_ci * HFIs in a single system but since there can be other 177962306a36Sopenharmony_ci * device types in the system, we can't be sure this is unique. 178062306a36Sopenharmony_ci */ 178162306a36Sopenharmony_ci if (!ib_hfi1_sys_image_guid) 178262306a36Sopenharmony_ci ib_hfi1_sys_image_guid = ibdev->node_guid; 178362306a36Sopenharmony_ci ibdev->phys_port_cnt = dd->num_pports; 178462306a36Sopenharmony_ci ibdev->dev.parent = &dd->pcidev->dev; 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci ib_set_device_ops(ibdev, &hfi1_dev_ops); 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci strscpy(ibdev->node_desc, init_utsname()->nodename, 178962306a36Sopenharmony_ci sizeof(ibdev->node_desc)); 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci /* 179262306a36Sopenharmony_ci * Fill in rvt info object. 179362306a36Sopenharmony_ci */ 179462306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.get_pci_dev = get_pci_dev; 179562306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.check_ah = hfi1_check_ah; 179662306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.notify_new_ah = hfi1_notify_new_ah; 179762306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.get_guid_be = hfi1_get_guid_be; 179862306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.query_port_state = query_port; 179962306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.shut_down_port = shut_down_port; 180062306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.cap_mask_chg = hfi1_cap_mask_chg; 180162306a36Sopenharmony_ci /* 180262306a36Sopenharmony_ci * Fill in rvt info device attributes. 180362306a36Sopenharmony_ci */ 180462306a36Sopenharmony_ci hfi1_fill_device_attr(dd); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci /* queue pair */ 180762306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.qp_table_size = hfi1_qp_table_size; 180862306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.qpn_start = 0; 180962306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.qpn_inc = 1; 181062306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.qos_shift = dd->qos_shift; 181162306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.qpn_res_start = RVT_KDETH_QP_BASE; 181262306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.qpn_res_end = RVT_AIP_QP_MAX; 181362306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.max_rdma_atomic = HFI1_MAX_RDMA_ATOMIC; 181462306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.psn_mask = PSN_MASK; 181562306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.psn_shift = PSN_SHIFT; 181662306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.psn_modify_mask = PSN_MODIFY_MASK; 181762306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.core_cap_flags = RDMA_CORE_PORT_INTEL_OPA | 181862306a36Sopenharmony_ci RDMA_CORE_CAP_OPA_AH; 181962306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.max_mad_size = OPA_MGMT_MAD_SIZE; 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.qp_priv_alloc = qp_priv_alloc; 182262306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.qp_priv_init = hfi1_qp_priv_init; 182362306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.qp_priv_free = qp_priv_free; 182462306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.free_all_qps = free_all_qps; 182562306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.notify_qp_reset = notify_qp_reset; 182662306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.do_send = hfi1_do_send_from_rvt; 182762306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.schedule_send = hfi1_schedule_send; 182862306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.schedule_send_no_lock = _hfi1_schedule_send; 182962306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.get_pmtu_from_attr = get_pmtu_from_attr; 183062306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.notify_error_qp = notify_error_qp; 183162306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.flush_qp_waiters = flush_qp_waiters; 183262306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.stop_send_queue = stop_send_queue; 183362306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.quiesce_qp = quiesce_qp; 183462306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.notify_error_qp = notify_error_qp; 183562306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.mtu_from_qp = mtu_from_qp; 183662306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.mtu_to_path_mtu = mtu_to_path_mtu; 183762306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.check_modify_qp = hfi1_check_modify_qp; 183862306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.modify_qp = hfi1_modify_qp; 183962306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.notify_restart_rc = hfi1_restart_rc; 184062306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.setup_wqe = hfi1_setup_wqe; 184162306a36Sopenharmony_ci dd->verbs_dev.rdi.driver_f.comp_vect_cpu_lookup = 184262306a36Sopenharmony_ci hfi1_comp_vect_mappings_lookup; 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci /* completeion queue */ 184562306a36Sopenharmony_ci dd->verbs_dev.rdi.ibdev.num_comp_vectors = dd->comp_vect_possible_cpus; 184662306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.node = dd->node; 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci /* misc settings */ 184962306a36Sopenharmony_ci dd->verbs_dev.rdi.flags = 0; /* Let rdmavt handle it all */ 185062306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.lkey_table_size = hfi1_lkey_table_size; 185162306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.nports = dd->num_pports; 185262306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.npkeys = hfi1_get_npkeys(dd); 185362306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.sge_copy_mode = sge_copy_mode; 185462306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.wss_threshold = wss_threshold; 185562306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.wss_clean_period = wss_clean_period; 185662306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.reserved_operations = 1; 185762306a36Sopenharmony_ci dd->verbs_dev.rdi.dparms.extra_rdma_atomic = HFI1_TID_RDMA_WRITE_CNT; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci /* post send table */ 186062306a36Sopenharmony_ci dd->verbs_dev.rdi.post_parms = hfi1_post_parms; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci /* opcode translation table */ 186362306a36Sopenharmony_ci dd->verbs_dev.rdi.wc_opcode = ib_hfi1_wc_opcode; 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci ppd = dd->pport; 186662306a36Sopenharmony_ci for (i = 0; i < dd->num_pports; i++, ppd++) 186762306a36Sopenharmony_ci rvt_init_port(&dd->verbs_dev.rdi, 186862306a36Sopenharmony_ci &ppd->ibport_data.rvp, 186962306a36Sopenharmony_ci i, 187062306a36Sopenharmony_ci ppd->pkeys); 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci ret = rvt_register_device(&dd->verbs_dev.rdi); 187362306a36Sopenharmony_ci if (ret) 187462306a36Sopenharmony_ci goto err_verbs_txreq; 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci ret = hfi1_verbs_register_sysfs(dd); 187762306a36Sopenharmony_ci if (ret) 187862306a36Sopenharmony_ci goto err_class; 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_ci return ret; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_cierr_class: 188362306a36Sopenharmony_ci rvt_unregister_device(&dd->verbs_dev.rdi); 188462306a36Sopenharmony_cierr_verbs_txreq: 188562306a36Sopenharmony_ci verbs_txreq_exit(dev); 188662306a36Sopenharmony_ci dd_dev_err(dd, "cannot register verbs: %d!\n", -ret); 188762306a36Sopenharmony_ci return ret; 188862306a36Sopenharmony_ci} 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_civoid hfi1_unregister_ib_device(struct hfi1_devdata *dd) 189162306a36Sopenharmony_ci{ 189262306a36Sopenharmony_ci struct hfi1_ibdev *dev = &dd->verbs_dev; 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci hfi1_verbs_unregister_sysfs(dd); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci rvt_unregister_device(&dd->verbs_dev.rdi); 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci if (!list_empty(&dev->txwait)) 189962306a36Sopenharmony_ci dd_dev_err(dd, "txwait list not empty!\n"); 190062306a36Sopenharmony_ci if (!list_empty(&dev->memwait)) 190162306a36Sopenharmony_ci dd_dev_err(dd, "memwait list not empty!\n"); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci del_timer_sync(&dev->mem_timer); 190462306a36Sopenharmony_ci verbs_txreq_exit(dev); 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci kfree(dev_cntr_descs); 190762306a36Sopenharmony_ci kfree(port_cntr_descs); 190862306a36Sopenharmony_ci dev_cntr_descs = NULL; 190962306a36Sopenharmony_ci port_cntr_descs = NULL; 191062306a36Sopenharmony_ci} 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_civoid hfi1_cnp_rcv(struct hfi1_packet *packet) 191362306a36Sopenharmony_ci{ 191462306a36Sopenharmony_ci struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); 191562306a36Sopenharmony_ci struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); 191662306a36Sopenharmony_ci struct ib_header *hdr = packet->hdr; 191762306a36Sopenharmony_ci struct rvt_qp *qp = packet->qp; 191862306a36Sopenharmony_ci u32 lqpn, rqpn = 0; 191962306a36Sopenharmony_ci u16 rlid = 0; 192062306a36Sopenharmony_ci u8 sl, sc5, svc_type; 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci switch (packet->qp->ibqp.qp_type) { 192362306a36Sopenharmony_ci case IB_QPT_UC: 192462306a36Sopenharmony_ci rlid = rdma_ah_get_dlid(&qp->remote_ah_attr); 192562306a36Sopenharmony_ci rqpn = qp->remote_qpn; 192662306a36Sopenharmony_ci svc_type = IB_CC_SVCTYPE_UC; 192762306a36Sopenharmony_ci break; 192862306a36Sopenharmony_ci case IB_QPT_RC: 192962306a36Sopenharmony_ci rlid = rdma_ah_get_dlid(&qp->remote_ah_attr); 193062306a36Sopenharmony_ci rqpn = qp->remote_qpn; 193162306a36Sopenharmony_ci svc_type = IB_CC_SVCTYPE_RC; 193262306a36Sopenharmony_ci break; 193362306a36Sopenharmony_ci case IB_QPT_SMI: 193462306a36Sopenharmony_ci case IB_QPT_GSI: 193562306a36Sopenharmony_ci case IB_QPT_UD: 193662306a36Sopenharmony_ci svc_type = IB_CC_SVCTYPE_UD; 193762306a36Sopenharmony_ci break; 193862306a36Sopenharmony_ci default: 193962306a36Sopenharmony_ci ibp->rvp.n_pkt_drops++; 194062306a36Sopenharmony_ci return; 194162306a36Sopenharmony_ci } 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci sc5 = hfi1_9B_get_sc5(hdr, packet->rhf); 194462306a36Sopenharmony_ci sl = ibp->sc_to_sl[sc5]; 194562306a36Sopenharmony_ci lqpn = qp->ibqp.qp_num; 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci process_becn(ppd, sl, rlid, lqpn, rqpn, svc_type); 194862306a36Sopenharmony_ci} 1949