9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER START
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The contents of this file are subject to the terms of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Common Development and Distribution License (the "License").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You may not use this file except in compliance with the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or http://www.opensolaris.org/os/licensing.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * See the License for the specific language governing permissions
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and limitations under the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When distributing Covered Code, include this CDDL HEADER in each
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If applicable, add the following below this CDDL HEADER, with the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER END
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wr.c
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon Work Request Processing Routines
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements all the routines necessary to provide the PostSend(),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PostRecv() and PostSRQ() verbs. Also contains all the code
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * necessary to implement the Hermon WRID tracking mechanism.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/types.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/conf.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ddi.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/sunddi.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/modctl.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/avl.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ib/adapters/hermon/hermon.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint32_t hermon_wr_get_immediate(ibt_send_wr_t *wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_wr_bind_check(hermon_state_t *state, ibt_send_wr_t *wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_wqe_send_build(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint64_t *desc, uint_t *size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_wqe_mlx_build(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint64_t *desc, uint_t *size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_wqe_headroom(uint_t from, hermon_qphdl_t qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_wqe_recv_build(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_recv_wr_t *wr, uint64_t *desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_wqe_srq_build(hermon_state_t *state, hermon_srqhdl_t srq,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_recv_wr_t *wr, uint64_t *desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic hermon_workq_avl_t *hermon_wrid_wqavl_find(hermon_cqhdl_t cq, uint_t qpn,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t send_or_recv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_cq_workq_add(hermon_cqhdl_t cq, hermon_workq_avl_t *wqavl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_cq_workq_remove(hermon_cqhdl_t cq,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_avl_t *wqavl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic ibt_wr_ds_t null_sgl = { 0, 0x00000100, 0 };
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor/*
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor * Add ability to try to debug RDMA_READ/RDMA_WRITE failures.
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor *
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor * 0x1 - print rkey used during post_send
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor * 0x2 - print sgls used during post_send
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor * 0x4 - print FMR comings and goings
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor */
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylorint hermon_rdma_debug = 0x0;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_post_send_ud(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint_t num_wr, uint_t *num_posted)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_ud_t *ud;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ahhdl_t ah;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ibt_wr_rfci_send_t *rfci;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ibt_wr_init_send_t *is;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_ud_dest_t *dest;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t desc_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t signaled_dbd, solicited;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t head, tail, next_tail, qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t hdrmwqes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t nopcode, fence, immed_data = 0;
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam hermon_hw_wqe_sgl_t *ds, *old_ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_wr_ds_t *sgl;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor int nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, j, last_ds, num_ds, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *wqe_start;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int sectperwqe;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t posted_cnt = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor int total_len, strong_order, fc_bits, cksum;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&qp->qp_sq_lock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&qp->qp_sq_lock))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Grab the lock for the WRID list */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_consumer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away some initial QP state */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq = qp->qp_sq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qsize_msk = wq->wq_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdrmwqes = qp->qp_sq_hdrmwqes; /* in WQEs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sectperwqe = 1 << (qp->qp_sq_log_wqesz - 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = wq->wq_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor head = wq->wq_head;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = DDI_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpost_next:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for "queue full" condition. If the queue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is already full, then no more WQEs can be posted.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * So break out, ring a doorbell (if necessary) and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return an error
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wq->wq_full != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_FULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor next_tail = (tail + 1) & qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (((tail + hdrmwqes) & qsize_msk) == head) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_full = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = HERMON_QP_SQ_ENTRY(qp, tail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = wr->wr_nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgl = wr->wr_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor strong_order = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor fc_bits = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor cksum = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build a Send or Send_LSO WQE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor switch (wr->wr_opcode) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_SEND_LSO:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_UD_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_LSO;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_flags & IBT_WR_SEND_CKSUM)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor cksum = 0x30;
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam if (wr->wr.ud_lso.lso_hdr_sz > 60) {
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam nopcode |= (1 << 6); /* ReRead bit must be set */
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dest = wr->wr.ud_lso.lso_ud_dest;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = (hermon_ahhdl_t)dest->ud_ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ah == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_AH_HDL_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ud = (hermon_hw_snd_wqe_ud_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ud +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ud_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_UD(qp, ud, ah, dest);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor total_len = (4 + 0xf + wr->wr.ud_lso.lso_hdr_sz) & ~0xf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((uintptr_t)ds + total_len + (nds * 16) >
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uintptr_t)desc + (1 << qp->qp_sq_log_wqesz)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_SGL_LEN_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor old_ds = ds;
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam bcopy(wr->wr.ud_lso.lso_hdr, (uint32_t *)old_ds + 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr->wr.ud_lso.lso_hdr_sz);
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ds + total_len);
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam i = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_SEND:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_SEND;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_serv_type == HERMON_QP_UD) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_UD_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_flags & IBT_WR_SEND_CKSUM)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor cksum = 0x30;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor dest = wr->wr.ud.udwr_dest;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor } else if (qp->qp_serv_type == HERMON_QP_RFCI) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_RFCI_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor rfci = &wr->wr.fc.rfci_send;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if ((wr->wr_flags & IBT_WR_SEND_FC_CRC) != 0) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode |= (rfci->rfci_eof << 16);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor fc_bits = 0x40; /* set FCRC */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor dest = rfci->rfci_dest;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor } else {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_OP_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_flags & IBT_WR_SEND_IMMED) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* "|=" changes 0xa to 0xb without touching FCEOF */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode |= HERMON_WQE_SEND_NOPCODE_SENDI;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor immed_data = wr->wr.ud.udwr_immed;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = (hermon_ahhdl_t)dest->ud_ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ah == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_AH_HDL_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ud = (hermon_hw_snd_wqe_ud_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ud +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ud_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_UD(qp, ud, ah, dest);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_INIT_SEND_FCMD:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_serv_type != HERMON_QP_FCMND) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_OP_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_FCMD_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_FCP_OPCODE_INIT_AND_SEND;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor is = wr->wr.fc.fc_is;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor dest = is->is_ctl.fc_dest;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ah = (hermon_ahhdl_t)dest->ud_ah;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (ah == NULL) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_AH_HDL_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ud = (hermon_hw_snd_wqe_ud_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ud +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ud_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_WQE_BUILD_UD(qp, ud, ah, dest);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor old_ds = ds;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* move ds beyond the FCP-3 Init Segment */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ds + 0x10);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor i = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_FAST_REG_PMR:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_hw_snd_wqe_frwr_t *frwr;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_serv_type != HERMON_QP_FCMND) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_OP_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_FCMD_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_FRWR;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor frwr = (hermon_hw_snd_wqe_frwr_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_WQE_BUILD_FRWR(qp, frwr, wr->wr.fc.reg_pmr);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)frwr +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_frwr_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor strong_order = 0x80;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor#if 0
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* firmware does not support this */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_LOCAL_INVALIDATE:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_hw_snd_wqe_local_inv_t *li;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_serv_type != HERMON_QP_FCMND) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_OP_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_FCMD_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_LCL_INV;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor li = (hermon_hw_snd_wqe_local_inv_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_WQE_BUILD_LI(qp, li, wr->wr.fc.li);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)li +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_local_inv_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor strong_order = 0x80;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor#endif
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_OP_TYPE_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nds > qp->qp_sq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_SGL_LEN_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (last_ds = num_ds, j = i; j < nds; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[j].ds_len != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last_ds++; /* real last ds of wqe to fill */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc_sz = ((uintptr_t)&ds[last_ds] - (uintptr_t)desc) >> 0x4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = nds; --j >= i; ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[j].ds_len == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segment(s) for the current WQE, using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information contained in the scatter-gather list of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last_ds--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_SEND(&ds[last_ds], &sgl[j]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam membar_producer();
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam if (wr->wr_opcode == IBT_WRC_SEND_LSO) {
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam HERMON_WQE_BUILD_LSO(qp, old_ds, wr->wr.ud_lso.lso_mss,
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam wr->wr.ud_lso.lso_hdr_sz);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor } else if (wr->wr_opcode == IBT_WRC_INIT_SEND_FCMD) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* This sits in the STAMP, so must be set after setting SGL */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_WQE_BUILD_FCP3_INIT(old_ds, is->is_ctl.fc_frame_ctrl,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor is->is_cs_priority, is->is_tx_seq_id, is->is_fc_mtu,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor is->is_dest_id, is->is_op, is->is_rem_exch,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor is->is_exch_qp_idx);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* The following will be used in HERMON_WQE_SET_CTRL_SEGMENT */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* SIT bit in FCP-3 ctrl segment */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor desc_sz |= (is->is_ctl.fc_frame_ctrl & IBT_FCTL_SIT) ? 0x80 : 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* LS bit in FCP-3 ctrl segment */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor fc_bits |= (is->is_ctl.fc_frame_ctrl & IBT_FCTL_LAST_SEQ) ?
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor 0x10000 : 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor fc_bits |= ((is->is_ctl.fc_routing_ctrl & 0xF) << 20) |
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (is->is_ctl.fc_seq_id << 24);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor immed_data = is->is_ctl.fc_parameter;
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam }
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fence = (wr->wr_flags & IBT_WR_SEND_FENCE) ? 1 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor signaled_dbd = ((qp->qp_sq_sigtype == HERMON_QP_SQ_ALL_SIGNALED) ||
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (wr->wr_flags & IBT_WR_SEND_SIGNAL)) ? 0xC : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor solicited = (wr->wr_flags & IBT_WR_SEND_SOLICIT) ? 0x2 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_SET_CTRL_SEGMENT(desc, desc_sz, fence, immed_data,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor solicited, signaled_dbd, cksum, qp, strong_order, fc_bits);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_wrid[tail] = wr->wr_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = next_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update some of the state in the QP */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_tail = tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Now set the ownership bit and opcode (first dword). */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SET_SEND_WQE_OWNER(qp, (uint32_t *)desc, nopcode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (--num_wr > 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* do the invalidate of the headroom */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start = (uint32_t *)HERMON_QP_SQ_ENTRY(qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (tail + hdrmwqes) & qsize_msk);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 16; i < sectperwqe; i += 16) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start[i] = 0xFFFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto post_next;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylordone:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (posted_cnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t uarhdl = hermon_get_uarhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts for Hermon doorbell register. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, uarhdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_UAR_DOORBELL(state, uarhdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t *)(void *)&state->hs_uar->send,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t)qp->qp_ring);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, uarhdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* do the invalidate of the headroom */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start = (uint32_t *)HERMON_QP_SQ_ENTRY(qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (tail + hdrmwqes) & qsize_msk);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 16; i < sectperwqe; i += 16) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start[i] = 0xFFFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_posted != NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *num_posted = posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_post_send_rc(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint_t num_wr, uint_t *num_posted)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t desc_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t signaled_dbd, solicited;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t head, tail, next_tail, qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t hdrmwqes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t nopcode, fence, immed_data = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_remaddr_t *rc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_atomic_t *at;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_bind_t *bn;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_hw_snd_wqe_frwr_t *frwr;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_hw_snd_wqe_local_inv_t *li;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_wqe_sgl_t *ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_wr_ds_t *sgl;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor int nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, last_ds, num_ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *wqe_start;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int sectperwqe;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t posted_cnt = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor int strong_order;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor int print_rdma;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor int rlen;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor uint32_t rkey;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor uint64_t raddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&qp->qp_sq_lock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&qp->qp_sq_lock))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away some initial QP state */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq = qp->qp_sq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qsize_msk = wq->wq_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdrmwqes = qp->qp_sq_hdrmwqes; /* in WQEs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sectperwqe = 1 << (qp->qp_sq_log_wqesz - 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = wq->wq_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor head = wq->wq_head;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = DDI_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpost_next:
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor print_rdma = 0;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor rlen = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor strong_order = 0;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for "queue full" condition. If the queue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is already full, then no more WQEs can be posted.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * So break out, ring a doorbell (if necessary) and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return an error
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wq->wq_full != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_FULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor next_tail = (tail + 1) & qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (((tail + hdrmwqes) & qsize_msk) == head) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_full = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = HERMON_QP_SQ_ENTRY(qp, tail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = wr->wr_nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgl = wr->wr_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_trans != IBT_RC_SRV) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SRV_TYPE_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Validate the operation type. For RC requests, we allow
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "Send", "RDMA Read", "RDMA Write", various "Atomic"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operations, and memory window "Bind"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (wr->wr_opcode) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_OP_TYPE_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_SEND:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (wr->wr_flags & IBT_WR_SEND_REMOTE_INVAL) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_SND_INV;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor immed_data = wr->wr.rc.rcwr.send_inval;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor } else if (wr->wr_flags & IBT_WR_SEND_IMMED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_SENDI;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor immed_data = wr->wr.rc.rcwr.send_immed;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_SEND;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is an RDMA Read or RDMA Write request, then fill
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in the "Remote Address" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_RDMAW:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_flags & IBT_WR_SEND_IMMED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_RDMAWI;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor immed_data = wr->wr.rc.rcwr.rdma.rdma_immed;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_RDMAW;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_RDMAR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_RDMAR)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_RDMAR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rc = (hermon_hw_snd_wqe_remaddr_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Remote Address Segment for the WQE, using
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information from the RC work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_REMADDR(qp, rc, &wr->wr.rc.rcwr.rdma);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor if (hermon_rdma_debug) {
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor print_rdma = hermon_rdma_debug;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor rkey = wr->wr.rc.rcwr.rdma.rdma_rkey;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor raddr = wr->wr.rc.rcwr.rdma.rdma_raddr;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor }
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update "ds" for filling in Data Segments (below) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)rc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_remaddr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is one of the Atomic type operations (i.e
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Compare-Swap or Fetch-Add), then fill in both the "Remote
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Address" header fields and the "Atomic" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_CSWAP:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_ATMCS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_FADD:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_FADD)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_ATMFA;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rc = (hermon_hw_snd_wqe_remaddr_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor at = (hermon_hw_snd_wqe_atomic_t *)((uintptr_t)rc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_remaddr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Remote Address and Atomic Segments for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the WQE, using the information from the RC Atomic
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_RC_ATOMIC_REMADDR(qp, rc, wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_ATOMIC(qp, at, wr->wr.rc.rcwr.atomic);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update "ds" for filling in Data Segments (below) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)at +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_atomic_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update "nds" and "sgl" because Atomic requests have
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * only a single Data Segment.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgl = wr->wr_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is memory window Bind operation, then we call the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wr_bind_check() routine to validate the request and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to generate the updated RKey. If this is successful, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we fill in the WQE's "Bind" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_BIND:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_BIND;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wr_bind_check(state, wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bn = (hermon_hw_snd_wqe_bind_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Bind Memory Window Segments for the WQE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * using the information from the RC Bind memory
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * window work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_BIND(qp, bn, wr->wr.rc.rcwr.bind);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the "ds" pointer. Even though the "bind"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation requires no SGLs, this is necessary to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * facilitate the correct descriptor size calculations
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (below).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)bn +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_bind_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_FAST_REG_PMR:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_FRWR;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor frwr = (hermon_hw_snd_wqe_frwr_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_WQE_BUILD_FRWR(qp, frwr, wr->wr.rc.rcwr.reg_pmr);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)frwr +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_frwr_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor strong_order = 0x80;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor case IBT_WRC_LOCAL_INVALIDATE:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_LCL_INV;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor li = (hermon_hw_snd_wqe_local_inv_t *)((uintptr_t)desc +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_WQE_BUILD_LI(qp, li, wr->wr.rc.rcwr.li);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)li +
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor sizeof (hermon_hw_snd_wqe_local_inv_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor nds = 0;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor strong_order = 0x80;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now fill in the Data Segments (SGL) for the Send WQE based
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * on the values setup above (i.e. "sgl", "nds", and the "ds"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * pointer. Start by checking for a valid number of SGL entries
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nds > qp->qp_sq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_SGL_LEN_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (last_ds = num_ds, i = 0; i < nds; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[i].ds_len != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last_ds++; /* real last ds of wqe to fill */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc_sz = ((uintptr_t)&ds[last_ds] - (uintptr_t)desc) >> 0x4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = nds; --i >= 0; ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[i].ds_len == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor rlen += sgl[i].ds_len;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor if (print_rdma & 0x2)
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor IBTF_DPRINTF_L2("rdma", "post: [%d]: laddr %llx "
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor "llen %x", i, sgl[i].ds_va, sgl[i].ds_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segment(s) for the current WQE, using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information contained in the scatter-gather list of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last_ds--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_SEND(&ds[last_ds], &sgl[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* ensure RDMA READ does not exceed HCA limit */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if ((wr->wr_opcode == IBT_WRC_RDMAR) && (desc_sz >
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_ibtfinfo.hca_attr->hca_conn_rdma_read_sgl_sz + 2)) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = IBT_QP_SGL_LEN_INVALID;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor goto done;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor if (print_rdma & 0x1) {
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor IBTF_DPRINTF_L2("rdma", "post: indx %x rkey %x raddr %llx "
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor "total len %x", tail, rkey, raddr, rlen);
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor }
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fence = (wr->wr_flags & IBT_WR_SEND_FENCE) ? 1 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor signaled_dbd = ((qp->qp_sq_sigtype == HERMON_QP_SQ_ALL_SIGNALED) ||
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (wr->wr_flags & IBT_WR_SEND_SIGNAL)) ? 0xC : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor solicited = (wr->wr_flags & IBT_WR_SEND_SOLICIT) ? 0x2 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_SET_CTRL_SEGMENT(desc, desc_sz, fence, immed_data, solicited,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor signaled_dbd, 0, qp, strong_order, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_wrid[tail] = wr->wr_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = next_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update some of the state in the QP */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_tail = tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Now set the ownership bit of the first one in the chain. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SET_SEND_WQE_OWNER(qp, (uint32_t *)desc, nopcode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (--num_wr > 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* do the invalidate of the headroom */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start = (uint32_t *)HERMON_QP_SQ_ENTRY(qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (tail + hdrmwqes) & qsize_msk);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 16; i < sectperwqe; i += 16) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start[i] = 0xFFFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto post_next;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylordone:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (posted_cnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t uarhdl = hermon_get_uarhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts for Hermon doorbell register. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, uarhdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ring the doorbell */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_UAR_DOORBELL(state, uarhdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t *)(void *)&state->hs_uar->send,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t)qp->qp_ring);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, uarhdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* do the invalidate of the headroom */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start = (uint32_t *)HERMON_QP_SQ_ENTRY(qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (tail + hdrmwqes) & qsize_msk);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 16; i < sectperwqe; i += 16) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start[i] = 0xFFFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the "num_posted" return value (if necessary).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Then drop the locks and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_posted != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *num_posted = posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_post_send()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_post_send(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint_t num_wr, uint_t *num_posted)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *curr_wr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ahhdl_t ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *desc, *prev;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t desc_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t signaled_dbd, solicited;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t head, tail, next_tail, qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t hdrmwqes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t currindx, wrindx, numremain;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t chainlen;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t posted_cnt, maxstat;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t total_posted;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t nopcode, fence, immed_data = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t prev_nopcode;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint_t qp_state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for user-mappable QP memory. Note: We do not allow kernel
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * clients to post to QP memory that is accessible directly by the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * user. If the QP memory is user accessible, then return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USER_MAP) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_enter(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check QP state. Can not post Send requests from the "Reset",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "Init", or "RTR" states
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor qp_state = qp->qp_state_for_post_send;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if ((qp_state == HERMON_QP_RESET) ||
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (qp_state == HERMON_QP_INIT) ||
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (qp_state == HERMON_QP_RTR)) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_STATE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_is_special)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto post_many;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Use these optimized functions most of the time */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_type == IBT_UD_RQP) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (hermon_post_send_ud(state, qp, wr, num_wr, num_posted));
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor if (qp->qp_serv_type == HERMON_QP_RC) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (hermon_post_send_rc(state, qp, wr, num_wr, num_posted));
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_serv_type == HERMON_QP_UC)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto post_many;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SRV_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpost_many:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* general loop for non-optimized posting */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away some initial QP state */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq = qp->qp_sq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qsize_msk = wq->wq_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = wq->wq_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor head = wq->wq_head;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdrmwqes = qp->qp_sq_hdrmwqes; /* in WQEs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize posted_cnt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor total_posted = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For each ibt_send_wr_t in the wr[] list passed in, parse the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * request and build a Send WQE. NOTE: Because we are potentially
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * building a chain of WQEs to post, we want to build them all first,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and set the valid (HW Ownership) bit on all but the first.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * However, we do not want to validate the first one until the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entire chain of WQEs has been built. Then in the final
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we set the valid bit in the first, flush if needed, and as a last
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * step ring the appropriate doorbell. NOTE: the doorbell ring may
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOT be needed if the HCA is already processing, but the doorbell
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ring will be done regardless. NOTE ALSO: It is possible for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * more Work Requests to be posted than the HW will support at one
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * shot. If this happens, we need to be able to post and ring
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * several chains here until the the entire request is complete.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE ALSO: the term "chain" is used to differentiate it from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Work Request List passed in; and because that's the terminology
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from the previous generations of HCA - but the WQEs are not, in fact
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chained together for Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wrindx = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor numremain = num_wr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = DDI_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while ((wrindx < num_wr) && (status == DDI_SUCCESS)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For the first WQE on a new chain we need "prev" to point
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the current descriptor.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev = HERMON_QP_SQ_ENTRY(qp, tail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Break the request up into lists that are less than or
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * equal to the maximum number of WQEs that can be posted
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * per doorbell ring - 256 currently
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor chainlen = (numremain > HERMON_QP_MAXDESC_PER_DB) ?
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_QP_MAXDESC_PER_DB : numremain;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor numremain -= chainlen;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (currindx = 0; currindx < chainlen; currindx++, wrindx++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for "queue full" condition. If the queue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is already full, then no more WQEs can be posted.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * So break out, ring a doorbell (if necessary) and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return an error
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wq->wq_full != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_FULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Increment the "tail index". Check for "queue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * full" condition incl. headroom. If we detect that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the current work request is going to fill the work
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * queue, then we mark this condition and continue.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Don't need >=, because going one-by-one we have to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hit it exactly sooner or later
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor next_tail = (tail + 1) & qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (((tail + hdrmwqes) & qsize_msk) == head) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_full = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Get the address of the location where the next
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Send WQE should be built
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = HERMON_QP_SQ_ENTRY(qp, tail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Call hermon_wqe_send_build() to build the WQE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * at the given address. This routine uses the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information in the ibt_send_wr_t list (wr[]) and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * returns the size of the WQE when it returns.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wqe_send_build(state, qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &wr[wrindx], desc, &desc_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now, build the Ctrl Segment based on
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * what was just done
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_wr = &wr[wrindx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (curr_wr->wr_opcode) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_RDMAW:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (curr_wr->wr_flags & IBT_WR_SEND_IMMED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_SEND_NOPCODE_RDMAWI;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor immed_data =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wr_get_immediate(curr_wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_RDMAW;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_SEND:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (curr_wr->wr_flags & IBT_WR_SEND_IMMED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_SENDI;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor immed_data =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wr_get_immediate(curr_wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_SEND;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_SEND_LSO:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_LSO;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_RDMAR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_RDMAR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_CSWAP:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_ATMCS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_FADD:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_ATMFA;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_WRC_BIND:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nopcode = HERMON_WQE_SEND_NOPCODE_BIND;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fence = (curr_wr->wr_flags & IBT_WR_SEND_FENCE) ? 1 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * now, build up the control segment, leaving the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * owner bit as it is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((qp->qp_sq_sigtype == HERMON_QP_SQ_ALL_SIGNALED) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (curr_wr->wr_flags & IBT_WR_SEND_SIGNAL)) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor signaled_dbd = 0xC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor signaled_dbd = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (curr_wr->wr_flags & IBT_WR_SEND_SOLICIT)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor solicited = 0x2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor solicited = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_is_special) {
949b58c70cf907006b9f724dfad665d44eca5881Bill Taylor /* Ensure correctness, set the ReRead bit */
949b58c70cf907006b9f724dfad665d44eca5881Bill Taylor nopcode |= (1 << 6);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = (hermon_ahhdl_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_wr->wr.ud.udwr_dest->ud_ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxstat = ah->ah_udav->max_stat_rate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_SET_MLX_CTRL_SEGMENT(desc, desc_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor signaled_dbd, maxstat, ah->ah_udav->rlid,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp, ah->ah_udav->sl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_SET_CTRL_SEGMENT(desc, desc_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fence, immed_data, solicited,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor signaled_dbd, 0, qp, 0, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_wrid[tail] = curr_wr->wr_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is not the first descriptor on the current
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chain, then set the ownership bit.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (currindx != 0) { /* not the first */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SET_SEND_WQE_OWNER(qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t *)desc, nopcode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev_nopcode = nopcode;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the current "tail index" and increment
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "posted_cnt"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = next_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we reach here and there are one or more WQEs which have
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * been successfully built as a chain, we have to finish up
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and prepare them for writing to the HW
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The steps are:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1. do the headroom fixup
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 2. add in the size of the headroom for the sync
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 3. write the owner bit for the first WQE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 4. sync them
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 5. fix up the structures
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 6. hit the doorbell in UAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (posted_cnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t uarhdl = hermon_get_uarhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* do the invalidate of the headroom */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wqe_headroom(tail, qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update some of the state in the QP */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_tail = tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor total_posted += posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now set the ownership bit of the first
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * one in the chain
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SET_SEND_WQE_OWNER(qp, (uint32_t *)prev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev_nopcode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts for Hermon doorbell. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, uarhdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_UAR_DOORBELL(state, uarhdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t *)(void *)&state->hs_uar->send,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t)qp->qp_ring);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, uarhdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the "num_posted" return value (if necessary).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Then drop the locks and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_posted != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *num_posted = total_posted;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_post_recv()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_post_recv(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_recv_wr_t *wr, uint_t num_wr, uint_t *num_posted)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t head, tail, next_tail, qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t wrindx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for user-mappable QP memory. Note: We do not allow kernel
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * clients to post to QP memory that is accessible directly by the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * user. If the QP memory is user accessible, then return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USER_MAP) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize posted_cnt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check if QP is associated with an SRQ
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_SRQ_IN_USE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check QP state. Can not post Recv requests from the "Reset" state
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_state == HERMON_QP_RESET) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_STATE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check that work request transport type is valid */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if ((qp->qp_type != IBT_UD_RQP) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (qp->qp_serv_type != HERMON_QP_RC) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (qp->qp_serv_type != HERMON_QP_UC)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SRV_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Grab the lock for the WRID list, i.e., membar_consumer().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is not needed because the mutex_enter() above has
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the same effect.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away some initial QP state */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq = qp->qp_rq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qsize_msk = wq->wq_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = wq->wq_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor head = wq->wq_head;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wrindx = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = DDI_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (wrindx = 0; wrindx < num_wr; wrindx++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wq->wq_full != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_FULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor next_tail = (tail + 1) & qsize_msk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (next_tail == head) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_full = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = HERMON_QP_RQ_ENTRY(qp, tail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wqe_recv_build(state, qp, &wr[wrindx], desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_wrid[tail] = wr[wrindx].wr_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp->qp_rq_wqecntr++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tail = next_tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (posted_cnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_tail = tail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer(); /* ensure wrids are visible */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update the doorbell record w/ wqecntr */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_UAR_DB_RECORD_WRITE(qp->qp_rq_vdbr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp->qp_rq_wqecntr & 0xFFFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_posted != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *num_posted = posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_exit(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_post_srq()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_post_srq(hermon_state_t *state, hermon_srqhdl_t srq,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_recv_wr_t *wr, uint_t num_wr, uint_t *num_posted)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t indx, wrindx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for user-mappable QP memory. Note: We do not allow kernel
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * clients to post to QP memory that is accessible directly by the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * user. If the QP memory is user accessible, then return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_SRQ_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check SRQ state. Can not post Recv requests when SRQ is in error
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_state == HERMON_SRQ_STATE_ERROR) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_STATE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = DDI_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq = srq->srq_wq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor indx = wq->wq_head;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (wrindx = 0; wrindx < num_wr; wrindx++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (indx == wq->wq_tail) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_QP_FULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = HERMON_SRQ_WQE_ADDR(srq, indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_wrid[indx] = wr[wrindx].wr_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wqe_srq_build(state, srq, &wr[wrindx], desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor posted_cnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor indx = htons(((uint16_t *)desc)[1]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_head = indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (posted_cnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_wqecntr += posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer(); /* ensure wrids are visible */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ring the doorbell w/ wqecntr */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_UAR_DB_RECORD_WRITE(srq->srq_wq_vdbr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_wqecntr & 0xFFFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_posted != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *num_posted = posted_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wqe_send_build()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wqe_send_build(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint64_t *desc, uint_t *size)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_ud_t *ud;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_remaddr_t *rc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_atomic_t *at;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_remaddr_t *uc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_snd_wqe_bind_t *bn;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_wqe_sgl_t *ds, *old_ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_ud_dest_t *dest;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_wr_ds_t *sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ahhdl_t ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, j, last_ds, num_ds, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int tmpsize;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&qp->qp_sq_lock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the information for the Data Segments */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = wr->wr_nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgl = wr->wr_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build a Send WQE depends first and foremost on the transport
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * type of Work Request (i.e. UD, RC, or UC)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (wr->wr_trans) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_UD_SRV:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that work request transport type matches QP type */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_serv_type != HERMON_QP_UD) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SRV_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Validate the operation type. For UD requests, only the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "Send" and "Send LSO" operations are valid.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode != IBT_WRC_SEND &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr->wr_opcode != IBT_WRC_SEND_LSO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_OP_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is a Special QP (QP0 or QP1), then we need to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * build MLX WQEs instead. So jump to hermon_wqe_mlx_build()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and return whatever status it returns
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_is_special) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND_LSO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_OP_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wqe_mlx_build(state, qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr, desc, size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise, if this is a normal UD Send request, then fill
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all the fields in the Hermon UD header for the WQE. Note:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to do this we'll need to extract some information from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Address Handle passed with the work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ud = (hermon_hw_snd_wqe_ud_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dest = wr->wr.ud.udwr_dest;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dest = wr->wr.ud_lso.lso_ud_dest;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = (hermon_ahhdl_t)dest->ud_ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ah == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_AH_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Unreliable Datagram Segment for the WQE, using
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information from the address handle and the work
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* mutex_enter(&ah->ah_lock); */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_UD(qp, ud, ah, wr->wr.ud.udwr_dest);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else { /* IBT_WRC_SEND_LSO */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_UD(qp, ud, ah,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr->wr.ud_lso.lso_ud_dest);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* mutex_exit(&ah->ah_lock); */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update "ds" for filling in Data Segments (below) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ud +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ud_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND_LSO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int total_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor total_len = (4 + 0xf + wr->wr.ud_lso.lso_hdr_sz) & ~0xf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((uintptr_t)ds + total_len + (nds * 16) >
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uintptr_t)desc + (1 << qp->qp_sq_log_wqesz))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SGL_LEN_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bcopy(wr->wr.ud_lso.lso_hdr, (uint32_t *)ds + 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr->wr.ud_lso.lso_hdr_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor old_ds = ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)ds + total_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (; i < nds; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[i].ds_len == 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_SEND(&ds[num_ds],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &sgl[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor membar_producer();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_LSO(qp, old_ds, wr->wr.ud_lso.lso_mss,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr->wr.ud_lso.lso_hdr_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_RC_SRV:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that work request transport type matches QP type */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_serv_type != HERMON_QP_RC) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SRV_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Validate the operation type. For RC requests, we allow
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "Send", "RDMA Read", "RDMA Write", various "Atomic"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operations, and memory window "Bind"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((wr->wr_opcode != IBT_WRC_SEND) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_RDMAR) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_RDMAW) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_CSWAP) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_FADD) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_BIND)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_OP_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is a Send request, then all we need to do is break
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * out and here and begin the Data Segment processing below
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is an RDMA Read or RDMA Write request, then fill
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in the "Remote Address" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((wr->wr_opcode == IBT_WRC_RDMAR) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode == IBT_WRC_RDMAW)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rc = (hermon_hw_snd_wqe_remaddr_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Remote Address Segment for the WQE, using
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information from the RC work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_REMADDR(qp, rc, &wr->wr.rc.rcwr.rdma);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update "ds" for filling in Data Segments (below) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)rc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_remaddr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is one of the Atomic type operations (i.e
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Compare-Swap or Fetch-Add), then fill in both the "Remote
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Address" header fields and the "Atomic" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((wr->wr_opcode == IBT_WRC_CSWAP) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode == IBT_WRC_FADD)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rc = (hermon_hw_snd_wqe_remaddr_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor at = (hermon_hw_snd_wqe_atomic_t *)((uintptr_t)rc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_remaddr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Remote Address and Atomic Segments for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the WQE, using the information from the RC Atomic
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_RC_ATOMIC_REMADDR(qp, rc, wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_ATOMIC(qp, at, wr->wr.rc.rcwr.atomic);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update "ds" for filling in Data Segments (below) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)at +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_atomic_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update "nds" and "sgl" because Atomic requests have
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * only a single Data Segment (and they are encoded
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * somewhat differently in the work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgl = wr->wr_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is memory window Bind operation, then we call the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wr_bind_check() routine to validate the request and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to generate the updated RKey. If this is successful, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we fill in the WQE's "Bind" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_BIND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wr_bind_check(state, wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bn = (hermon_hw_snd_wqe_bind_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Bind Memory Window Segments for the WQE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * using the information from the RC Bind memory
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * window work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_BIND(qp, bn, wr->wr.rc.rcwr.bind);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the "ds" pointer. Even though the "bind"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation requires no SGLs, this is necessary to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * facilitate the correct descriptor size calculations
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (below).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)bn +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_bind_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case IBT_UC_SRV:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that work request transport type matches QP type */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_serv_type != HERMON_QP_UC) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SRV_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Validate the operation type. For UC requests, we only
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * allow "Send", "RDMA Write", and memory window "Bind".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: Unlike RC, UC does not allow "RDMA Read" or "Atomic"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operations
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((wr->wr_opcode != IBT_WRC_SEND) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_RDMAW) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (wr->wr_opcode != IBT_WRC_BIND)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_OP_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is a Send request, then all we need to do is break
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * out and here and begin the Data Segment processing below
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is an RDMA Write request, then fill in the "Remote
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Address" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_RDMAW) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uc = (hermon_hw_snd_wqe_remaddr_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Remote Address Segment for the WQE, using
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information from the UC work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_REMADDR(qp, uc, &wr->wr.uc.ucwr.rdma);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update "ds" for filling in Data Segments (below) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)uc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_remaddr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is memory window Bind operation, then we call the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wr_bind_check() routine to validate the request and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to generate the updated RKey. If this is successful, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we fill in the WQE's "Bind" header fields.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_BIND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_wr_bind_check(state, wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bn = (hermon_hw_snd_wqe_bind_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_ctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build the Bind Memory Window Segments for the WQE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * using the information from the UC Bind memory
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * window work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_BIND(qp, bn, wr->wr.uc.ucwr.bind);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the "ds" pointer. Even though the "bind"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation requires no SGLs, this is necessary to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * facilitate the correct descriptor size calculations
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (below).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)bn +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_snd_wqe_bind_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SRV_TYPE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now fill in the Data Segments (SGL) for the Send WQE based on
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the values setup above (i.e. "sgl", "nds", and the "ds" pointer
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Start by checking for a valid number of SGL entries
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nds > qp->qp_sq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SGL_LEN_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For each SGL in the Send Work Request, fill in the Send WQE's data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * segments. Note: We skip any SGL with zero size because Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware cannot handle a zero for "byte_cnt" in the WQE. Actually
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the encoding for zero means a 2GB transfer.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (last_ds = num_ds, j = i; j < nds; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[j].ds_len != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last_ds++; /* real last ds of wqe to fill */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Return the size of descriptor (in 16-byte chunks)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For Hermon, we want them (for now) to be on stride size
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * boundaries, which was implicit in Tavor/Arbel
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tmpsize = ((uintptr_t)&ds[last_ds] - (uintptr_t)desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *size = tmpsize >> 0x4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = nds; --j >= i; ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[j].ds_len == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segment(s) for the current WQE, using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information contained in the scatter-gather list of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last_ds--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_SEND(&ds[last_ds], &sgl[j]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wqe_mlx_build()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wqe_mlx_build(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_send_wr_t *wr, uint64_t *desc, uint_t *size)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ahhdl_t ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_udav_t *udav;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_lrh_hdr_t *lrh;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_grh_t *grh;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_bth_hdr_t *bth;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_deth_hdr_t *deth;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_wqe_sgl_t *ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_wr_ds_t *sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint8_t *mgmtclass, *hpoint, *hcount;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t nds, offset, pktlen;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t desc_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, num_ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int tmpsize;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&qp->qp_sq_lock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the information for the Data Segments */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_mlx_wqe_nextctrl_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pull the address handle from the work request. The UDAV will
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be used to answer some questions about the request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = (hermon_ahhdl_t)wr->wr.ud.udwr_dest->ud_ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ah == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_AH_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav = ah->ah_udav;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the request is for QP1 and the destination LID is equal to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the Permissive LID, then return an error. This combination is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * not allowed
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((udav->rlid == IB_LID_PERMISSIVE) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (qp->qp_is_special == HERMON_QP_GSI)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_AH_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the size of the packet headers, including the GRH
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (if necessary)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc_sz = sizeof (ib_lrh_hdr_t) + sizeof (ib_bth_hdr_t) +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (ib_deth_hdr_t);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (udav->grh) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc_sz += sizeof (ib_grh_t);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Begin to build the first "inline" data segment for the packet
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * headers. Note: By specifying "inline" we can build the contents
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * of the MAD packet headers directly into the work queue (as part
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * descriptor). This has the advantage of both speeding things up
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and of not requiring the driver to allocate/register any additional
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * memory for the packet headers.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_INLINE(qp, &ds[0], desc_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc_sz += 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build Local Route Header (LRH)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We start here by building the LRH into a temporary location.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When we have finished we copy the LRH data into the descriptor.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Notice that the VL values are hardcoded. This is not a problem
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * because VL15 is decided later based on the value in the MLX
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * transport "next/ctrl" header (see the "vl15" bit below), and it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is otherwise (meaning for QP1) chosen from the SL-to-VL table
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * values. This rule does not hold for loopback packets however
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (all of which bypass the SL-to-VL tables) and it is the reason
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that non-QP0 MADs are setup with VL hardcoded to zero below.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Notice also that Source LID is hardcoded to the Permissive LID
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (0xFFFF). This is also not a problem because if the Destination
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * LID is not the Permissive LID, then the "slr" value in the MLX
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * transport "next/ctrl" header will be set to zero and the hardware
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will pull the LID from value in the port.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lrh = (ib_lrh_hdr_t *)((uintptr_t)&ds[0] + 4);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pktlen = (desc_sz + 0x100) >> 2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_MLX_LRH(lrh, qp, udav, pktlen);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build Global Route Header (GRH)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is only built if necessary as defined by the "grh" bit in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the address vector. Note: We also calculate the offset to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * next header (BTH) based on whether or not the "grh" bit is set.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (udav->grh) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the request is for QP0, then return an error. The
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * combination of global routine (GRH) and QP0 is not allowed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_is_special == HERMON_QP_SMI) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_AH_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor grh = (ib_grh_t *)((uintptr_t)lrh + sizeof (ib_lrh_hdr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_MLX_GRH(state, grh, qp, udav, pktlen);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bth = (ib_bth_hdr_t *)((uintptr_t)grh + sizeof (ib_grh_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bth = (ib_bth_hdr_t *)((uintptr_t)lrh + sizeof (ib_lrh_hdr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build Base Transport Header (BTH)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Notice that the M, PadCnt, and TVer fields are all set
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to zero implicitly. This is true for all Management Datagrams
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MADs whether GSI are SMI.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_MLX_BTH(state, bth, qp, wr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Build Datagram Extended Transport Header (DETH)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor deth = (ib_deth_hdr_t *)((uintptr_t)bth + sizeof (ib_bth_hdr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_MLX_DETH(deth, qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that the Data Segment is aligned on a 16-byte boundary */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)deth + sizeof (ib_deth_hdr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)(((uintptr_t)ds + 0xF) & ~0xF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nds = wr->wr_nds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgl = wr->wr_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now fill in the Data Segments (SGL) for the MLX WQE based on the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * values set up above (i.e. "sgl", "nds", and the "ds" pointer
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Start by checking for a valid number of SGL entries
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nds > qp->qp_sq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SGL_LEN_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For each SGL in the Send Work Request, fill in the MLX WQE's data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * segments. Note: We skip any SGL with zero size because Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware cannot handle a zero for "byte_cnt" in the WQE. Actually
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the encoding for zero means a 2GB transfer. Because of this special
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * encoding in the hardware, we mask the requested length with
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HERMON_WQE_SGL_BYTE_CNT_MASK (so that 2GB will end up encoded as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * zero.)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mgmtclass = hpoint = hcount = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < nds; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sgl[i].ds_len == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segment(s) for the MLX send WQE, using
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information contained in the scatter-gather list of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_SEND(&ds[num_ds], &sgl[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Search through the contents of all MADs posted to QP0 to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * initialize pointers to the places where Directed Route "hop
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * pointer", "hop count", and "mgmtclass" would be. Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * needs these updated (i.e. incremented or decremented, as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * necessary) by software.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_is_special == HERMON_QP_SMI) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SPECIAL_QP_DRMAD_GET_MGMTCLASS(mgmtclass,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset, sgl[i].ds_va, sgl[i].ds_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SPECIAL_QP_DRMAD_GET_HOPPOINTER(hpoint,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset, sgl[i].ds_va, sgl[i].ds_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SPECIAL_QP_DRMAD_GET_HOPCOUNT(hcount,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset, sgl[i].ds_va, sgl[i].ds_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset += sgl[i].ds_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon's Directed Route MADs need to have the "hop pointer"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * incremented/decremented (as necessary) depending on whether it is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * currently less than or greater than the "hop count" (i.e. whether
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the MAD is a request or a response.)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_is_special == HERMON_QP_SMI) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SPECIAL_QP_DRMAD_DO_HOPPOINTER_MODIFY(*mgmtclass,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *hpoint, *hcount);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now fill in the ICRC Data Segment. This data segment is inlined
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * just like the packets headers above, but it is only four bytes and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * set to zero (to indicate that we wish the hardware to generate ICRC.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_INLINE_ICRC(qp, &ds[num_ds], 4, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Return the size of descriptor (in 16-byte chunks)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For Hermon, we want them (for now) to be on stride size
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * boundaries, which was implicit in Tavor/Arbel
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tmpsize = ((uintptr_t)&ds[num_ds] - (uintptr_t)desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *size = tmpsize >> 0x04;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wqe_recv_build()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wqe_recv_build(hermon_state_t *state, hermon_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_recv_wr_t *wr, uint64_t *desc)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_wqe_sgl_t *ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, num_ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ASSERT(MUTEX_HELD(&qp->qp_lock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segments (SGL) for the Recv WQE - don't
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * need to have a reserved for the ctrl, there is none on the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * recv queue for hermon, but will need to put an invalid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (null) scatter pointer per PRM
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)(uintptr_t)desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for valid number of SGL entries */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_nds > qp->qp_rq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SGL_LEN_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For each SGL in the Recv Work Request, fill in the Recv WQE's data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * segments. Note: We skip any SGL with zero size because Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware cannot handle a zero for "byte_cnt" in the WQE. Actually
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the encoding for zero means a 2GB transfer. Because of this special
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * encoding in the hardware, we mask the requested length with
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HERMON_WQE_SGL_BYTE_CNT_MASK (so that 2GB will end up encoded as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * zero.)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < wr->wr_nds; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_sgl[i].ds_len == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segment(s) for the receive WQE, using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information contained in the scatter-gather list of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_RECV(&ds[num_ds], &wr->wr_sgl[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* put the null sgl pointer as well if needed */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_ds < qp->qp_rq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_RECV(&ds[num_ds], &null_sgl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wqe_srq_build()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wqe_srq_build(hermon_state_t *state, hermon_srqhdl_t srq,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_recv_wr_t *wr, uint64_t *desc)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_wqe_sgl_t *ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, num_ds;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&srq->srq_lock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Fill in the Data Segments (SGL) for the Recv WQE */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ds = (hermon_hw_wqe_sgl_t *)((uintptr_t)desc +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_srq_wqe_next_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for valid number of SGL entries */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_nds > srq->srq_wq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_SGL_LEN_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For each SGL in the Recv Work Request, fill in the Recv WQE's data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * segments. Note: We skip any SGL with zero size because Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware cannot handle a zero for "byte_cnt" in the WQE. Actually
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the encoding for zero means a 2GB transfer. Because of this special
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * encoding in the hardware, we mask the requested length with
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HERMON_WQE_SGL_BYTE_CNT_MASK (so that 2GB will end up encoded as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * zero.)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < wr->wr_nds; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_sgl[i].ds_len == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the Data Segment(s) for the receive WQE, using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information contained in the scatter-gather list of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_RECV(&ds[num_ds], &wr->wr_sgl[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ds++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * put in the null sgl pointer as well, if needed
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (num_ds < srq->srq_wq_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WQE_BUILD_DATA_SEG_RECV(&ds[num_ds], &null_sgl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wr_get_immediate()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint32_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wr_get_immediate(ibt_send_wr_t *wr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This routine extracts the "immediate data" from the appropriate
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * location in the IBTF work request. Because of the way the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * work request structure is defined, the location for this data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * depends on the actual work request operation type.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* For RDMA Write, test if RC or UC */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_RDMAW) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_trans == IBT_RC_SRV) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wr->wr.rc.rcwr.rdma.rdma_immed);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else { /* IBT_UC_SRV */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wr->wr.uc.ucwr.rdma.rdma_immed);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* For Send, test if RC, UD, or UC */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_opcode == IBT_WRC_SEND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wr->wr_trans == IBT_RC_SRV) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wr->wr.rc.rcwr.send_immed);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (wr->wr_trans == IBT_UD_SRV) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wr->wr.ud.udwr_immed);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else { /* IBT_UC_SRV */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wr->wr.uc.ucwr.send_immed);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If any other type of request, then immediate is undefined
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wqe_headroom()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: can be called from interrupt or base, currently only from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Routine that fills in the headroom for the Send Queue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wqe_headroom(uint_t from, hermon_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *wqe_start, *wqe_top, *wqe_base, qsize;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int hdrmwqes, wqesizebytes, sectperwqe;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t invalue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qsize = qp->qp_sq_bufsz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqesizebytes = 1 << qp->qp_sq_log_wqesz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sectperwqe = wqesizebytes >> 6; /* 64 bytes/section */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdrmwqes = qp->qp_sq_hdrmwqes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_base = (uint32_t *)HERMON_QP_SQ_ENTRY(qp, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_top = (uint32_t *)HERMON_QP_SQ_ENTRY(qp, qsize);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start = (uint32_t *)HERMON_QP_SQ_ENTRY(qp, from);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < hdrmwqes; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < sectperwqe; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (j == 0) { /* 1st section of wqe */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* perserve ownership bit */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor invalue = ddi_get32(qp->qp_wqinfo.qa_acchdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start) | 0x7FFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* or just invalidate it */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor invalue = 0xFFFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(qp->qp_wqinfo.qa_acchdl, wqe_start, invalue);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start += 16; /* move 64 bytes */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wqe_start == wqe_top) /* hit the end of the queue */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqe_start = wqe_base; /* wrap to start */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wr_bind_check()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wr_bind_check(hermon_state_t *state, ibt_send_wr_t *wr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_bind_flags_t bind_flags;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t vaddr, len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t reg_start_addr, reg_end_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mwhdl_t mw;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mrhdl_t mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *mpt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t new_rkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for a valid Memory Window handle in the WR */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mw = (hermon_mwhdl_t)wr->wr.rc.rcwr.bind->bind_ibt_mw_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mw == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MW_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for a valid Memory Region handle in the WR */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr = (hermon_mrhdl_t)wr->wr.rc.rcwr.bind->bind_ibt_mr_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mr == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check here to see if the memory region has already been partially
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * deregistered as a result of a hermon_umap_umemlock_cb() callback.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If so, this is an error, return failure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((mr->mr_is_umem) && (mr->mr_umemcookie == NULL)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for a valid Memory Window RKey (i.e. a matching RKey) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mw->mr_rkey != wr->wr.rc.rcwr.bind->bind_rkey) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_RKEY_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for a valid Memory Region LKey (i.e. a matching LKey) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mr->mr_lkey != wr->wr.rc.rcwr.bind->bind_lkey) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_LKEY_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now check for valid "vaddr" and "len". Note: We don't check the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "vaddr" range when "len == 0" (i.e. on unbind operations)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor len = wr->wr.rc.rcwr.bind->bind_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (len != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vaddr = wr->wr.rc.rcwr.bind->bind_va;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor reg_start_addr = mr->mr_bindinfo.bi_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor reg_end_addr = mr->mr_bindinfo.bi_addr +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (mr->mr_bindinfo.bi_len - 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((vaddr < reg_start_addr) || (vaddr > reg_end_addr)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_VA_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vaddr = (vaddr + len) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (vaddr > reg_end_addr) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_LEN_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Validate the bind access flags. Remote Write and Atomic access for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the Memory Window require that Local Write access be set in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * corresponding Memory Region.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind_flags = wr->wr.rc.rcwr.bind->bind_flags;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (((bind_flags & IBT_WR_BIND_WRITE) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (bind_flags & IBT_WR_BIND_ATOMIC)) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor !(mr->mr_accflag & IBT_MR_LOCAL_WRITE)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MR_ACCESS_REQ_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Calculate the new RKey for the Memory Window */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mpt = mw->mr_mptrsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_rkey = hermon_mr_keycalc(mpt->hr_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_rkey = hermon_mr_key_swap(new_rkey);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wr->wr.rc.rcwr.bind->bind_rkey_out = new_rkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mw->mr_rkey = new_rkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mw->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wrid_from_reset_handling()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_from_reset_handling(hermon_state_t *state, hermon_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *swq, *rwq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USER_MAP)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_enter(&qp->qp_rq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_sq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* grab the cq lock(s) to modify the wqavl tree */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_enter(&qp->qp_rq_cqhdl->cq_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl != qp->qp_sq_cqhdl &&
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor qp->qp_sq_cqhdl != NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_sq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Chain the newly allocated work queue header to the CQ's list */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_sq_cqhdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_cq_workq_add(qp->qp_sq_cqhdl, &qp->qp_sq_wqavl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor swq = qp->qp_sq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor swq->wq_head = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor swq->wq_tail = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor swq->wq_full = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now we repeat all the above operations for the receive work queue,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or shared receive work queue.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: We still use the 'qp_rq_cqhdl' even in the SRQ case.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rwq = qp->qp_rq_wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rwq->wq_head = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rwq->wq_tail = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rwq->wq_full = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp->qp_rq_wqecntr = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cq_workq_add(qp->qp_rq_cqhdl, &qp->qp_rq_wqavl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_cqhdl->cq_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_exit(&qp->qp_rq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl != qp->qp_sq_cqhdl &&
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor qp->qp_sq_cqhdl != NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_cqhdl->cq_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_exit(&qp->qp_rq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wrid_to_reset_handling()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_to_reset_handling(hermon_state_t *state, hermon_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USER_MAP)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If there are unpolled entries in these CQs, they are
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * polled/flushed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Grab the CQ lock(s) before manipulating the lists.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_enter(&qp->qp_rq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_sq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* grab the cq lock(s) to modify the wqavl tree */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_enter(&qp->qp_rq_cqhdl->cq_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl != qp->qp_sq_cqhdl &&
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor qp->qp_sq_cqhdl != NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_sq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Flush the entries on the CQ for this QP's QPN.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cq_entries_flush(state, qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_srqhdl->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cq_workq_remove(qp->qp_rq_cqhdl, &qp->qp_rq_wqavl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_sq_cqhdl != NULL)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_cq_workq_remove(qp->qp_sq_cqhdl, &qp->qp_sq_wqavl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_cqhdl->cq_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_exit(&qp->qp_rq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl != qp->qp_sq_cqhdl &&
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor qp->qp_sq_cqhdl != NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_sq_cqhdl->cq_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (qp->qp_rq_cqhdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_exit(&qp->qp_rq_cqhdl->cq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wrid_get_entry()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Tayloruint64_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_get_entry(hermon_cqhdl_t cq, hermon_hw_cqe_t *cqe)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_avl_t *wqa;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t wrid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t send_or_recv, qpnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether this CQE is a send or receive completion.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor send_or_recv = HERMON_CQE_SENDRECV_GET(cq, cqe);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Find the work queue for this QP number (send or receive side) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qpnum = HERMON_CQE_QPNUM_GET(cq, cqe);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqa = hermon_wrid_wqavl_find(cq, qpnum, send_or_recv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq = wqa->wqa_wq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Regardless of whether the completion is the result of a "success"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or a "failure", we lock the list of "containers" and attempt to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * search for the the first matching completion (i.e. the first WR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with a matching WQE addr and size). Once we find it, we pull out
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the "wrid" field and return it (see below). XXX Note: One possible
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * future enhancement would be to enable this routine to skip over
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * any "unsignaled" completions to go directly to the next "signaled"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entry on success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor indx = HERMON_CQE_WQEADDRSZ_GET(cq, cqe) & wq->wq_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wrid = wq->wq_wrid[indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wqa->wqa_srq_en) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor struct hermon_sw_srq_s *srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* put wqe back on the srq free list */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq = wqa->wqa_srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = HERMON_SRQ_WQE_ADDR(srq, wq->wq_tail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint16_t *)desc)[1] = htons(indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_tail = indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_head = (indx + 1) & wq->wq_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wq->wq_full = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wrid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_workq_compare(const void *p1, const void *p2)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_compare_t *cmpp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_avl_t *curr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmpp = (hermon_workq_compare_t *)p1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr = (hermon_workq_avl_t *)p2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (cmpp->cmp_qpn < curr->wqa_qpn)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (-1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (cmpp->cmp_qpn > curr->wqa_qpn)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (+1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (cmpp->cmp_type < curr->wqa_type)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (-1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (cmpp->cmp_type > curr->wqa_type)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (+1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wrid_workq_find()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic hermon_workq_avl_t *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_wqavl_find(hermon_cqhdl_t cq, uint_t qpn, uint_t wq_type)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_avl_t *curr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_compare_t cmp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Walk the CQ's work queue list, trying to find a send or recv queue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with the same QP number. We do this even if we are going to later
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * create a new entry because it helps us easily find the end of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * list.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmp.cmp_qpn = qpn;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmp.cmp_type = wq_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wrid_workq_compare(NULL, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr = avl_find(&cq->cq_wrid_wqhdr_avl_tree, &cmp, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (curr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_wrid_wqhdr_create()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_workq_hdr_t *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_wqhdr_create(int bufsz)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_hdr_t *wqhdr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate space for the wqhdr, and an array to record all the wrids.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqhdr = (hermon_workq_hdr_t *)kmem_zalloc(sizeof (*wqhdr), KM_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wqhdr == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*wqhdr))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqhdr->wq_wrid = kmem_zalloc(bufsz * sizeof (uint64_t), KM_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wqhdr->wq_wrid == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wqhdr, sizeof (*wqhdr));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqhdr->wq_size = bufsz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqhdr->wq_mask = bufsz - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (wqhdr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_wrid_wqhdr_destroy(hermon_workq_hdr_t *wqhdr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wqhdr->wq_wrid, wqhdr->wq_size * sizeof (uint64_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wqhdr, sizeof (*wqhdr));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_cq_workq_add()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_cq_workq_add(hermon_cqhdl_t cq, hermon_workq_avl_t *wqavl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_workq_compare_t cmp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor avl_index_t where;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmp.cmp_qpn = wqavl->wqa_qpn;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmp.cmp_type = wqavl->wqa_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wrid_workq_compare(NULL, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) avl_find(&cq->cq_wrid_wqhdr_avl_tree, &cmp, &where);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor avl_insert(&cq->cq_wrid_wqhdr_avl_tree, wqavl, where);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_cq_workq_remove()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_cq_workq_remove(hermon_cqhdl_t cq, hermon_workq_avl_t *wqavl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wrid_workq_compare(NULL, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor avl_remove(&cq->cq_wrid_wqhdr_avl_tree, wqavl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}