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/*
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Use is subject to license terms.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_misc.c
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor Miscellaneous routines - Address Handle, Multicast, Protection
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Domain, and port-related operations
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements all the routines necessary for allocating, freeing, querying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and modifying Address Handles and Protection Domains. Also implements
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all the routines necessary for adding and removing Queue Pairs to/from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Multicast Groups. Lastly, it implements the routines necessary for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * port-related query and modify operations.
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/bitmap.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/sysmacros.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ib/adapters/tavor/tavor.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void tavor_udav_sync(tavor_ahhdl_t ah, tavor_hw_udav_t *udav,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t flag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_mcg_qplist_add(tavor_state_t *state, tavor_mcghdl_t mcg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_qp_list_t *mcg_qplist, tavor_qphdl_t qp, uint_t *qp_found);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_mcg_qplist_remove(tavor_mcghdl_t mcg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_qp_list_t *mcg_qplist, tavor_qphdl_t qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void tavor_qp_mcg_refcnt_inc(tavor_qphdl_t qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void tavor_qp_mcg_refcnt_dec(tavor_qphdl_t qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint_t tavor_mcg_walk_mgid_hash(tavor_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t start_indx, ib_gid_t mgid, uint_t *prev_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void tavor_mcg_setup_new_hdr(tavor_mcghdl_t mcg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_t *mcg_hdr, ib_gid_t mgid, tavor_rsrc_t *mcg_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_mcg_hash_list_remove(tavor_state_t *state, uint_t curr_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t prev_indx, tavor_hw_mcg_t *mcg_entry);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_mcg_entry_invalidate(tavor_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_t *mcg_entry, uint_t indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_mgid_is_valid(ib_gid_t gid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int tavor_mlid_is_valid(ib_lid_t lid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_ah_alloc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_ah_alloc(tavor_state_t *state, tavor_pdhdl_t pd,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_adds_vect_t *attr_p, tavor_ahhdl_t *ahhdl, uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *udav, *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_udav_t udav_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_ahhdl_t ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_mr_attr_t mr_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mr_options_t op;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mrhdl_t mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status, i, flag;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *errormsg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_ah_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Someday maybe the "ibt_adds_vect_t *attr_p" will be NULL to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * indicate that we wish to allocate an "invalid" (i.e. empty)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * address handle XXX
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate that specified port number is legal */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!tavor_portnum_is_valid(state, attr_p->av_port_num)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_HCA_PORT_INVALID, "invalid port num");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto ahalloc_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate a UDAV entry. This will be filled in with all the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * necessary parameters to define the Address Handle. Unlike the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * other hardware resources no ownership transfer takes place as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * these UDAV entries are always owned by hardware.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_rsrc_alloc(state, TAVOR_UDAV, 1, sleepflag, &udav);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed UDAV");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto ahalloc_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the software structure for tracking the address handle
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (i.e. the Tavor Address Handle struct). If we fail here, we must
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * undo the previous resource allocation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_rsrc_alloc(state, TAVOR_AHHDL, 1, sleepflag, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed AH handler");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto ahalloc_fail1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = (tavor_ahhdl_t)rsrc->tr_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ah))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Increment the reference count on the protection domain (PD) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pd_refcnt_inc(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the UDAV entry. Note: We are only filling in a temporary
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * copy here, which we will later copy into the actual entry in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor DDR memory. This starts be zeroing out the temporary copy
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and then calling tavor_set_addr_path() to fill in the common
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * portions that can be pulled from the "ibt_adds_vect_t" passed in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&udav_entry, sizeof (tavor_hw_udav_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_set_addr_path(state, attr_p,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (tavor_hw_addr_path_t *)&udav_entry, TAVOR_ADDRPATH_UDAV, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pd_refcnt_dec(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &udav);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(status, "failed in tavor_set_addr_path");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto ahalloc_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav_entry.pd = pd->pd_pdnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav_entry.msg_sz = state->ts_cfg_profile->cp_max_mtu - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Register the memory for the UDAV. The memory for the UDAV must
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be registered in the Tavor TPT tables. This gives us the LKey
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that we will need when we later post a UD work request that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * uses this address handle.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We might be able to pre-register all the memory for the UDAV XXX
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor flag = (sleepflag == TAVOR_SLEEP) ? IBT_MR_SLEEP : IBT_MR_NOSLEEP;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_vaddr = (uint64_t)(uintptr_t)udav->tr_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_len = udav->tr_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_as = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr_attr.mr_flags = flag;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor op.mro_bind_type = state->ts_cfg_profile->cp_iommu_bypass;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor op.mro_bind_dmahdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor op.mro_bind_override_addr = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mr_register(state, pd, &mr_attr, &mr, &op);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed register mr");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto ahalloc_fail2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the UDAV entry. Here we copy all the information from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the temporary UDAV into the DDR memory for the real UDAV entry.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note that we copy everything but the first 64-bit word. This
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is where the PD number for the address handle resides.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * By filling everything except the PD and then writing the PD in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a separate step below, we can ensure that the UDAV is not
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * accessed while there are partially written values in it (something
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * which really should not happen anyway). This is guaranteed
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * because we take measures to ensure that the PD number is zero for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all unused UDAV (and because PD#0 is reserved for Tavor).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor size = sizeof (tavor_hw_udav_t) >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 1; i < size; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = ((uint64_t *)&udav_entry)[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put64(udav->tr_acchdl, ((uint64_t *)udav->tr_addr + i),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = ((uint64_t *)&udav_entry)[0];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put64(udav->tr_acchdl, (uint64_t *)udav->tr_addr, data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the rest of the Tavor Address Handle struct. Having
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successfully copied the UDAV into the hardware, we update the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * following fields for use in further operations on the AH.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: We are saving away a copy of the "av_dgid.gid_guid" field
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * here because we may need to return it later to the IBTF (as a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * result of a subsequent query operation). Unlike the other UDAV
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * parameters, the value of "av_dgid.gid_guid" is not always preserved
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * by being written to hardware. The reason for this is described in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_set_addr_path().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_udavrsrcp = udav;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_rsrcp = rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_pdhdl = pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_mrhdl = mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_save_guid = attr_p->av_dgid.gid_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_save_srate = attr_p->av_srate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *ahhdl = ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine if later ddi_dma_sync will be necessary */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_sync = TAVOR_UDAV_IS_SYNC_REQ(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Sync the UDAV for use by the hardware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_udav_sync(ah, udav->tr_addr, DDI_DMA_SYNC_FORDEV);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorahalloc_fail2:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pd_refcnt_dec(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorahalloc_fail1:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &udav);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorahalloc_fail:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_ah_alloc_fail, TAVOR_TNF_ERROR, "",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_string, msg, errormsg);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_ah_free()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_ah_free(tavor_state_t *state, tavor_ahhdl_t *ahhdl, uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *udav, *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pdhdl_t pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mrhdl_t mr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_ahhdl_t ah;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_ah_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pull all the necessary information from the Tavor Address Handle
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * struct. This is necessary here because the resource for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * AH is going to be freed up as part of this operation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah = *ahhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav = ah->ah_udavrsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rsrc = ah->ah_rsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd = ah->ah_pdhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mr = ah->ah_mrhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ah))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Deregister the memory for the UDAV. If this fails for any reason,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then it is an indication that something (either in HW or SW) has
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * gone seriously wrong. So we print a warning message and return
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * failure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mr_deregister(state, &mr, TAVOR_MR_DEREG_ALL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sleepflag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_ah_free_dereg_mr_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Write zero to the first 64-bit word in the UDAV entry. As
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * described above (in tavor_ah_alloc), the PD number is stored in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the first 64-bits of each UDAV and setting this to zero is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * guaranteed to invalidate the entry.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put64(udav->tr_acchdl, (uint64_t *)udav->tr_addr, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Sync the UDAV for use by the hardware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_udav_sync(ah, udav->tr_addr, DDI_DMA_SYNC_FORDEV);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Decrement the reference count on the protection domain (PD) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pd_refcnt_dec(pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the Tavor Address Handle structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up the UDAV entry resource */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &udav);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the ahhdl pointer to NULL and return success */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *ahhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_ah_query()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_ah_query(tavor_state_t *state, tavor_ahhdl_t ah, tavor_pdhdl_t *pd,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_adds_vect_t *attr_p)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_udav_t udav_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *udav;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_ah_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*attr_p))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pull all the necessary information from the Tavor Address Handle
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * structure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav = ah->ah_udavrsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *pd = ah->ah_pdhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copy the UDAV entry into the temporary copy. Here we copy all
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the information from the UDAV entry in DDR memory into the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * temporary UDAV. Note: We don't need to sync the UDAV for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * reading by software because Tavor HW never modifies the entry.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor size = sizeof (tavor_hw_udav_t) >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < size; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = ddi_get64(udav->tr_acchdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint64_t *)udav->tr_addr + i));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint64_t *)&udav_entry)[i] = data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in "ibt_adds_vect_t". We call tavor_get_addr_path() to fill
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the common portions that can be pulled from the UDAV we pass in.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: We will also fill the "av_dgid.gid_guid" field from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "ah_save_guid" field we have previously saved away. The reason
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for this is described in tavor_ah_alloc() and tavor_ah_modify().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_get_addr_path(state, (tavor_hw_addr_path_t *)&udav_entry,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor attr_p, TAVOR_ADDRPATH_UDAV, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor attr_p->av_dgid.gid_guid = ah->ah_save_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor attr_p->av_srate = ah->ah_save_srate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_ah_modify()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_ah_modify(tavor_state_t *state, tavor_ahhdl_t ah,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_adds_vect_t *attr_p)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_udav_t udav_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *udav;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t data_new, data_old;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t udav_pd, size, portnum_new;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_ah_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate that specified port number is legal */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!tavor_portnum_is_valid(state, attr_p->av_port_num)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_ah_modify_inv_portnum,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, port, attr_p->av_port_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_HCA_PORT_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pull all the necessary information from the Tavor Address Handle
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * structure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav = ah->ah_udavrsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the UDAV entry. Note: we are only filling in a temporary
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * copy here, which we will later copy into the actual entry in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor DDR memory. This starts be zeroing out the temporary copy
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and then calling tavor_set_addr_path() to fill in the common
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * portions that can be pulled from the "ibt_adds_vect_t" passed in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: We also need to save away a copy of the "av_dgid.gid_guid"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * field here (just as we did during tavor_ah_alloc()) because we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * may need to return it later to the IBTF (as a result of a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * subsequent query operation). As explained in tavor_ah_alloc(),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * unlike the other UDAV parameters, the value of "av_dgid.gid_guid"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is not always preserved by being written to hardware. The reason
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for this is described in tavor_set_addr_path().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&udav_entry, sizeof (tavor_hw_udav_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_set_addr_path(state, attr_p,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (tavor_hw_addr_path_t *)&udav_entry, TAVOR_ADDRPATH_UDAV, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_ah_modify_setaddrpath_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_save_guid = attr_p->av_dgid.gid_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ah->ah_save_srate = attr_p->av_srate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Save away the current PD number for this UDAV. Then temporarily
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * invalidate the entry (by setting the PD to zero). Note: Since
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the first 32 bits of the UDAV actually contain the current port
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * number _and_ current PD number, we need to mask off some bits.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav_pd = ddi_get32(udav->tr_acchdl, (uint32_t *)udav->tr_addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav_pd = udav_pd & 0xFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(udav->tr_acchdl, (uint32_t *)udav->tr_addr, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Sync the UDAV for use by the hardware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_udav_sync(ah, udav->tr_addr, DDI_DMA_SYNC_FORDEV);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copy UDAV structure to the entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: We copy in 64-bit chunks. For the first two of these
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chunks it is necessary to read the current contents of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * UDAV, mask off the modifiable portions (maintaining any
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * of the "reserved" portions), and then mask on the new data.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor size = sizeof (tavor_hw_udav_t) >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < size; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_new = ((uint64_t *)&udav_entry)[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_old = ddi_get64(udav->tr_acchdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint64_t *)udav->tr_addr + i));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Apply mask to change only the relevant values. Note: We
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * extract the new portnum from the address handle here
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * because the "PD" and "portnum" fields are in the same
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 32-bit word in the UDAV. We will use the (new) port
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * number extracted here when we write the valid PD number
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in the last step below.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_old = data_old & TAVOR_UDAV_MODIFY_MASK0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor portnum_new = data_new >> 56;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (i == 1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_old = data_old & TAVOR_UDAV_MODIFY_MASK1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_old = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Write the updated values to the UDAV (in DDR) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_new = data_old | data_new;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put64(udav->tr_acchdl, ((uint64_t *)udav->tr_addr + i),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data_new);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Sync the body of the UDAV for use by the hardware. After we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * have updated the PD number (to make the UDAV valid), we sync
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * again to push the entire entry out for hardware access.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_udav_sync(ah, udav->tr_addr, DDI_DMA_SYNC_FORDEV);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Put the valid PD number back into UDAV entry. Note: Because port
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * number and PD number are in the same word, we must mask the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * new port number with the old PD number before writing it back
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the UDAV entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor udav_pd = ((portnum_new << 24) | udav_pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(udav->tr_acchdl, (uint32_t *)udav->tr_addr, udav_pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Sync the rest of the UDAV for use by the hardware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_udav_sync(ah, udav->tr_addr, DDI_DMA_SYNC_FORDEV);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&ah->ah_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_ah_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_udav_sync()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_udav_sync(tavor_ahhdl_t ah, tavor_hw_udav_t *udav, uint_t flag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_handle_t dmahdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor off_t offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_udav_sync);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*ah))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine if AH needs to be synced or not */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ah->ah_sync == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_udav_sync);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get the DMA handle from AH handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dmahdl = ah->ah_mrhdl->mr_bindinfo.bi_dmahdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Calculate offset into address handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = (off_t)0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_dma_sync(dmahdl, offset, sizeof (tavor_hw_udav_t), flag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_udav_sync_getnextentry_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_udav_sync);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_udav_sync);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_attach()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_attach(tavor_state_t *state, tavor_qphdl_t qp, ib_gid_t gid,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_lid_t lid)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_t *mcg_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_qp_list_t *mcg_entry_qplist;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mcghdl_t mcg, newmcg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t mgid_hash;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t end_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t qp_found;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *errormsg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * It is only allowed to attach MCG to UD queue pairs. Verify
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the intended QP is of the appropriate transport type
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp->qp_serv_type != TAVOR_QP_UD) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_QP_SRV_TYPE_INVALID, "invalid service type");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for invalid Multicast DLID. Specifically, all Multicast
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * LIDs should be within a well defined range. If the specified LID
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is outside of that range, then return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (tavor_mlid_is_valid(lid) == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_MC_MLID_INVALID, "invalid MLID");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for invalid Multicast GID. All Multicast GIDs should have
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a well-defined pattern of bits and flags that are allowable. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the specified GID does not meet the criteria, then return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (tavor_mgid_is_valid(gid) == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_MC_MGID_INVALID, "invalid MGID");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Compute the MGID hash value. Since the MCG table is arranged as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a number of separate hash chains, this operation converts the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * specified MGID into the starting index of an entry in the hash
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * table (i.e. the index for the start of the appropriate hash chain).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Subsequent operations below will walk the chain searching for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * right place to add this new QP.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mgid_hash_cmd_post(state, gid.gid_prefix, gid.gid_guid,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &mgid_hash, TAVOR_SLEEPFLAG_FOR_CONTEXT());
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: MGID_HASH command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_mcg_attach_mgid_hash_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Grab the multicast group mutex. Then grab the pre-allocated
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * temporary buffer used for holding and/or modifying MCG entries.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Zero out the temporary MCG entry before we begin.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry = state->ts_mcgtmp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry_qplist = TAVOR_MCG_GET_QPLIST_PTR(mcg_entry);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(mcg_entry, TAVOR_MCGMEM_SZ(state));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Walk through the array of MCG entries starting at "mgid_hash".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Try to find the appropriate place for this new QP to be added.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This could happen when the first entry of the chain has MGID == 0
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (which means that the hash chain is empty), or because we find
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * an entry with the same MGID (in which case we'll add the QP to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that MCG), or because we come to the end of the chain (in which
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * case this is the first QP being added to the multicast group that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * corresponds to the MGID. The tavor_mcg_walk_mgid_hash() routine
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * walks the list and returns an index into the MCG table. The entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * at this index is then checked to determine which case we have
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fallen into (see below). Note: We are using the "shadow" MCG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * list (of tavor_mcg_t structs) for this lookup because the real
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG entries are in hardware (and the lookup process would be much
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * more time consuming).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor end_indx = tavor_mcg_walk_mgid_hash(state, mgid_hash, gid, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg = &state->ts_mcghdl[end_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If MGID == 0, then the hash chain is empty. Just fill in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * current entry. Note: No need to allocate an MCG table entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * as all the hash chain "heads" are already preallocated.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((mcg->mcg_mgid_h == 0) && (mcg->mcg_mgid_l == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Fill in the current entry in the "shadow" MCG list */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mcg_setup_new_hdr(mcg, mcg_entry, gid, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Try to add the new QP number to the list. This (and the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * above) routine fills in a temporary MCG. The "mcg_entry"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and "mcg_entry_qplist" pointers simply point to different
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * offsets within the same temporary copy of the MCG (for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * convenience). Note: If this fails, we need to invalidate
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the entries we've already put into the "shadow" list entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * above.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mcg_qplist_add(state, mcg, mcg_entry_qplist, qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &qp_found);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(mcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(status, "failed qplist add");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Once the temporary MCG has been filled in, write the entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * into the appropriate location in the Tavor MCG entry table.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If it's successful, then drop the lock and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: In general, this operation shouldn't fail. If it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * does, then it is an indication that something (probably in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HW, but maybe in SW) has gone seriously wrong. We still
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * want to zero out the entries that we've filled in above
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (in the tavor_mcg_setup_new_hdr() routine).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(mcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_attach_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now that we know all the Tavor firmware accesses have been
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successful, we update the "shadow" MCG entry by incrementing
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the "number of attached QPs" count.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We increment only if the QP is not already part of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG by checking the 'qp_found' flag returned from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * qplist_add above.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!qp_found) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_num_qps++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Increment the refcnt for this QP. Because the QP
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * was added to this MCG, the refcnt must be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * incremented.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_qp_mcg_refcnt_inc(qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We drop the lock and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the specified MGID matches the MGID in the current entry, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we need to try to add the QP to the current MCG entry. In this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * case, it means that we need to read the existing MCG entry (into
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the temporary MCG), add the new QP number to the temporary entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (using the same method we used above), and write the entry back
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the hardware (same as above).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((mcg->mcg_mgid_h == gid.gid_prefix) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (mcg->mcg_mgid_l == gid.gid_guid)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read the current MCG entry into the temporary MCG. Note:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * In general, this operation shouldn't fail. If it does,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then it is an indication that something (probably in HW,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but maybe in SW) has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_read_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to read MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: READ_MGM command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_attach_read_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Try to add the new QP number to the list. This routine
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fills in the necessary pieces of the temporary MCG. The
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "mcg_entry_qplist" pointer is used to point to the portion
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * of the temporary MCG that holds the QP numbers.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: tavor_mcg_qplist_add() returns SUCCESS if it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * already found the QP in the list. In this case, the QP is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * not added on to the list again. Check the flag 'qp_found'
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * if this value is needed to be known.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mcg_qplist_add(state, mcg, mcg_entry_qplist, qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &qp_found);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(status, "failed qplist add");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Once the temporary MCG has been updated, write the entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * into the appropriate location in the Tavor MCG entry table.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If it's successful, then drop the lock and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: In general, this operation shouldn't fail. If it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * does, then it is an indication that something (probably in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HW, but maybe in SW) has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_attach_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now that we know all the Tavor firmware accesses have been
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successful, we update the current "shadow" MCG entry by
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * incrementing the "number of attached QPs" count.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We increment only if the QP is not already part of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG by checking the 'qp_found' flag returned from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * qplist_add above.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!qp_found) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_num_qps++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Increment the refcnt for this QP. Because the QP
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * was added to this MCG, the refcnt must be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * incremented.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_qp_mcg_refcnt_inc(qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We drop the lock and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we've reached here, then we're at the end of the hash chain.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We need to allocate a new MCG entry, fill it in, write it to Tavor,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and update the previous entry to link the new one to the end of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chain.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate an MCG table entry. This will be filled in with all
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the necessary parameters to define the multicast group. Then it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will be written to the hardware in the next-to-last step below.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_rsrc_alloc(state, TAVOR_MCG, 1, TAVOR_NOSLEEP, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed MCG");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the new entry in the "shadow" MCG list. Note: Just as
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it does above, tavor_mcg_setup_new_hdr() also fills in a portion
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * of the temporary MCG entry (the rest of which will be filled in by
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_qplist_add() below)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor newmcg = &state->ts_mcghdl[rsrc->tr_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mcg_setup_new_hdr(newmcg, mcg_entry, gid, rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Try to add the new QP number to the list. This routine fills in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the final necessary pieces of the temporary MCG. The
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "mcg_entry_qplist" pointer is used to point to the portion of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * temporary MCG that holds the QP numbers. If we fail here, we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * must undo the previous resource allocation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: tavor_mcg_qplist_add() can we return SUCCESS if it already
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * found the QP in the list. In this case, the QP is not added on to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the list again. Check the flag 'qp_found' if this value is needed
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to be known.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mcg_qplist_add(state, newmcg, mcg_entry_qplist, qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &qp_found);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(newmcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "status" and "errormsg" and goto failure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_FAIL(status, "failed qplist add");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto mcgattach_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Once the temporary MCG has been updated, write the entry into the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * appropriate location in the Tavor MCG entry table. If this is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successful, then we need to chain the previous entry to this one.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: In general, this operation shouldn't fail. If it does, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it is an indication that something (probably in HW, but maybe in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SW) has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, rsrc->tr_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(newmcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_attach_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, rsrc->tr_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now read the current MCG entry (the one previously at the end of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hash chain) into the temporary MCG. We are going to update its
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "next_gid_indx" now and write the entry back to the MCG table.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: In general, this operation shouldn't fail. If it does, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it is an indication that something (probably in HW, but maybe in SW)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * has gone seriously wrong. We will free up the MCG entry resource,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but we will not undo the previously written MCG entry in the HW.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is OK, though, because the MCG entry is not currently attached
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to any hash chain.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_read_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(newmcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to read MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: READ_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_attach_read_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Finally, we update the "next_gid_indx" field in the temporary MCG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and attempt to write the entry back into the Tavor MCG table. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this succeeds, then we update the "shadow" list to reflect the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * change, drop the lock, and return success. Note: In general, this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation shouldn't fail. If it does, then it is an indication
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that something (probably in HW, but maybe in SW) has gone seriously
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * wrong. Just as we do above, we will free up the MCG entry resource,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but we will not try to undo the previously written MCG entry. This
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is OK, though, because (since we failed here to update the end of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the chain) that other entry is not currently attached to any chain.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry->next_gid_indx = rsrc->tr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(newmcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_attach_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg = &state->ts_mcghdl[end_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_next_indx = rsrc->tr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now that we know all the Tavor firmware accesses have been
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successful, we update the new "shadow" MCG entry by incrementing
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the "number of attached QPs" count. Then we drop the lock and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor newmcg->mcg_num_qps++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Increment the refcnt for this QP. Because the QP
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * was added to this MCG, the refcnt must be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * incremented.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_qp_mcg_refcnt_inc(qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylormcgattach_fail:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_mcg_attach_fail, TAVOR_TNF_ERROR, "", tnf_string,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msg, errormsg);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_detach()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_detach(tavor_state_t *state, tavor_qphdl_t qp, ib_gid_t gid,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_lid_t lid)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_t *mcg_entry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_qp_list_t *mcg_entry_qplist;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mcghdl_t mcg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t mgid_hash;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t end_indx, prev_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for invalid Multicast DLID. Specifically, all Multicast
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * LIDs should be within a well defined range. If the specified LID
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is outside of that range, then return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (tavor_mlid_is_valid(lid) == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_mcg_detach_invmlid_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MC_MLID_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Compute the MGID hash value. As described above, the MCG table is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * arranged as a number of separate hash chains. This operation
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * converts the specified MGID into the starting index of an entry in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the hash table (i.e. the index for the start of the appropriate
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hash chain). Subsequent operations below will walk the chain
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * searching for a matching entry from which to attempt to remove
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the specified QP.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mgid_hash_cmd_post(state, gid.gid_prefix, gid.gid_guid,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &mgid_hash, TAVOR_SLEEPFLAG_FOR_CONTEXT());
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: MGID_HASH command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_mcg_detach_mgid_hash_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Grab the multicast group mutex. Then grab the pre-allocated
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * temporary buffer used for holding and/or modifying MCG entries.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry = state->ts_mcgtmp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry_qplist = TAVOR_MCG_GET_QPLIST_PTR(mcg_entry);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Walk through the array of MCG entries starting at "mgid_hash".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Try to find an MCG entry with a matching MGID. The
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_walk_mgid_hash() routine walks the list and returns an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * index into the MCG table. The entry at this index is checked to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * determine whether it is a match or not. If it is a match, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we continue on to attempt to remove the QP from the MCG. If it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is not a match (or not a valid MCG entry), then we return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor end_indx = tavor_mcg_walk_mgid_hash(state, mgid_hash, gid, &prev_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg = &state->ts_mcghdl[end_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If MGID == 0 (the hash chain is empty) or if the specified MGID
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * does not match the MGID in the current entry, then return
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * IBT_MC_MGID_INVALID (to indicate that the specified MGID is not
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * valid).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (((mcg->mcg_mgid_h == 0) && (mcg->mcg_mgid_l == 0)) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((mcg->mcg_mgid_h != gid.gid_prefix) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (mcg->mcg_mgid_l != gid.gid_guid))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_mcg_detach_invmgid_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_MC_MGID_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read the current MCG entry into the temporary MCG. Note: In
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * general, this operation shouldn't fail. If it does, then it is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * an indication that something (probably in HW, but maybe in SW)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_read_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to read MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: READ_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_detach_read_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_attach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Search the QP number list for a match. If a match is found, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * remove the entry from the QP list. Otherwise, if no match is found,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return an error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mcg_qplist_remove(mcg, mcg_entry_qplist, qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Decrement the MCG count for this QP. When the 'qp_mcg'
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * field becomes 0, then this QP is no longer a member of any
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_qp_mcg_refcnt_dec(qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the current MCG's QP number list is about to be made empty
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ("mcg_num_qps" == 1), then remove the entry itself from the hash
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chain. Otherwise, just write the updated MCG entry back to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware. In either case, once we successfully update the hardware
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chain, then we decrement the "shadow" list entry's "mcg_num_qps"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * count (or zero out the entire "shadow" list entry) before returning
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * success. Note: Zeroing out the "shadow" list entry is done
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * inside of tavor_mcg_hash_list_remove().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mcg->mcg_num_qps == 1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Remove an MCG entry from the hash chain */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mcg_hash_list_remove(state, end_indx, prev_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Write the updated MCG entry back to the Tavor MCG table.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this succeeds, then we update the "shadow" list to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * reflect the change (i.e. decrement the "mcg_num_qps"),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * drop the lock, and return success. Note: In general,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this operation shouldn't fail. If it does, then it is an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * indication that something (probably in HW, but maybe in SW)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, end_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_detach_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, end_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_num_qps--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->ts_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_detach);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_qp_mcg_refcnt_inc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_qp_mcg_refcnt_inc(tavor_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Increment the QP's MCG reference count */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp->qp_mcg_refcnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1_DEBUG(tavor_qp_mcg_refcnt_inc, TAVOR_TNF_TRACE, "",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, refcnt, qp->qp_mcg_refcnt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_qp_mcg_refcnt_dec()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_qp_mcg_refcnt_dec(tavor_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Decrement the QP's MCG reference count */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp->qp_mcg_refcnt--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1_DEBUG(tavor_qp_mcg_refcnt_dec, TAVOR_TNF_TRACE, "",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, refcnt, qp->qp_mcg_refcnt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&qp->qp_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_qplist_add()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_qplist_add(tavor_state_t *state, tavor_mcghdl_t mcg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_mcg_qp_list_t *mcg_qplist, tavor_qphdl_t qp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t *qp_found)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t qplist_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_qplist_add);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&state->ts_mcglock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qplist_indx = mcg->mcg_num_qps;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine if we have exceeded the maximum number of QP per
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * multicast group. If we have, then return an error
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qplist_indx >= state->ts_cfg_profile->cp_num_qp_per_mcg) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_mcg_qplist_add_too_many_qps,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_qplist_add);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_HCA_MCG_QP_EXCEEDED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine if the QP is already attached to this MCG table. If it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is, then we break out and treat this operation as a NO-OP
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (qplist_indx = 0; qplist_indx < mcg->mcg_num_qps;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qplist_indx++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mcg_qplist[qplist_indx].qpn == qp->qp_qpnum) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the QP was already on the list, set 'qp_found' to TRUE. We still
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return SUCCESS in this case, but the qplist will not have been
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * updated because the QP was already on the list.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qplist_indx < mcg->mcg_num_qps) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *qp_found = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise, append the new QP number to the end of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * current QP list. Note: We will increment the "mcg_num_qps"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * field on the "shadow" MCG list entry later (after we know
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that all necessary Tavor firmware accesses have been
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successful).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set 'qp_found' to 0 so we know the QP was added on to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * list for sure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_qplist[qplist_indx].q = TAVOR_MCG_QPN_VALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_qplist[qplist_indx].qpn = qp->qp_qpnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *qp_found = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_qplist_add);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_qplist_remove()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_qplist_remove(tavor_mcghdl_t mcg, tavor_hw_mcg_qp_list_t *mcg_qplist,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t i, qplist_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_qplist_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Search the MCG QP list for a matching QPN. When
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it's found, we swap the last entry with the current
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * one, set the last entry to zero, decrement the last
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entry, and return. If it's not found, then it's
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qplist_indx = mcg->mcg_num_qps;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < qplist_indx; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (mcg_qplist[i].qpn == qp->qp_qpnum) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_qplist[i] = mcg_qplist[qplist_indx - 1];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_qplist[qplist_indx - 1].q = TAVOR_MCG_QPN_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_qplist[qplist_indx - 1].qpn = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_qplist_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_mcg_qplist_remove_invqphdl_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_qplist_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_QP_HDL_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_walk_mgid_hash()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_walk_mgid_hash(tavor_state_t *state, uint64_t start_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_gid_t mgid, uint_t *p_indx)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mcghdl_t curr_mcghdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t curr_indx, prev_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_walk_mgid_hash);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&state->ts_mcglock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Start at the head of the hash chain */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_indx = start_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev_indx = curr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_mcghdl = &state->ts_mcghdl[curr_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If the first entry in the chain has MGID == 0, then stop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((curr_mcghdl->mcg_mgid_h == 0) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (curr_mcghdl->mcg_mgid_l == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto end_mgid_hash_walk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If the first entry in the chain matches the MGID, then stop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((curr_mcghdl->mcg_mgid_h == mgid.gid_prefix) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (curr_mcghdl->mcg_mgid_l == mgid.gid_guid)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto end_mgid_hash_walk;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Otherwise, walk the hash chain looking for a match */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while (curr_mcghdl->mcg_next_indx != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev_indx = curr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_indx = curr_mcghdl->mcg_next_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_mcghdl = &state->ts_mcghdl[curr_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((curr_mcghdl->mcg_mgid_h == mgid.gid_prefix) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (curr_mcghdl->mcg_mgid_l == mgid.gid_guid)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorend_mgid_hash_walk:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If necessary, return the index of the previous entry too. This
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is primarily used for detaching a QP from a multicast group. It
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * may be necessary, in that case, to delete an MCG entry from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hash chain and having the index of the previous entry is helpful.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (p_indx != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *p_indx = prev_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_walk_mgid_hash);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (curr_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_setup_new_hdr()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_setup_new_hdr(tavor_mcghdl_t mcg, tavor_hw_mcg_t *mcg_hdr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_gid_t mgid, tavor_rsrc_t *mcg_rsrc)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_setup_new_hdr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the fields of the "shadow" entry used by software
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to track MCG hardware entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_mgid_h = mgid.gid_prefix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_mgid_l = mgid.gid_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_rsrcp = mcg_rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_next_indx = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg->mcg_num_qps = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill the header fields of the MCG entry (in the temporary copy)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_hdr->mgid_h = mgid.gid_prefix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_hdr->mgid_l = mgid.gid_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_hdr->next_gid_indx = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_setup_new_hdr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_hash_list_remove()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_hash_list_remove(tavor_state_t *state, uint_t curr_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t prev_indx, tavor_hw_mcg_t *mcg_entry)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_mcghdl_t curr_mcg, prev_mcg, next_mcg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t next_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get the pointer to "shadow" list for current entry */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_mcg = &state->ts_mcghdl[curr_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is the first entry on a hash chain, then attempt to replace
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the entry with the next entry on the chain. If there are no
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * subsequent entries on the chain, then this is the only entry and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * should be invalidated.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (curr_indx == prev_indx) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is the only entry on the chain, then invalidate it.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: Invalidating an MCG entry means writing all zeros
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the entry. This is only necessary for those MCG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entries that are the "head" entries of the individual hash
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * chains. Regardless of whether this operation returns
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * success or failure, return that result to the caller.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor next_indx = curr_mcg->mcg_next_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (next_indx == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_mcg_entry_invalidate(state, mcg_entry,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor curr_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(curr_mcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise, this is just the first entry on the chain, so
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * grab the next one
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor next_mcg = &state->ts_mcghdl[next_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read the next MCG entry into the temporary MCG. Note:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * In general, this operation shouldn't fail. If it does,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then it is an indication that something (probably in HW,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but maybe in SW) has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_read_mgm_cmd_post(state, mcg_entry, next_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to read MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: READ_MGM command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_hash_list_rem_read_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, next_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copy/Write the temporary MCG back to the hardware MCG list
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * using the current index. This essentially removes the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * current MCG entry from the list by writing over it with
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the next one. If this is successful, then we can do the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * same operation for the "shadow" list. And we can also
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * free up the Tavor MCG entry resource that was associated
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with the (old) next entry. Note: In general, this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation shouldn't fail. If it does, then it is an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * indication that something (probably in HW, but maybe in SW)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, curr_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_hash_list_rem_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, curr_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copy all the software tracking information from the next
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entry on the "shadow" MCG list into the current entry on
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the list. Then invalidate (zero out) the other "shadow"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * list entry.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bcopy(next_mcg, curr_mcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(next_mcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Free up the Tavor MCG entry resource used by the "next"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG entry. That resource is no longer needed by any
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG entry which is first on a hash chain (like the "next"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entry has just become).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &curr_mcg->mcg_rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Else if this is the last entry on the hash chain (or a middle
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * entry, then we update the previous entry's "next_gid_index" field
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to make it point instead to the next entry on the chain. By
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * skipping over the removed entry in this way, we can then free up
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * any resources associated with the current entry. Note: We don't
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * need to invalidate the "skipped over" hardware entry because it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will no be longer connected to any hash chains, and if/when it is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * finally re-used, it will be written with entirely new values.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read the next MCG entry into the temporary MCG. Note: In general,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this operation shouldn't fail. If it does, then it is an
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * indication that something (probably in HW, but maybe in SW) has
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_read_mgm_cmd_post(state, mcg_entry, prev_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to read MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: READ_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_hash_list_rem_read_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, prev_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Finally, we update the "next_gid_indx" field in the temporary MCG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and attempt to write the entry back into the Tavor MCG table. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this succeeds, then we update the "shadow" list to reflect the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * change, free up the Tavor MCG entry resource that was associated
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * with the current entry, and return success. Note: In general,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this operation shouldn't fail. If it does, then it is an indication
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that something (probably in HW, but maybe in SW) has gone seriously
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_entry->next_gid_indx = curr_mcg->mcg_next_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, prev_indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_hash_list_rem_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, prev_indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Get the pointer to the "shadow" MCG list entry for the previous
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG. Update its "mcg_next_indx" to point to the next entry
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the one after the current entry. Note: This next index may be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * zero, indicating the end of the list.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev_mcg = &state->ts_mcghdl[prev_indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor prev_mcg->mcg_next_indx = curr_mcg->mcg_next_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Free up the Tavor MCG entry resource used by the current entry.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This resource is no longer needed because the chain now skips over
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the current entry. Then invalidate (zero out) the current "shadow"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * list entry.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &curr_mcg->mcg_rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(curr_mcg, sizeof (struct tavor_sw_mcg_list_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_hash_list_remove);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mcg_entry_invalidate()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mcg_entry_invalidate(tavor_state_t *state, tavor_hw_mcg_t *mcg_entry,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t indx)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mcg_entry_invalidate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Invalidate the hardware MCG entry by zeroing out this temporary
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MCG and writing it the the hardware. Note: In general, this
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation shouldn't fail. If it does, then it is an indication
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that something (probably in HW, but maybe in SW) has gone seriously
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(mcg_entry, TAVOR_MCGMEM_SZ(state));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_write_mgm_cmd_post(state, mcg_entry, indx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to write MCG entry");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: WRITE_MGM command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_2(tavor_mcg_entry_invalidate_write_mgm_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, indx, indx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_entry_invalidate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mcg_entry_invalidate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mgid_is_valid()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mgid_is_valid(ib_gid_t gid)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t topbits, flags, scope;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mgid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * According to IBA 1.1 specification (section 4.1.1) a valid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "multicast GID" must have its top eight bits set to all ones
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor topbits = (gid.gid_prefix >> TAVOR_MCG_TOPBITS_SHIFT) &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_MCG_TOPBITS_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (topbits != TAVOR_MCG_TOPBITS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_mgid_is_valid_invbits_fail, TAVOR_TNF_ERROR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mgid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The next 4 bits are the "flag" bits. These are valid only
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * if they are "0" (which correspond to permanently assigned/
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "well-known" multicast GIDs) or "1" (for so-called "transient"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * multicast GIDs). All other values are reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor flags = (gid.gid_prefix >> TAVOR_MCG_FLAGS_SHIFT) &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_MCG_FLAGS_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!((flags == TAVOR_MCG_FLAGS_PERM) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (flags == TAVOR_MCG_FLAGS_NONPERM))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_mgid_is_valid_invflags_fail, TAVOR_TNF_ERROR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "", tnf_uint, flags, flags);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mgid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The next 4 bits are the "scope" bits. These are valid only
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * if they are "2" (Link-local), "5" (Site-local), "8"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (Organization-local) or "E" (Global). All other values
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * are reserved (or currently unassigned).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor scope = (gid.gid_prefix >> TAVOR_MCG_SCOPE_SHIFT) &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_MCG_SCOPE_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!((scope == TAVOR_MCG_SCOPE_LINKLOC) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (scope == TAVOR_MCG_SCOPE_SITELOC) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (scope == TAVOR_MCG_SCOPE_ORGLOC) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (scope == TAVOR_MCG_SCOPE_GLOBAL))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_mgid_is_valid_invscope_fail, TAVOR_TNF_ERROR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "", tnf_uint, scope, scope);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mgid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If it passes all of the above checks, then we will consider it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a valid multicast GID.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mgid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_mlid_is_valid()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_mlid_is_valid(ib_lid_t lid)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_mlid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * According to IBA 1.1 specification (section 4.1.1) a valid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "multicast DLID" must be between 0xC000 and 0xFFFE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((lid < IB_LID_MC_FIRST) || (lid > IB_LID_MC_LAST)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_mlid_is_valid_invdlid_fail, TAVOR_TNF_ERROR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "", tnf_uint, mlid, lid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mlid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_mlid_is_valid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_pd_alloc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_pd_alloc(tavor_state_t *state, tavor_pdhdl_t *pdhdl, uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pdhdl_t pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_pd_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the software structure for tracking the protection domain
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (i.e. the Tavor Protection Domain handle). By default each PD
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * structure will have a unique PD number assigned to it. All that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * is necessary is for software to initialize the PD reference count
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (to zero) and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_rsrc_alloc(state, TAVOR_PDHDL, 1, sleepflag, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_pd_alloc_rsrcalloc_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_pd_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_INSUFF_RESOURCE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd = (tavor_pdhdl_t)rsrc->tr_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pd))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd->pd_refcnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *pdhdl = pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_pd_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_pd_free()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_pd_free(tavor_state_t *state, tavor_pdhdl_t *pdhdl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_t *rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_pdhdl_t pd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_pd_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pull all the necessary information from the Tavor Protection Domain
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * handle. This is necessary here because the resource for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PD is going to be freed up as part of this operation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd = *pdhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pd))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rsrc = pd->pd_rsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check the PD reference count. If the reference count is non-zero,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * then it means that this protection domain is still referenced by
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * some memory region, queue pair, address handle, or other IB object
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If it is non-zero, then return an error. Otherwise, free the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor resource and return success.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (pd->pd_refcnt != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_pd_free_refcnt_fail, TAVOR_TNF_ERROR, "",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_int, refcnt, pd->pd_refcnt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_pd_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_PD_IN_USE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the Tavor Protection Domain handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_rsrc_free(state, &rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the pdhdl pointer to NULL and return success */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *pdhdl = (tavor_pdhdl_t)NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_pd_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_pd_refcnt_inc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_pd_refcnt_inc(tavor_pdhdl_t pd)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Increment the protection domain's reference count */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&pd->pd_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1_DEBUG(tavor_pd_refcnt_inc, TAVOR_TNF_TRACE, "",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, refcnt, pd->pd_refcnt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd->pd_refcnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&pd->pd_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_pd_refcnt_dec()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_pd_refcnt_dec(tavor_pdhdl_t pd)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Decrement the protection domain's reference count */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&pd->pd_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pd->pd_refcnt--;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1_DEBUG(tavor_pd_refcnt_dec, TAVOR_TNF_TRACE, "",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tnf_uint, refcnt, pd->pd_refcnt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&pd->pd_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_port_query()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_port_query(tavor_state_t *state, uint_t port, ibt_hca_portinfo_t *pi)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sm_portinfo_t portinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sm_guidinfo_t guidinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sm_pkey_table_t pkeytable;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_gid_t *sgid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t sgid_max, pkey_max, tbl_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, j, indx, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_port_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pi))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate that specified port number is legal */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!tavor_portnum_is_valid(state, port)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_query_inv_portnum_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, port, port);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_HCA_PORT_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We use the Tavor MAD_IFC command to post a GetPortInfo MAD
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the firmware (for the specified port number). This returns
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a full PortInfo MAD (in "portinfo") which we subsequently
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * parse to fill in the "ibt_hca_portinfo_t" structure returned
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the IBTF.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_getportinfo_cmd_post(state, port,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_SLEEPFLAG_FOR_CONTEXT(), &portinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: GetPortInfo (port %02d) command "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "failed: %08x\n", port, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_query_getportinfo_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Parse the PortInfo MAD and fill in the IBTF structure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_base_lid = portinfo.LID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_qkey_violations = portinfo.Q_KeyViolations;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_pkey_violations = portinfo.P_KeyViolations;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_sm_sl = portinfo.MasterSMSL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_sm_lid = portinfo.MasterSMLID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_linkstate = portinfo.PortState;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_port_num = portinfo.LocalPortNum;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_phys_state = portinfo.PortPhysicalState;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_width_supported = portinfo.LinkWidthSupported;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_width_enabled = portinfo.LinkWidthEnabled;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_width_active = portinfo.LinkWidthActive;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_speed_supported = portinfo.LinkSpeedSupported;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_speed_enabled = portinfo.LinkSpeedEnabled;
d9c882fa1001c77987b156290d6733010c824ec4Bill Taylor pi->p_speed_active = portinfo.LinkSpeedActive;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_mtu = portinfo.MTUCap;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_lmc = portinfo.LMC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_max_vl = portinfo.VLCap;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_subnet_timeout = portinfo.SubnetTimeOut;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_msg_sz = ((uint32_t)1 << TAVOR_QP_LOG_MAX_MSGSZ);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = state->ts_cfg_profile->cp_log_max_gidtbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_sgid_tbl_sz = (1 << tbl_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = state->ts_cfg_profile->cp_log_max_pkeytbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_pkey_tbl_sz = (1 << tbl_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Convert InfiniBand-defined port capability flags to the format
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * specified by the IBTF
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (portinfo.CapabilityMask & SM_CAP_MASK_IS_SM)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_capabilities |= IBT_PORT_CAP_SM;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (portinfo.CapabilityMask & SM_CAP_MASK_IS_SM_DISABLED)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_capabilities |= IBT_PORT_CAP_SM_DISABLED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (portinfo.CapabilityMask & SM_CAP_MASK_IS_SNMP_SUPPD)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_capabilities |= IBT_PORT_CAP_SNMP_TUNNEL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (portinfo.CapabilityMask & SM_CAP_MASK_IS_DM_SUPPD)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_capabilities |= IBT_PORT_CAP_DM;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (portinfo.CapabilityMask & SM_CAP_MASK_IS_VM_SUPPD)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_capabilities |= IBT_PORT_CAP_VENDOR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the SGID table. Since the only access to the Tavor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * GID tables is through the firmware's MAD_IFC interface, we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * post as many GetGUIDInfo MADs as necessary to read in the entire
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * contents of the SGID table (for the specified port). Note: The
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * GetGUIDInfo command only gets eight GUIDs per operation. These
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * GUIDs are then appended to the GID prefix for the port (from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * GetPortInfo above) to form the entire SGID table.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < pi->p_sgid_tbl_sz; i += 8) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_getguidinfo_cmd_post(state, port, i >> 3,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_SLEEPFLAG_FOR_CONTEXT(), &guidinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: GetGUIDInfo (port %02d) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "command failed: %08x\n", port, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_query_getguidinfo_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Figure out how many of the entries are valid */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgid_max = min((pi->p_sgid_tbl_sz - i), 8);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < sgid_max; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor indx = (i + j);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgid = &pi->p_sgid_tbl[indx];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgid))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgid->gid_prefix = portinfo.GidPrefix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgid->gid_guid = guidinfo.GUIDBlocks[j];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in the PKey table. Just as for the GID tables above, the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * only access to the Tavor PKey tables is through the firmware's
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MAD_IFC interface. We post as many GetPKeyTable MADs as necessary
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to read in the entire contents of the PKey table (for the specified
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * port). Note: The GetPKeyTable command only gets 32 PKeys per
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * operation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < pi->p_pkey_tbl_sz; i += 32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_getpkeytable_cmd_post(state, port, i,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_SLEEPFLAG_FOR_CONTEXT(), &pkeytable);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: GetPKeyTable (port %02d) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "command failed: %08x\n", port, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_query_getpkeytable_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Figure out how many of the entries are valid */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pkey_max = min((pi->p_pkey_tbl_sz - i), 32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < pkey_max; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor indx = (i + j);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi->p_pkey_tbl[indx] = pkeytable.P_KeyTableBlocks[j];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_query);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_port_modify()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called only from user or kernel context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_port_modify(tavor_state_t *state, uint8_t port,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_port_modify_flags_t flags, uint8_t init_type)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sm_portinfo_t portinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t capmask, reset_qkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_port_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Return an error if either of the unsupported flags are set
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((flags & IBT_PORT_SHUTDOWN) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (flags & IBT_PORT_SET_INIT_TYPE)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_modify_inv_flags_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, flags, flags);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_NOT_SUPPORTED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether we are trying to reset the QKey counter
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor reset_qkey = (flags & IBT_PORT_RESET_QKEY) ? 1 : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate that specified port number is legal */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!tavor_portnum_is_valid(state, port)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_modify_inv_portnum_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, port, port);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_HCA_PORT_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Use the Tavor MAD_IFC command to post a GetPortInfo MAD to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware (for the specified port number). This returns a full
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PortInfo MAD (in "portinfo") from which we pull the current
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * capability mask. We then modify the capability mask as directed
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * by the "pmod_flags" field, and write the updated capability mask
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * using the Tavor SET_IB command (below).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_getportinfo_cmd_post(state, port,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_SLEEPFLAG_FOR_CONTEXT(), &portinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_modify_getportinfo_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Convert InfiniBand-defined port capability flags to the format
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * specified by the IBTF. Specifically, we modify the capability
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mask based on the specified values.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask = portinfo.CapabilityMask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (flags & IBT_PORT_RESET_SM)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask &= ~SM_CAP_MASK_IS_SM;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (flags & IBT_PORT_SET_SM)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask |= SM_CAP_MASK_IS_SM;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (flags & IBT_PORT_RESET_SNMP)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask &= ~SM_CAP_MASK_IS_SNMP_SUPPD;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (flags & IBT_PORT_SET_SNMP)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask |= SM_CAP_MASK_IS_SNMP_SUPPD;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (flags & IBT_PORT_RESET_DEVMGT)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask &= ~SM_CAP_MASK_IS_DM_SUPPD;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (flags & IBT_PORT_SET_DEVMGT)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask |= SM_CAP_MASK_IS_DM_SUPPD;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (flags & IBT_PORT_RESET_VENDOR)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask &= ~SM_CAP_MASK_IS_VM_SUPPD;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor else if (flags & IBT_PORT_SET_VENDOR)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor capmask |= SM_CAP_MASK_IS_VM_SUPPD;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Use the Tavor SET_IB command to update the capability mask and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (possibly) reset the QKey violation counter for the specified port.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: In general, this operation shouldn't fail. If it does, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it is an indication that something (probably in HW, but maybe in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SW) has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = tavor_set_ib_cmd_post(state, capmask, port, reset_qkey,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_SLEEPFLAG_FOR_CONTEXT());
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != TAVOR_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_WARNING(state, "failed to modify port capabilities");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Tavor: SET_IB (port %02d) command failed: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%08x\n", port, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_port_modify_set_ib_cmd_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, cmd_status, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ibc_get_ci_failure(0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_port_modify);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_set_addr_path()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: This routine is used for two purposes. It is used to fill in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor UDAV fields, and it is used to fill in the address path information
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for QPs. Because the two Tavor structures are similar, common fields can
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be filled in here. Because they are slightly different, however, we pass
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * an additional flag to indicate which type is being filled.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_set_addr_path(tavor_state_t *state, ibt_adds_vect_t *av,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_hw_addr_path_t *path, uint_t type, tavor_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t gidtbl_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_set_addr_path);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*av))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->ml_path = av->av_src_path;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->rlid = av->av_dlid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->sl = av->av_srvl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Port number only valid (in "av_port_num") if this is a UDAV */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (type == TAVOR_ADDRPATH_UDAV) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->portnum = av->av_port_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Validate (and fill in) static rate.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The stat_rate_sup is used to decide how to set the rate and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * if it is zero, the driver uses the old interface.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->ts_devlim.stat_rate_sup) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (av->av_srate == IBT_SRATE_20) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 0; /* 4x@DDR injection rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (av->av_srate == IBT_SRATE_5) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 3; /* 1x@DDR injection rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (av->av_srate == IBT_SRATE_10) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 2; /* 4x@SDR injection rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (av->av_srate == IBT_SRATE_2) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 1; /* 1x@SDR injection rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (av->av_srate == IBT_SRATE_NOT_SPECIFIED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 0; /* Max */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_set_addr_path_inv_srate_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, srate, av->av_srate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_set_addr_path);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_STATIC_RATE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (av->av_srate == IBT_SRATE_10) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 0; /* 4x@SDR injection rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (av->av_srate == IBT_SRATE_2) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 1; /* 1x@SDR injection rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (av->av_srate == IBT_SRATE_NOT_SPECIFIED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->max_stat_rate = 0; /* Max */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_set_addr_path_inv_srate_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, srate, av->av_srate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_set_addr_path);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_STATIC_RATE_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is a QP operation save asoft copy.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(qp->qp_save_srate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qp->qp_save_srate = av->av_srate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If "grh" flag is set, then check for valid SGID index too */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor gidtbl_sz = (1 << state->ts_devlim.log_max_gid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((av->av_send_grh) && (av->av_sgid_ix > gidtbl_sz)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_1(tavor_set_addr_path_inv_sgid_ix_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "", tnf_uint, sgid_ix, av->av_sgid_ix);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_set_addr_path);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (IBT_SGID_INVALID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Fill in all "global" values regardless of the value in the GRH
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * flag. Because "grh" is not set unless "av_send_grh" is set, the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware will ignore the other "global" values as necessary. Note:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SW does this here to enable later query operations to return
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * exactly the same params that were passed when the addr path was
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * last written.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->grh = av->av_send_grh;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (type == TAVOR_ADDRPATH_QP) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->mgid_index = av->av_sgid_ix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For Tavor UDAV, the "mgid_index" field is the index into
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a combined table (not a per-port table). So some extra
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * calculations are necessary.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->mgid_index = ((av->av_port_num - 1) * gidtbl_sz) +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_sgid_ix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->flow_label = av->av_flow;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->tclass = av->av_tclass;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->hop_limit = av->av_hop;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->rgid_h = av->av_dgid.gid_prefix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * According to Tavor PRM, the (31:0) part of rgid_l must be set to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "0x2" if the 'grh' or 'g' bit is cleared. It also says that we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * only need to do it for UDAV's. So we enforce that here.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: The entire 64 bits worth of GUID info is actually being
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * preserved (for UDAVs) by the callers of this function
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (tavor_ah_alloc() and tavor_ah_modify()) and as long as the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 'grh' bit is not set, the upper 32 bits (63:32) of rgid_l are
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "don't care".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((path->grh) || (type == TAVOR_ADDRPATH_QP)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->rgid_l = av->av_dgid.gid_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor path->rgid_l = 0x2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_set_addr_path);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_get_addr_path()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: Just like tavor_set_addr_path() above, this routine is used for two
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * purposes. It is used to read in the Tavor UDAV fields, and it is used to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * read in the address path information for QPs. Because the two Tavor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * structures are similar, common fields can be read in here. But because
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * they are slightly different, we pass an additional flag to indicate which
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * type is being read.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_get_addr_path(tavor_state_t *state, tavor_hw_addr_path_t *path,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_adds_vect_t *av, uint_t type, tavor_qphdl_t qp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t gidtbl_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*av))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_src_path = path->ml_path;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_port_num = path->portnum;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_dlid = path->rlid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srvl = path->sl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set "av_ipd" value from max_stat_rate.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qp) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If a QP operation use the soft copy
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(qp->qp_save_srate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = qp->qp_save_srate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The stat_rate_sup is used to decide how the srate value is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * set and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * if it is zero, the driver uses the old interface.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->ts_devlim.stat_rate_sup) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (path->max_stat_rate == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = IBT_SRATE_20; /* 4x@DDR rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (path->max_stat_rate == 1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = IBT_SRATE_2; /* 1x@SDR rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (path->max_stat_rate == 2) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = IBT_SRATE_10; /* 4x@SDR rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (path->max_stat_rate == 3) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = IBT_SRATE_5; /* 1xDDR rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (path->max_stat_rate == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = IBT_SRATE_10; /* 4x@SDR rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (path->max_stat_rate == 1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_srate = IBT_SRATE_2; /* 1x@SDR rate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Extract all "global" values regardless of the value in the GRH
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * flag. Because "av_send_grh" is set only if "grh" is set, software
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * knows to ignore the other "global" values as necessary. Note: SW
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * does it this way to enable these query operations to return exactly
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the same params that were passed when the addr path was last written.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_send_grh = path->grh;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (type == TAVOR_ADDRPATH_QP) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_sgid_ix = path->mgid_index;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For Tavor UDAV, the "mgid_index" field is the index into
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a combined table (not a per-port table). So some extra
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * calculations are necessary.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor gidtbl_sz = (1 << state->ts_devlim.log_max_gid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_sgid_ix = path->mgid_index - ((av->av_port_num - 1) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor gidtbl_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_flow = path->flow_label;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_tclass = path->tclass;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_hop = path->hop_limit;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_dgid.gid_prefix = path->rgid_h;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor av->av_dgid.gid_guid = path->rgid_l;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_portnum_is_valid()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_portnum_is_valid(tavor_state_t *state, uint_t portnum)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t max_port;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_port = state->ts_cfg_profile->cp_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((portnum <= max_port) && (portnum != 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_pkeyindex_is_valid()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_pkeyindex_is_valid(tavor_state_t *state, uint_t pkeyindx)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t max_pkeyindx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_pkeyindx = 1 << state->ts_cfg_profile->cp_log_max_pkeytbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (pkeyindx < max_pkeyindx) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_queue_alloc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_queue_alloc(tavor_state_t *state, tavor_qalloc_info_t *qa_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t sleepflag)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_attr_t dma_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int (*callback)(caddr_t);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t realsize, alloc_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t dma_xfer_mode, type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int flag, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_queue_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qa_info))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the callback flag appropriately */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor callback = (sleepflag == TAVOR_SLEEP) ? DDI_DMA_SLEEP :
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_DMA_DONTWAIT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize many of the default DMA attributes. Then set additional
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * alignment restrictions as necessary for the queue memory. Also
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * respect the configured value for IOMMU bypass
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tavor_dma_attr_init(&dma_attr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr.dma_attr_align = qa_info->qa_bind_align;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor type = state->ts_cfg_profile->cp_iommu_bypass;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (type == TAVOR_BINDMEM_BYPASS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate a DMA handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_dma_alloc_handle(state->ts_dip, &dma_attr, callback, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &qa_info->qa_dmahdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_queue_alloc_dmahdl_fail, TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_queue_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine the amount of memory to allocate, depending on the values
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in "qa_bind_align" and "qa_alloc_align". The problem we are trying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to solve here is that allocating a DMA handle with IOMMU bypass
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (DDI_DMA_FORCE_PHYSICAL) constrains us to only requesting alignments
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that are less than the page size. Since we may need stricter
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * alignments on the memory allocated by ddi_dma_mem_alloc() (e.g. in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Tavor QP work queue memory allocation), we use the following method
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to calculate how much additional memory to request, and we enforce
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * our own alignment on the allocated result.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor alloc_mask = qa_info->qa_alloc_align - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qa_info->qa_bind_align == qa_info->qa_alloc_align) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor realsize = qa_info->qa_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor realsize = qa_info->qa_size + alloc_mask;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we are to allocate the queue from system memory, then use
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ddi_dma_mem_alloc() to find the space. Otherwise, if we are to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * allocate the queue from locally-attached DDR memory, then use the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * vmem allocator to find the space. In either case, return a pointer
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to the memory range allocated (including any necessary alignment
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * adjustments), the "real" memory pointer, the "real" size, and a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ddi_acc_handle_t to use when reading from/writing to the memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qa_info->qa_location == TAVOR_QUEUE_LOCATION_NORMAL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether to map STREAMING or CONSISTENT. This is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * based on the value set in the configuration profile at
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * attach time.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_xfer_mode = state->ts_cfg_profile->cp_streaming_consistent;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate system memory for the queue */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_dma_mem_alloc(qa_info->qa_dmahdl, realsize,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->ts_reg_accattr, dma_xfer_mode, callback, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr_t *)&qa_info->qa_buf_real,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (size_t *)&qa_info->qa_buf_realsz, &qa_info->qa_acchdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&qa_info->qa_dmahdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_queue_alloc_dma_memalloc_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_queue_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Save temporary copy of the real pointer. (This may be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * modified in the last step below).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_aligned = qa_info->qa_buf_real;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (qa_info->qa_location == TAVOR_QUEUE_LOCATION_USERLAND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate userland mappable memory for the queue */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor flag = (sleepflag == TAVOR_SLEEP) ? DDI_UMEM_SLEEP :
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_UMEM_NOSLEEP;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_real = ddi_umem_alloc(realsize, flag,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &qa_info->qa_umemcookie);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qa_info->qa_buf_real == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&qa_info->qa_dmahdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_queue_alloc_umem_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_queue_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Save temporary copy of the real pointer. (This may be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * modified in the last step below).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_aligned = qa_info->qa_buf_real;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else { /* TAVOR_QUEUE_LOCATION_INDDR */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate DDR memory for the queue */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor flag = (sleepflag == TAVOR_SLEEP) ? VM_SLEEP : VM_NOSLEEP;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_real = (uint32_t *)vmem_xalloc(
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->ts_ddrvmem, realsize, qa_info->qa_bind_align, 0, 0,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL, NULL, flag);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qa_info->qa_buf_real == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&qa_info->qa_dmahdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TNF_PROBE_0(tavor_queue_alloc_vmxa_fail,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ERROR, "");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_queue_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Since "qa_buf_real" will be a PCI address (the offset into
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the DDR memory), we first need to do some calculations to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * convert it to its kernel mapped address. (Note: This may
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be modified again below, when any additional "alloc"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * alignment constraint is applied).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_aligned = (uint32_t *)(uintptr_t)(((uintptr_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->ts_reg_ddr_baseaddr) + ((uintptr_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_real - state->ts_ddr.ddr_baseaddr));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_realsz = realsize;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_acchdl = state->ts_reg_ddrhdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The last step is to ensure that the final address ("qa_buf_aligned")
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * has the appropriate "alloc" alignment restriction applied to it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (if necessary).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qa_info->qa_bind_align != qa_info->qa_alloc_align) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_aligned = (uint32_t *)(uintptr_t)(((uintptr_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_aligned + alloc_mask) & ~alloc_mask);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_queue_alloc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_queue_free()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_queue_free(tavor_state_t *state, tavor_qalloc_info_t *qa_info)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_ENTER(tavor_queue_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*qa_info))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Depending on how (i.e. from where) we allocated the memory for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this queue, we choose the appropriate method for releasing the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * resources.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (qa_info->qa_location == TAVOR_QUEUE_LOCATION_NORMAL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_mem_free(&qa_info->qa_acchdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (qa_info->qa_location == TAVOR_QUEUE_LOCATION_USERLAND) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_umem_free(qa_info->qa_umemcookie);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else { /* TAVOR_QUEUE_LOCATION_INDDR */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vmem_xfree(state->ts_ddrvmem, qa_info->qa_buf_real,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qa_info->qa_buf_realsz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Always free the dma handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&qa_info->qa_dmahdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor TAVOR_TNF_EXIT(tavor_queue_free);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tavor_dmaattr_get()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylortavor_dma_attr_init(ddi_dma_attr_t *dma_attr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dma_attr))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_version = DMA_ATTR_V0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_addr_lo = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_count_max = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_align = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_burstsizes = 0x3FF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_minxfer = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_maxxfer = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_seg = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_sgllen = 0x7FFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_granular = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_flags = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}