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_srq.c
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon Shared Receive Queue Processing Routines
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements all the routines necessary for allocating, freeing, querying,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * modifying and posting shared receive queues.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek#include <sys/sysmacros.h>
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/bitmap.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ib/adapters/hermon/hermon.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srq_alloc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srq_alloc(hermon_state_t *state, hermon_srq_info_t *srqinfo,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_srq_hdl_t ibt_srqhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pdhdl_t pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_srq_sizes_t *sizes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_srq_sizes_t *real_sizes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_srqhdl_t *srqhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_srq_flags_t flags;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *srqc, *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_srqc_t srqc_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_srqhdl_t srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_entry_t *umapdb;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_mr_attr_t mr_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mr_options_t mr_op;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mrhdl_t mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t value, srq_desc_off;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t log_srq_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t uarpg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t srq_is_umap;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int flag, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t max_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t wqesz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t srq_wr_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sizes))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * options-->wq_location used to be for location, now explicitly
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * LOCATION_NORMAL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Extract the necessary info from the hermon_srq_info_t structure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor real_sizes = srqinfo->srqi_real_sizes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizes = srqinfo->srqi_sizes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd = srqinfo->srqi_pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_srqhdl = srqinfo->srqi_ibt_srqhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor flags = srqinfo->srqi_flags;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqhdl = srqinfo->srqi_srqhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether SRQ is being allocated for userland access or
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * whether it is being allocated for kernel access. If the SRQ is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * being allocated for userland access, then lookup the UAR doorbell
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * page number for the current process. Note: If this is not found
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (e.g. if the process has not previously open()'d the Hermon driver),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then an error is returned.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq_is_umap = (flags & IBT_SRQ_USER_MAP) ? 1 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_umap_db_find(state->hs_instance, ddi_get_pid(),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor MLNX_UMAP_UARPG_RSRC, &value, 0, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INVALID_PARAM;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uarpg = ((hermon_rsrc_t *)(uintptr_t)value)->hr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uarpg = state->hs_kernel_uar_index;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Increase PD refcnt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pd_refcnt_inc(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate an SRQ context entry */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_SRQC, 1, sleepflag, &srqc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate the SRQ Handle entry */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_SRQHDL, 1, sleepflag, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq = (hermon_srqhdl_t)rsrc->hr_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(srq, sizeof (struct hermon_sw_srq_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Calculate the SRQ number */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* just use the index, implicit in Hermon */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_srqnum = srqc->hr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this will be a user-mappable SRQ, then allocate an entry for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the "userland resources database". This will later be added to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the database (after all further SRQ operations are successful).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we fail here, we must undo the reference counts and the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * previous resource allocation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor umapdb = hermon_umap_db_alloc(state->hs_instance,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t)(uintptr_t)rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (umapdb == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the doorbell record. Hermon just needs one for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SRQ, and use uarpg (above) as the uar index
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_dbr_alloc(state, uarpg, &srq->srq_wq_dbr_acchdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &srq->srq_wq_vdbr, &srq->srq_wq_pdbr, &srq->srq_rdbr_mapoffset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the appropriate size for the SRQ.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: All Hermon SRQs must be a power-of-2 in size. Also
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is to round the requested size up to the next highest power-of-2
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq_wr_sz = max(sizes->srq_wr_sz + 1, HERMON_SRQ_MIN_SIZE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log_srq_size = highbit(srq_wr_sz);
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek if (ISP2(srq_wr_sz)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log_srq_size = log_srq_size - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Next we verify that the rounded-up size is valid (i.e. consistent
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with the device limits and/or software-configured limits). If not,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then obviously we have a lot of cleanup to do before returning.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_HCA_WR_EXCEEDED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail4a;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Next we verify that the requested number of SGL is valid (i.e.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * consistent with the device limits and/or software-configured
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * limits). If not, then obviously the same cleanup needs to be done.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_sgl = state->hs_ibtfinfo.hca_attr->hca_max_srq_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sizes->srq_sgl_sz > max_sgl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_HCA_SGL_EXCEEDED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail4a;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine the SRQ's WQE sizes. This depends on the requested
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * number of SGLs. Note: This also has the side-effect of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * calculating the real number of SGLs (for the calculated WQE size)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_srq_sgl_to_logwqesz(state, sizes->srq_sgl_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_QP_WQ_TYPE_RECVQ, &srq->srq_wq_log_wqesz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &srq->srq_wq_sgl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the memory for SRQ work queues. Note: The location from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * which we will allocate these work queues is always
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * QUEUE_LOCATION_NORMAL. Since Hermon work queues are not
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * allowed to cross a 32-bit (4GB) boundary, the alignment of the work
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * queue memory is very important. We used to allocate work queues
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (the combined receive and send queues) so that they would be aligned
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * on their combined size. That alignment guaranteed that they would
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * never cross the 4GB boundary (Hermon work queues are on the order of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MBs at maximum). Now we are able to relax this alignment constraint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * by ensuring that the IB address assigned to the queue memory (as a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * result of the hermon_mr_register() call) is offset from zero.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Previously, we had wanted to use the ddi_dma_mem_alloc() routine to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * guarantee the alignment, but when attempting to use IOMMU bypass
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mode we found that we were not allowed to specify any alignment that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * was more restrictive than the system page size. So we avoided this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * constraint by passing two alignment values, one for the memory
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * allocation itself and the other for the DMA handle (for later bind).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This used to cause more memory than necessary to be allocated (in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * order to guarantee the more restrictive alignment contraint). But
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be guaranteeing the zero-based IB virtual address for the queue, we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * are able to conserve this memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: If SRQ is not user-mappable, then it may come from either
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * kernel system memory or from HCA-attached local DDR memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note2: We align this queue on a pagesize boundary. This is required
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to make sure that all the resulting IB addresses will start at 0, for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a zero-based queue. By making sure we are aligned on at least a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * page, any offset we use into our queue will be the same as when we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * perform hermon_srq_modify() operations later.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqesz = (1 << srq->srq_wq_log_wqesz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wqinfo.qa_size = (1 << log_srq_size) * wqesz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wqinfo.qa_alloc_align = PAGESIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wqinfo.qa_bind_align = PAGESIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wqinfo.qa_location = HERMON_QUEUE_LOCATION_USERLAND;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wqinfo.qa_location = HERMON_QUEUE_LOCATION_NORMAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_queue_alloc(state, &srq->srq_wqinfo, sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail4a;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor buf = (uint32_t *)srq->srq_wqinfo.qa_buf_aligned;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*buf))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Register the memory for the SRQ work queues. The memory for the SRQ
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * must be registered in the Hermon cMPT tables. This gives us the LKey
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to specify in the SRQ context later. Note: If the work queue is to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be allocated from DDR memory, then only a "bypass" mapping is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * appropriate. And if the SRQ memory is user-mappable, then we force
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * DDI_DMA_CONSISTENT mapping. Also, in order to meet the alignment
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * restriction, we pass the "mro_bind_override_addr" flag in the call
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to hermon_mr_register(). This guarantees that the resulting IB vaddr
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will be zero-based (modulo the offset into the first page). If we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fail here, we still have the bunch of resource and reference count
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * cleanup to do.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor flag = (sleepflag == HERMON_SLEEP) ? IBT_MR_SLEEP :
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_MR_NOSLEEP;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_vaddr = (uint64_t)(uintptr_t)buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_len = srq->srq_wqinfo.qa_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_as = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_flags = flag | IBT_MR_ENABLE_LOCAL_WRITE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_op.mro_bind_type = state->hs_cfg_profile->cp_iommu_bypass;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_op.mro_bind_dmahdl = srq->srq_wqinfo.qa_dmahdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_op.mro_bind_override_addr = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_mr_register(state, pd, &mr_attr, &mr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &mr_op, HERMON_SRQ_CMPT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mr))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the offset between the kernel virtual address space
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and the IB virtual address space. This will be used when
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * posting work requests to properly initialize each WQE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq_desc_off = (uint64_t)(uintptr_t)srq->srq_wqinfo.qa_buf_aligned -
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t)mr->mr_bindinfo.bi_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_wqhdr = hermon_wrid_wqhdr_create(1 << log_srq_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in all the return arguments (if necessary). This includes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * real queue size and real SGLs.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (real_sizes != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor real_sizes->srq_wr_sz = (1 << log_srq_size) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor real_sizes->srq_sgl_sz = srq->srq_wq_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the SRQC entry. This is the final step before passing
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ownership of the SRQC entry to the Hermon hardware. We use all of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information collected/calculated above to fill in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * requisite portions of the SRQC. Note: If this SRQ is going to be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * used for userland access, then we need to set the UAR page number
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * appropriately (otherwise it's a "don't care")
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&srqc_entry, sizeof (hermon_hw_srqc_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.state = HERMON_SRQ_STATE_HW_OWNER;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.log_srq_size = log_srq_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.srqn = srq->srq_srqnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.log_rq_stride = srq->srq_wq_log_wqesz - 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* 16-byte chunks */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.page_offs = srq->srq_wqinfo.qa_pgoffs >> 6;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.log2_pgsz = mr->mr_log2_pgsz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.mtt_base_addrh = (uint32_t)((mr->mr_mttaddr >> 32) & 0xFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.mtt_base_addrl = mr->mr_mttaddr >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.pd = pd->pd_pdnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.dbr_addrh = (uint32_t)((uint64_t)srq->srq_wq_pdbr >> 32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.dbr_addrl = (uint32_t)((uint64_t)srq->srq_wq_pdbr >> 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all others - specifically, xrcd, cqn_xrc, lwm, wqe_cnt, and wqe_cntr
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * are zero thanks to the bzero of the structure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Write the SRQC entry to hardware. Lastly, we pass ownership of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the entry to the hardware (using the Hermon SW2HW_SRQ firmware
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * command). Note: In general, this operation shouldn't fail. But
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * if it does, we have to undo everything we've done above before
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * returning error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_ownership_cmd_post(state, SW2HW_SRQ, &srqc_entry,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_srqc_t), srq->srq_srqnum,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: SW2HW_SRQ command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == HERMON_CMD_INVALID_STATUS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ibc_get_ci_failure(0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqalloc_fail8;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the rest of the Hermon SRQ handle. We can update
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the following fields for use in further operations on the SRQ.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_srqcrsrcp = srqc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_rsrcp = rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_mrhdl = mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_refcnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_is_umap = srq_is_umap;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_uarpg = uarpg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_umap_dhp = (devmap_cookie_t)NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_pdhdl = pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_bufsz = (1 << log_srq_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_buf = buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_desc_off = srq_desc_off;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_hdlrarg = (void *)ibt_srqhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_state = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_real_sizes.srq_wr_sz = (1 << log_srq_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_real_sizes.srq_sgl_sz = srq->srq_wq_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Put SRQ handle in Hermon SRQNum-to-SRQhdl list. Then fill in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "srqhdl" and return success
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_icm_set_num_to_hdl(state, HERMON_SRQC, srqc->hr_indx, srq);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is a user-mappable SRQ, then we need to insert the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * previously allocated entry into the "userland resources database".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This will allow for later lookup during devmap() (i.e. mmap())
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * calls.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_add(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else { /* initialize work queue for kernel SRQs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, len, last;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint16_t *desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc = (uint16_t *)buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor len = wqesz / sizeof (*desc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor last = srq->srq_wq_bufsz - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < last; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc[1] = htons(i + 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor desc += len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_wqhdr->wq_tail = last;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_wqhdr->wq_head = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *srqhdl = srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The following is cleanup for all possible failure cases in this routine
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail8:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wrid_wqhdr_destroy(srq->srq_wq_wqhdr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail7:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_mr_deregister(state, &mr, HERMON_MR_DEREG_ALL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SLEEPFLAG_FOR_CONTEXT()) != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to deregister SRQ memory");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail5:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_queue_free(&srq->srq_wqinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail4a:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dbr_free(state, uarpg, srq->srq_wq_vdbr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail4:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_free(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail3:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail2:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &srqc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail1:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pd_refcnt_dec(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqalloc_fail:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srq_free()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srq_free(hermon_state_t *state, hermon_srqhdl_t *srqhdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *srqc, *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_entry_t *umapdb;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t value;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_srqhdl_t srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mrhdl_t mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pdhdl_t pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_srqc_t srqc_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t srqnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t maxprot;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pull all the necessary information from the Hermon Shared Receive
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Queue handle. This is necessary here because the resource for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SRQ handle is going to be freed up as part of this operation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq = *srqhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc = srq->srq_srqcrsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rsrc = srq->srq_rsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd = srq->srq_pdhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr = srq->srq_mrhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqnum = srq->srq_srqnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If there are work queues still associated with the SRQ, then return
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * an error. Otherwise, we will be holding the SRQ lock.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_refcnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_SRQ_IN_USE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this was a user-mappable SRQ, then we need to remove its entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from the "userland resources database". If it is also currently
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mmap()'d out to a user process, then we need to call
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * devmap_devmem_remap() to remap the SRQ memory to an invalid mapping.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We also need to invalidate the SRQ tracking information for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * user mapping.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_umap_db_find(state->hs_instance,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC, &value,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_UMAP_DB_REMOVE, &umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to find in database");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_free(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_umap_dhp != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = devmap_devmem_remap(srq->srq_umap_dhp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_dip, 0, 0, srq->srq_wqinfo.qa_size,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxprot, DEVMAP_MAPPING_INVALID, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed in SRQ memory "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "devmap_devmem_remap()");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_umap_dhp = (devmap_cookie_t)NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Put NULL into the Hermon SRQNum-to-SRQHdl list. This will allow any
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in-progress events to detect that the SRQ corresponding to this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * number has been freed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_icm_set_num_to_hdl(state, HERMON_SRQC, srqc->hr_indx, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*srq));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Reclaim SRQC entry from hardware (using the Hermon HW2SW_SRQ
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware command). If the ownership transfer fails for any reason,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then it is an indication that something (either in HW or SW) has
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_ownership_cmd_post(state, HW2SW_SRQ, &srqc_entry,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_srqc_t), srqnum, sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to reclaim SRQC ownership");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: HW2SW_SRQ command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == HERMON_CMD_INVALID_STATUS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Deregister the memory for the Shared Receive Queue. If this fails
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for any reason, then it is an indication that something (either
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in HW or SW) has gone seriously wrong. So we print a warning
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * message and return.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_mr_deregister(state, &mr, HERMON_MR_DEREG_ALL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to deregister SRQ memory");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_wrid_wqhdr_destroy(srq->srq_wq_wqhdr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the memory for the SRQ */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_queue_free(&srq->srq_wqinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the dbr */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dbr_free(state, srq->srq_uarpg, srq->srq_wq_vdbr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the Hermon SRQ Handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the SRQC entry resource */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &srqc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Decrement the reference count on the protection domain (PD) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pd_refcnt_dec(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the srqhdl pointer to NULL and return success */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *srqhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srq_modify()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srq_modify(hermon_state_t *state, hermon_srqhdl_t srq, uint_t size,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t *real_size, uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qalloc_info_t new_srqinfo, old_srqinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *mtt, *old_mtt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_bind_info_t bind;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_bind_info_t old_bind;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mrhdl_t mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_srqc_t srqc_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_dmpt_t mpt_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t *wre_new, *wre_old;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t mtt_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t srq_pgoffs;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t srq_desc_off;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *buf, srq_old_bufsz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t wqesz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t max_srq_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t mtt_pgsize_bits;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t log_srq_size, maxprot;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_devlim.mod_wr_srq == 0) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_cfg_profile->cp_srq_resize_enabled == 0))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_NOT_SUPPORTED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If size requested is larger than device capability, return
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Insufficient Resources
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_srq_size = (1 << state->hs_cfg_profile->cp_log_max_srq_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (size > max_srq_size) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_HCA_WR_EXCEEDED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the appropriate size for the SRQ.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: All Hermon SRQs must be a power-of-2 in size. Also
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is to round the requested size up to the next highest power-of-2
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor size = max(size, HERMON_SRQ_MIN_SIZE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log_srq_size = highbit(size);
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek if (ISP2(size)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log_srq_size = log_srq_size - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Next we verify that the rounded-up size is valid (i.e. consistent
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with the device limits and/or software-configured limits).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_HCA_WR_EXCEEDED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqmodify_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the memory for newly resized Shared Receive Queue.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: If SRQ is not user-mappable, then it may come from either
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * kernel system memory or from HCA-attached local DDR memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note2: We align this queue on a pagesize boundary. This is required
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to make sure that all the resulting IB addresses will start at 0,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for a zero-based queue. By making sure we are aligned on at least a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * page, any offset we use into our queue will be the same as it was
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * when we allocated it at hermon_srq_alloc() time.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wqesz = (1 << srq->srq_wq_log_wqesz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_srqinfo.qa_size = (1 << log_srq_size) * wqesz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_srqinfo.qa_alloc_align = PAGESIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_srqinfo.qa_bind_align = PAGESIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (srq->srq_is_umap) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_srqinfo.qa_location = HERMON_QUEUE_LOCATION_USERLAND;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor new_srqinfo.qa_location = HERMON_QUEUE_LOCATION_NORMAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_queue_alloc(state, &new_srqinfo, sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqmodify_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor buf = (uint32_t *)new_srqinfo.qa_buf_aligned;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*buf))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the memory for the new WRE list. This will be used later
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * when we resize the wridlist based on the new SRQ size.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wre_new = kmem_zalloc((1 << log_srq_size) * sizeof (uint64_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (wre_new == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = IBT_INSUFF_RESOURCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqmodify_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the "bind" struct. This struct provides the majority
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * of the information that will be used to distinguish between an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "addr" binding (as is the case here) and a "buf" binding (see
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * below). The "bind" struct is later passed to hermon_mr_mem_bind()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * which does most of the "heavy lifting" for the Hermon memory
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * registration routines.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(bind))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&bind, sizeof (hermon_bind_info_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_type = HERMON_BINDHDL_VADDR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_addr = (uint64_t)(uintptr_t)buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_len = new_srqinfo.qa_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_as = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_flags = sleepflag == HERMON_SLEEP ? IBT_MR_SLEEP :
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_MR_NOSLEEP | IBT_MR_ENABLE_LOCAL_WRITE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_bypass = state->hs_cfg_profile->cp_iommu_bypass;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_mr_mtt_bind(state, &bind, new_srqinfo.qa_dmahdl, &mtt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &mtt_pgsize_bits, 0); /* no relaxed ordering */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wre_new, (1 << log_srq_size) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (uint64_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_queue_free(&new_srqinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqmodify_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the offset between the kernel virtual address space
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and the IB virtual address space. This will be used when
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * posting work requests to properly initialize each WQE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: bind addr is zero-based (from alloc) so we calculate the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * correct new offset here.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bind.bi_addr = bind.bi_addr & ((1 << mtt_pgsize_bits) - 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq_desc_off = (uint64_t)(uintptr_t)new_srqinfo.qa_buf_aligned -
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t)bind.bi_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq_pgoffs = (uint_t)
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor ((uintptr_t)new_srqinfo.qa_buf_aligned & HERMON_PAGEOFFSET);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the MPT entry. This is the final step before passing
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ownership of the MPT entry to the Hermon hardware. We use all of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information collected/calculated above to fill in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * requisite portions of the MPT.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&mpt_entry, sizeof (hermon_hw_dmpt_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mpt_entry.reg_win_len = bind.bi_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mtt_addr = (mtt->hr_indx << HERMON_MTT_SIZE_SHIFT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mpt_entry.mtt_addr_h = mtt_addr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mpt_entry.mtt_addr_l = mtt_addr >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for hermon we build up a new srqc and pass that (partially filled
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to resize SRQ instead of modifying the (d)mpt directly
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now we grab the SRQ lock. Since we will be updating the actual
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SRQ location and the producer/consumer indexes, we should hold
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the lock.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We do a HERMON_NOSLEEP here (and below), though, because we are
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * holding the "srq_lock" and if we got raised to interrupt level
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * by priority inversion, we would not want to block in this routine
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * waiting for success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copy old entries to new buffer
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq_old_bufsz = srq->srq_wq_bufsz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bcopy(srq->srq_wq_buf, buf, srq_old_bufsz * wqesz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Setup MPT information for use in the MODIFY_MPT command
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr = srq->srq_mrhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * now, setup the srqc information needed for resize - limit the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * values, but use the same structure as the srqc
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.log_srq_size = log_srq_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.page_offs = srq_pgoffs >> 6;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.log2_pgsz = mr->mr_log2_pgsz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.mtt_base_addrl = (uint64_t)mtt_addr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqc_entry.mtt_base_addrh = mtt_addr >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * RESIZE_SRQ
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this fails for any reason, then it is an indication that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * something (either in HW or SW) has gone seriously wrong. So we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * print a warning message and return.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_resize_srq_cmd_post(state, &srqc_entry,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_srqnum, sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: RESIZE_SRQ command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == HERMON_CMD_INVALID_STATUS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_mr_mtt_unbind(state, &bind, mtt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wre_new, (1 << log_srq_size) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (uint64_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_queue_free(&new_srqinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Update the Hermon Shared Receive Queue handle with all the new
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information. At the same time, save away all the necessary
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information for freeing up the old resources
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor old_srqinfo = srq->srq_wqinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor old_mtt = srq->srq_mrhdl->mr_mttrsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bcopy(&srq->srq_mrhdl->mr_bindinfo, &old_bind,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_bind_info_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Now set the new info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wqinfo = new_srqinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_buf = buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_bufsz = (1 << log_srq_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bcopy(&bind, &srq->srq_mrhdl->mr_bindinfo, sizeof (hermon_bind_info_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_mrhdl->mr_mttrsrcp = mtt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_desc_off = srq_desc_off;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_real_sizes.srq_wr_sz = (1 << log_srq_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Update MR mtt pagesize */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr->mr_logmttpgsz = mtt_pgsize_bits;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&mr->mr_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize new wridlist, if needed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If a wridlist already is setup on an SRQ (the QP associated with an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SRQ has moved "from_reset") then we must update this wridlist based
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * on the new SRQ size. We allocate the new size of Work Request ID
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Entries, copy over the old entries to the new list, and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * re-initialize the srq wridlist in non-umap case
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor wre_old = srq->srq_wq_wqhdr->wq_wrid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bcopy(wre_old, wre_new, srq_old_bufsz * sizeof (uint64_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup new sizes in wre */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_wq_wqhdr->wq_wrid = wre_new;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If "old" SRQ was a user-mappable SRQ that is currently mmap()'d out
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to a user process, then we need to call devmap_devmem_remap() to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * invalidate the mapping to the SRQ memory. We also need to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * invalidate the SRQ tracking information for the user mapping.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: On failure, the remap really shouldn't ever happen. So, if it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * does, it is an indication that something has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * So we print a warning message and return error (knowing, of course,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the "old" SRQ memory will be leaked)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((srq->srq_is_umap) && (srq->srq_umap_dhp != NULL)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxprot = (PROT_READ | PROT_WRITE | PROT_USER);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = devmap_devmem_remap(srq->srq_umap_dhp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_dip, 0, 0, srq->srq_wqinfo.qa_size, maxprot,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DEVMAP_MAPPING_INVALID, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed in SRQ memory "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "devmap_devmem_remap()");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* We can, however, free the memory for old wre */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wre_old, srq_old_bufsz * sizeof (uint64_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_umap_dhp = (devmap_cookie_t)NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Drop the SRQ lock now. The only thing left to do is to free up
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the old resources.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Unbind the MTT entries.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_mr_mtt_unbind(state, &old_bind, old_mtt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to unbind old SRQ memory");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ibc_get_ci_failure(0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto srqmodify_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the memory for old wre */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(wre_old, srq_old_bufsz * sizeof (uint64_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the memory for the old SRQ */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_queue_free(&old_srqinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the return arguments (if necessary). This includes the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * real new completion queue size.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (real_size != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *real_size = (1 << log_srq_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorsrqmodify_fail:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srq_refcnt_inc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srq_refcnt_inc(hermon_srqhdl_t srq)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_refcnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srq_refcnt_dec()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srq_refcnt_dec(hermon_srqhdl_t srq)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srq->srq_refcnt--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&srq->srq_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srqhdl_from_srqnum()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This routine is important because changing the unconstrained
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * portion of the SRQ number is critical to the detection of a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * potential race condition in the SRQ handler code (i.e. the case
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * where a SRQ is freed and alloc'd again before an event for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "old" SRQ can be handled).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * While this is not a perfect solution (not sure that one exists)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it does help to mitigate the chance that this race condition will
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * cause us to deliver a "stale" event to the new SRQ owner. Note:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this solution does not scale well because the number of constrained
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * bits increases (and, hence, the number of unconstrained bits
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * decreases) as the number of supported SRQ grows. For small and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * intermediate values, it should hopefully provide sufficient
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * protection.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srqhdl_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srqhdl_from_srqnum(hermon_state_t *state, uint_t srqnum)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t srqindx, srqmask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Calculate the SRQ table index from the srqnum */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqmask = (1 << state->hs_cfg_profile->cp_log_num_srq) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor srqindx = srqnum & srqmask;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (hermon_icm_num_to_hdl(state, HERMON_SRQC, srqindx));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_srq_sgl_to_logwqesz()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t max_size, log2, actual_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (wq_type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_QP_WQ_TYPE_RECVQ:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Use requested maximum SGL to calculate max descriptor size
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (while guaranteeing that the descriptor size is a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * power-of-2 cachelines).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_size = (HERMON_QP_WQE_MLX_SRQ_HDRS + (num_sgl << 4));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log2 = highbit(max_size);
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek if (ISP2(max_size)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log2 = log2 - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Make sure descriptor is at least the minimum size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor log2 = max(log2, HERMON_QP_WQE_LOG_MINIMUM);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Calculate actual number of SGL (given WQE size) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor actual_sgl = ((1 << log2) - HERMON_QP_WQE_MLX_SRQ_HDRS) >> 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "unexpected work queue type");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Fill in the return values */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *logwqesz = log2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *max_sgl = min(state->hs_cfg_profile->cp_srq_max_sgl, actual_sgl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}