19517SBill.Taylor@Sun.COM /*
29517SBill.Taylor@Sun.COM * CDDL HEADER START
39517SBill.Taylor@Sun.COM *
49517SBill.Taylor@Sun.COM * The contents of this file are subject to the terms of the
59517SBill.Taylor@Sun.COM * Common Development and Distribution License (the "License").
69517SBill.Taylor@Sun.COM * You may not use this file except in compliance with the License.
79517SBill.Taylor@Sun.COM *
89517SBill.Taylor@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99517SBill.Taylor@Sun.COM * or http://www.opensolaris.org/os/licensing.
109517SBill.Taylor@Sun.COM * See the License for the specific language governing permissions
119517SBill.Taylor@Sun.COM * and limitations under the License.
129517SBill.Taylor@Sun.COM *
139517SBill.Taylor@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149517SBill.Taylor@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159517SBill.Taylor@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169517SBill.Taylor@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179517SBill.Taylor@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189517SBill.Taylor@Sun.COM *
199517SBill.Taylor@Sun.COM * CDDL HEADER END
209517SBill.Taylor@Sun.COM */
219517SBill.Taylor@Sun.COM
229517SBill.Taylor@Sun.COM /*
23*12965SWilliam.Taylor@Oracle.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
249517SBill.Taylor@Sun.COM */
259517SBill.Taylor@Sun.COM
269517SBill.Taylor@Sun.COM /*
279517SBill.Taylor@Sun.COM * hermon_qpmod.c
289517SBill.Taylor@Sun.COM * Hermon Queue Pair Modify Routines
299517SBill.Taylor@Sun.COM *
309517SBill.Taylor@Sun.COM * This contains all the routines necessary to implement the
319517SBill.Taylor@Sun.COM * ModifyQP() verb. This includes all the code for legal
329517SBill.Taylor@Sun.COM * transitions to and from Reset, Init, RTR, RTS, SQD, SQErr,
339517SBill.Taylor@Sun.COM * and Error.
349517SBill.Taylor@Sun.COM */
359517SBill.Taylor@Sun.COM
369517SBill.Taylor@Sun.COM #include <sys/types.h>
379517SBill.Taylor@Sun.COM #include <sys/conf.h>
389517SBill.Taylor@Sun.COM #include <sys/ddi.h>
399517SBill.Taylor@Sun.COM #include <sys/sunddi.h>
409517SBill.Taylor@Sun.COM #include <sys/modctl.h>
419517SBill.Taylor@Sun.COM #include <sys/bitmap.h>
429517SBill.Taylor@Sun.COM
439517SBill.Taylor@Sun.COM #include <sys/ib/adapters/hermon/hermon.h>
449517SBill.Taylor@Sun.COM #include <sys/ib/ib_pkt_hdrs.h>
459517SBill.Taylor@Sun.COM
469517SBill.Taylor@Sun.COM static int hermon_qp_reset2init(hermon_state_t *state, hermon_qphdl_t qp,
479517SBill.Taylor@Sun.COM ibt_qp_info_t *info_p);
489517SBill.Taylor@Sun.COM static int hermon_qp_init2init(hermon_state_t *state, hermon_qphdl_t qp,
499517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
509517SBill.Taylor@Sun.COM static int hermon_qp_init2rtr(hermon_state_t *state, hermon_qphdl_t qp,
519517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
529517SBill.Taylor@Sun.COM static int hermon_qp_rtr2rts(hermon_state_t *state, hermon_qphdl_t qp,
539517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
549517SBill.Taylor@Sun.COM static int hermon_qp_rts2rts(hermon_state_t *state, hermon_qphdl_t qp,
559517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
569517SBill.Taylor@Sun.COM #ifdef HERMON_NOTNOW
579517SBill.Taylor@Sun.COM static int hermon_qp_rts2sqd(hermon_state_t *state, hermon_qphdl_t qp,
589517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags);
599517SBill.Taylor@Sun.COM #endif
609517SBill.Taylor@Sun.COM static int hermon_qp_sqd2rts(hermon_state_t *state, hermon_qphdl_t qp,
619517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
629517SBill.Taylor@Sun.COM static int hermon_qp_sqd2sqd(hermon_state_t *state, hermon_qphdl_t qp,
639517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
649517SBill.Taylor@Sun.COM static int hermon_qp_sqerr2rts(hermon_state_t *state, hermon_qphdl_t qp,
659517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p);
669517SBill.Taylor@Sun.COM static int hermon_qp_to_error(hermon_state_t *state, hermon_qphdl_t qp);
679517SBill.Taylor@Sun.COM static int hermon_qp_reset2err(hermon_state_t *state, hermon_qphdl_t qp);
689517SBill.Taylor@Sun.COM
699517SBill.Taylor@Sun.COM static uint_t hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
709517SBill.Taylor@Sun.COM ibt_qp_info_t *info_p, hermon_hw_qpc_t *qpc);
719517SBill.Taylor@Sun.COM static int hermon_qp_validate_resp_rsrc(hermon_state_t *state,
729517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc, uint_t *rra_max);
739517SBill.Taylor@Sun.COM static int hermon_qp_validate_init_depth(hermon_state_t *state,
749517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc, uint_t *sra_max);
759517SBill.Taylor@Sun.COM static int hermon_qp_validate_mtu(hermon_state_t *state, uint_t mtu);
769517SBill.Taylor@Sun.COM
779517SBill.Taylor@Sun.COM /*
789517SBill.Taylor@Sun.COM * hermon_qp_modify()
799517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
809517SBill.Taylor@Sun.COM */
819517SBill.Taylor@Sun.COM /* ARGSUSED */
829517SBill.Taylor@Sun.COM int
hermon_qp_modify(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p,ibt_queue_sizes_t * actual_sz)839517SBill.Taylor@Sun.COM hermon_qp_modify(hermon_state_t *state, hermon_qphdl_t qp,
849517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p,
859517SBill.Taylor@Sun.COM ibt_queue_sizes_t *actual_sz)
869517SBill.Taylor@Sun.COM {
879517SBill.Taylor@Sun.COM ibt_cep_state_t cur_state, mod_state;
889517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t okflags;
899517SBill.Taylor@Sun.COM int status;
909517SBill.Taylor@Sun.COM
919517SBill.Taylor@Sun.COM /*
929517SBill.Taylor@Sun.COM * TODO add support for SUSPEND and RESUME
939517SBill.Taylor@Sun.COM */
949517SBill.Taylor@Sun.COM
959517SBill.Taylor@Sun.COM /*
969517SBill.Taylor@Sun.COM * Lock the QP so that we can modify it atomically. After grabbing
979517SBill.Taylor@Sun.COM * the lock, get the current QP state. We will use this current QP
989517SBill.Taylor@Sun.COM * state to determine the legal transitions (and the checks that need
999517SBill.Taylor@Sun.COM * to be performed.)
1009517SBill.Taylor@Sun.COM * Below is a case for every possible QP state. In each case, we
1019517SBill.Taylor@Sun.COM * check that no flags are set which are not valid for the possible
1029517SBill.Taylor@Sun.COM * transitions from that state. If these tests pass and the
1039517SBill.Taylor@Sun.COM * state transition we are attempting is legal, then we call one
1049517SBill.Taylor@Sun.COM * of the helper functions. Each of these functions does some
1059517SBill.Taylor@Sun.COM * additional setup before posting the firmware command for the
1069517SBill.Taylor@Sun.COM * appropriate state transition.
1079517SBill.Taylor@Sun.COM */
1089517SBill.Taylor@Sun.COM mutex_enter(&qp->qp_lock);
1099517SBill.Taylor@Sun.COM
1109517SBill.Taylor@Sun.COM /*
1119517SBill.Taylor@Sun.COM * Verify that the transport type matches between the serv_type and the
1129517SBill.Taylor@Sun.COM * qp_trans. A caller to IBT must specify the qp_trans field as
1139517SBill.Taylor@Sun.COM * IBT_UD_SRV, IBT_RC_SRV, or IBT_UC_SRV, depending on the QP. We
1149517SBill.Taylor@Sun.COM * check here that the correct value was specified, based on our
1159517SBill.Taylor@Sun.COM * understanding of the QP serv type.
1169517SBill.Taylor@Sun.COM *
1179517SBill.Taylor@Sun.COM * Because callers specify part of a 'union' based on what QP type they
1189517SBill.Taylor@Sun.COM * think they're working with, this ensures that we do not pickup bogus
1199517SBill.Taylor@Sun.COM * data if the caller thought they were working with a different QP
1209517SBill.Taylor@Sun.COM * type.
1219517SBill.Taylor@Sun.COM */
1229517SBill.Taylor@Sun.COM if (!(HERMON_QP_TYPE_VALID(info_p->qp_trans, qp->qp_serv_type))) {
1239517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
1249517SBill.Taylor@Sun.COM return (IBT_QP_SRV_TYPE_INVALID);
1259517SBill.Taylor@Sun.COM }
1269517SBill.Taylor@Sun.COM
1279517SBill.Taylor@Sun.COM /*
1289517SBill.Taylor@Sun.COM * If this is a transition to RTS (which is valid from RTR, RTS,
1299517SBill.Taylor@Sun.COM * SQError, and SQ Drain) then we should honor the "current QP state"
1309517SBill.Taylor@Sun.COM * specified by the consumer. This means converting the IBTF QP state
1319517SBill.Taylor@Sun.COM * in "info_p->qp_current_state" to an Hermon QP state. Otherwise, we
1329517SBill.Taylor@Sun.COM * assume that we already know the current state (i.e. whatever it was
1339517SBill.Taylor@Sun.COM * last modified to or queried as - in "qp->qp_state").
1349517SBill.Taylor@Sun.COM */
1359517SBill.Taylor@Sun.COM mod_state = info_p->qp_state;
1369517SBill.Taylor@Sun.COM
1379517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RTR_RTS) {
1389517SBill.Taylor@Sun.COM cur_state = HERMON_QP_RTR; /* Ready to Receive */
1399517SBill.Taylor@Sun.COM
1409517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
1419517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RTS)) {
1429517SBill.Taylor@Sun.COM
1439517SBill.Taylor@Sun.COM /* Convert the current IBTF QP state to an Hermon QP state */
1449517SBill.Taylor@Sun.COM switch (info_p->qp_current_state) {
1459517SBill.Taylor@Sun.COM case IBT_STATE_RTR:
1469517SBill.Taylor@Sun.COM cur_state = HERMON_QP_RTR; /* Ready to Receive */
1479517SBill.Taylor@Sun.COM break;
1489517SBill.Taylor@Sun.COM case IBT_STATE_RTS:
1499517SBill.Taylor@Sun.COM cur_state = HERMON_QP_RTS; /* Ready to Send */
1509517SBill.Taylor@Sun.COM break;
1519517SBill.Taylor@Sun.COM case IBT_STATE_SQE:
1529517SBill.Taylor@Sun.COM cur_state = HERMON_QP_SQERR; /* Send Queue Error */
1539517SBill.Taylor@Sun.COM break;
1549517SBill.Taylor@Sun.COM case IBT_STATE_SQD:
1559517SBill.Taylor@Sun.COM cur_state = HERMON_QP_SQD; /* SQ Drained */
1569517SBill.Taylor@Sun.COM break;
1579517SBill.Taylor@Sun.COM default:
1589517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
1599517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
1609517SBill.Taylor@Sun.COM }
1619517SBill.Taylor@Sun.COM } else {
1629517SBill.Taylor@Sun.COM cur_state = qp->qp_state;
1639517SBill.Taylor@Sun.COM }
1649517SBill.Taylor@Sun.COM
1659517SBill.Taylor@Sun.COM switch (cur_state) {
1669517SBill.Taylor@Sun.COM case HERMON_QP_RESET:
1679517SBill.Taylor@Sun.COM okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RESET_INIT |
1689517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
1699517SBill.Taylor@Sun.COM IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
1709517SBill.Taylor@Sun.COM IBT_CEP_SET_PORT | IBT_CEP_SET_QKEY);
1719517SBill.Taylor@Sun.COM
1729517SBill.Taylor@Sun.COM /*
1739517SBill.Taylor@Sun.COM * Check for attempts to modify invalid attributes from the
1749517SBill.Taylor@Sun.COM * "Reset" state
1759517SBill.Taylor@Sun.COM */
1769517SBill.Taylor@Sun.COM if (flags & ~okflags) {
1779517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
1789517SBill.Taylor@Sun.COM status = IBT_QP_ATTR_RO;
1799517SBill.Taylor@Sun.COM goto qpmod_fail;
1809517SBill.Taylor@Sun.COM }
1819517SBill.Taylor@Sun.COM
1829517SBill.Taylor@Sun.COM /*
1839517SBill.Taylor@Sun.COM * Verify state transition is to either "Init", back to
1849517SBill.Taylor@Sun.COM * "Reset", or to "Error".
1859517SBill.Taylor@Sun.COM */
1869517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_RESET_INIT) &&
1879517SBill.Taylor@Sun.COM (flags & IBT_CEP_SET_STATE) &&
1889517SBill.Taylor@Sun.COM (mod_state != IBT_STATE_INIT)) {
1899517SBill.Taylor@Sun.COM /* Invalid transition - ambiguous flags */
1909517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
1919517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
1929517SBill.Taylor@Sun.COM goto qpmod_fail;
1939517SBill.Taylor@Sun.COM
1949517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_RESET_INIT) ||
1959517SBill.Taylor@Sun.COM ((flags & IBT_CEP_SET_STATE) &&
1969517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_INIT))) {
1979517SBill.Taylor@Sun.COM /*
1989517SBill.Taylor@Sun.COM * Attempt to transition from "Reset" to "Init"
1999517SBill.Taylor@Sun.COM */
2009517SBill.Taylor@Sun.COM status = hermon_qp_reset2init(state, qp, info_p);
2019517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2029517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2039517SBill.Taylor@Sun.COM goto qpmod_fail;
2049517SBill.Taylor@Sun.COM }
2059517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_INIT;
206*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_INIT);
2079517SBill.Taylor@Sun.COM
2089517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
2099517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
2109517SBill.Taylor@Sun.COM /*
2119517SBill.Taylor@Sun.COM * Attempt to transition from "Reset" back to "Reset"
2129517SBill.Taylor@Sun.COM * Nothing to do here really... just drop the lock
2139517SBill.Taylor@Sun.COM * and return success. The qp->qp_state should
2149517SBill.Taylor@Sun.COM * already be set to HERMON_QP_RESET.
2159517SBill.Taylor@Sun.COM *
2169517SBill.Taylor@Sun.COM * Note: We return here because we do not want to fall
2179517SBill.Taylor@Sun.COM * through to the hermon_wrid_from_reset_handling()
2189517SBill.Taylor@Sun.COM * routine below (since we are not really moving
2199517SBill.Taylor@Sun.COM * _out_ of the "Reset" state.
2209517SBill.Taylor@Sun.COM */
2219517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2229517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
2239517SBill.Taylor@Sun.COM
2249517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
2259517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
2269517SBill.Taylor@Sun.COM /*
2279517SBill.Taylor@Sun.COM * Attempt to transition from "Reset" to "Error"
2289517SBill.Taylor@Sun.COM */
2299517SBill.Taylor@Sun.COM status = hermon_qp_reset2err(state, qp);
2309517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2319517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2329517SBill.Taylor@Sun.COM goto qpmod_fail;
2339517SBill.Taylor@Sun.COM }
2349517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_ERR;
235*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
2369517SBill.Taylor@Sun.COM
2379517SBill.Taylor@Sun.COM } else {
2389517SBill.Taylor@Sun.COM /* Invalid transition - return error */
2399517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2409517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
2419517SBill.Taylor@Sun.COM goto qpmod_fail;
2429517SBill.Taylor@Sun.COM }
2439517SBill.Taylor@Sun.COM
2449517SBill.Taylor@Sun.COM /*
2459517SBill.Taylor@Sun.COM * Do any additional handling necessary here for the transition
2469517SBill.Taylor@Sun.COM * from the "Reset" state (e.g. re-initialize the workQ WRID
2479517SBill.Taylor@Sun.COM * lists). Note: If hermon_wrid_from_reset_handling() fails,
2489517SBill.Taylor@Sun.COM * then we attempt to transition the QP back to the "Reset"
2499517SBill.Taylor@Sun.COM * state. If that fails, then it is an indication of a serious
2509517SBill.Taylor@Sun.COM * problem (either HW or SW). So we print out a warning
2519517SBill.Taylor@Sun.COM * message and return failure.
2529517SBill.Taylor@Sun.COM */
2539517SBill.Taylor@Sun.COM status = hermon_wrid_from_reset_handling(state, qp);
2549517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
2559517SBill.Taylor@Sun.COM if (hermon_qp_to_reset(state, qp) != DDI_SUCCESS) {
2569517SBill.Taylor@Sun.COM HERMON_WARNING(state, "failed to reset QP");
2579517SBill.Taylor@Sun.COM }
2589517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
259*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
2609517SBill.Taylor@Sun.COM
2619517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2629517SBill.Taylor@Sun.COM goto qpmod_fail;
2639517SBill.Taylor@Sun.COM }
2649517SBill.Taylor@Sun.COM break;
2659517SBill.Taylor@Sun.COM
2669517SBill.Taylor@Sun.COM case HERMON_QP_INIT:
2679517SBill.Taylor@Sun.COM okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_INIT_RTR |
2689517SBill.Taylor@Sun.COM IBT_CEP_SET_ADDS_VECT | IBT_CEP_SET_RDMARA_IN |
2699517SBill.Taylor@Sun.COM IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_ALT_PATH |
2709517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
2719517SBill.Taylor@Sun.COM IBT_CEP_SET_ATOMIC | IBT_CEP_SET_PKEY_IX |
2729517SBill.Taylor@Sun.COM IBT_CEP_SET_QKEY | IBT_CEP_SET_PORT);
2739517SBill.Taylor@Sun.COM
2749517SBill.Taylor@Sun.COM /*
2759517SBill.Taylor@Sun.COM * Check for attempts to modify invalid attributes from the
2769517SBill.Taylor@Sun.COM * "Init" state
2779517SBill.Taylor@Sun.COM */
2789517SBill.Taylor@Sun.COM if (flags & ~okflags) {
2799517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2809517SBill.Taylor@Sun.COM status = IBT_QP_ATTR_RO;
2819517SBill.Taylor@Sun.COM goto qpmod_fail;
2829517SBill.Taylor@Sun.COM }
2839517SBill.Taylor@Sun.COM
2849517SBill.Taylor@Sun.COM /*
2859517SBill.Taylor@Sun.COM * Verify state transition is to either "RTR", back to "Init",
2869517SBill.Taylor@Sun.COM * to "Reset", or to "Error"
2879517SBill.Taylor@Sun.COM */
2889517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_INIT_RTR) &&
2899517SBill.Taylor@Sun.COM (flags & IBT_CEP_SET_STATE) &&
2909517SBill.Taylor@Sun.COM (mod_state != IBT_STATE_RTR)) {
2919517SBill.Taylor@Sun.COM /* Invalid transition - ambiguous flags */
2929517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
2939517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
2949517SBill.Taylor@Sun.COM goto qpmod_fail;
2959517SBill.Taylor@Sun.COM
2969517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_INIT_RTR) ||
2979517SBill.Taylor@Sun.COM ((flags & IBT_CEP_SET_STATE) &&
2989517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RTR))) {
2999517SBill.Taylor@Sun.COM /*
3009517SBill.Taylor@Sun.COM * Attempt to transition from "Init" to "RTR"
3019517SBill.Taylor@Sun.COM */
3029517SBill.Taylor@Sun.COM status = hermon_qp_init2rtr(state, qp, flags, info_p);
3039517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
3049517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3059517SBill.Taylor@Sun.COM goto qpmod_fail;
3069517SBill.Taylor@Sun.COM }
3079517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RTR;
308*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTR);
3099517SBill.Taylor@Sun.COM
3109517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
3119517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_INIT)) {
3129517SBill.Taylor@Sun.COM /*
3139517SBill.Taylor@Sun.COM * Attempt to transition from "Init" to "Init"
3149517SBill.Taylor@Sun.COM */
3159517SBill.Taylor@Sun.COM status = hermon_qp_init2init(state, qp, flags, info_p);
3169517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
3179517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3189517SBill.Taylor@Sun.COM goto qpmod_fail;
3199517SBill.Taylor@Sun.COM }
3209517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_INIT;
321*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_INIT);
3229517SBill.Taylor@Sun.COM
3239517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
3249517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
3259517SBill.Taylor@Sun.COM /*
3269517SBill.Taylor@Sun.COM * Attempt to transition from "Init" to "Reset"
3279517SBill.Taylor@Sun.COM */
3289517SBill.Taylor@Sun.COM status = hermon_qp_to_reset(state, qp);
3299517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
3309517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3319517SBill.Taylor@Sun.COM goto qpmod_fail;
3329517SBill.Taylor@Sun.COM }
3339517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
334*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
3359517SBill.Taylor@Sun.COM
3369517SBill.Taylor@Sun.COM /*
3379517SBill.Taylor@Sun.COM * Do any additional handling necessary for the
3389517SBill.Taylor@Sun.COM * transition _to_ the "Reset" state (e.g. update the
3399517SBill.Taylor@Sun.COM * workQ WRID lists)
3409517SBill.Taylor@Sun.COM */
3419517SBill.Taylor@Sun.COM status = hermon_wrid_to_reset_handling(state, qp);
3429517SBill.Taylor@Sun.COM if (status != IBT_SUCCESS) {
3439517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3449517SBill.Taylor@Sun.COM goto qpmod_fail;
3459517SBill.Taylor@Sun.COM }
3469517SBill.Taylor@Sun.COM
3479517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
3489517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
3499517SBill.Taylor@Sun.COM /*
3509517SBill.Taylor@Sun.COM * Attempt to transition from "Init" to "Error"
3519517SBill.Taylor@Sun.COM */
3529517SBill.Taylor@Sun.COM status = hermon_qp_to_error(state, qp);
3539517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
3549517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3559517SBill.Taylor@Sun.COM goto qpmod_fail;
3569517SBill.Taylor@Sun.COM }
3579517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_ERR;
358*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
3599517SBill.Taylor@Sun.COM
3609517SBill.Taylor@Sun.COM } else {
3619517SBill.Taylor@Sun.COM /* Invalid transition - return error */
3629517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3639517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
3649517SBill.Taylor@Sun.COM goto qpmod_fail;
3659517SBill.Taylor@Sun.COM }
3669517SBill.Taylor@Sun.COM break;
3679517SBill.Taylor@Sun.COM
3689517SBill.Taylor@Sun.COM case HERMON_QP_RTR:
3699517SBill.Taylor@Sun.COM okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RTR_RTS |
3709517SBill.Taylor@Sun.COM IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
3719517SBill.Taylor@Sun.COM IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_RDMARA_OUT |
3729517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMA_R | IBT_CEP_SET_RDMA_W |
3739517SBill.Taylor@Sun.COM IBT_CEP_SET_ATOMIC | IBT_CEP_SET_QKEY |
3749517SBill.Taylor@Sun.COM IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
3759517SBill.Taylor@Sun.COM IBT_CEP_SET_MIN_RNR_NAK);
3769517SBill.Taylor@Sun.COM
3779517SBill.Taylor@Sun.COM /*
3789517SBill.Taylor@Sun.COM * Check for attempts to modify invalid attributes from the
3799517SBill.Taylor@Sun.COM * "RTR" state
3809517SBill.Taylor@Sun.COM */
3819517SBill.Taylor@Sun.COM if (flags & ~okflags) {
3829517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3839517SBill.Taylor@Sun.COM status = IBT_QP_ATTR_RO;
3849517SBill.Taylor@Sun.COM goto qpmod_fail;
3859517SBill.Taylor@Sun.COM }
3869517SBill.Taylor@Sun.COM
3879517SBill.Taylor@Sun.COM /*
3889517SBill.Taylor@Sun.COM * Verify state transition is to either "RTS", "Reset",
3899517SBill.Taylor@Sun.COM * or "Error"
3909517SBill.Taylor@Sun.COM */
3919517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_RTR_RTS) &&
3929517SBill.Taylor@Sun.COM (flags & IBT_CEP_SET_STATE) &&
3939517SBill.Taylor@Sun.COM (mod_state != IBT_STATE_RTS)) {
3949517SBill.Taylor@Sun.COM /* Invalid transition - ambiguous flags */
3959517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
3969517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
3979517SBill.Taylor@Sun.COM goto qpmod_fail;
3989517SBill.Taylor@Sun.COM
3999517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_RTR_RTS) ||
4009517SBill.Taylor@Sun.COM ((flags & IBT_CEP_SET_STATE) &&
4019517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RTS))) {
4029517SBill.Taylor@Sun.COM /*
4039517SBill.Taylor@Sun.COM * Attempt to transition from "RTR" to "RTS"
4049517SBill.Taylor@Sun.COM */
4059517SBill.Taylor@Sun.COM status = hermon_qp_rtr2rts(state, qp, flags, info_p);
4069517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
4079517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4089517SBill.Taylor@Sun.COM goto qpmod_fail;
4099517SBill.Taylor@Sun.COM }
4109517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RTS;
411*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
4129517SBill.Taylor@Sun.COM
4139517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
4149517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
4159517SBill.Taylor@Sun.COM /*
4169517SBill.Taylor@Sun.COM * Attempt to transition from "RTR" to "Reset"
4179517SBill.Taylor@Sun.COM */
4189517SBill.Taylor@Sun.COM status = hermon_qp_to_reset(state, qp);
4199517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
4209517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4219517SBill.Taylor@Sun.COM goto qpmod_fail;
4229517SBill.Taylor@Sun.COM }
4239517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
424*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
4259517SBill.Taylor@Sun.COM
4269517SBill.Taylor@Sun.COM /*
4279517SBill.Taylor@Sun.COM * Do any additional handling necessary for the
4289517SBill.Taylor@Sun.COM * transition _to_ the "Reset" state (e.g. update the
4299517SBill.Taylor@Sun.COM * workQ WRID lists)
4309517SBill.Taylor@Sun.COM */
4319517SBill.Taylor@Sun.COM status = hermon_wrid_to_reset_handling(state, qp);
4329517SBill.Taylor@Sun.COM if (status != IBT_SUCCESS) {
4339517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4349517SBill.Taylor@Sun.COM goto qpmod_fail;
4359517SBill.Taylor@Sun.COM }
4369517SBill.Taylor@Sun.COM
4379517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
4389517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
4399517SBill.Taylor@Sun.COM /*
4409517SBill.Taylor@Sun.COM * Attempt to transition from "RTR" to "Error"
4419517SBill.Taylor@Sun.COM */
4429517SBill.Taylor@Sun.COM status = hermon_qp_to_error(state, qp);
4439517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
4449517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4459517SBill.Taylor@Sun.COM goto qpmod_fail;
4469517SBill.Taylor@Sun.COM }
4479517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_ERR;
448*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
4499517SBill.Taylor@Sun.COM
4509517SBill.Taylor@Sun.COM } else {
4519517SBill.Taylor@Sun.COM /* Invalid transition - return error */
4529517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4539517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
4549517SBill.Taylor@Sun.COM goto qpmod_fail;
4559517SBill.Taylor@Sun.COM }
4569517SBill.Taylor@Sun.COM break;
4579517SBill.Taylor@Sun.COM
4589517SBill.Taylor@Sun.COM case HERMON_QP_RTS:
4599517SBill.Taylor@Sun.COM okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
4609517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
4619517SBill.Taylor@Sun.COM IBT_CEP_SET_QKEY | IBT_CEP_SET_ALT_PATH |
4629517SBill.Taylor@Sun.COM IBT_CEP_SET_MIG | IBT_CEP_SET_MIN_RNR_NAK |
4639517SBill.Taylor@Sun.COM IBT_CEP_SET_SQD_EVENT);
4649517SBill.Taylor@Sun.COM
4659517SBill.Taylor@Sun.COM /*
4669517SBill.Taylor@Sun.COM * Check for attempts to modify invalid attributes from the
4679517SBill.Taylor@Sun.COM * "RTS" state
4689517SBill.Taylor@Sun.COM */
4699517SBill.Taylor@Sun.COM if (flags & ~okflags) {
4709517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4719517SBill.Taylor@Sun.COM status = IBT_QP_ATTR_RO;
4729517SBill.Taylor@Sun.COM goto qpmod_fail;
4739517SBill.Taylor@Sun.COM }
4749517SBill.Taylor@Sun.COM
4759517SBill.Taylor@Sun.COM /*
4769517SBill.Taylor@Sun.COM * Verify state transition is to either "RTS", "SQD", "Reset",
4779517SBill.Taylor@Sun.COM * or "Error"
4789517SBill.Taylor@Sun.COM */
4799517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_STATE) &&
4809517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RTS)) {
4819517SBill.Taylor@Sun.COM /*
4829517SBill.Taylor@Sun.COM * Attempt to transition from "RTS" to "RTS"
4839517SBill.Taylor@Sun.COM */
4849517SBill.Taylor@Sun.COM status = hermon_qp_rts2rts(state, qp, flags, info_p);
4859517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
4869517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
4879517SBill.Taylor@Sun.COM goto qpmod_fail;
4889517SBill.Taylor@Sun.COM }
4899517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RTS;
490*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
4919517SBill.Taylor@Sun.COM
4929517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
4939517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_SQD)) {
4949517SBill.Taylor@Sun.COM #ifdef HERMON_NOTNOW
4959517SBill.Taylor@Sun.COM /*
4969517SBill.Taylor@Sun.COM * Attempt to transition from "RTS" to "SQD"
4979517SBill.Taylor@Sun.COM */
4989517SBill.Taylor@Sun.COM status = hermon_qp_rts2sqd(state, qp, flags);
4999517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
5009517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5019517SBill.Taylor@Sun.COM goto qpmod_fail;
5029517SBill.Taylor@Sun.COM }
5039517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_SQD;
504*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
5059517SBill.Taylor@Sun.COM #else
5069517SBill.Taylor@Sun.COM /* hack because of the lack of fw support for SQD */
5079517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5089517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
5099517SBill.Taylor@Sun.COM goto qpmod_fail;
5109517SBill.Taylor@Sun.COM #endif
5119517SBill.Taylor@Sun.COM
5129517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
5139517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
5149517SBill.Taylor@Sun.COM /*
5159517SBill.Taylor@Sun.COM * Attempt to transition from "RTS" to "Reset"
5169517SBill.Taylor@Sun.COM */
5179517SBill.Taylor@Sun.COM status = hermon_qp_to_reset(state, qp);
5189517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
5199517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5209517SBill.Taylor@Sun.COM goto qpmod_fail;
5219517SBill.Taylor@Sun.COM }
5229517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
523*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
5249517SBill.Taylor@Sun.COM
5259517SBill.Taylor@Sun.COM /*
5269517SBill.Taylor@Sun.COM * Do any additional handling necessary for the
5279517SBill.Taylor@Sun.COM * transition _to_ the "Reset" state (e.g. update the
5289517SBill.Taylor@Sun.COM * workQ WRID lists)
5299517SBill.Taylor@Sun.COM */
5309517SBill.Taylor@Sun.COM status = hermon_wrid_to_reset_handling(state, qp);
5319517SBill.Taylor@Sun.COM if (status != IBT_SUCCESS) {
5329517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5339517SBill.Taylor@Sun.COM goto qpmod_fail;
5349517SBill.Taylor@Sun.COM }
5359517SBill.Taylor@Sun.COM
5369517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
5379517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
5389517SBill.Taylor@Sun.COM /*
5399517SBill.Taylor@Sun.COM * Attempt to transition from "RTS" to "Error"
5409517SBill.Taylor@Sun.COM */
5419517SBill.Taylor@Sun.COM status = hermon_qp_to_error(state, qp);
5429517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
5439517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5449517SBill.Taylor@Sun.COM goto qpmod_fail;
5459517SBill.Taylor@Sun.COM }
5469517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_ERR;
547*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
5489517SBill.Taylor@Sun.COM
5499517SBill.Taylor@Sun.COM } else {
5509517SBill.Taylor@Sun.COM /* Invalid transition - return error */
5519517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5529517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
5539517SBill.Taylor@Sun.COM goto qpmod_fail;
5549517SBill.Taylor@Sun.COM }
5559517SBill.Taylor@Sun.COM break;
5569517SBill.Taylor@Sun.COM
5579517SBill.Taylor@Sun.COM case HERMON_QP_SQERR:
5589517SBill.Taylor@Sun.COM okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_RDMA_R |
5599517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC |
5609517SBill.Taylor@Sun.COM IBT_CEP_SET_QKEY | IBT_CEP_SET_MIN_RNR_NAK);
5619517SBill.Taylor@Sun.COM
5629517SBill.Taylor@Sun.COM /*
5639517SBill.Taylor@Sun.COM * Check for attempts to modify invalid attributes from the
5649517SBill.Taylor@Sun.COM * "SQErr" state
5659517SBill.Taylor@Sun.COM */
5669517SBill.Taylor@Sun.COM if (flags & ~okflags) {
5679517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5689517SBill.Taylor@Sun.COM status = IBT_QP_ATTR_RO;
5699517SBill.Taylor@Sun.COM goto qpmod_fail;
5709517SBill.Taylor@Sun.COM }
5719517SBill.Taylor@Sun.COM
5729517SBill.Taylor@Sun.COM /*
5739517SBill.Taylor@Sun.COM * Verify state transition is to either "RTS", "Reset", or
5749517SBill.Taylor@Sun.COM * "Error"
5759517SBill.Taylor@Sun.COM */
5769517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_STATE) &&
5779517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RTS)) {
5789517SBill.Taylor@Sun.COM /*
5799517SBill.Taylor@Sun.COM * Attempt to transition from "SQErr" to "RTS"
5809517SBill.Taylor@Sun.COM */
5819517SBill.Taylor@Sun.COM status = hermon_qp_sqerr2rts(state, qp, flags, info_p);
5829517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
5839517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5849517SBill.Taylor@Sun.COM goto qpmod_fail;
5859517SBill.Taylor@Sun.COM }
5869517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RTS;
587*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
5889517SBill.Taylor@Sun.COM
5899517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
5909517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
5919517SBill.Taylor@Sun.COM /*
5929517SBill.Taylor@Sun.COM * Attempt to transition from "SQErr" to "Reset"
5939517SBill.Taylor@Sun.COM */
5949517SBill.Taylor@Sun.COM status = hermon_qp_to_reset(state, qp);
5959517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
5969517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
5979517SBill.Taylor@Sun.COM goto qpmod_fail;
5989517SBill.Taylor@Sun.COM }
5999517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
600*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
6019517SBill.Taylor@Sun.COM
6029517SBill.Taylor@Sun.COM /*
6039517SBill.Taylor@Sun.COM * Do any additional handling necessary for the
6049517SBill.Taylor@Sun.COM * transition _to_ the "Reset" state (e.g. update the
6059517SBill.Taylor@Sun.COM * workQ WRID lists)
6069517SBill.Taylor@Sun.COM */
6079517SBill.Taylor@Sun.COM status = hermon_wrid_to_reset_handling(state, qp);
6089517SBill.Taylor@Sun.COM if (status != IBT_SUCCESS) {
6099517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6109517SBill.Taylor@Sun.COM goto qpmod_fail;
6119517SBill.Taylor@Sun.COM }
6129517SBill.Taylor@Sun.COM
6139517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
6149517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
6159517SBill.Taylor@Sun.COM /*
6169517SBill.Taylor@Sun.COM * Attempt to transition from "SQErr" to "Error"
6179517SBill.Taylor@Sun.COM */
6189517SBill.Taylor@Sun.COM status = hermon_qp_to_error(state, qp);
6199517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
6209517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6219517SBill.Taylor@Sun.COM goto qpmod_fail;
6229517SBill.Taylor@Sun.COM }
6239517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_ERR;
624*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
6259517SBill.Taylor@Sun.COM
6269517SBill.Taylor@Sun.COM } else {
6279517SBill.Taylor@Sun.COM /* Invalid transition - return error */
6289517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6299517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
6309517SBill.Taylor@Sun.COM goto qpmod_fail;
6319517SBill.Taylor@Sun.COM }
6329517SBill.Taylor@Sun.COM break;
6339517SBill.Taylor@Sun.COM
6349517SBill.Taylor@Sun.COM case HERMON_QP_SQD:
6359517SBill.Taylor@Sun.COM okflags = (IBT_CEP_SET_STATE | IBT_CEP_SET_ADDS_VECT |
6369517SBill.Taylor@Sun.COM IBT_CEP_SET_ALT_PATH | IBT_CEP_SET_MIG |
6379517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_RDMARA_IN |
6389517SBill.Taylor@Sun.COM IBT_CEP_SET_QKEY | IBT_CEP_SET_PKEY_IX |
6399517SBill.Taylor@Sun.COM IBT_CEP_SET_TIMEOUT | IBT_CEP_SET_RETRY |
6409517SBill.Taylor@Sun.COM IBT_CEP_SET_RNR_NAK_RETRY | IBT_CEP_SET_PORT |
6419517SBill.Taylor@Sun.COM IBT_CEP_SET_MIN_RNR_NAK | IBT_CEP_SET_RDMA_R |
6429517SBill.Taylor@Sun.COM IBT_CEP_SET_RDMA_W | IBT_CEP_SET_ATOMIC);
6439517SBill.Taylor@Sun.COM
6449517SBill.Taylor@Sun.COM /*
6459517SBill.Taylor@Sun.COM * Check for attempts to modify invalid attributes from the
6469517SBill.Taylor@Sun.COM * "SQD" state
6479517SBill.Taylor@Sun.COM */
6489517SBill.Taylor@Sun.COM if (flags & ~okflags) {
6499517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6509517SBill.Taylor@Sun.COM status = IBT_QP_ATTR_RO;
6519517SBill.Taylor@Sun.COM goto qpmod_fail;
6529517SBill.Taylor@Sun.COM }
6539517SBill.Taylor@Sun.COM
6549517SBill.Taylor@Sun.COM /*
6559517SBill.Taylor@Sun.COM * Verify state transition is to either "SQD", "RTS", "Reset",
6569517SBill.Taylor@Sun.COM * or "Error"
6579517SBill.Taylor@Sun.COM */
6589517SBill.Taylor@Sun.COM
6599517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_STATE) &&
6609517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_SQD)) {
6619517SBill.Taylor@Sun.COM /*
6629517SBill.Taylor@Sun.COM * Attempt to transition from "SQD" to "SQD"
6639517SBill.Taylor@Sun.COM */
6649517SBill.Taylor@Sun.COM status = hermon_qp_sqd2sqd(state, qp, flags, info_p);
6659517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
6669517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6679517SBill.Taylor@Sun.COM goto qpmod_fail;
6689517SBill.Taylor@Sun.COM }
6699517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_SQD;
670*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
6719517SBill.Taylor@Sun.COM
6729517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
6739517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RTS)) {
6749517SBill.Taylor@Sun.COM /*
6759517SBill.Taylor@Sun.COM * If still draining SQ, then fail transition attempt
6769517SBill.Taylor@Sun.COM * to RTS, even though this is now done is two steps
6779517SBill.Taylor@Sun.COM * (see below) if the consumer has tried this before
6789517SBill.Taylor@Sun.COM * it's drained, let him fail and wait appropriately
6799517SBill.Taylor@Sun.COM */
6809517SBill.Taylor@Sun.COM if (qp->qp_sqd_still_draining) {
6819517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6829517SBill.Taylor@Sun.COM goto qpmod_fail;
6839517SBill.Taylor@Sun.COM }
6849517SBill.Taylor@Sun.COM /*
6859517SBill.Taylor@Sun.COM * IBA 1.2 has changed - most/all the things that were
6869517SBill.Taylor@Sun.COM * done in SQD2RTS can be done in SQD2SQD. So make this
6879517SBill.Taylor@Sun.COM * a 2-step process. First, set any attributes requsted
6889517SBill.Taylor@Sun.COM * w/ SQD2SQD, but no real transition.
6899517SBill.Taylor@Sun.COM *
6909517SBill.Taylor@Sun.COM * First, Attempt to transition from "SQD" to "SQD"
6919517SBill.Taylor@Sun.COM */
6929517SBill.Taylor@Sun.COM status = hermon_qp_sqd2sqd(state, qp, flags, info_p);
6939517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
6949517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
6959517SBill.Taylor@Sun.COM goto qpmod_fail;
6969517SBill.Taylor@Sun.COM }
6979517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_SQD;
698*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_SQD);
6999517SBill.Taylor@Sun.COM
7009517SBill.Taylor@Sun.COM /*
7019517SBill.Taylor@Sun.COM * The, attempt to transition from "SQD" to "RTS", but
7029517SBill.Taylor@Sun.COM * request only the state transition, no attributes
7039517SBill.Taylor@Sun.COM */
7049517SBill.Taylor@Sun.COM
7059517SBill.Taylor@Sun.COM status = hermon_qp_sqd2rts(state, qp,
7069517SBill.Taylor@Sun.COM IBT_CEP_SET_STATE, info_p);
7079517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
7089517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7099517SBill.Taylor@Sun.COM goto qpmod_fail;
7109517SBill.Taylor@Sun.COM }
7119517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RTS;
712*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RTS);
7139517SBill.Taylor@Sun.COM
7149517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
7159517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
7169517SBill.Taylor@Sun.COM /*
7179517SBill.Taylor@Sun.COM * Attempt to transition from "SQD" to "Reset"
7189517SBill.Taylor@Sun.COM */
7199517SBill.Taylor@Sun.COM status = hermon_qp_to_reset(state, qp);
7209517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
7219517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7229517SBill.Taylor@Sun.COM goto qpmod_fail;
7239517SBill.Taylor@Sun.COM }
7249517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
725*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
7269517SBill.Taylor@Sun.COM
7279517SBill.Taylor@Sun.COM /*
7289517SBill.Taylor@Sun.COM * Do any additional handling necessary for the
7299517SBill.Taylor@Sun.COM * transition _to_ the "Reset" state (e.g. update the
7309517SBill.Taylor@Sun.COM * workQ WRID lists)
7319517SBill.Taylor@Sun.COM */
7329517SBill.Taylor@Sun.COM status = hermon_wrid_to_reset_handling(state, qp);
7339517SBill.Taylor@Sun.COM if (status != IBT_SUCCESS) {
7349517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7359517SBill.Taylor@Sun.COM goto qpmod_fail;
7369517SBill.Taylor@Sun.COM }
7379517SBill.Taylor@Sun.COM
7389517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
7399517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
7409517SBill.Taylor@Sun.COM /*
7419517SBill.Taylor@Sun.COM * Attempt to transition from "SQD" to "Error"
7429517SBill.Taylor@Sun.COM */
7439517SBill.Taylor@Sun.COM status = hermon_qp_to_error(state, qp);
7449517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
7459517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7469517SBill.Taylor@Sun.COM goto qpmod_fail;
7479517SBill.Taylor@Sun.COM }
7489517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_ERR;
749*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_ERR);
7509517SBill.Taylor@Sun.COM
7519517SBill.Taylor@Sun.COM } else {
7529517SBill.Taylor@Sun.COM /* Invalid transition - return error */
7539517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7549517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
7559517SBill.Taylor@Sun.COM goto qpmod_fail;
7569517SBill.Taylor@Sun.COM }
7579517SBill.Taylor@Sun.COM break;
7589517SBill.Taylor@Sun.COM
7599517SBill.Taylor@Sun.COM case HERMON_QP_ERR:
7609517SBill.Taylor@Sun.COM /*
7619517SBill.Taylor@Sun.COM * Verify state transition is to either "Reset" or back to
7629517SBill.Taylor@Sun.COM * "Error"
7639517SBill.Taylor@Sun.COM */
7649517SBill.Taylor@Sun.COM if ((flags & IBT_CEP_SET_STATE) &&
7659517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_RESET)) {
7669517SBill.Taylor@Sun.COM /*
7679517SBill.Taylor@Sun.COM * Attempt to transition from "Error" to "Reset"
7689517SBill.Taylor@Sun.COM */
7699517SBill.Taylor@Sun.COM status = hermon_qp_to_reset(state, qp);
7709517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
7719517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7729517SBill.Taylor@Sun.COM goto qpmod_fail;
7739517SBill.Taylor@Sun.COM }
7749517SBill.Taylor@Sun.COM qp->qp_state = HERMON_QP_RESET;
775*12965SWilliam.Taylor@Oracle.COM HERMON_SET_QP_POST_SEND_STATE(qp, HERMON_QP_RESET);
7769517SBill.Taylor@Sun.COM
7779517SBill.Taylor@Sun.COM /*
7789517SBill.Taylor@Sun.COM * Do any additional handling necessary for the
7799517SBill.Taylor@Sun.COM * transition _to_ the "Reset" state (e.g. update the
7809517SBill.Taylor@Sun.COM * workQ WRID lists)
7819517SBill.Taylor@Sun.COM */
7829517SBill.Taylor@Sun.COM status = hermon_wrid_to_reset_handling(state, qp);
7839517SBill.Taylor@Sun.COM if (status != IBT_SUCCESS) {
7849517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7859517SBill.Taylor@Sun.COM goto qpmod_fail;
7869517SBill.Taylor@Sun.COM }
7879517SBill.Taylor@Sun.COM
7889517SBill.Taylor@Sun.COM } else if ((flags & IBT_CEP_SET_STATE) &&
7899517SBill.Taylor@Sun.COM (mod_state == IBT_STATE_ERROR)) {
7909517SBill.Taylor@Sun.COM /*
7919517SBill.Taylor@Sun.COM * Attempt to transition from "Error" back to "Error"
7929517SBill.Taylor@Sun.COM * Nothing to do here really... just drop the lock
7939517SBill.Taylor@Sun.COM * and return success. The qp->qp_state should
7949517SBill.Taylor@Sun.COM * already be set to HERMON_QP_ERR.
7959517SBill.Taylor@Sun.COM *
7969517SBill.Taylor@Sun.COM */
7979517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
7989517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
7999517SBill.Taylor@Sun.COM
8009517SBill.Taylor@Sun.COM } else {
8019517SBill.Taylor@Sun.COM /* Invalid transition - return error */
8029517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
8039517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
8049517SBill.Taylor@Sun.COM goto qpmod_fail;
8059517SBill.Taylor@Sun.COM }
8069517SBill.Taylor@Sun.COM break;
8079517SBill.Taylor@Sun.COM
8089517SBill.Taylor@Sun.COM default:
8099517SBill.Taylor@Sun.COM /*
8109517SBill.Taylor@Sun.COM * Invalid QP state. If we got here then it's a warning of
8119517SBill.Taylor@Sun.COM * a probably serious problem. So print a message and return
8129517SBill.Taylor@Sun.COM * failure
8139517SBill.Taylor@Sun.COM */
8149517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
8159517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP state in modify");
8169517SBill.Taylor@Sun.COM status = IBT_QP_STATE_INVALID;
8179517SBill.Taylor@Sun.COM goto qpmod_fail;
8189517SBill.Taylor@Sun.COM }
8199517SBill.Taylor@Sun.COM
8209517SBill.Taylor@Sun.COM mutex_exit(&qp->qp_lock);
8219517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
8229517SBill.Taylor@Sun.COM
8239517SBill.Taylor@Sun.COM qpmod_fail:
8249517SBill.Taylor@Sun.COM return (status);
8259517SBill.Taylor@Sun.COM }
8269517SBill.Taylor@Sun.COM
8279517SBill.Taylor@Sun.COM
8289517SBill.Taylor@Sun.COM /*
8299517SBill.Taylor@Sun.COM * hermon_qp_reset2init()
8309517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
8319517SBill.Taylor@Sun.COM */
8329517SBill.Taylor@Sun.COM static int
hermon_qp_reset2init(hermon_state_t * state,hermon_qphdl_t qp,ibt_qp_info_t * info_p)8339517SBill.Taylor@Sun.COM hermon_qp_reset2init(hermon_state_t *state, hermon_qphdl_t qp,
8349517SBill.Taylor@Sun.COM ibt_qp_info_t *info_p)
8359517SBill.Taylor@Sun.COM {
8369517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
8379517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
8389517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
8399517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
8409517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx;
8419517SBill.Taylor@Sun.COM int status;
8429517SBill.Taylor@Sun.COM uint32_t cqnmask;
843*12965SWilliam.Taylor@Oracle.COM int qp_srq_en;
8449517SBill.Taylor@Sun.COM
8459517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
8469517SBill.Taylor@Sun.COM
8479517SBill.Taylor@Sun.COM /*
8489517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
8499517SBill.Taylor@Sun.COM */
8509517SBill.Taylor@Sun.COM qpc = &qp->qpc;
8519517SBill.Taylor@Sun.COM
8529517SBill.Taylor@Sun.COM /*
8539517SBill.Taylor@Sun.COM * Fill in the common fields in the QPC
8549517SBill.Taylor@Sun.COM */
8559517SBill.Taylor@Sun.COM
8569517SBill.Taylor@Sun.COM if (qp->qp_is_special) {
8579517SBill.Taylor@Sun.COM qpc->serv_type = HERMON_QP_MLX;
8589517SBill.Taylor@Sun.COM } else {
8599517SBill.Taylor@Sun.COM qpc->serv_type = qp->qp_serv_type;
8609517SBill.Taylor@Sun.COM }
8619517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
8629517SBill.Taylor@Sun.COM
8639517SBill.Taylor@Sun.COM qpc->pd = qp->qp_pdhdl->pd_pdnum;
8649517SBill.Taylor@Sun.COM
8659517SBill.Taylor@Sun.COM qpc->log_sq_stride = qp->qp_sq_log_wqesz - 4;
8669517SBill.Taylor@Sun.COM qpc->log_rq_stride = qp->qp_rq_log_wqesz - 4;
8679517SBill.Taylor@Sun.COM qpc->sq_no_prefetch = qp->qp_no_prefetch;
8689517SBill.Taylor@Sun.COM qpc->log_sq_size = highbit(qp->qp_sq_bufsz) - 1;
8699517SBill.Taylor@Sun.COM qpc->log_rq_size = highbit(qp->qp_rq_bufsz) - 1;
8709517SBill.Taylor@Sun.COM
8719517SBill.Taylor@Sun.COM qpc->usr_page = qp->qp_uarpg;
8729517SBill.Taylor@Sun.COM
8739517SBill.Taylor@Sun.COM cqnmask = (1 << state->hs_cfg_profile->cp_log_num_cq) - 1;
874*12965SWilliam.Taylor@Oracle.COM qpc->cqn_snd =
875*12965SWilliam.Taylor@Oracle.COM (qp->qp_sq_cqhdl == NULL) ? 0 : qp->qp_sq_cqhdl->cq_cqnum & cqnmask;
8769517SBill.Taylor@Sun.COM qpc->page_offs = qp->qp_wqinfo.qa_pgoffs >> 6;
877*12965SWilliam.Taylor@Oracle.COM qpc->cqn_rcv =
878*12965SWilliam.Taylor@Oracle.COM (qp->qp_rq_cqhdl == NULL) ? 0 : qp->qp_rq_cqhdl->cq_cqnum & cqnmask;
8799517SBill.Taylor@Sun.COM
8809517SBill.Taylor@Sun.COM /* dbr is now an address, not an index */
8819517SBill.Taylor@Sun.COM qpc->dbr_addrh = ((uint64_t)qp->qp_rq_pdbr >> 32);
8829517SBill.Taylor@Sun.COM qpc->dbr_addrl = ((uint64_t)qp->qp_rq_pdbr & 0xFFFFFFFC) >> 2;
8839517SBill.Taylor@Sun.COM qpc->sq_wqe_counter = 0;
8849517SBill.Taylor@Sun.COM qpc->rq_wqe_counter = 0;
8859517SBill.Taylor@Sun.COM /*
8869517SBill.Taylor@Sun.COM * HERMON:
8879517SBill.Taylor@Sun.COM * qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
8889517SBill.Taylor@Sun.COM * page_offset, mtt_base_addr_h/l, and log2_page_size will
8899517SBill.Taylor@Sun.COM * be used to map the WQE buffer
8909517SBill.Taylor@Sun.COM * NOTE that the cMPT is created implicitly when the QP is
8919517SBill.Taylor@Sun.COM * transitioned from reset to init
8929517SBill.Taylor@Sun.COM */
8939517SBill.Taylor@Sun.COM qpc->log2_pgsz = qp->qp_mrhdl->mr_log2_pgsz;
8949517SBill.Taylor@Sun.COM qpc->mtt_base_addrl = (qp->qp_mrhdl->mr_mttaddr) >> 3;
8959517SBill.Taylor@Sun.COM qpc->mtt_base_addrh = (uint32_t)((qp->qp_mrhdl->mr_mttaddr >> 32) &
8969517SBill.Taylor@Sun.COM 0xFF);
897*12965SWilliam.Taylor@Oracle.COM qp_srq_en = (qp->qp_alloc_flags & IBT_QP_USES_SRQ) != 0;
898*12965SWilliam.Taylor@Oracle.COM qpc->srq_en = qp_srq_en;
899*12965SWilliam.Taylor@Oracle.COM
900*12965SWilliam.Taylor@Oracle.COM if (qp_srq_en) {
9019517SBill.Taylor@Sun.COM qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
9029517SBill.Taylor@Sun.COM } else {
9039517SBill.Taylor@Sun.COM qpc->srq_number = 0;
9049517SBill.Taylor@Sun.COM }
9059517SBill.Taylor@Sun.COM
906*12965SWilliam.Taylor@Oracle.COM /*
907*12965SWilliam.Taylor@Oracle.COM * Fast Registration Work Requests and Reserved Lkey are enabled
908*12965SWilliam.Taylor@Oracle.COM * with the single IBT bit stored in qp_rlky.
909*12965SWilliam.Taylor@Oracle.COM */
910*12965SWilliam.Taylor@Oracle.COM qpc->fre = qp->qp_rlky;
9119517SBill.Taylor@Sun.COM qpc->rlky = qp->qp_rlky;
912*12965SWilliam.Taylor@Oracle.COM
913*12965SWilliam.Taylor@Oracle.COM /* 1.2 verbs extensions disabled for now */
914*12965SWilliam.Taylor@Oracle.COM qpc->header_sep = 0; /* disable header separation for now */
915*12965SWilliam.Taylor@Oracle.COM qpc->rss = qp->qp_alloc_flags & IBT_QP_USES_RSS ? 1 : 0;
9169517SBill.Taylor@Sun.COM qpc->inline_scatter = 0; /* disable inline scatter for now */
9179517SBill.Taylor@Sun.COM
9189517SBill.Taylor@Sun.COM /*
9199517SBill.Taylor@Sun.COM * Now fill in the QPC fields which are specific to transport type
9209517SBill.Taylor@Sun.COM */
921*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
922*12965SWilliam.Taylor@Oracle.COM int my_fc_id_idx, exch_base;
923*12965SWilliam.Taylor@Oracle.COM
9249517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
9259517SBill.Taylor@Sun.COM
9269517SBill.Taylor@Sun.COM /* Set the QKey */
9279517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
9289517SBill.Taylor@Sun.COM
9299517SBill.Taylor@Sun.COM /*
9309517SBill.Taylor@Sun.COM * Set MTU and message max. Hermon checks the QPC
9319517SBill.Taylor@Sun.COM * MTU settings rather than just the port MTU,
9329517SBill.Taylor@Sun.COM * so set it to maximum size.
9339517SBill.Taylor@Sun.COM */
9349517SBill.Taylor@Sun.COM qpc->mtu = HERMON_MAX_MTU;
9359517SBill.Taylor@Sun.COM if (qp->qp_uses_lso)
9369517SBill.Taylor@Sun.COM qpc->msg_max = state->hs_devlim.log_max_gso_sz;
937*12965SWilliam.Taylor@Oracle.COM else if (qp->qp_is_special)
938*12965SWilliam.Taylor@Oracle.COM qpc->msg_max = HERMON_MAX_MTU + 6;
9399517SBill.Taylor@Sun.COM else
9409517SBill.Taylor@Sun.COM qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
9419517SBill.Taylor@Sun.COM
9429517SBill.Taylor@Sun.COM /* Check for valid port number and fill it in */
9439517SBill.Taylor@Sun.COM portnum = ud->ud_port;
9449517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
9459517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
9469517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
9479517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
9489517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
9499517SBill.Taylor@Sun.COM } else {
9509517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
9519517SBill.Taylor@Sun.COM }
9529517SBill.Taylor@Sun.COM
9539517SBill.Taylor@Sun.COM
9549517SBill.Taylor@Sun.COM /* Check for valid PKey index and fill it in */
9559517SBill.Taylor@Sun.COM pkeyindx = ud->ud_pkey_ix;
9569517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
9579517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
9589517SBill.Taylor@Sun.COM qp->qp_pkeyindx = pkeyindx;
9599517SBill.Taylor@Sun.COM } else {
9609517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
9619517SBill.Taylor@Sun.COM }
9629517SBill.Taylor@Sun.COM
963*12965SWilliam.Taylor@Oracle.COM /* fill in the RSS fields */
964*12965SWilliam.Taylor@Oracle.COM if (qpc->rss) {
965*12965SWilliam.Taylor@Oracle.COM struct hermon_hw_rss_s *rssp;
966*12965SWilliam.Taylor@Oracle.COM ibt_rss_flags_t flags = ud->ud_rss.rss_flags;
967*12965SWilliam.Taylor@Oracle.COM
968*12965SWilliam.Taylor@Oracle.COM rssp = (struct hermon_hw_rss_s *)&qpc->pri_addr_path;
969*12965SWilliam.Taylor@Oracle.COM rssp->log2_tbl_sz = ud->ud_rss.rss_log2_table;
970*12965SWilliam.Taylor@Oracle.COM rssp->base_qpn = ud->ud_rss.rss_base_qpn;
971*12965SWilliam.Taylor@Oracle.COM rssp->default_qpn = ud->ud_rss.rss_def_qpn;
972*12965SWilliam.Taylor@Oracle.COM if (flags & IBT_RSS_ALG_XOR)
973*12965SWilliam.Taylor@Oracle.COM rssp->hash_fn = 0; /* XOR Hash Function */
974*12965SWilliam.Taylor@Oracle.COM else if (flags & IBT_RSS_ALG_TPL)
975*12965SWilliam.Taylor@Oracle.COM rssp->hash_fn = 1; /* Toeplitz Hash Fn */
976*12965SWilliam.Taylor@Oracle.COM else
977*12965SWilliam.Taylor@Oracle.COM return (IBT_INVALID_PARAM);
978*12965SWilliam.Taylor@Oracle.COM rssp->ipv4 = (flags & IBT_RSS_HASH_IPV4) != 0;
979*12965SWilliam.Taylor@Oracle.COM rssp->tcp_ipv4 = (flags & IBT_RSS_HASH_TCP_IPV4) != 0;
980*12965SWilliam.Taylor@Oracle.COM rssp->ipv6 = (flags & IBT_RSS_HASH_IPV6) != 0;
981*12965SWilliam.Taylor@Oracle.COM rssp->tcp_ipv4 = (flags & IBT_RSS_HASH_TCP_IPV6) != 0;
982*12965SWilliam.Taylor@Oracle.COM bcopy(ud->ud_rss.rss_toe_key, rssp->rss_key, 40);
983*12965SWilliam.Taylor@Oracle.COM } else if (qp->qp_serv_type == HERMON_QP_RFCI) {
984*12965SWilliam.Taylor@Oracle.COM status = hermon_fcoib_set_id(state, portnum,
985*12965SWilliam.Taylor@Oracle.COM qp->qp_qpnum, ud->ud_fc.fc_src_id);
986*12965SWilliam.Taylor@Oracle.COM if (status != DDI_SUCCESS)
987*12965SWilliam.Taylor@Oracle.COM return (status);
988*12965SWilliam.Taylor@Oracle.COM qp->qp_fc_attr = ud->ud_fc;
989*12965SWilliam.Taylor@Oracle.COM } else if (qp->qp_serv_type == HERMON_QP_FEXCH) {
990*12965SWilliam.Taylor@Oracle.COM my_fc_id_idx = hermon_fcoib_get_id_idx(state,
991*12965SWilliam.Taylor@Oracle.COM portnum, &ud->ud_fc);
992*12965SWilliam.Taylor@Oracle.COM if (my_fc_id_idx == -1)
993*12965SWilliam.Taylor@Oracle.COM return (IBT_INVALID_PARAM);
994*12965SWilliam.Taylor@Oracle.COM qpc->my_fc_id_idx = my_fc_id_idx;
995*12965SWilliam.Taylor@Oracle.COM
996*12965SWilliam.Taylor@Oracle.COM status = hermon_fcoib_fexch_mkey_init(state,
997*12965SWilliam.Taylor@Oracle.COM qp->qp_pdhdl, ud->ud_fc.fc_hca_port,
998*12965SWilliam.Taylor@Oracle.COM qp->qp_qpnum, HERMON_CMD_NOSLEEP_SPIN);
999*12965SWilliam.Taylor@Oracle.COM if (status != DDI_SUCCESS)
1000*12965SWilliam.Taylor@Oracle.COM return (status);
1001*12965SWilliam.Taylor@Oracle.COM qp->qp_fc_attr = ud->ud_fc;
1002*12965SWilliam.Taylor@Oracle.COM } else if (qp->qp_serv_type == HERMON_QP_FCMND) {
1003*12965SWilliam.Taylor@Oracle.COM my_fc_id_idx = hermon_fcoib_get_id_idx(state,
1004*12965SWilliam.Taylor@Oracle.COM portnum, &ud->ud_fc);
1005*12965SWilliam.Taylor@Oracle.COM if (my_fc_id_idx == -1)
1006*12965SWilliam.Taylor@Oracle.COM return (IBT_INVALID_PARAM);
1007*12965SWilliam.Taylor@Oracle.COM qpc->my_fc_id_idx = my_fc_id_idx;
1008*12965SWilliam.Taylor@Oracle.COM exch_base = hermon_fcoib_check_exch_base_off(state,
1009*12965SWilliam.Taylor@Oracle.COM portnum, &ud->ud_fc);
1010*12965SWilliam.Taylor@Oracle.COM if (exch_base == -1)
1011*12965SWilliam.Taylor@Oracle.COM return (IBT_INVALID_PARAM);
1012*12965SWilliam.Taylor@Oracle.COM qpc->exch_base = exch_base;
1013*12965SWilliam.Taylor@Oracle.COM qpc->exch_size = ud->ud_fc.fc_exch_log2_sz;
1014*12965SWilliam.Taylor@Oracle.COM qp->qp_fc_attr = ud->ud_fc;
1015*12965SWilliam.Taylor@Oracle.COM }
1016*12965SWilliam.Taylor@Oracle.COM
10179517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
10189517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
10199517SBill.Taylor@Sun.COM
10209517SBill.Taylor@Sun.COM /* Set the RDMA (recv) enable/disable flags */
10219517SBill.Taylor@Sun.COM qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0;
10229517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
10239517SBill.Taylor@Sun.COM qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0;
10249517SBill.Taylor@Sun.COM
10259517SBill.Taylor@Sun.COM /* Check for valid port number and fill it in */
10269517SBill.Taylor@Sun.COM portnum = rc->rc_path.cep_hca_port_num;
10279517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
10289517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
10299517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
10309517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
10319517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
10329517SBill.Taylor@Sun.COM } else {
10339517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
10349517SBill.Taylor@Sun.COM }
10359517SBill.Taylor@Sun.COM
10369517SBill.Taylor@Sun.COM /* Check for valid PKey index and fill it in */
10379517SBill.Taylor@Sun.COM pkeyindx = rc->rc_path.cep_pkey_ix;
10389517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
10399517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
10409517SBill.Taylor@Sun.COM } else {
10419517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
10429517SBill.Taylor@Sun.COM }
10439517SBill.Taylor@Sun.COM
10449517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
10459517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
10469517SBill.Taylor@Sun.COM
10479517SBill.Taylor@Sun.COM /*
10489517SBill.Taylor@Sun.COM * Set the RDMA (recv) enable/disable flags. Note: RDMA Read
10499517SBill.Taylor@Sun.COM * and Atomic are ignored by default.
10509517SBill.Taylor@Sun.COM */
10519517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
10529517SBill.Taylor@Sun.COM
10539517SBill.Taylor@Sun.COM /* Check for valid port number and fill it in */
10549517SBill.Taylor@Sun.COM portnum = uc->uc_path.cep_hca_port_num;
10559517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
10569517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
10579517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
10589517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
10599517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
10609517SBill.Taylor@Sun.COM } else {
10619517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
10629517SBill.Taylor@Sun.COM }
10639517SBill.Taylor@Sun.COM
10649517SBill.Taylor@Sun.COM /* Check for valid PKey index and fill it in */
10659517SBill.Taylor@Sun.COM pkeyindx = uc->uc_path.cep_pkey_ix;
10669517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
10679517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
10689517SBill.Taylor@Sun.COM } else {
10699517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
10709517SBill.Taylor@Sun.COM }
10719517SBill.Taylor@Sun.COM
10729517SBill.Taylor@Sun.COM } else {
10739517SBill.Taylor@Sun.COM /*
10749517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
10759517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
10769517SBill.Taylor@Sun.COM * and return failure
10779517SBill.Taylor@Sun.COM */
10789517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in rst2init");
10799517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
10809517SBill.Taylor@Sun.COM }
10819517SBill.Taylor@Sun.COM
10829517SBill.Taylor@Sun.COM /*
10839517SBill.Taylor@Sun.COM * Post the RST2INIT_QP command to the Hermon firmware
10849517SBill.Taylor@Sun.COM *
10859517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
10869517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
10879517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
10889517SBill.Taylor@Sun.COM * success.
10899517SBill.Taylor@Sun.COM */
10909517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum,
10919517SBill.Taylor@Sun.COM 0, HERMON_CMD_NOSLEEP_SPIN);
10929517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
10939517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: RST2INIT_QP command failed: %08x\n",
10949517SBill.Taylor@Sun.COM state->hs_instance, status);
10959517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
10969517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
10979517SBill.Taylor@Sun.COM }
10989517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
10999517SBill.Taylor@Sun.COM }
11009517SBill.Taylor@Sun.COM
11019517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
11029517SBill.Taylor@Sun.COM }
11039517SBill.Taylor@Sun.COM
11049517SBill.Taylor@Sun.COM
11059517SBill.Taylor@Sun.COM /*
11069517SBill.Taylor@Sun.COM * hermon_qp_init2init()
11079517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
11089517SBill.Taylor@Sun.COM */
11099517SBill.Taylor@Sun.COM static int
hermon_qp_init2init(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)11109517SBill.Taylor@Sun.COM hermon_qp_init2init(hermon_state_t *state, hermon_qphdl_t qp,
11119517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
11129517SBill.Taylor@Sun.COM {
11139517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
11149517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
11159517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
11169517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
11179517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx;
11189517SBill.Taylor@Sun.COM uint32_t opmask = 0;
11199517SBill.Taylor@Sun.COM int status;
11209517SBill.Taylor@Sun.COM
11219517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
11229517SBill.Taylor@Sun.COM
11239517SBill.Taylor@Sun.COM /*
11249517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
11259517SBill.Taylor@Sun.COM */
11269517SBill.Taylor@Sun.COM qpc = &qp->qpc;
11279517SBill.Taylor@Sun.COM
11289517SBill.Taylor@Sun.COM /*
11299517SBill.Taylor@Sun.COM * Since there are no common fields to be filled in for this command,
11309517SBill.Taylor@Sun.COM * we begin with the QPC fields which are specific to transport type.
11319517SBill.Taylor@Sun.COM */
1132*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
11339517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
11349517SBill.Taylor@Sun.COM
11359517SBill.Taylor@Sun.COM /*
11369517SBill.Taylor@Sun.COM * If we are attempting to modify the port for this QP, then
11379517SBill.Taylor@Sun.COM * check for valid port number and fill it in. Also set the
11389517SBill.Taylor@Sun.COM * appropriate flag in the "opmask" parameter.
11399517SBill.Taylor@Sun.COM */
11409517SBill.Taylor@Sun.COM /*
11419517SBill.Taylor@Sun.COM * set port is not supported in init2init - however, in init2rtr it will
11429517SBill.Taylor@Sun.COM * take the entire qpc, including the embedded sched_q in the path
11439517SBill.Taylor@Sun.COM * structure - so, we can just skip setting the opmask for it explicitly
11449517SBill.Taylor@Sun.COM * and allow it to be set later on
11459517SBill.Taylor@Sun.COM */
11469517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PORT) {
11479517SBill.Taylor@Sun.COM portnum = ud->ud_port;
11489517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
11499517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1; /* save it away */
11509517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
11519517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
11529517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
11539517SBill.Taylor@Sun.COM } else {
11549517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
11559517SBill.Taylor@Sun.COM }
11569517SBill.Taylor@Sun.COM }
11579517SBill.Taylor@Sun.COM
11589517SBill.Taylor@Sun.COM /*
11599517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
11609517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
11619517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
11629517SBill.Taylor@Sun.COM */
11639517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
11649517SBill.Taylor@Sun.COM pkeyindx = ud->ud_pkey_ix;
11659517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
11669517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
11679517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
11689517SBill.Taylor@Sun.COM qp->qp_pkeyindx = pkeyindx;
11699517SBill.Taylor@Sun.COM } else {
11709517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
11719517SBill.Taylor@Sun.COM }
11729517SBill.Taylor@Sun.COM }
11739517SBill.Taylor@Sun.COM
11749517SBill.Taylor@Sun.COM /*
11759517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
11769517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
11779517SBill.Taylor@Sun.COM * parameter.
11789517SBill.Taylor@Sun.COM */
11799517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
11809517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
11819517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
11829517SBill.Taylor@Sun.COM }
11839517SBill.Taylor@Sun.COM
11849517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
11859517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
11869517SBill.Taylor@Sun.COM
11879517SBill.Taylor@Sun.COM /*
11889517SBill.Taylor@Sun.COM * If we are attempting to modify the port for this QP, then
11899517SBill.Taylor@Sun.COM * check for valid port number and fill it in. Also set the
11909517SBill.Taylor@Sun.COM * appropriate flag in the "opmask" parameter.
11919517SBill.Taylor@Sun.COM */
11929517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PORT) {
11939517SBill.Taylor@Sun.COM portnum = rc->rc_path.cep_hca_port_num;
11949517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
11959517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
11969517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
11979517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
11989517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
11999517SBill.Taylor@Sun.COM } else {
12009517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
12019517SBill.Taylor@Sun.COM }
12029517SBill.Taylor@Sun.COM
12039517SBill.Taylor@Sun.COM }
12049517SBill.Taylor@Sun.COM
12059517SBill.Taylor@Sun.COM /*
12069517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
12079517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
12089517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
12099517SBill.Taylor@Sun.COM */
12109517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
12119517SBill.Taylor@Sun.COM pkeyindx = rc->rc_path.cep_pkey_ix;
12129517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
12139517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
12149517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
12159517SBill.Taylor@Sun.COM } else {
12169517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
12179517SBill.Taylor@Sun.COM }
12189517SBill.Taylor@Sun.COM }
12199517SBill.Taylor@Sun.COM
12209517SBill.Taylor@Sun.COM /*
12219517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
12229517SBill.Taylor@Sun.COM * (recv) enable/disable flags and set the appropriate flag in
12239517SBill.Taylor@Sun.COM * the "opmask" parameter
12249517SBill.Taylor@Sun.COM */
12259517SBill.Taylor@Sun.COM opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
12269517SBill.Taylor@Sun.COM
12279517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
12289517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
12299517SBill.Taylor@Sun.COM
12309517SBill.Taylor@Sun.COM /*
12319517SBill.Taylor@Sun.COM * If we are attempting to modify the port for this QP, then
12329517SBill.Taylor@Sun.COM * check for valid port number and fill it in. Also set the
12339517SBill.Taylor@Sun.COM * appropriate flag in the "opmask" parameter.
12349517SBill.Taylor@Sun.COM */
12359517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PORT) {
12369517SBill.Taylor@Sun.COM portnum = uc->uc_path.cep_hca_port_num;
12379517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
12389517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
12399517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
12409517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
12419517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
12429517SBill.Taylor@Sun.COM } else {
12439517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
12449517SBill.Taylor@Sun.COM }
12459517SBill.Taylor@Sun.COM /* port# cannot be set in this transition - defer to init2rtr */
12469517SBill.Taylor@Sun.COM }
12479517SBill.Taylor@Sun.COM
12489517SBill.Taylor@Sun.COM /*
12499517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
12509517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
12519517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
12529517SBill.Taylor@Sun.COM */
12539517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
12549517SBill.Taylor@Sun.COM pkeyindx = uc->uc_path.cep_pkey_ix;
12559517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
12569517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
12579517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
12589517SBill.Taylor@Sun.COM } else {
12599517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
12609517SBill.Taylor@Sun.COM }
12619517SBill.Taylor@Sun.COM }
12629517SBill.Taylor@Sun.COM
12639517SBill.Taylor@Sun.COM /*
12649517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
12659517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
12669517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
12679517SBill.Taylor@Sun.COM * not valid for UC transport.
12689517SBill.Taylor@Sun.COM */
12699517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
12709517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
12719517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
12729517SBill.Taylor@Sun.COM }
12739517SBill.Taylor@Sun.COM } else {
12749517SBill.Taylor@Sun.COM /*
12759517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
12769517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
12779517SBill.Taylor@Sun.COM * and return failure
12789517SBill.Taylor@Sun.COM */
12799517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in init2init");
12809517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
12819517SBill.Taylor@Sun.COM }
12829517SBill.Taylor@Sun.COM
12839517SBill.Taylor@Sun.COM /*
12849517SBill.Taylor@Sun.COM * Post the INIT2INIT_QP command to the Hermon firmware
12859517SBill.Taylor@Sun.COM *
12869517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
12879517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
12889517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
12899517SBill.Taylor@Sun.COM * success.
12909517SBill.Taylor@Sun.COM */
12919517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, INIT2INIT_QP, qpc, qp->qp_qpnum,
12929517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
12939517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
12949517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
12959517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: INIT2INIT_QP command "
12969517SBill.Taylor@Sun.COM "failed: %08x\n", state->hs_instance, status);
12979517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
12989517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
12999517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
13009517SBill.Taylor@Sun.COM }
13019517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
13029517SBill.Taylor@Sun.COM } else {
13039517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
13049517SBill.Taylor@Sun.COM }
13059517SBill.Taylor@Sun.COM }
13069517SBill.Taylor@Sun.COM
13079517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
13089517SBill.Taylor@Sun.COM }
13099517SBill.Taylor@Sun.COM
13109517SBill.Taylor@Sun.COM
13119517SBill.Taylor@Sun.COM /*
13129517SBill.Taylor@Sun.COM * hermon_qp_init2rtr()
13139517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
13149517SBill.Taylor@Sun.COM */
13159517SBill.Taylor@Sun.COM static int
hermon_qp_init2rtr(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)13169517SBill.Taylor@Sun.COM hermon_qp_init2rtr(hermon_state_t *state, hermon_qphdl_t qp,
13179517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
13189517SBill.Taylor@Sun.COM {
13199517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
13209517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
13219517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
13229517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
13239517SBill.Taylor@Sun.COM hermon_hw_addr_path_t *qpc_path;
13249517SBill.Taylor@Sun.COM ibt_adds_vect_t *adds_vect;
13259517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx, rra_max;
13269517SBill.Taylor@Sun.COM uint_t mtu;
13279517SBill.Taylor@Sun.COM uint32_t opmask = 0;
13289517SBill.Taylor@Sun.COM int status;
13299517SBill.Taylor@Sun.COM
13309517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
13319517SBill.Taylor@Sun.COM
13329517SBill.Taylor@Sun.COM /*
13339517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
13349517SBill.Taylor@Sun.COM */
13359517SBill.Taylor@Sun.COM qpc = &qp->qpc;
13369517SBill.Taylor@Sun.COM
13379517SBill.Taylor@Sun.COM /*
13389517SBill.Taylor@Sun.COM * Since there are few common fields to be filled in for this command,
13399517SBill.Taylor@Sun.COM * we just do the QPC fields that are specific to transport type.
13409517SBill.Taylor@Sun.COM */
1341*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
13429517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
13439517SBill.Taylor@Sun.COM
13449517SBill.Taylor@Sun.COM /*
13459517SBill.Taylor@Sun.COM * If this UD QP is also a "special QP" (QP0 or QP1), then
13469517SBill.Taylor@Sun.COM * the MTU is 256 bytes. However, Hermon checks the QPC
13479517SBill.Taylor@Sun.COM * MTU settings rather than just the port MTU, so we will
13489517SBill.Taylor@Sun.COM * set it to maximum size for all UD.
13499517SBill.Taylor@Sun.COM */
13509517SBill.Taylor@Sun.COM qpc->mtu = HERMON_MAX_MTU;
13519517SBill.Taylor@Sun.COM if (qp->qp_uses_lso)
13529517SBill.Taylor@Sun.COM qpc->msg_max = state->hs_devlim.log_max_gso_sz;
13539517SBill.Taylor@Sun.COM else
13549517SBill.Taylor@Sun.COM qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
13559517SBill.Taylor@Sun.COM
13569517SBill.Taylor@Sun.COM /*
13579517SBill.Taylor@Sun.COM * Save away the MTU value. This is used in future sqd2sqd
13589517SBill.Taylor@Sun.COM * transitions, as the MTU must remain the same in future
13599517SBill.Taylor@Sun.COM * changes.
13609517SBill.Taylor@Sun.COM */
13619517SBill.Taylor@Sun.COM qp->qp_save_mtu = qpc->mtu;
13629517SBill.Taylor@Sun.COM
13639517SBill.Taylor@Sun.COM /*
13649517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
13659517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
13669517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
13679517SBill.Taylor@Sun.COM */
13689517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
13699517SBill.Taylor@Sun.COM pkeyindx = ud->ud_pkey_ix;
13709517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
13719517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
13729517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
13739517SBill.Taylor@Sun.COM qp->qp_pkeyindx = pkeyindx;
13749517SBill.Taylor@Sun.COM } else {
13759517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
13769517SBill.Taylor@Sun.COM }
13779517SBill.Taylor@Sun.COM }
13789517SBill.Taylor@Sun.COM
13799517SBill.Taylor@Sun.COM /*
13809517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
13819517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
13829517SBill.Taylor@Sun.COM * parameter.
13839517SBill.Taylor@Sun.COM */
13849517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
13859517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
13869517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
13879517SBill.Taylor@Sun.COM }
13889517SBill.Taylor@Sun.COM
13899517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
13909517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
13919517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
13929517SBill.Taylor@Sun.COM adds_vect = &rc->rc_path.cep_adds_vect;
13939517SBill.Taylor@Sun.COM
13949517SBill.Taylor@Sun.COM /*
13959517SBill.Taylor@Sun.COM * Set the common primary address path fields
13969517SBill.Taylor@Sun.COM */
13979517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect, qpc_path,
13989517SBill.Taylor@Sun.COM HERMON_ADDRPATH_QP);
13999517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
14009517SBill.Taylor@Sun.COM return (status);
14019517SBill.Taylor@Sun.COM }
14029517SBill.Taylor@Sun.COM /* set the primary port number/sched_q */
14039517SBill.Taylor@Sun.COM portnum = qp->qp_portnum + 1;
14049517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
14059517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
14069517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
14079517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
14089517SBill.Taylor@Sun.COM } else {
14099517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
14109517SBill.Taylor@Sun.COM }
14119517SBill.Taylor@Sun.COM
14129517SBill.Taylor@Sun.COM /*
14139517SBill.Taylor@Sun.COM * The following values are apparently "required" here (as
14149517SBill.Taylor@Sun.COM * they are part of the IBA-defined "Remote Node Address
14159517SBill.Taylor@Sun.COM * Vector"). However, they are also going to be "required"
14169517SBill.Taylor@Sun.COM * later - at RTR2RTS_QP time. Not sure why. But we set
14179517SBill.Taylor@Sun.COM * them here anyway.
14189517SBill.Taylor@Sun.COM */
14199517SBill.Taylor@Sun.COM qpc->rnr_retry = rc->rc_rnr_retry_cnt;
14209517SBill.Taylor@Sun.COM qpc->retry_cnt = rc->rc_retry_cnt;
14219517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_path.cep_timeout;
14229517SBill.Taylor@Sun.COM
14239517SBill.Taylor@Sun.COM /*
14249517SBill.Taylor@Sun.COM * Setup the destination QP, recv PSN, MTU, max msg size,etc.
14259517SBill.Taylor@Sun.COM * Note max message size is defined to be the maximum IB
14269517SBill.Taylor@Sun.COM * allowed message size (which is 2^31 bytes). Also max
14279517SBill.Taylor@Sun.COM * MTU is defined by HCA port properties.
14289517SBill.Taylor@Sun.COM */
14299517SBill.Taylor@Sun.COM qpc->rem_qpn = rc->rc_dst_qpn;
14309517SBill.Taylor@Sun.COM qpc->next_rcv_psn = rc->rc_rq_psn;
14319517SBill.Taylor@Sun.COM qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
14329517SBill.Taylor@Sun.COM qpc->ric = 0;
14339517SBill.Taylor@Sun.COM mtu = rc->rc_path_mtu;
14349517SBill.Taylor@Sun.COM
14359517SBill.Taylor@Sun.COM if (hermon_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
14369517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_MTU_EXCEEDED);
14379517SBill.Taylor@Sun.COM }
14389517SBill.Taylor@Sun.COM qpc->mtu = mtu;
14399517SBill.Taylor@Sun.COM
14409517SBill.Taylor@Sun.COM /*
14419517SBill.Taylor@Sun.COM * Save away the MTU value. This is used in future sqd2sqd
14429517SBill.Taylor@Sun.COM * transitions, as the MTU must remain the same in future
14439517SBill.Taylor@Sun.COM * changes.
14449517SBill.Taylor@Sun.COM */
14459517SBill.Taylor@Sun.COM qp->qp_save_mtu = qpc->mtu;
14469517SBill.Taylor@Sun.COM
14479517SBill.Taylor@Sun.COM /*
14489517SBill.Taylor@Sun.COM * Though it is a "required" parameter, "min_rnr_nak" is
14499517SBill.Taylor@Sun.COM * optionally specifiable in Hermon. So we force the
14509517SBill.Taylor@Sun.COM * optional flag here.
14519517SBill.Taylor@Sun.COM */
14529517SBill.Taylor@Sun.COM qpc->min_rnr_nak = rc->rc_min_rnr_nak;
14539517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_MINRNRNAK;
14549517SBill.Taylor@Sun.COM
14559517SBill.Taylor@Sun.COM /*
14569517SBill.Taylor@Sun.COM * Check that the number of specified "incoming RDMA resources"
14579517SBill.Taylor@Sun.COM * is valid. And if it is, then setup the "rra_max
14589517SBill.Taylor@Sun.COM */
14599517SBill.Taylor@Sun.COM if (hermon_qp_validate_resp_rsrc(state, rc, &rra_max) !=
14609517SBill.Taylor@Sun.COM DDI_SUCCESS) {
14619517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
14629517SBill.Taylor@Sun.COM }
14639517SBill.Taylor@Sun.COM qpc->rra_max = rra_max;
14649517SBill.Taylor@Sun.COM
14659517SBill.Taylor@Sun.COM /* don't need to set up ra_buff_indx, implicit for hermon */
14669517SBill.Taylor@Sun.COM
14679517SBill.Taylor@Sun.COM /*
14689517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
14699517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
14709517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
14719517SBill.Taylor@Sun.COM */
14729517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
14739517SBill.Taylor@Sun.COM pkeyindx = rc->rc_path.cep_pkey_ix;
14749517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
14759517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
14769517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
14779517SBill.Taylor@Sun.COM } else {
14789517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
14799517SBill.Taylor@Sun.COM }
14809517SBill.Taylor@Sun.COM }
14819517SBill.Taylor@Sun.COM
14829517SBill.Taylor@Sun.COM /*
14839517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
14849517SBill.Taylor@Sun.COM * (recv) enable/disable flags and set the appropriate flag in
14859517SBill.Taylor@Sun.COM * the "opmask" parameter
14869517SBill.Taylor@Sun.COM */
14879517SBill.Taylor@Sun.COM opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
14889517SBill.Taylor@Sun.COM
14899517SBill.Taylor@Sun.COM /*
14909517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
14919517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
14929517SBill.Taylor@Sun.COM */
14939517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
14949517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
14959517SBill.Taylor@Sun.COM adds_vect = &rc->rc_alt_path.cep_adds_vect;
14969517SBill.Taylor@Sun.COM
14979517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
14989517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
14999517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
15009517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
15019517SBill.Taylor@Sun.COM return (status);
15029517SBill.Taylor@Sun.COM }
15039517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
15049517SBill.Taylor@Sun.COM
15059517SBill.Taylor@Sun.COM
15069517SBill.Taylor@Sun.COM /*
15079517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
15089517SBill.Taylor@Sun.COM * it in
15099517SBill.Taylor@Sun.COM */
15109517SBill.Taylor@Sun.COM portnum = rc->rc_alt_path.cep_hca_port_num;
15119517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
15129517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
15139517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
15149517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
15159517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
15169517SBill.Taylor@Sun.COM } else {
15179517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
15189517SBill.Taylor@Sun.COM }
15199517SBill.Taylor@Sun.COM /*
15209517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
15219517SBill.Taylor@Sun.COM * it in
15229517SBill.Taylor@Sun.COM */
15239517SBill.Taylor@Sun.COM pkeyindx = rc->rc_alt_path.cep_pkey_ix;
15249517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
15259517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
15269517SBill.Taylor@Sun.COM } else {
15279517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
15289517SBill.Taylor@Sun.COM }
15299517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
15309517SBill.Taylor@Sun.COM }
15319517SBill.Taylor@Sun.COM
15329517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
15339517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
15349517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
15359517SBill.Taylor@Sun.COM adds_vect = &uc->uc_path.cep_adds_vect;
15369517SBill.Taylor@Sun.COM
15379517SBill.Taylor@Sun.COM /*
15389517SBill.Taylor@Sun.COM * Set the common primary address path fields
15399517SBill.Taylor@Sun.COM */
15409517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect, qpc_path,
15419517SBill.Taylor@Sun.COM HERMON_ADDRPATH_QP);
15429517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
15439517SBill.Taylor@Sun.COM return (status);
15449517SBill.Taylor@Sun.COM }
15459517SBill.Taylor@Sun.COM
15469517SBill.Taylor@Sun.COM /* set the primary port num/schedq */
15479517SBill.Taylor@Sun.COM portnum = qp->qp_portnum + 1;
15489517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
15499517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
15509517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
15519517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
15529517SBill.Taylor@Sun.COM } else {
15539517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
15549517SBill.Taylor@Sun.COM }
15559517SBill.Taylor@Sun.COM
15569517SBill.Taylor@Sun.COM /*
15579517SBill.Taylor@Sun.COM * Setup the destination QP, recv PSN, MTU, max msg size,etc.
15589517SBill.Taylor@Sun.COM * Note max message size is defined to be the maximum IB
15599517SBill.Taylor@Sun.COM * allowed message size (which is 2^31 bytes). Also max
15609517SBill.Taylor@Sun.COM * MTU is defined by HCA port properties.
15619517SBill.Taylor@Sun.COM */
15629517SBill.Taylor@Sun.COM qpc->rem_qpn = uc->uc_dst_qpn;
15639517SBill.Taylor@Sun.COM qpc->next_rcv_psn = uc->uc_rq_psn;
15649517SBill.Taylor@Sun.COM qpc->msg_max = HERMON_QP_LOG_MAX_MSGSZ;
15659517SBill.Taylor@Sun.COM mtu = uc->uc_path_mtu;
15669517SBill.Taylor@Sun.COM if (hermon_qp_validate_mtu(state, mtu) != DDI_SUCCESS) {
15679517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_MTU_EXCEEDED);
15689517SBill.Taylor@Sun.COM }
15699517SBill.Taylor@Sun.COM qpc->mtu = mtu;
15709517SBill.Taylor@Sun.COM
15719517SBill.Taylor@Sun.COM /*
15729517SBill.Taylor@Sun.COM * Save away the MTU value. This is used in future sqd2sqd
15739517SBill.Taylor@Sun.COM * transitions, as the MTU must remain the same in future
15749517SBill.Taylor@Sun.COM * changes.
15759517SBill.Taylor@Sun.COM */
15769517SBill.Taylor@Sun.COM qp->qp_save_mtu = qpc->mtu;
15779517SBill.Taylor@Sun.COM
15789517SBill.Taylor@Sun.COM /*
15799517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
15809517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
15819517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
15829517SBill.Taylor@Sun.COM */
15839517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
15849517SBill.Taylor@Sun.COM pkeyindx = uc->uc_path.cep_pkey_ix;
15859517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
15869517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
15879517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
15889517SBill.Taylor@Sun.COM } else {
15899517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
15909517SBill.Taylor@Sun.COM }
15919517SBill.Taylor@Sun.COM }
15929517SBill.Taylor@Sun.COM
15939517SBill.Taylor@Sun.COM /*
15949517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
15959517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
15969517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
15979517SBill.Taylor@Sun.COM * not valid for UC transport.
15989517SBill.Taylor@Sun.COM */
15999517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
16009517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
16019517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
16029517SBill.Taylor@Sun.COM }
16039517SBill.Taylor@Sun.COM
16049517SBill.Taylor@Sun.COM /*
16059517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
16069517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
16079517SBill.Taylor@Sun.COM */
16089517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
16099517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
16109517SBill.Taylor@Sun.COM adds_vect = &uc->uc_alt_path.cep_adds_vect;
16119517SBill.Taylor@Sun.COM
16129517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
16139517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
16149517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
16159517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
16169517SBill.Taylor@Sun.COM return (status);
16179517SBill.Taylor@Sun.COM }
16189517SBill.Taylor@Sun.COM
16199517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
16209517SBill.Taylor@Sun.COM
16219517SBill.Taylor@Sun.COM /*
16229517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
16239517SBill.Taylor@Sun.COM * it in
16249517SBill.Taylor@Sun.COM */
16259517SBill.Taylor@Sun.COM portnum = uc->uc_alt_path.cep_hca_port_num;
16269517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
16279517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
16289517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
16299517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
16309517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
16319517SBill.Taylor@Sun.COM } else {
16329517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
16339517SBill.Taylor@Sun.COM }
16349517SBill.Taylor@Sun.COM
16359517SBill.Taylor@Sun.COM /*
16369517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
16379517SBill.Taylor@Sun.COM * it in
16389517SBill.Taylor@Sun.COM */
16399517SBill.Taylor@Sun.COM pkeyindx = uc->uc_alt_path.cep_pkey_ix;
16409517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
16419517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
16429517SBill.Taylor@Sun.COM } else {
16439517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
16449517SBill.Taylor@Sun.COM }
16459517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
16469517SBill.Taylor@Sun.COM }
16479517SBill.Taylor@Sun.COM } else {
16489517SBill.Taylor@Sun.COM /*
16499517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
16509517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
16519517SBill.Taylor@Sun.COM * and return failure
16529517SBill.Taylor@Sun.COM */
16539517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in init2rtr");
16549517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
16559517SBill.Taylor@Sun.COM }
16569517SBill.Taylor@Sun.COM
16579517SBill.Taylor@Sun.COM /*
16589517SBill.Taylor@Sun.COM * Post the INIT2RTR_QP command to the Hermon firmware
16599517SBill.Taylor@Sun.COM *
16609517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
16619517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
16629517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
16639517SBill.Taylor@Sun.COM * success.
16649517SBill.Taylor@Sun.COM */
16659517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, INIT2RTR_QP, qpc, qp->qp_qpnum,
16669517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
16679517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
16689517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
16699517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: INIT2RTR_QP command "
16709517SBill.Taylor@Sun.COM "failed: %08x\n", state->hs_instance, status);
16719517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
16729517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
16739517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
16749517SBill.Taylor@Sun.COM }
16759517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
16769517SBill.Taylor@Sun.COM } else {
16779517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
16789517SBill.Taylor@Sun.COM }
16799517SBill.Taylor@Sun.COM }
16809517SBill.Taylor@Sun.COM
16819517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
16829517SBill.Taylor@Sun.COM }
16839517SBill.Taylor@Sun.COM
16849517SBill.Taylor@Sun.COM
16859517SBill.Taylor@Sun.COM /*
16869517SBill.Taylor@Sun.COM * hermon_qp_rtr2rts()
16879517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
16889517SBill.Taylor@Sun.COM */
16899517SBill.Taylor@Sun.COM static int
hermon_qp_rtr2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)16909517SBill.Taylor@Sun.COM hermon_qp_rtr2rts(hermon_state_t *state, hermon_qphdl_t qp,
16919517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
16929517SBill.Taylor@Sun.COM {
16939517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
16949517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
16959517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
16969517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
16979517SBill.Taylor@Sun.COM hermon_hw_addr_path_t *qpc_path;
16989517SBill.Taylor@Sun.COM ibt_adds_vect_t *adds_vect;
16999517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx, sra_max;
17009517SBill.Taylor@Sun.COM uint32_t opmask = 0;
17019517SBill.Taylor@Sun.COM int status;
17029517SBill.Taylor@Sun.COM
17039517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
17049517SBill.Taylor@Sun.COM
17059517SBill.Taylor@Sun.COM /*
17069517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
17079517SBill.Taylor@Sun.COM */
17089517SBill.Taylor@Sun.COM qpc = &qp->qpc;
17099517SBill.Taylor@Sun.COM
17109517SBill.Taylor@Sun.COM /*
17119517SBill.Taylor@Sun.COM * Now fill in the QPC fields which are specific to transport type
17129517SBill.Taylor@Sun.COM */
1713*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
17149517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
17159517SBill.Taylor@Sun.COM
17169517SBill.Taylor@Sun.COM /* Set the send PSN */
17179517SBill.Taylor@Sun.COM qpc->next_snd_psn = ud->ud_sq_psn;
17189517SBill.Taylor@Sun.COM
17199517SBill.Taylor@Sun.COM /*
17209517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
17219517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
17229517SBill.Taylor@Sun.COM * parameter.
17239517SBill.Taylor@Sun.COM */
17249517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
17259517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
17269517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
17279517SBill.Taylor@Sun.COM }
17289517SBill.Taylor@Sun.COM
17299517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
17309517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
17319517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
17329517SBill.Taylor@Sun.COM
17339517SBill.Taylor@Sun.COM /*
17349517SBill.Taylor@Sun.COM * Setup the send PSN, ACK timeout, and retry counts
17359517SBill.Taylor@Sun.COM */
17369517SBill.Taylor@Sun.COM qpc->next_snd_psn = rc->rc_sq_psn;
17379517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_path.cep_timeout;
17389517SBill.Taylor@Sun.COM qpc->rnr_retry = rc->rc_rnr_retry_cnt;
17399517SBill.Taylor@Sun.COM /* in qpc now, not path */
17409517SBill.Taylor@Sun.COM qpc->retry_cnt = rc->rc_retry_cnt;
17419517SBill.Taylor@Sun.COM
17429517SBill.Taylor@Sun.COM /*
17439517SBill.Taylor@Sun.COM * Set "ack_req_freq" based on the configuration variable
17449517SBill.Taylor@Sun.COM */
17459517SBill.Taylor@Sun.COM qpc->ack_req_freq = state->hs_cfg_profile->cp_ackreq_freq;
17469517SBill.Taylor@Sun.COM
17479517SBill.Taylor@Sun.COM /*
17489517SBill.Taylor@Sun.COM * Check that the number of specified "outgoing RDMA resources"
17499517SBill.Taylor@Sun.COM * is valid. And if it is, then setup the "sra_max"
17509517SBill.Taylor@Sun.COM * appropriately
17519517SBill.Taylor@Sun.COM */
17529517SBill.Taylor@Sun.COM if (hermon_qp_validate_init_depth(state, rc, &sra_max) !=
17539517SBill.Taylor@Sun.COM DDI_SUCCESS) {
17549517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
17559517SBill.Taylor@Sun.COM }
17569517SBill.Taylor@Sun.COM qpc->sra_max = sra_max;
17579517SBill.Taylor@Sun.COM
17589517SBill.Taylor@Sun.COM
17599517SBill.Taylor@Sun.COM /*
17609517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
17619517SBill.Taylor@Sun.COM * (recv) enable/disable flags and set the appropriate flag in
17629517SBill.Taylor@Sun.COM * the "opmask" parameter
17639517SBill.Taylor@Sun.COM */
17649517SBill.Taylor@Sun.COM opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
17659517SBill.Taylor@Sun.COM
17669517SBill.Taylor@Sun.COM /*
17679517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
17689517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
17699517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
17709517SBill.Taylor@Sun.COM */
17719517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
17729517SBill.Taylor@Sun.COM if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
17739517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
17749517SBill.Taylor@Sun.COM } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
17759517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
17769517SBill.Taylor@Sun.COM } else {
17779517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
17789517SBill.Taylor@Sun.COM }
17799517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
17809517SBill.Taylor@Sun.COM }
17819517SBill.Taylor@Sun.COM
17829517SBill.Taylor@Sun.COM /*
17839517SBill.Taylor@Sun.COM * If we are attempting to modify the "Minimum RNR NAK" value
17849517SBill.Taylor@Sun.COM * for this QP, then fill it in and set the appropriate flag
17859517SBill.Taylor@Sun.COM * in the "opmask" parameter.
17869517SBill.Taylor@Sun.COM */
17879517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
17889517SBill.Taylor@Sun.COM qpc->min_rnr_nak = rc->rc_min_rnr_nak;
17899517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_MINRNRNAK;
17909517SBill.Taylor@Sun.COM }
17919517SBill.Taylor@Sun.COM
17929517SBill.Taylor@Sun.COM /*
17939517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
17949517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
17959517SBill.Taylor@Sun.COM */
17969517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
17979517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
17989517SBill.Taylor@Sun.COM adds_vect = &rc->rc_alt_path.cep_adds_vect;
17999517SBill.Taylor@Sun.COM
18009517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
18019517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
18029517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
18039517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
18049517SBill.Taylor@Sun.COM return (status);
18059517SBill.Taylor@Sun.COM }
18069517SBill.Taylor@Sun.COM
18079517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
18089517SBill.Taylor@Sun.COM
18099517SBill.Taylor@Sun.COM /*
18109517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
18119517SBill.Taylor@Sun.COM * it in
18129517SBill.Taylor@Sun.COM */
18139517SBill.Taylor@Sun.COM portnum = rc->rc_alt_path.cep_hca_port_num;
18149517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
18159517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
18169517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
18179517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
18189517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
18199517SBill.Taylor@Sun.COM } else {
18209517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
18219517SBill.Taylor@Sun.COM }
18229517SBill.Taylor@Sun.COM
18239517SBill.Taylor@Sun.COM /*
18249517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
18259517SBill.Taylor@Sun.COM * it in
18269517SBill.Taylor@Sun.COM */
18279517SBill.Taylor@Sun.COM pkeyindx = rc->rc_alt_path.cep_pkey_ix;
18289517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
18299517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
18309517SBill.Taylor@Sun.COM } else {
18319517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
18329517SBill.Taylor@Sun.COM }
18339517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
18349517SBill.Taylor@Sun.COM }
18359517SBill.Taylor@Sun.COM
18369517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
18379517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
18389517SBill.Taylor@Sun.COM
18399517SBill.Taylor@Sun.COM /* Set the send PSN */
18409517SBill.Taylor@Sun.COM qpc->next_snd_psn = uc->uc_sq_psn;
18419517SBill.Taylor@Sun.COM
18429517SBill.Taylor@Sun.COM /*
18439517SBill.Taylor@Sun.COM * Configure the QP to allow (sending of) all types of allowable
18449517SBill.Taylor@Sun.COM * UC traffic (i.e. RDMA Write).
18459517SBill.Taylor@Sun.COM */
18469517SBill.Taylor@Sun.COM
18479517SBill.Taylor@Sun.COM
18489517SBill.Taylor@Sun.COM /*
18499517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
18509517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
18519517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
18529517SBill.Taylor@Sun.COM * not valid for UC transport.
18539517SBill.Taylor@Sun.COM */
18549517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
18559517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
18569517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
18579517SBill.Taylor@Sun.COM }
18589517SBill.Taylor@Sun.COM
18599517SBill.Taylor@Sun.COM /*
18609517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
18619517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
18629517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
18639517SBill.Taylor@Sun.COM */
18649517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
18659517SBill.Taylor@Sun.COM if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
18669517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
18679517SBill.Taylor@Sun.COM } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
18689517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
18699517SBill.Taylor@Sun.COM } else {
18709517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
18719517SBill.Taylor@Sun.COM }
18729517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
18739517SBill.Taylor@Sun.COM }
18749517SBill.Taylor@Sun.COM
18759517SBill.Taylor@Sun.COM /*
18769517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
18779517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
18789517SBill.Taylor@Sun.COM */
18799517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
18809517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
18819517SBill.Taylor@Sun.COM adds_vect = &uc->uc_alt_path.cep_adds_vect;
18829517SBill.Taylor@Sun.COM
18839517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
18849517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
18859517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
18869517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
18879517SBill.Taylor@Sun.COM return (status);
18889517SBill.Taylor@Sun.COM }
18899517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
18909517SBill.Taylor@Sun.COM
18919517SBill.Taylor@Sun.COM /*
18929517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
18939517SBill.Taylor@Sun.COM * it in
18949517SBill.Taylor@Sun.COM */
18959517SBill.Taylor@Sun.COM portnum = uc->uc_alt_path.cep_hca_port_num;
18969517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
18979517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
18989517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
18999517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
19009517SBill.Taylor@Sun.COM } else {
19019517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
19029517SBill.Taylor@Sun.COM }
19039517SBill.Taylor@Sun.COM
19049517SBill.Taylor@Sun.COM /*
19059517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
19069517SBill.Taylor@Sun.COM * it in
19079517SBill.Taylor@Sun.COM */
19089517SBill.Taylor@Sun.COM pkeyindx = uc->uc_alt_path.cep_pkey_ix;
19099517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
19109517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
19119517SBill.Taylor@Sun.COM } else {
19129517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
19139517SBill.Taylor@Sun.COM }
19149517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
19159517SBill.Taylor@Sun.COM }
19169517SBill.Taylor@Sun.COM } else {
19179517SBill.Taylor@Sun.COM /*
19189517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
19199517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
19209517SBill.Taylor@Sun.COM * and return failure
19219517SBill.Taylor@Sun.COM */
19229517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in rtr2rts");
19239517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
19249517SBill.Taylor@Sun.COM }
19259517SBill.Taylor@Sun.COM
19269517SBill.Taylor@Sun.COM /*
19279517SBill.Taylor@Sun.COM * Post the RTR2RTS_QP command to the Hermon firmware
19289517SBill.Taylor@Sun.COM *
19299517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
19309517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
19319517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
19329517SBill.Taylor@Sun.COM * success.
19339517SBill.Taylor@Sun.COM */
19349517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, RTR2RTS_QP, qpc, qp->qp_qpnum,
19359517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
19369517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
19379517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
19389517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: RTR2RTS_QP command failed: "
19399517SBill.Taylor@Sun.COM "%08x\n", state->hs_instance, status);
19409517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
19419517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
19429517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
19439517SBill.Taylor@Sun.COM }
19449517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
19459517SBill.Taylor@Sun.COM } else {
19469517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
19479517SBill.Taylor@Sun.COM }
19489517SBill.Taylor@Sun.COM }
19499517SBill.Taylor@Sun.COM
19509517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
19519517SBill.Taylor@Sun.COM }
19529517SBill.Taylor@Sun.COM
19539517SBill.Taylor@Sun.COM
19549517SBill.Taylor@Sun.COM /*
19559517SBill.Taylor@Sun.COM * hermon_qp_rts2rts()
19569517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
19579517SBill.Taylor@Sun.COM */
19589517SBill.Taylor@Sun.COM static int
hermon_qp_rts2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)19599517SBill.Taylor@Sun.COM hermon_qp_rts2rts(hermon_state_t *state, hermon_qphdl_t qp,
19609517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
19619517SBill.Taylor@Sun.COM {
19629517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
19639517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
19649517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
19659517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
19669517SBill.Taylor@Sun.COM hermon_hw_addr_path_t *qpc_path;
19679517SBill.Taylor@Sun.COM ibt_adds_vect_t *adds_vect;
19689517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx;
19699517SBill.Taylor@Sun.COM uint32_t opmask = 0;
19709517SBill.Taylor@Sun.COM int status;
19719517SBill.Taylor@Sun.COM
19729517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
19739517SBill.Taylor@Sun.COM
19749517SBill.Taylor@Sun.COM /*
19759517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
19769517SBill.Taylor@Sun.COM */
19779517SBill.Taylor@Sun.COM
19789517SBill.Taylor@Sun.COM qpc = &qp->qpc;
19799517SBill.Taylor@Sun.COM
19809517SBill.Taylor@Sun.COM /*
19819517SBill.Taylor@Sun.COM * Since there are no common fields to be filled in for this command,
19829517SBill.Taylor@Sun.COM * we begin with the QPC fields which are specific to transport type.
19839517SBill.Taylor@Sun.COM */
1984*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
19859517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
19869517SBill.Taylor@Sun.COM
19879517SBill.Taylor@Sun.COM /*
19889517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
19899517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
19909517SBill.Taylor@Sun.COM * parameter.
19919517SBill.Taylor@Sun.COM */
19929517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
19939517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
19949517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
19959517SBill.Taylor@Sun.COM }
19969517SBill.Taylor@Sun.COM
19979517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
19989517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
19999517SBill.Taylor@Sun.COM
20009517SBill.Taylor@Sun.COM /*
20019517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
20029517SBill.Taylor@Sun.COM * (recv) enable/disable flags and set the appropriate flag in
20039517SBill.Taylor@Sun.COM * the "opmask" parameter
20049517SBill.Taylor@Sun.COM */
20059517SBill.Taylor@Sun.COM opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
20069517SBill.Taylor@Sun.COM
20079517SBill.Taylor@Sun.COM /*
20089517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
20099517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
20109517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
20119517SBill.Taylor@Sun.COM */
20129517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
20139517SBill.Taylor@Sun.COM if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
20149517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
20159517SBill.Taylor@Sun.COM } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
20169517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
20179517SBill.Taylor@Sun.COM } else {
20189517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
20199517SBill.Taylor@Sun.COM }
20209517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
20219517SBill.Taylor@Sun.COM }
20229517SBill.Taylor@Sun.COM
20239517SBill.Taylor@Sun.COM /*
20249517SBill.Taylor@Sun.COM * If we are attempting to modify the "Minimum RNR NAK" value
20259517SBill.Taylor@Sun.COM * for this QP, then fill it in and set the appropriate flag
20269517SBill.Taylor@Sun.COM * in the "opmask" parameter.
20279517SBill.Taylor@Sun.COM */
20289517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
20299517SBill.Taylor@Sun.COM qpc->min_rnr_nak = rc->rc_min_rnr_nak;
20309517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_MINRNRNAK;
20319517SBill.Taylor@Sun.COM }
20329517SBill.Taylor@Sun.COM
20339517SBill.Taylor@Sun.COM /*
20349517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
20359517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
20369517SBill.Taylor@Sun.COM */
20379517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
20389517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
20399517SBill.Taylor@Sun.COM adds_vect = &rc->rc_alt_path.cep_adds_vect;
20409517SBill.Taylor@Sun.COM
20419517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
20429517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
20439517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
20449517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
20459517SBill.Taylor@Sun.COM return (status);
20469517SBill.Taylor@Sun.COM }
20479517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
20489517SBill.Taylor@Sun.COM
20499517SBill.Taylor@Sun.COM /*
20509517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
20519517SBill.Taylor@Sun.COM * it in
20529517SBill.Taylor@Sun.COM */
20539517SBill.Taylor@Sun.COM portnum = rc->rc_alt_path.cep_hca_port_num;
20549517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
20559517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
20569517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
20579517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
20589517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
20599517SBill.Taylor@Sun.COM } else {
20609517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
20619517SBill.Taylor@Sun.COM }
20629517SBill.Taylor@Sun.COM
20639517SBill.Taylor@Sun.COM /*
20649517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
20659517SBill.Taylor@Sun.COM * it in
20669517SBill.Taylor@Sun.COM */
20679517SBill.Taylor@Sun.COM pkeyindx = rc->rc_alt_path.cep_pkey_ix;
20689517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
20699517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
20709517SBill.Taylor@Sun.COM } else {
20719517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
20729517SBill.Taylor@Sun.COM }
20739517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
20749517SBill.Taylor@Sun.COM }
20759517SBill.Taylor@Sun.COM
20769517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
20779517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
20789517SBill.Taylor@Sun.COM
20799517SBill.Taylor@Sun.COM /*
20809517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
20819517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
20829517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
20839517SBill.Taylor@Sun.COM * not valid for UC transport.
20849517SBill.Taylor@Sun.COM */
20859517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
20869517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
20879517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
20889517SBill.Taylor@Sun.COM }
20899517SBill.Taylor@Sun.COM
20909517SBill.Taylor@Sun.COM /*
20919517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
20929517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
20939517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
20949517SBill.Taylor@Sun.COM */
20959517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
20969517SBill.Taylor@Sun.COM if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
20979517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
20989517SBill.Taylor@Sun.COM } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
20999517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
21009517SBill.Taylor@Sun.COM } else {
21019517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
21029517SBill.Taylor@Sun.COM }
21039517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
21049517SBill.Taylor@Sun.COM }
21059517SBill.Taylor@Sun.COM
21069517SBill.Taylor@Sun.COM /*
21079517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
21089517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
21099517SBill.Taylor@Sun.COM */
21109517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
21119517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
21129517SBill.Taylor@Sun.COM adds_vect = &uc->uc_alt_path.cep_adds_vect;
21139517SBill.Taylor@Sun.COM
21149517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
21159517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
21169517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
21179517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
21189517SBill.Taylor@Sun.COM return (status);
21199517SBill.Taylor@Sun.COM }
21209517SBill.Taylor@Sun.COM
21219517SBill.Taylor@Sun.COM /*
21229517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
21239517SBill.Taylor@Sun.COM * it in
21249517SBill.Taylor@Sun.COM */
21259517SBill.Taylor@Sun.COM portnum = uc->uc_alt_path.cep_hca_port_num;
21269517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
21279517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
21289517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
21299517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
21309517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
21319517SBill.Taylor@Sun.COM } else {
21329517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
21339517SBill.Taylor@Sun.COM }
21349517SBill.Taylor@Sun.COM
21359517SBill.Taylor@Sun.COM /*
21369517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
21379517SBill.Taylor@Sun.COM * it in
21389517SBill.Taylor@Sun.COM */
21399517SBill.Taylor@Sun.COM pkeyindx = uc->uc_alt_path.cep_pkey_ix;
21409517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
21419517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
21429517SBill.Taylor@Sun.COM } else {
21439517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
21449517SBill.Taylor@Sun.COM }
21459517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
21469517SBill.Taylor@Sun.COM }
21479517SBill.Taylor@Sun.COM } else {
21489517SBill.Taylor@Sun.COM /*
21499517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
21509517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
21519517SBill.Taylor@Sun.COM * and return failure
21529517SBill.Taylor@Sun.COM */
21539517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in rts2rts");
21549517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
21559517SBill.Taylor@Sun.COM }
21569517SBill.Taylor@Sun.COM
21579517SBill.Taylor@Sun.COM /*
21589517SBill.Taylor@Sun.COM * Post the RTS2RTS_QP command to the Hermon firmware
21599517SBill.Taylor@Sun.COM *
21609517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
21619517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
21629517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
21639517SBill.Taylor@Sun.COM * success.
21649517SBill.Taylor@Sun.COM */
21659517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, RTS2RTS_QP, qpc, qp->qp_qpnum,
21669517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
21679517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
21689517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
21699517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: RTS2RTS_QP command failed: "
21709517SBill.Taylor@Sun.COM "%08x\n", state->hs_instance, status);
21719517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
21729517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
21739517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
21749517SBill.Taylor@Sun.COM }
21759517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
21769517SBill.Taylor@Sun.COM } else {
21779517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
21789517SBill.Taylor@Sun.COM }
21799517SBill.Taylor@Sun.COM }
21809517SBill.Taylor@Sun.COM
21819517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
21829517SBill.Taylor@Sun.COM }
21839517SBill.Taylor@Sun.COM
21849517SBill.Taylor@Sun.COM
21859517SBill.Taylor@Sun.COM #ifdef HERMON_NOTNOW
21869517SBill.Taylor@Sun.COM /*
21879517SBill.Taylor@Sun.COM * hermon_qp_rts2sqd()
21889517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
21899517SBill.Taylor@Sun.COM */
21909517SBill.Taylor@Sun.COM static int
hermon_qp_rts2sqd(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags)21919517SBill.Taylor@Sun.COM hermon_qp_rts2sqd(hermon_state_t *state, hermon_qphdl_t qp,
21929517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags)
21939517SBill.Taylor@Sun.COM {
21949517SBill.Taylor@Sun.COM int status;
21959517SBill.Taylor@Sun.COM
21969517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
21979517SBill.Taylor@Sun.COM
21989517SBill.Taylor@Sun.COM /*
21999517SBill.Taylor@Sun.COM * Set a flag to indicate whether or not the consumer is interested
22009517SBill.Taylor@Sun.COM * in receiving the SQ drained event. Since we are going to always
22019517SBill.Taylor@Sun.COM * request hardware generation of the SQD event, we use the value in
22029517SBill.Taylor@Sun.COM * "qp_forward_sqd_event" to determine whether or not to pass the event
22039517SBill.Taylor@Sun.COM * to the IBTF or to silently consume it.
22049517SBill.Taylor@Sun.COM */
22059517SBill.Taylor@Sun.COM qp->qp_forward_sqd_event = (flags & IBT_CEP_SET_SQD_EVENT) ? 1 : 0;
22069517SBill.Taylor@Sun.COM
22079517SBill.Taylor@Sun.COM /*
22089517SBill.Taylor@Sun.COM * Post the RTS2SQD_QP command to the Hermon firmware
22099517SBill.Taylor@Sun.COM *
22109517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
22119517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
22129517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
22139517SBill.Taylor@Sun.COM * success.
22149517SBill.Taylor@Sun.COM */
22159517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, RTS2SQD_QP, NULL, qp->qp_qpnum,
22169517SBill.Taylor@Sun.COM 0, HERMON_CMD_NOSLEEP_SPIN);
22179517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
22189517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
22199517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: RTS2SQD_QP command failed: "
22209517SBill.Taylor@Sun.COM "%08x\n", state->hs_instance, status);
22219517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
22229517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
22239517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
22249517SBill.Taylor@Sun.COM }
22259517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
22269517SBill.Taylor@Sun.COM } else {
22279517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
22289517SBill.Taylor@Sun.COM }
22299517SBill.Taylor@Sun.COM }
22309517SBill.Taylor@Sun.COM
22319517SBill.Taylor@Sun.COM /*
22329517SBill.Taylor@Sun.COM * Mark the current QP state as "SQ Draining". This allows us to
22339517SBill.Taylor@Sun.COM * distinguish between the two underlying states in SQD. (see QueryQP()
22349517SBill.Taylor@Sun.COM * code in hermon_qp.c)
22359517SBill.Taylor@Sun.COM */
22369517SBill.Taylor@Sun.COM qp->qp_sqd_still_draining = 1;
22379517SBill.Taylor@Sun.COM
22389517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
22399517SBill.Taylor@Sun.COM }
22409517SBill.Taylor@Sun.COM #endif
22419517SBill.Taylor@Sun.COM
22429517SBill.Taylor@Sun.COM
22439517SBill.Taylor@Sun.COM /*
22449517SBill.Taylor@Sun.COM * hermon_qp_sqd2rts()
22459517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
22469517SBill.Taylor@Sun.COM */
22479517SBill.Taylor@Sun.COM static int
hermon_qp_sqd2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)22489517SBill.Taylor@Sun.COM hermon_qp_sqd2rts(hermon_state_t *state, hermon_qphdl_t qp,
22499517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
22509517SBill.Taylor@Sun.COM {
22519517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
22529517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
22539517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
22549517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
22559517SBill.Taylor@Sun.COM hermon_hw_addr_path_t *qpc_path;
22569517SBill.Taylor@Sun.COM ibt_adds_vect_t *adds_vect;
22579517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx;
22589517SBill.Taylor@Sun.COM uint_t rra_max, sra_max;
22599517SBill.Taylor@Sun.COM uint32_t opmask = 0;
22609517SBill.Taylor@Sun.COM int status;
22619517SBill.Taylor@Sun.COM
22629517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
22639517SBill.Taylor@Sun.COM
22649517SBill.Taylor@Sun.COM /*
22659517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
22669517SBill.Taylor@Sun.COM */
22679517SBill.Taylor@Sun.COM qpc = &qp->qpc;
22689517SBill.Taylor@Sun.COM
22699517SBill.Taylor@Sun.COM /*
22709517SBill.Taylor@Sun.COM * Fill in the common fields in the QPC
22719517SBill.Taylor@Sun.COM */
22729517SBill.Taylor@Sun.COM
22739517SBill.Taylor@Sun.COM /*
22749517SBill.Taylor@Sun.COM * Now fill in the QPC fields which are specific to transport type
22759517SBill.Taylor@Sun.COM */
2276*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
22779517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
22789517SBill.Taylor@Sun.COM
22799517SBill.Taylor@Sun.COM /*
22809517SBill.Taylor@Sun.COM * If we are attempting to modify the port for this QP, then
22819517SBill.Taylor@Sun.COM * check for valid port number and fill it in. Also set the
22829517SBill.Taylor@Sun.COM * appropriate flag in the "opmask" parameter.
22839517SBill.Taylor@Sun.COM */
22849517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PORT) {
22859517SBill.Taylor@Sun.COM portnum = ud->ud_port;
22869517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
22879517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
22889517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
22899517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
22909517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
22919517SBill.Taylor@Sun.COM } else {
22929517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
22939517SBill.Taylor@Sun.COM }
22949517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PRIM_PORT;
22959517SBill.Taylor@Sun.COM }
22969517SBill.Taylor@Sun.COM
22979517SBill.Taylor@Sun.COM /*
22989517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
22999517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
23009517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
23019517SBill.Taylor@Sun.COM */
23029517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
23039517SBill.Taylor@Sun.COM pkeyindx = ud->ud_pkey_ix;
23049517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
23059517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
23069517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
23079517SBill.Taylor@Sun.COM qp->qp_pkeyindx = pkeyindx;
23089517SBill.Taylor@Sun.COM } else {
23099517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
23109517SBill.Taylor@Sun.COM }
23119517SBill.Taylor@Sun.COM }
23129517SBill.Taylor@Sun.COM
23139517SBill.Taylor@Sun.COM /*
23149517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
23159517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
23169517SBill.Taylor@Sun.COM * parameter.
23179517SBill.Taylor@Sun.COM */
23189517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
23199517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
23209517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
23219517SBill.Taylor@Sun.COM }
23229517SBill.Taylor@Sun.COM
23239517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
23249517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
23259517SBill.Taylor@Sun.COM
23269517SBill.Taylor@Sun.COM /*
23279517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
23289517SBill.Taylor@Sun.COM * (recv) enable/disable flags and set the appropriate flag in
23299517SBill.Taylor@Sun.COM * the "opmask" parameter
23309517SBill.Taylor@Sun.COM */
23319517SBill.Taylor@Sun.COM opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
23329517SBill.Taylor@Sun.COM
23339517SBill.Taylor@Sun.COM qpc->retry_cnt = rc->rc_retry_cnt;
23349517SBill.Taylor@Sun.COM
23359517SBill.Taylor@Sun.COM /*
23369517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
23379517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
23389517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
23399517SBill.Taylor@Sun.COM */
23409517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
23419517SBill.Taylor@Sun.COM if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
23429517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
23439517SBill.Taylor@Sun.COM } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
23449517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
23459517SBill.Taylor@Sun.COM } else {
23469517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
23479517SBill.Taylor@Sun.COM }
23489517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
23499517SBill.Taylor@Sun.COM }
23509517SBill.Taylor@Sun.COM
23519517SBill.Taylor@Sun.COM /*
23529517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
23539517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
23549517SBill.Taylor@Sun.COM */
23559517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
23569517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
23579517SBill.Taylor@Sun.COM adds_vect = &rc->rc_alt_path.cep_adds_vect;
23589517SBill.Taylor@Sun.COM
23599517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
23609517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
23619517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
23629517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
23639517SBill.Taylor@Sun.COM return (status);
23649517SBill.Taylor@Sun.COM }
23659517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
23669517SBill.Taylor@Sun.COM /*
23679517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
23689517SBill.Taylor@Sun.COM * it in
23699517SBill.Taylor@Sun.COM */
23709517SBill.Taylor@Sun.COM portnum = rc->rc_alt_path.cep_hca_port_num;
23719517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
23729517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
23739517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
23749517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
23759517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
23769517SBill.Taylor@Sun.COM } else {
23779517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
23789517SBill.Taylor@Sun.COM }
23799517SBill.Taylor@Sun.COM
23809517SBill.Taylor@Sun.COM /*
23819517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
23829517SBill.Taylor@Sun.COM * it in
23839517SBill.Taylor@Sun.COM */
23849517SBill.Taylor@Sun.COM pkeyindx = rc->rc_alt_path.cep_pkey_ix;
23859517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
23869517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
23879517SBill.Taylor@Sun.COM } else {
23889517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
23899517SBill.Taylor@Sun.COM }
23909517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
23919517SBill.Taylor@Sun.COM }
23929517SBill.Taylor@Sun.COM
23939517SBill.Taylor@Sun.COM /*
23949517SBill.Taylor@Sun.COM * If we are attempting to modify the number of "outgoing
23959517SBill.Taylor@Sun.COM * RDMA resources" for this QP, then check for valid value and
23969517SBill.Taylor@Sun.COM * fill it in. Also set the appropriate flag in the "opmask"
23979517SBill.Taylor@Sun.COM * parameter.
23989517SBill.Taylor@Sun.COM */
23999517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMARA_OUT) {
24009517SBill.Taylor@Sun.COM if (hermon_qp_validate_init_depth(state, rc,
24019517SBill.Taylor@Sun.COM &sra_max) != DDI_SUCCESS) {
24029517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
24039517SBill.Taylor@Sun.COM }
24049517SBill.Taylor@Sun.COM qpc->sra_max = sra_max;
24059517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_SRA_SET;
24069517SBill.Taylor@Sun.COM }
24079517SBill.Taylor@Sun.COM
24089517SBill.Taylor@Sun.COM /*
24099517SBill.Taylor@Sun.COM * If we are attempting to modify the number of "incoming
24109517SBill.Taylor@Sun.COM * RDMA resources" for this QP, then check for valid value and
24119517SBill.Taylor@Sun.COM * update the "rra_max" and "ra_buf_index" fields in the QPC to
24129517SBill.Taylor@Sun.COM * point to the pre-allocated RDB resources (in DDR). Also set
24139517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
24149517SBill.Taylor@Sun.COM */
24159517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMARA_IN) {
24169517SBill.Taylor@Sun.COM if (hermon_qp_validate_resp_rsrc(state, rc,
24179517SBill.Taylor@Sun.COM &rra_max) != DDI_SUCCESS) {
24189517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
24199517SBill.Taylor@Sun.COM }
24209517SBill.Taylor@Sun.COM qpc->rra_max = rra_max;
24219517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RRA_SET;
24229517SBill.Taylor@Sun.COM }
24239517SBill.Taylor@Sun.COM
24249517SBill.Taylor@Sun.COM
24259517SBill.Taylor@Sun.COM /*
24269517SBill.Taylor@Sun.COM * If we are attempting to modify the "Minimum RNR NAK" value
24279517SBill.Taylor@Sun.COM * for this QP, then fill it in and set the appropriate flag
24289517SBill.Taylor@Sun.COM * in the "opmask" parameter.
24299517SBill.Taylor@Sun.COM */
24309517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
24319517SBill.Taylor@Sun.COM qpc->min_rnr_nak = rc->rc_min_rnr_nak;
24329517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_MINRNRNAK;
24339517SBill.Taylor@Sun.COM }
24349517SBill.Taylor@Sun.COM
24359517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
24369517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
24379517SBill.Taylor@Sun.COM
24389517SBill.Taylor@Sun.COM /*
24399517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
24409517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
24419517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
24429517SBill.Taylor@Sun.COM * not valid for UC transport.
24439517SBill.Taylor@Sun.COM */
24449517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
24459517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
24469517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
24479517SBill.Taylor@Sun.COM }
24489517SBill.Taylor@Sun.COM
24499517SBill.Taylor@Sun.COM /*
24509517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
24519517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
24529517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
24539517SBill.Taylor@Sun.COM */
24549517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
24559517SBill.Taylor@Sun.COM if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
24569517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
24579517SBill.Taylor@Sun.COM } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
24589517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
24599517SBill.Taylor@Sun.COM } else {
24609517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
24619517SBill.Taylor@Sun.COM }
24629517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
24639517SBill.Taylor@Sun.COM }
24649517SBill.Taylor@Sun.COM
24659517SBill.Taylor@Sun.COM /*
24669517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
24679517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
24689517SBill.Taylor@Sun.COM */
24699517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
24709517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
24719517SBill.Taylor@Sun.COM adds_vect = &uc->uc_alt_path.cep_adds_vect;
24729517SBill.Taylor@Sun.COM
24739517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
24749517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
24759517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
24769517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
24779517SBill.Taylor@Sun.COM return (status);
24789517SBill.Taylor@Sun.COM }
24799517SBill.Taylor@Sun.COM
24809517SBill.Taylor@Sun.COM /*
24819517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
24829517SBill.Taylor@Sun.COM * it in
24839517SBill.Taylor@Sun.COM */
24849517SBill.Taylor@Sun.COM portnum = uc->uc_alt_path.cep_hca_port_num;
24859517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
24869517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
24879517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
24889517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
24899517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
24909517SBill.Taylor@Sun.COM } else {
24919517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
24929517SBill.Taylor@Sun.COM }
24939517SBill.Taylor@Sun.COM
24949517SBill.Taylor@Sun.COM /*
24959517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
24969517SBill.Taylor@Sun.COM * it in
24979517SBill.Taylor@Sun.COM */
24989517SBill.Taylor@Sun.COM pkeyindx = uc->uc_alt_path.cep_pkey_ix;
24999517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
25009517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
25019517SBill.Taylor@Sun.COM } else {
25029517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
25039517SBill.Taylor@Sun.COM }
25049517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
25059517SBill.Taylor@Sun.COM }
25069517SBill.Taylor@Sun.COM } else {
25079517SBill.Taylor@Sun.COM /*
25089517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
25099517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
25109517SBill.Taylor@Sun.COM * and return failure
25119517SBill.Taylor@Sun.COM */
25129517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in sqd2rts");
25139517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
25149517SBill.Taylor@Sun.COM }
25159517SBill.Taylor@Sun.COM
25169517SBill.Taylor@Sun.COM /*
25179517SBill.Taylor@Sun.COM * Post the SQD2RTS_QP command to the Hermon firmware
25189517SBill.Taylor@Sun.COM *
25199517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
25209517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
25219517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
25229517SBill.Taylor@Sun.COM * success.
25239517SBill.Taylor@Sun.COM */
25249517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, SQD2RTS_QP, qpc, qp->qp_qpnum,
25259517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
25269517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
25279517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
25289517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: SQD2RTS_QP command failed: "
25299517SBill.Taylor@Sun.COM "%08x\n", state->hs_instance, status);
25309517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
25319517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
25329517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
25339517SBill.Taylor@Sun.COM }
25349517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
25359517SBill.Taylor@Sun.COM } else {
25369517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
25379517SBill.Taylor@Sun.COM }
25389517SBill.Taylor@Sun.COM }
25399517SBill.Taylor@Sun.COM
25409517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
25419517SBill.Taylor@Sun.COM }
25429517SBill.Taylor@Sun.COM
25439517SBill.Taylor@Sun.COM
25449517SBill.Taylor@Sun.COM /*
25459517SBill.Taylor@Sun.COM * hermon_qp_sqd2sqd()
25469517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
25479517SBill.Taylor@Sun.COM */
25489517SBill.Taylor@Sun.COM static int
hermon_qp_sqd2sqd(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)25499517SBill.Taylor@Sun.COM hermon_qp_sqd2sqd(hermon_state_t *state, hermon_qphdl_t qp,
25509517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
25519517SBill.Taylor@Sun.COM {
25529517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
25539517SBill.Taylor@Sun.COM ibt_qp_rc_attr_t *rc;
25549517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
25559517SBill.Taylor@Sun.COM ibt_qp_uc_attr_t *uc;
25569517SBill.Taylor@Sun.COM hermon_hw_addr_path_t *qpc_path;
25579517SBill.Taylor@Sun.COM ibt_adds_vect_t *adds_vect;
25589517SBill.Taylor@Sun.COM uint_t portnum, pkeyindx;
25599517SBill.Taylor@Sun.COM uint_t rra_max, sra_max;
25609517SBill.Taylor@Sun.COM uint32_t opmask = 0;
25619517SBill.Taylor@Sun.COM int status;
25629517SBill.Taylor@Sun.COM
25639517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
25649517SBill.Taylor@Sun.COM
25659517SBill.Taylor@Sun.COM /*
25669517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
25679517SBill.Taylor@Sun.COM */
25689517SBill.Taylor@Sun.COM qpc = &qp->qpc;
25699517SBill.Taylor@Sun.COM
25709517SBill.Taylor@Sun.COM /*
25719517SBill.Taylor@Sun.COM * Fill in the common fields in the QPC
25729517SBill.Taylor@Sun.COM */
25739517SBill.Taylor@Sun.COM
25749517SBill.Taylor@Sun.COM /*
25759517SBill.Taylor@Sun.COM * Now fill in the QPC fields which are specific to transport type
25769517SBill.Taylor@Sun.COM */
2577*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
25789517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
25799517SBill.Taylor@Sun.COM
25809517SBill.Taylor@Sun.COM /*
25819517SBill.Taylor@Sun.COM * If we are attempting to modify the port for this QP, then
25829517SBill.Taylor@Sun.COM * check for valid port number and fill it in. Also set the
25839517SBill.Taylor@Sun.COM * appropriate flag in the "opmask" parameter.
25849517SBill.Taylor@Sun.COM */
25859517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PORT) {
25869517SBill.Taylor@Sun.COM portnum = ud->ud_port;
25879517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
25889517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
25899517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
25909517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
25919517SBill.Taylor@Sun.COM 0, qp->qp_is_special);
25929517SBill.Taylor@Sun.COM } else {
25939517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
25949517SBill.Taylor@Sun.COM }
25959517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_SCHEDQUEUE;
25969517SBill.Taylor@Sun.COM }
25979517SBill.Taylor@Sun.COM
25989517SBill.Taylor@Sun.COM /*
25999517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
26009517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
26019517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
26029517SBill.Taylor@Sun.COM */
26039517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
26049517SBill.Taylor@Sun.COM pkeyindx = ud->ud_pkey_ix;
26059517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
26069517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
26079517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
26089517SBill.Taylor@Sun.COM qp->qp_pkeyindx = pkeyindx;
26099517SBill.Taylor@Sun.COM } else {
26109517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
26119517SBill.Taylor@Sun.COM }
26129517SBill.Taylor@Sun.COM }
26139517SBill.Taylor@Sun.COM
26149517SBill.Taylor@Sun.COM /*
26159517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
26169517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
26179517SBill.Taylor@Sun.COM * parameter.
26189517SBill.Taylor@Sun.COM */
26199517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
26209517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
26219517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
26229517SBill.Taylor@Sun.COM }
26239517SBill.Taylor@Sun.COM
26249517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
26259517SBill.Taylor@Sun.COM rc = &info_p->qp_transport.rc;
26269517SBill.Taylor@Sun.COM
26279517SBill.Taylor@Sun.COM /*
26289517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
26299517SBill.Taylor@Sun.COM * (recv) enable/disable flags and set the appropriate flag in
26309517SBill.Taylor@Sun.COM * the "opmask" parameter
26319517SBill.Taylor@Sun.COM */
26329517SBill.Taylor@Sun.COM opmask |= hermon_check_rdma_enable_flags(flags, info_p, qpc);
26339517SBill.Taylor@Sun.COM
26349517SBill.Taylor@Sun.COM /*
26359517SBill.Taylor@Sun.COM * Check for optional primary path and fill in the
26369517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
26379517SBill.Taylor@Sun.COM */
26389517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ADDS_VECT) {
26399517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
26409517SBill.Taylor@Sun.COM adds_vect = &rc->rc_path.cep_adds_vect;
26419517SBill.Taylor@Sun.COM
26429517SBill.Taylor@Sun.COM /* Set the common primary address path fields */
26439517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
26449517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
26459517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
26469517SBill.Taylor@Sun.COM return (status);
26479517SBill.Taylor@Sun.COM }
26489517SBill.Taylor@Sun.COM qpc->rnr_retry = rc->rc_rnr_retry_cnt;
26499517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_path.cep_timeout;
26509517SBill.Taylor@Sun.COM qpc->retry_cnt = rc->rc_retry_cnt;
26519517SBill.Taylor@Sun.COM
26529517SBill.Taylor@Sun.COM portnum = qp->qp_portnum + 1;
26539517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
26549517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
26559517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
26569517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
26579517SBill.Taylor@Sun.COM } else {
26589517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
26599517SBill.Taylor@Sun.COM }
26609517SBill.Taylor@Sun.COM
26619517SBill.Taylor@Sun.COM /*
26629517SBill.Taylor@Sun.COM * MTU changes as part of sqd2sqd are not allowed.
26639517SBill.Taylor@Sun.COM * Simply keep the same MTU value here, stored in the
26649517SBill.Taylor@Sun.COM * qphdl from init2rtr time.
26659517SBill.Taylor@Sun.COM */
26669517SBill.Taylor@Sun.COM qpc->mtu = qp->qp_save_mtu;
26679517SBill.Taylor@Sun.COM
26689517SBill.Taylor@Sun.COM opmask |= (HERMON_CMD_OP_PRIM_PATH |
26699517SBill.Taylor@Sun.COM HERMON_CMD_OP_RETRYCNT | HERMON_CMD_OP_ACKTIMEOUT |
26709517SBill.Taylor@Sun.COM HERMON_CMD_OP_PRIM_RNRRETRY);
26719517SBill.Taylor@Sun.COM }
26729517SBill.Taylor@Sun.COM
26739517SBill.Taylor@Sun.COM /*
26749517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
26759517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
26769517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
26779517SBill.Taylor@Sun.COM */
26789517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
26799517SBill.Taylor@Sun.COM if (rc->rc_mig_state == IBT_STATE_MIGRATED) {
26809517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
26819517SBill.Taylor@Sun.COM } else if (rc->rc_mig_state == IBT_STATE_REARMED) {
26829517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
26839517SBill.Taylor@Sun.COM } else {
26849517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
26859517SBill.Taylor@Sun.COM }
26869517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
26879517SBill.Taylor@Sun.COM }
26889517SBill.Taylor@Sun.COM
26899517SBill.Taylor@Sun.COM /*
26909517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
26919517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
26929517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
26939517SBill.Taylor@Sun.COM */
26949517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
26959517SBill.Taylor@Sun.COM pkeyindx = rc->rc_path.cep_pkey_ix;
26969517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
26979517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
26989517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
26999517SBill.Taylor@Sun.COM } else {
27009517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
27019517SBill.Taylor@Sun.COM }
27029517SBill.Taylor@Sun.COM }
27039517SBill.Taylor@Sun.COM
27049517SBill.Taylor@Sun.COM /*
27059517SBill.Taylor@Sun.COM * If we are attempting to modify the port for this QP, then
27069517SBill.Taylor@Sun.COM * check for valid port number and fill it in. Also set the
27079517SBill.Taylor@Sun.COM * appropriate flag in the "opmask" parameter.
27089517SBill.Taylor@Sun.COM */
27099517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PORT) {
27109517SBill.Taylor@Sun.COM portnum = rc->rc_path.cep_hca_port_num;
27119517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
27129517SBill.Taylor@Sun.COM qp->qp_portnum = portnum - 1;
27139517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
27149517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
27159517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
27169517SBill.Taylor@Sun.COM } else {
27179517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
27189517SBill.Taylor@Sun.COM }
27199517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_SCHEDQUEUE;
27209517SBill.Taylor@Sun.COM }
27219517SBill.Taylor@Sun.COM
27229517SBill.Taylor@Sun.COM /*
27239517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
27249517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
27259517SBill.Taylor@Sun.COM */
27269517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
27279517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
27289517SBill.Taylor@Sun.COM adds_vect = &rc->rc_alt_path.cep_adds_vect;
27299517SBill.Taylor@Sun.COM
27309517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
27319517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
27329517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
27339517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
27349517SBill.Taylor@Sun.COM return (status);
27359517SBill.Taylor@Sun.COM }
27369517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_alt_path.cep_timeout;
27379517SBill.Taylor@Sun.COM
27389517SBill.Taylor@Sun.COM /*
27399517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
27409517SBill.Taylor@Sun.COM * it in
27419517SBill.Taylor@Sun.COM */
27429517SBill.Taylor@Sun.COM portnum = rc->rc_alt_path.cep_hca_port_num;
27439517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
27449517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
27459517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
27469517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
27479517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
27489517SBill.Taylor@Sun.COM } else {
27499517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
27509517SBill.Taylor@Sun.COM }
27519517SBill.Taylor@Sun.COM
27529517SBill.Taylor@Sun.COM /*
27539517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
27549517SBill.Taylor@Sun.COM * it in
27559517SBill.Taylor@Sun.COM */
27569517SBill.Taylor@Sun.COM pkeyindx = rc->rc_alt_path.cep_pkey_ix;
27579517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
27589517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
27599517SBill.Taylor@Sun.COM } else {
27609517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
27619517SBill.Taylor@Sun.COM }
27629517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
27639517SBill.Taylor@Sun.COM }
27649517SBill.Taylor@Sun.COM
27659517SBill.Taylor@Sun.COM /*
27669517SBill.Taylor@Sun.COM * If we are attempting to modify the number of "outgoing
27679517SBill.Taylor@Sun.COM * RDMA resources" for this QP, then check for valid value and
27689517SBill.Taylor@Sun.COM * fill it in. Also set the appropriate flag in the "opmask"
27699517SBill.Taylor@Sun.COM * parameter.
27709517SBill.Taylor@Sun.COM */
27719517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMARA_OUT) {
27729517SBill.Taylor@Sun.COM if (hermon_qp_validate_init_depth(state, rc,
27739517SBill.Taylor@Sun.COM &sra_max) != DDI_SUCCESS) {
27749517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
27759517SBill.Taylor@Sun.COM }
27769517SBill.Taylor@Sun.COM qpc->sra_max = sra_max;
27779517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_SRA_SET;
27789517SBill.Taylor@Sun.COM }
27799517SBill.Taylor@Sun.COM
27809517SBill.Taylor@Sun.COM /*
27819517SBill.Taylor@Sun.COM * If we are attempting to modify the number of "incoming
27829517SBill.Taylor@Sun.COM * RDMA resources" for this QP, then check for valid value and
27839517SBill.Taylor@Sun.COM * update the "rra_max" and "ra_buf_index" fields in the QPC to
27849517SBill.Taylor@Sun.COM * point to the pre-allocated RDB resources (in DDR). Also set
27859517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
27869517SBill.Taylor@Sun.COM */
27879517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMARA_IN) {
27889517SBill.Taylor@Sun.COM if (hermon_qp_validate_resp_rsrc(state, rc,
27899517SBill.Taylor@Sun.COM &rra_max) != DDI_SUCCESS) {
27909517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
27919517SBill.Taylor@Sun.COM }
27929517SBill.Taylor@Sun.COM qpc->rra_max = rra_max;
27939517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RRA_SET;
27949517SBill.Taylor@Sun.COM }
27959517SBill.Taylor@Sun.COM
27969517SBill.Taylor@Sun.COM /*
27979517SBill.Taylor@Sun.COM * If we are attempting to modify the "Local Ack Timeout" value
27989517SBill.Taylor@Sun.COM * for this QP, then fill it in and set the appropriate flag in
27999517SBill.Taylor@Sun.COM * the "opmask" parameter.
28009517SBill.Taylor@Sun.COM */
28019517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_TIMEOUT) {
28029517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
28039517SBill.Taylor@Sun.COM qpc_path->ack_timeout = rc->rc_path.cep_timeout;
28049517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ACKTIMEOUT;
28059517SBill.Taylor@Sun.COM }
28069517SBill.Taylor@Sun.COM
28079517SBill.Taylor@Sun.COM /*
28089517SBill.Taylor@Sun.COM * If we are attempting to modify the "Retry Count" for this QP,
28099517SBill.Taylor@Sun.COM * then fill it in and set the appropriate flag in the "opmask"
28109517SBill.Taylor@Sun.COM * parameter.
28119517SBill.Taylor@Sun.COM */
28129517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RETRY) {
28139517SBill.Taylor@Sun.COM qpc->retry_cnt = rc->rc_retry_cnt;
28149517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PRIM_RNRRETRY;
28159517SBill.Taylor@Sun.COM }
28169517SBill.Taylor@Sun.COM
28179517SBill.Taylor@Sun.COM /*
28189517SBill.Taylor@Sun.COM * If we are attempting to modify the "RNR Retry Count" for this
28199517SBill.Taylor@Sun.COM * QP, then fill it in and set the appropriate flag in the
28209517SBill.Taylor@Sun.COM * "opmask" parameter.
28219517SBill.Taylor@Sun.COM */
28229517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RNR_NAK_RETRY) {
28239517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
28249517SBill.Taylor@Sun.COM qpc->rnr_retry = rc->rc_rnr_retry_cnt;
28259517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RETRYCNT;
28269517SBill.Taylor@Sun.COM }
28279517SBill.Taylor@Sun.COM
28289517SBill.Taylor@Sun.COM /*
28299517SBill.Taylor@Sun.COM * If we are attempting to modify the "Minimum RNR NAK" value
28309517SBill.Taylor@Sun.COM * for this QP, then fill it in and set the appropriate flag
28319517SBill.Taylor@Sun.COM * in the "opmask" parameter.
28329517SBill.Taylor@Sun.COM */
28339517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIN_RNR_NAK) {
28349517SBill.Taylor@Sun.COM qpc->min_rnr_nak = rc->rc_min_rnr_nak;
28359517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_MINRNRNAK;
28369517SBill.Taylor@Sun.COM }
28379517SBill.Taylor@Sun.COM
28389517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
28399517SBill.Taylor@Sun.COM uc = &info_p->qp_transport.uc;
28409517SBill.Taylor@Sun.COM
28419517SBill.Taylor@Sun.COM /*
28429517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
28439517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
28449517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
28459517SBill.Taylor@Sun.COM * not valid for UC transport.
28469517SBill.Taylor@Sun.COM */
28479517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
28489517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
28499517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
28509517SBill.Taylor@Sun.COM }
28519517SBill.Taylor@Sun.COM
28529517SBill.Taylor@Sun.COM /*
28539517SBill.Taylor@Sun.COM * Check for optional primary path and fill in the
28549517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
28559517SBill.Taylor@Sun.COM */
28569517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ADDS_VECT) {
28579517SBill.Taylor@Sun.COM qpc_path = &qpc->pri_addr_path;
28589517SBill.Taylor@Sun.COM adds_vect = &uc->uc_path.cep_adds_vect;
28599517SBill.Taylor@Sun.COM
28609517SBill.Taylor@Sun.COM /* Set the common primary address path fields */
28619517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
28629517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
28639517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
28649517SBill.Taylor@Sun.COM return (status);
28659517SBill.Taylor@Sun.COM }
28669517SBill.Taylor@Sun.COM portnum = qp->qp_portnum + 1;
28679517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
28689517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
28699517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(qp->qp_portnum,
28709517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
28719517SBill.Taylor@Sun.COM } else {
28729517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
28739517SBill.Taylor@Sun.COM }
28749517SBill.Taylor@Sun.COM
28759517SBill.Taylor@Sun.COM /*
28769517SBill.Taylor@Sun.COM * MTU changes as part of sqd2sqd are not allowed.
28779517SBill.Taylor@Sun.COM * Simply keep the same MTU value here, stored in the
28789517SBill.Taylor@Sun.COM * qphdl from init2rtr time.
28799517SBill.Taylor@Sun.COM */
28809517SBill.Taylor@Sun.COM qpc->mtu = qp->qp_save_mtu;
28819517SBill.Taylor@Sun.COM
28829517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PRIM_PATH;
28839517SBill.Taylor@Sun.COM }
28849517SBill.Taylor@Sun.COM
28859517SBill.Taylor@Sun.COM /*
28869517SBill.Taylor@Sun.COM * If we are attempting to modify the path migration state for
28879517SBill.Taylor@Sun.COM * this QP, then check for valid state and fill it in. Also
28889517SBill.Taylor@Sun.COM * set the appropriate flag in the "opmask" parameter.
28899517SBill.Taylor@Sun.COM */
28909517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_MIG) {
28919517SBill.Taylor@Sun.COM if (uc->uc_mig_state == IBT_STATE_MIGRATED) {
28929517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
28939517SBill.Taylor@Sun.COM } else if (uc->uc_mig_state == IBT_STATE_REARMED) {
28949517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_REARM;
28959517SBill.Taylor@Sun.COM } else {
28969517SBill.Taylor@Sun.COM return (IBT_QP_APM_STATE_INVALID);
28979517SBill.Taylor@Sun.COM }
28989517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PM_STATE;
28999517SBill.Taylor@Sun.COM }
29009517SBill.Taylor@Sun.COM
29019517SBill.Taylor@Sun.COM /*
29029517SBill.Taylor@Sun.COM * If we are attempting to modify the PKey index for this QP,
29039517SBill.Taylor@Sun.COM * then check for valid PKey index and fill it in. Also set
29049517SBill.Taylor@Sun.COM * the appropriate flag in the "opmask" parameter.
29059517SBill.Taylor@Sun.COM */
29069517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_PKEY_IX) {
29079517SBill.Taylor@Sun.COM pkeyindx = uc->uc_path.cep_pkey_ix;
29089517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
29099517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = pkeyindx;
29109517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_PKEYINDX;
29119517SBill.Taylor@Sun.COM } else {
29129517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
29139517SBill.Taylor@Sun.COM }
29149517SBill.Taylor@Sun.COM }
29159517SBill.Taylor@Sun.COM
29169517SBill.Taylor@Sun.COM /*
29179517SBill.Taylor@Sun.COM * Check for optional alternate path and fill in the
29189517SBill.Taylor@Sun.COM * appropriate QPC fields if one is specified
29199517SBill.Taylor@Sun.COM */
29209517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ALT_PATH) {
29219517SBill.Taylor@Sun.COM qpc_path = &qpc->alt_addr_path;
29229517SBill.Taylor@Sun.COM adds_vect = &uc->uc_alt_path.cep_adds_vect;
29239517SBill.Taylor@Sun.COM
29249517SBill.Taylor@Sun.COM /* Set the common alternate address path fields */
29259517SBill.Taylor@Sun.COM status = hermon_set_addr_path(state, adds_vect,
29269517SBill.Taylor@Sun.COM qpc_path, HERMON_ADDRPATH_QP);
29279517SBill.Taylor@Sun.COM if (status != DDI_SUCCESS) {
29289517SBill.Taylor@Sun.COM return (status);
29299517SBill.Taylor@Sun.COM }
29309517SBill.Taylor@Sun.COM
29319517SBill.Taylor@Sun.COM /*
29329517SBill.Taylor@Sun.COM * Check for valid alternate path port number and fill
29339517SBill.Taylor@Sun.COM * it in
29349517SBill.Taylor@Sun.COM */
29359517SBill.Taylor@Sun.COM portnum = uc->uc_alt_path.cep_hca_port_num;
29369517SBill.Taylor@Sun.COM if (hermon_portnum_is_valid(state, portnum)) {
29379517SBill.Taylor@Sun.COM qp->qp_portnum_alt = portnum - 1;
29389517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
29399517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(portnum - 1,
29409517SBill.Taylor@Sun.COM adds_vect->av_srvl, qp->qp_is_special);
29419517SBill.Taylor@Sun.COM } else {
29429517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_INVALID);
29439517SBill.Taylor@Sun.COM }
29449517SBill.Taylor@Sun.COM
29459517SBill.Taylor@Sun.COM /*
29469517SBill.Taylor@Sun.COM * Check for valid alternate path PKey index and fill
29479517SBill.Taylor@Sun.COM * it in
29489517SBill.Taylor@Sun.COM */
29499517SBill.Taylor@Sun.COM pkeyindx = uc->uc_alt_path.cep_pkey_ix;
29509517SBill.Taylor@Sun.COM if (hermon_pkeyindex_is_valid(state, pkeyindx)) {
29519517SBill.Taylor@Sun.COM qpc->alt_addr_path.pkey_indx = pkeyindx;
29529517SBill.Taylor@Sun.COM } else {
29539517SBill.Taylor@Sun.COM return (IBT_PKEY_IX_ILLEGAL);
29549517SBill.Taylor@Sun.COM }
29559517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_ALT_PATH;
29569517SBill.Taylor@Sun.COM }
29579517SBill.Taylor@Sun.COM } else {
29589517SBill.Taylor@Sun.COM /*
29599517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
29609517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
29619517SBill.Taylor@Sun.COM * and return failure
29629517SBill.Taylor@Sun.COM */
29639517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in sqd2sqd");
29649517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
29659517SBill.Taylor@Sun.COM }
29669517SBill.Taylor@Sun.COM
29679517SBill.Taylor@Sun.COM /*
29689517SBill.Taylor@Sun.COM * Post the SQD2SQD_QP command to the Hermon firmware
29699517SBill.Taylor@Sun.COM *
29709517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
29719517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
29729517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
29739517SBill.Taylor@Sun.COM * success.
29749517SBill.Taylor@Sun.COM */
29759517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, SQD2SQD_QP, qpc, qp->qp_qpnum,
29769517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
29779517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
29789517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
29799517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: SQD2SQD_QP command failed: "
29809517SBill.Taylor@Sun.COM "%08x\n", state->hs_instance, status);
29819517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
29829517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
29839517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
29849517SBill.Taylor@Sun.COM }
29859517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
29869517SBill.Taylor@Sun.COM } else {
29879517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
29889517SBill.Taylor@Sun.COM }
29899517SBill.Taylor@Sun.COM }
29909517SBill.Taylor@Sun.COM
29919517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
29929517SBill.Taylor@Sun.COM }
29939517SBill.Taylor@Sun.COM
29949517SBill.Taylor@Sun.COM
29959517SBill.Taylor@Sun.COM /*
29969517SBill.Taylor@Sun.COM * hermon_qp_sqerr2rts()
29979517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
29989517SBill.Taylor@Sun.COM */
29999517SBill.Taylor@Sun.COM static int
hermon_qp_sqerr2rts(hermon_state_t * state,hermon_qphdl_t qp,ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p)30009517SBill.Taylor@Sun.COM hermon_qp_sqerr2rts(hermon_state_t *state, hermon_qphdl_t qp,
30019517SBill.Taylor@Sun.COM ibt_cep_modify_flags_t flags, ibt_qp_info_t *info_p)
30029517SBill.Taylor@Sun.COM {
30039517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
30049517SBill.Taylor@Sun.COM ibt_qp_ud_attr_t *ud;
30059517SBill.Taylor@Sun.COM uint32_t opmask = 0;
30069517SBill.Taylor@Sun.COM int status;
30079517SBill.Taylor@Sun.COM
30089517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
30099517SBill.Taylor@Sun.COM
30109517SBill.Taylor@Sun.COM /*
30119517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
30129517SBill.Taylor@Sun.COM */
30139517SBill.Taylor@Sun.COM qpc = &qp->qpc;
30149517SBill.Taylor@Sun.COM
30159517SBill.Taylor@Sun.COM /*
30169517SBill.Taylor@Sun.COM * Since there are no common fields to be filled in for this command,
30179517SBill.Taylor@Sun.COM * we begin with the QPC fields which are specific to transport type.
30189517SBill.Taylor@Sun.COM */
3019*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
30209517SBill.Taylor@Sun.COM ud = &info_p->qp_transport.ud;
30219517SBill.Taylor@Sun.COM
30229517SBill.Taylor@Sun.COM /*
30239517SBill.Taylor@Sun.COM * If we are attempting to modify the QKey for this QP, then
30249517SBill.Taylor@Sun.COM * fill it in and set the appropriate flag in the "opmask"
30259517SBill.Taylor@Sun.COM * parameter.
30269517SBill.Taylor@Sun.COM */
30279517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_QKEY) {
30289517SBill.Taylor@Sun.COM qpc->qkey = ud->ud_qkey;
30299517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_QKEY;
30309517SBill.Taylor@Sun.COM }
30319517SBill.Taylor@Sun.COM
30329517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
30339517SBill.Taylor@Sun.COM
30349517SBill.Taylor@Sun.COM /*
30359517SBill.Taylor@Sun.COM * Check if any of the flags indicate a change in the RDMA
30369517SBill.Taylor@Sun.COM * Write (recv) enable/disable and set the appropriate flag
30379517SBill.Taylor@Sun.COM * in the "opmask" parameter. Note: RDMA Read and Atomic are
30389517SBill.Taylor@Sun.COM * not valid for UC transport.
30399517SBill.Taylor@Sun.COM */
30409517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
30419517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
30429517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
30439517SBill.Taylor@Sun.COM }
30449517SBill.Taylor@Sun.COM } else {
30459517SBill.Taylor@Sun.COM /*
30469517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
30479517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
30489517SBill.Taylor@Sun.COM * and return failure
30499517SBill.Taylor@Sun.COM */
30509517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in sqerr2rts");
30519517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
30529517SBill.Taylor@Sun.COM }
30539517SBill.Taylor@Sun.COM
30549517SBill.Taylor@Sun.COM /*
30559517SBill.Taylor@Sun.COM * Post the SQERR2RTS_QP command to the Hermon firmware
30569517SBill.Taylor@Sun.COM *
30579517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
30589517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
30599517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
30609517SBill.Taylor@Sun.COM * success.
30619517SBill.Taylor@Sun.COM */
30629517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, SQERR2RTS_QP, qpc, qp->qp_qpnum,
30639517SBill.Taylor@Sun.COM opmask, HERMON_CMD_NOSLEEP_SPIN);
30649517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
30659517SBill.Taylor@Sun.COM if (status != HERMON_CMD_BAD_QP_STATE) {
30669517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: SQERR2RTS_QP command "
30679517SBill.Taylor@Sun.COM "failed: %08x\n", state->hs_instance, status);
30689517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
30699517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR,
30709517SBill.Taylor@Sun.COM HCA_ERR_SRV_LOST);
30719517SBill.Taylor@Sun.COM }
30729517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
30739517SBill.Taylor@Sun.COM } else {
30749517SBill.Taylor@Sun.COM return (IBT_QP_STATE_INVALID);
30759517SBill.Taylor@Sun.COM }
30769517SBill.Taylor@Sun.COM }
30779517SBill.Taylor@Sun.COM
30789517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
30799517SBill.Taylor@Sun.COM }
30809517SBill.Taylor@Sun.COM
30819517SBill.Taylor@Sun.COM
30829517SBill.Taylor@Sun.COM /*
30839517SBill.Taylor@Sun.COM * hermon_qp_to_error()
30849517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
30859517SBill.Taylor@Sun.COM */
30869517SBill.Taylor@Sun.COM static int
hermon_qp_to_error(hermon_state_t * state,hermon_qphdl_t qp)30879517SBill.Taylor@Sun.COM hermon_qp_to_error(hermon_state_t *state, hermon_qphdl_t qp)
30889517SBill.Taylor@Sun.COM {
30899517SBill.Taylor@Sun.COM int status;
30909517SBill.Taylor@Sun.COM
30919517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
30929517SBill.Taylor@Sun.COM
30939517SBill.Taylor@Sun.COM /*
30949517SBill.Taylor@Sun.COM * Post the TOERR_QP command to the Hermon firmware
30959517SBill.Taylor@Sun.COM *
30969517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
30979517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
30989517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
30999517SBill.Taylor@Sun.COM * success.
31009517SBill.Taylor@Sun.COM */
31019517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum,
31029517SBill.Taylor@Sun.COM 0, HERMON_CMD_NOSLEEP_SPIN);
31039517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
31049517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: TOERR_QP command failed: %08x\n",
31059517SBill.Taylor@Sun.COM state->hs_instance, status);
31069517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
31079517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
31089517SBill.Taylor@Sun.COM }
31099517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
31109517SBill.Taylor@Sun.COM }
31119517SBill.Taylor@Sun.COM
31129517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
31139517SBill.Taylor@Sun.COM }
31149517SBill.Taylor@Sun.COM
31159517SBill.Taylor@Sun.COM
31169517SBill.Taylor@Sun.COM /*
31179517SBill.Taylor@Sun.COM * hermon_qp_to_reset()
31189517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
31199517SBill.Taylor@Sun.COM */
31209517SBill.Taylor@Sun.COM int
hermon_qp_to_reset(hermon_state_t * state,hermon_qphdl_t qp)31219517SBill.Taylor@Sun.COM hermon_qp_to_reset(hermon_state_t *state, hermon_qphdl_t qp)
31229517SBill.Taylor@Sun.COM {
31239517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
31249517SBill.Taylor@Sun.COM int status;
31259517SBill.Taylor@Sun.COM
31269517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
31279517SBill.Taylor@Sun.COM
31289517SBill.Taylor@Sun.COM /*
31299517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
31309517SBill.Taylor@Sun.COM */
31319517SBill.Taylor@Sun.COM qpc = &qp->qpc;
31329517SBill.Taylor@Sun.COM
31339517SBill.Taylor@Sun.COM /*
31349517SBill.Taylor@Sun.COM * Post the TORST_QP command to the Hermon firmware
31359517SBill.Taylor@Sun.COM *
31369517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
31379517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
31389517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
31399517SBill.Taylor@Sun.COM * success.
31409517SBill.Taylor@Sun.COM */
31419517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, TORST_QP, qpc, qp->qp_qpnum,
31429517SBill.Taylor@Sun.COM 0, HERMON_CMD_NOSLEEP_SPIN);
31439517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
31449517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: TORST_QP command failed: %08x\n",
31459517SBill.Taylor@Sun.COM state->hs_instance, status);
31469517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
31479517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
31489517SBill.Taylor@Sun.COM }
31499517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
31509517SBill.Taylor@Sun.COM }
3151*12965SWilliam.Taylor@Oracle.COM if (qp->qp_serv_type == HERMON_QP_FEXCH) {
3152*12965SWilliam.Taylor@Oracle.COM status = hermon_fcoib_fexch_mkey_fini(state, qp->qp_pdhdl,
3153*12965SWilliam.Taylor@Oracle.COM qp->qp_qpnum, HERMON_CMD_NOSLEEP_SPIN);
3154*12965SWilliam.Taylor@Oracle.COM if (status != DDI_SUCCESS)
3155*12965SWilliam.Taylor@Oracle.COM cmn_err(CE_NOTE, "hermon%d: fexch_mkey_fini failed "
3156*12965SWilliam.Taylor@Oracle.COM "%08x\n", state->hs_instance, status);
3157*12965SWilliam.Taylor@Oracle.COM }
31589517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
31599517SBill.Taylor@Sun.COM }
31609517SBill.Taylor@Sun.COM
31619517SBill.Taylor@Sun.COM
31629517SBill.Taylor@Sun.COM /*
31639517SBill.Taylor@Sun.COM * hermon_qp_reset2err()
31649517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
31659517SBill.Taylor@Sun.COM */
31669517SBill.Taylor@Sun.COM static int
hermon_qp_reset2err(hermon_state_t * state,hermon_qphdl_t qp)31679517SBill.Taylor@Sun.COM hermon_qp_reset2err(hermon_state_t *state, hermon_qphdl_t qp)
31689517SBill.Taylor@Sun.COM {
31699517SBill.Taylor@Sun.COM hermon_hw_qpc_t *qpc;
31709517SBill.Taylor@Sun.COM int status;
31719517SBill.Taylor@Sun.COM uint32_t cqnmask;
31729517SBill.Taylor@Sun.COM
31739517SBill.Taylor@Sun.COM ASSERT(MUTEX_HELD(&qp->qp_lock));
31749517SBill.Taylor@Sun.COM
31759517SBill.Taylor@Sun.COM /*
31769517SBill.Taylor@Sun.COM * In order to implement the transition from "Reset" directly to the
31779517SBill.Taylor@Sun.COM * "Error" state, it is necessary to first give ownership of the QP
31789517SBill.Taylor@Sun.COM * context to the Hermon hardware. This is accomplished by
31799517SBill.Taylor@Sun.COM * transitioning the QP to "Init" as an intermediate step and then,
31809517SBill.Taylor@Sun.COM * immediately transitioning to "Error".
31819517SBill.Taylor@Sun.COM *
31829517SBill.Taylor@Sun.COM * When this function returns success, the QP context will be owned by
31839517SBill.Taylor@Sun.COM * the Hermon hardware and will be in the "Error" state.
31849517SBill.Taylor@Sun.COM */
31859517SBill.Taylor@Sun.COM
31869517SBill.Taylor@Sun.COM /*
31879517SBill.Taylor@Sun.COM * Grab the temporary QPC entry from QP software state
31889517SBill.Taylor@Sun.COM */
31899517SBill.Taylor@Sun.COM qpc = &qp->qpc;
31909517SBill.Taylor@Sun.COM
31919517SBill.Taylor@Sun.COM /*
31929517SBill.Taylor@Sun.COM * Fill in the common fields in the QPC
31939517SBill.Taylor@Sun.COM */
31949517SBill.Taylor@Sun.COM if (qp->qp_is_special) {
31959517SBill.Taylor@Sun.COM qpc->serv_type = HERMON_QP_MLX;
31969517SBill.Taylor@Sun.COM } else {
31979517SBill.Taylor@Sun.COM qpc->serv_type = qp->qp_serv_type;
31989517SBill.Taylor@Sun.COM }
31999517SBill.Taylor@Sun.COM qpc->pm_state = HERMON_QP_PMSTATE_MIGRATED;
32009517SBill.Taylor@Sun.COM qpc->usr_page = qp->qp_uarpg;
32019517SBill.Taylor@Sun.COM /* dbr is now an address, not an index */
32029517SBill.Taylor@Sun.COM qpc->dbr_addrh = ((uint64_t)qp->qp_rq_pdbr >> 32);
32039517SBill.Taylor@Sun.COM qpc->dbr_addrl = ((uint64_t)qp->qp_rq_pdbr & 0xFFFFFFFC) >> 2;
32049517SBill.Taylor@Sun.COM qpc->pd = qp->qp_pdhdl->pd_pdnum;
32059517SBill.Taylor@Sun.COM /*
32069517SBill.Taylor@Sun.COM * HERMON:
32079517SBill.Taylor@Sun.COM * qpc->wqe_baseaddr is replaced by LKey from the cMPT, and
32089517SBill.Taylor@Sun.COM * page_offset, mtt_base_addr_h/l, and log2_page_size will
32099517SBill.Taylor@Sun.COM * be used to map the WQE buffer
32109517SBill.Taylor@Sun.COM * NOTE that the cMPT is created implicitly when the QP is
32119517SBill.Taylor@Sun.COM * transitioned from reset to init
32129517SBill.Taylor@Sun.COM */
32139517SBill.Taylor@Sun.COM qpc->log2_pgsz = qp->qp_mrhdl->mr_log2_pgsz;
32149517SBill.Taylor@Sun.COM qpc->mtt_base_addrh = (qp->qp_mrhdl->mr_mttaddr) >> 32 & 0xFF;
32159517SBill.Taylor@Sun.COM qpc->mtt_base_addrl = (qp->qp_mrhdl->mr_mttaddr) >> 3 & 0xFFFFFFFF;
32169517SBill.Taylor@Sun.COM cqnmask = (1 << state->hs_cfg_profile->cp_log_num_cq) - 1;
3217*12965SWilliam.Taylor@Oracle.COM qpc->cqn_snd =
3218*12965SWilliam.Taylor@Oracle.COM (qp->qp_sq_cqhdl == NULL) ? 0 : qp->qp_sq_cqhdl->cq_cqnum & cqnmask;
32199517SBill.Taylor@Sun.COM qpc->page_offs = qp->qp_wqinfo.qa_pgoffs >> 6;
3220*12965SWilliam.Taylor@Oracle.COM qpc->cqn_rcv =
3221*12965SWilliam.Taylor@Oracle.COM (qp->qp_rq_cqhdl == NULL) ? 0 : qp->qp_rq_cqhdl->cq_cqnum & cqnmask;
32229517SBill.Taylor@Sun.COM
32239517SBill.Taylor@Sun.COM qpc->sq_wqe_counter = 0;
32249517SBill.Taylor@Sun.COM qpc->rq_wqe_counter = 0;
32259517SBill.Taylor@Sun.COM qpc->log_sq_stride = qp->qp_sq_log_wqesz - 4;
32269517SBill.Taylor@Sun.COM qpc->log_rq_stride = qp->qp_rq_log_wqesz - 4;
32279517SBill.Taylor@Sun.COM qpc->log_sq_size = highbit(qp->qp_sq_bufsz) - 1;
32289517SBill.Taylor@Sun.COM qpc->log_rq_size = highbit(qp->qp_rq_bufsz) - 1;
3229*12965SWilliam.Taylor@Oracle.COM qpc->srq_en = (qp->qp_alloc_flags & IBT_QP_USES_SRQ) != 0;
32309517SBill.Taylor@Sun.COM qpc->sq_no_prefetch = qp->qp_no_prefetch;
32319517SBill.Taylor@Sun.COM
3232*12965SWilliam.Taylor@Oracle.COM if (qp->qp_alloc_flags & IBT_QP_USES_SRQ) {
32339517SBill.Taylor@Sun.COM qpc->srq_number = qp->qp_srqhdl->srq_srqnum;
32349517SBill.Taylor@Sun.COM } else {
32359517SBill.Taylor@Sun.COM qpc->srq_number = 0;
32369517SBill.Taylor@Sun.COM }
32379517SBill.Taylor@Sun.COM
32389517SBill.Taylor@Sun.COM qpc->fre = 0; /* default disable fast registration WR */
32399517SBill.Taylor@Sun.COM qpc->rlky = 0; /* default disable reserved lkey */
32409517SBill.Taylor@Sun.COM
32419517SBill.Taylor@Sun.COM /*
32429517SBill.Taylor@Sun.COM * Now fill in the QPC fields which are specific to transport type
32439517SBill.Taylor@Sun.COM */
3244*12965SWilliam.Taylor@Oracle.COM if (qp->qp_type == IBT_UD_RQP) {
32459517SBill.Taylor@Sun.COM /* Set the UD parameters to an invalid default */
32469517SBill.Taylor@Sun.COM qpc->qkey = 0;
32479517SBill.Taylor@Sun.COM qpc->pri_addr_path.sched_q =
32489517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
32499517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = 0;
32509517SBill.Taylor@Sun.COM
32519517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_RC) {
32529517SBill.Taylor@Sun.COM /* Set the RC parameters to invalid default */
32539517SBill.Taylor@Sun.COM qpc->rre = 0;
32549517SBill.Taylor@Sun.COM qpc->rwe = 0;
32559517SBill.Taylor@Sun.COM qpc->rae = 0;
32569517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
32579517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
32589517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = 0;
32599517SBill.Taylor@Sun.COM
32609517SBill.Taylor@Sun.COM } else if (qp->qp_serv_type == HERMON_QP_UC) {
32619517SBill.Taylor@Sun.COM /* Set the UC parameters to invalid default */
32629517SBill.Taylor@Sun.COM qpc->rwe = 0;
32639517SBill.Taylor@Sun.COM qpc->alt_addr_path.sched_q =
32649517SBill.Taylor@Sun.COM HERMON_QP_SCHEDQ_GET(0, 0, qp->qp_is_special);
32659517SBill.Taylor@Sun.COM qpc->pri_addr_path.pkey_indx = 0;
32669517SBill.Taylor@Sun.COM
32679517SBill.Taylor@Sun.COM } else {
32689517SBill.Taylor@Sun.COM /*
32699517SBill.Taylor@Sun.COM * Invalid QP transport type. If we got here then it's a
32709517SBill.Taylor@Sun.COM * warning of a probably serious problem. So print a message
32719517SBill.Taylor@Sun.COM * and return failure
32729517SBill.Taylor@Sun.COM */
32739517SBill.Taylor@Sun.COM HERMON_WARNING(state, "unknown QP transport type in rst2err");
32749517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
32759517SBill.Taylor@Sun.COM }
32769517SBill.Taylor@Sun.COM
32779517SBill.Taylor@Sun.COM /*
32789517SBill.Taylor@Sun.COM * Post the RST2INIT_QP command to the Hermon firmware
32799517SBill.Taylor@Sun.COM *
32809517SBill.Taylor@Sun.COM * We do a HERMON_NOSLEEP here because we are still holding the
32819517SBill.Taylor@Sun.COM * "qp_lock". If we got raised to interrupt level by priority
32829517SBill.Taylor@Sun.COM * inversion, we do not want to block in this routine waiting for
32839517SBill.Taylor@Sun.COM * success.
32849517SBill.Taylor@Sun.COM */
32859517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, RST2INIT_QP, qpc, qp->qp_qpnum,
32869517SBill.Taylor@Sun.COM 0, HERMON_CMD_NOSLEEP_SPIN);
32879517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
32889517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: RST2INIT_QP command failed: %08x\n",
32899517SBill.Taylor@Sun.COM state->hs_instance, status);
32909517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
32919517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
32929517SBill.Taylor@Sun.COM }
32939517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
32949517SBill.Taylor@Sun.COM }
32959517SBill.Taylor@Sun.COM
32969517SBill.Taylor@Sun.COM /*
32979517SBill.Taylor@Sun.COM * Now post the TOERR_QP command to the Hermon firmware
32989517SBill.Taylor@Sun.COM *
32999517SBill.Taylor@Sun.COM * We still do a HERMON_NOSLEEP here because we are still holding the
33009517SBill.Taylor@Sun.COM * "qp_lock". Note: If this fails (which it really never should),
33019517SBill.Taylor@Sun.COM * it indicates a serious problem in the HW or SW. We try to move
33029517SBill.Taylor@Sun.COM * the QP back to the "Reset" state if possible and print a warning
33039517SBill.Taylor@Sun.COM * message if not. In any case, we return an error here.
33049517SBill.Taylor@Sun.COM */
33059517SBill.Taylor@Sun.COM status = hermon_cmn_qp_cmd_post(state, TOERR_QP, NULL, qp->qp_qpnum,
33069517SBill.Taylor@Sun.COM 0, HERMON_CMD_NOSLEEP_SPIN);
33079517SBill.Taylor@Sun.COM if (status != HERMON_CMD_SUCCESS) {
33089517SBill.Taylor@Sun.COM cmn_err(CE_NOTE, "hermon%d: TOERR_QP command failed: %08x\n",
33099517SBill.Taylor@Sun.COM state->hs_instance, status);
33109517SBill.Taylor@Sun.COM if (status == HERMON_CMD_INVALID_STATUS) {
33119517SBill.Taylor@Sun.COM hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
33129517SBill.Taylor@Sun.COM }
33139517SBill.Taylor@Sun.COM if (hermon_qp_to_reset(state, qp) != DDI_SUCCESS) {
33149517SBill.Taylor@Sun.COM HERMON_WARNING(state, "failed to reset QP context");
33159517SBill.Taylor@Sun.COM }
33169517SBill.Taylor@Sun.COM return (ibc_get_ci_failure(0));
33179517SBill.Taylor@Sun.COM }
33189517SBill.Taylor@Sun.COM
33199517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
33209517SBill.Taylor@Sun.COM }
33219517SBill.Taylor@Sun.COM
33229517SBill.Taylor@Sun.COM
33239517SBill.Taylor@Sun.COM /*
33249517SBill.Taylor@Sun.COM * hermon_check_rdma_enable_flags()
33259517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
33269517SBill.Taylor@Sun.COM */
33279517SBill.Taylor@Sun.COM static uint_t
hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,ibt_qp_info_t * info_p,hermon_hw_qpc_t * qpc)33289517SBill.Taylor@Sun.COM hermon_check_rdma_enable_flags(ibt_cep_modify_flags_t flags,
33299517SBill.Taylor@Sun.COM ibt_qp_info_t *info_p, hermon_hw_qpc_t *qpc)
33309517SBill.Taylor@Sun.COM {
33319517SBill.Taylor@Sun.COM uint_t opmask = 0;
33329517SBill.Taylor@Sun.COM
33339517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_R) {
33349517SBill.Taylor@Sun.COM qpc->rre = (info_p->qp_flags & IBT_CEP_RDMA_RD) ? 1 : 0;
33359517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RRE;
33369517SBill.Taylor@Sun.COM }
33379517SBill.Taylor@Sun.COM
33389517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_RDMA_W) {
33399517SBill.Taylor@Sun.COM qpc->rwe = (info_p->qp_flags & IBT_CEP_RDMA_WR) ? 1 : 0;
33409517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RWE;
33419517SBill.Taylor@Sun.COM }
33429517SBill.Taylor@Sun.COM
33439517SBill.Taylor@Sun.COM if (flags & IBT_CEP_SET_ATOMIC) {
33449517SBill.Taylor@Sun.COM qpc->rae = (info_p->qp_flags & IBT_CEP_ATOMIC) ? 1 : 0;
33459517SBill.Taylor@Sun.COM opmask |= HERMON_CMD_OP_RAE;
33469517SBill.Taylor@Sun.COM }
33479517SBill.Taylor@Sun.COM
33489517SBill.Taylor@Sun.COM return (opmask);
33499517SBill.Taylor@Sun.COM }
33509517SBill.Taylor@Sun.COM
33519517SBill.Taylor@Sun.COM /*
33529517SBill.Taylor@Sun.COM * hermon_qp_validate_resp_rsrc()
33539517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
33549517SBill.Taylor@Sun.COM */
33559517SBill.Taylor@Sun.COM static int
hermon_qp_validate_resp_rsrc(hermon_state_t * state,ibt_qp_rc_attr_t * rc,uint_t * rra_max)33569517SBill.Taylor@Sun.COM hermon_qp_validate_resp_rsrc(hermon_state_t *state, ibt_qp_rc_attr_t *rc,
33579517SBill.Taylor@Sun.COM uint_t *rra_max)
33589517SBill.Taylor@Sun.COM {
33599517SBill.Taylor@Sun.COM uint_t rdma_ra_in;
33609517SBill.Taylor@Sun.COM
33619517SBill.Taylor@Sun.COM rdma_ra_in = rc->rc_rdma_ra_in;
33629517SBill.Taylor@Sun.COM
33639517SBill.Taylor@Sun.COM /*
33649517SBill.Taylor@Sun.COM * Check if number of responder resources is too large. Return an
33659517SBill.Taylor@Sun.COM * error if it is
33669517SBill.Taylor@Sun.COM */
33679517SBill.Taylor@Sun.COM if (rdma_ra_in > state->hs_cfg_profile->cp_hca_max_rdma_in_qp) {
33689517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
33699517SBill.Taylor@Sun.COM }
33709517SBill.Taylor@Sun.COM
33719517SBill.Taylor@Sun.COM /*
33729517SBill.Taylor@Sun.COM * If the number of responder resources is too small, round it up.
33739517SBill.Taylor@Sun.COM * Then find the next highest power-of-2
33749517SBill.Taylor@Sun.COM */
33759517SBill.Taylor@Sun.COM if (rdma_ra_in == 0) {
33769517SBill.Taylor@Sun.COM rdma_ra_in = 1;
33779517SBill.Taylor@Sun.COM }
33789517SBill.Taylor@Sun.COM if ((rdma_ra_in & (rdma_ra_in - 1)) == 0) {
33799517SBill.Taylor@Sun.COM *rra_max = highbit(rdma_ra_in) - 1;
33809517SBill.Taylor@Sun.COM } else {
33819517SBill.Taylor@Sun.COM *rra_max = highbit(rdma_ra_in);
33829517SBill.Taylor@Sun.COM }
33839517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
33849517SBill.Taylor@Sun.COM }
33859517SBill.Taylor@Sun.COM
33869517SBill.Taylor@Sun.COM
33879517SBill.Taylor@Sun.COM /*
33889517SBill.Taylor@Sun.COM * hermon_qp_validate_init_depth()
33899517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
33909517SBill.Taylor@Sun.COM */
33919517SBill.Taylor@Sun.COM static int
hermon_qp_validate_init_depth(hermon_state_t * state,ibt_qp_rc_attr_t * rc,uint_t * sra_max)33929517SBill.Taylor@Sun.COM hermon_qp_validate_init_depth(hermon_state_t *state, ibt_qp_rc_attr_t *rc,
33939517SBill.Taylor@Sun.COM uint_t *sra_max)
33949517SBill.Taylor@Sun.COM {
33959517SBill.Taylor@Sun.COM uint_t rdma_ra_out;
33969517SBill.Taylor@Sun.COM
33979517SBill.Taylor@Sun.COM rdma_ra_out = rc->rc_rdma_ra_out;
33989517SBill.Taylor@Sun.COM
33999517SBill.Taylor@Sun.COM /*
34009517SBill.Taylor@Sun.COM * Check if requested initiator depth is too large. Return an error
34019517SBill.Taylor@Sun.COM * if it is
34029517SBill.Taylor@Sun.COM */
34039517SBill.Taylor@Sun.COM if (rdma_ra_out > state->hs_cfg_profile->cp_hca_max_rdma_out_qp) {
34049517SBill.Taylor@Sun.COM return (IBT_INVALID_PARAM);
34059517SBill.Taylor@Sun.COM }
34069517SBill.Taylor@Sun.COM
34079517SBill.Taylor@Sun.COM /*
34089517SBill.Taylor@Sun.COM * If the requested initiator depth is too small, round it up.
34099517SBill.Taylor@Sun.COM * Then find the next highest power-of-2
34109517SBill.Taylor@Sun.COM */
34119517SBill.Taylor@Sun.COM if (rdma_ra_out == 0) {
34129517SBill.Taylor@Sun.COM rdma_ra_out = 1;
34139517SBill.Taylor@Sun.COM }
34149517SBill.Taylor@Sun.COM if ((rdma_ra_out & (rdma_ra_out - 1)) == 0) {
34159517SBill.Taylor@Sun.COM *sra_max = highbit(rdma_ra_out) - 1;
34169517SBill.Taylor@Sun.COM } else {
34179517SBill.Taylor@Sun.COM *sra_max = highbit(rdma_ra_out);
34189517SBill.Taylor@Sun.COM }
34199517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
34209517SBill.Taylor@Sun.COM }
34219517SBill.Taylor@Sun.COM
34229517SBill.Taylor@Sun.COM
34239517SBill.Taylor@Sun.COM /*
34249517SBill.Taylor@Sun.COM * hermon_qp_validate_mtu()
34259517SBill.Taylor@Sun.COM * Context: Can be called from interrupt or base context.
34269517SBill.Taylor@Sun.COM */
34279517SBill.Taylor@Sun.COM static int
hermon_qp_validate_mtu(hermon_state_t * state,uint_t mtu)34289517SBill.Taylor@Sun.COM hermon_qp_validate_mtu(hermon_state_t *state, uint_t mtu)
34299517SBill.Taylor@Sun.COM {
34309517SBill.Taylor@Sun.COM /*
34319517SBill.Taylor@Sun.COM * Check for invalid MTU values (i.e. zero or any value larger than
34329517SBill.Taylor@Sun.COM * the HCA's port maximum).
34339517SBill.Taylor@Sun.COM */
34349517SBill.Taylor@Sun.COM if ((mtu == 0) || (mtu > state->hs_cfg_profile->cp_max_mtu)) {
34359517SBill.Taylor@Sun.COM return (IBT_HCA_PORT_MTU_EXCEEDED);
34369517SBill.Taylor@Sun.COM }
34379517SBill.Taylor@Sun.COM return (DDI_SUCCESS);
34389517SBill.Taylor@Sun.COM }
3439