1*c39526b7SPramod Gunjikar /* 2*c39526b7SPramod Gunjikar * CDDL HEADER START 3*c39526b7SPramod Gunjikar * 4*c39526b7SPramod Gunjikar * The contents of this file are subject to the terms of the 5*c39526b7SPramod Gunjikar * Common Development and Distribution License (the "License"). 6*c39526b7SPramod Gunjikar * You may not use this file except in compliance with the License. 7*c39526b7SPramod Gunjikar * 8*c39526b7SPramod Gunjikar * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*c39526b7SPramod Gunjikar * or http://www.opensolaris.org/os/licensing. 10*c39526b7SPramod Gunjikar * See the License for the specific language governing permissions 11*c39526b7SPramod Gunjikar * and limitations under the License. 12*c39526b7SPramod Gunjikar * 13*c39526b7SPramod Gunjikar * When distributing Covered Code, include this CDDL HEADER in each 14*c39526b7SPramod Gunjikar * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*c39526b7SPramod Gunjikar * If applicable, add the following below this CDDL HEADER, with the 16*c39526b7SPramod Gunjikar * fields enclosed by brackets "[]" replaced with your own identifying 17*c39526b7SPramod Gunjikar * information: Portions Copyright [yyyy] [name of copyright owner] 18*c39526b7SPramod Gunjikar * 19*c39526b7SPramod Gunjikar * CDDL HEADER END 20*c39526b7SPramod Gunjikar */ 21*c39526b7SPramod Gunjikar 22*c39526b7SPramod Gunjikar /* 23*c39526b7SPramod Gunjikar * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24*c39526b7SPramod Gunjikar */ 25*c39526b7SPramod Gunjikar /* 26*c39526b7SPramod Gunjikar * sol_uverbs_qp.c 27*c39526b7SPramod Gunjikar * 28*c39526b7SPramod Gunjikar * OFED User Verbs kernel agent QP implementation. 29*c39526b7SPramod Gunjikar * 30*c39526b7SPramod Gunjikar */ 31*c39526b7SPramod Gunjikar #include <sys/vfs.h> 32*c39526b7SPramod Gunjikar #include <sys/vnode.h> 33*c39526b7SPramod Gunjikar #include <sys/errno.h> 34*c39526b7SPramod Gunjikar #include <sys/cred.h> 35*c39526b7SPramod Gunjikar #include <sys/uio.h> 36*c39526b7SPramod Gunjikar #include <sys/semaphore.h> 37*c39526b7SPramod Gunjikar #include <sys/ddi.h> 38*c39526b7SPramod Gunjikar #include <sys/sunddi.h> 39*c39526b7SPramod Gunjikar 40*c39526b7SPramod Gunjikar #include <sys/ib/ibtl/ibvti.h> 41*c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofa_solaris.h> 42*c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_ofs/sol_ofs_common.h> 43*c39526b7SPramod Gunjikar #include <sys/ib/clients/of/ofed_kernel.h> 44*c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs.h> 45*c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_qp.h> 46*c39526b7SPramod Gunjikar #include <sys/ib/clients/of/sol_uverbs/sol_uverbs_event.h> 47*c39526b7SPramod Gunjikar 48*c39526b7SPramod Gunjikar 49*c39526b7SPramod Gunjikar static uint32_t ibt_cep_flags2ibv(ibt_cep_flags_t); 50*c39526b7SPramod Gunjikar static void uverbs_cq_ctrl(uverbs_ucq_uobj_t *, sol_uverbs_cq_ctrl_t); 51*c39526b7SPramod Gunjikar 52*c39526b7SPramod Gunjikar extern char *sol_uverbs_dbg_str; 53*c39526b7SPramod Gunjikar 54*c39526b7SPramod Gunjikar /* 55*c39526b7SPramod Gunjikar * Multicast Element 56*c39526b7SPramod Gunjikar */ 57*c39526b7SPramod Gunjikar typedef struct uverbs_mcast_entry { 58*c39526b7SPramod Gunjikar llist_head_t list; 59*c39526b7SPramod Gunjikar ibt_mcg_info_t mcg; 60*c39526b7SPramod Gunjikar } uverbs_mcast_entry_t; 61*c39526b7SPramod Gunjikar 62*c39526b7SPramod Gunjikar /* 63*c39526b7SPramod Gunjikar * uverbs_qp_state_table 64*c39526b7SPramod Gunjikar * 65*c39526b7SPramod Gunjikar * Determine if the requested QP modify operation is valid. To maintain/ensure 66*c39526b7SPramod Gunjikar * consistency with the semantics expected by OFED user verbs operaton, this 67*c39526b7SPramod Gunjikar * table is used to verify a QP transition. A valid transition is one that is 68*c39526b7SPramod Gunjikar * a legal state transition and meets the required/optional attributes 69*c39526b7SPramod Gunjikar * associated with that transition for that QP type. 70*c39526b7SPramod Gunjikar * 71*c39526b7SPramod Gunjikar * Note: The OFED kern-abi (See ib_user_verbs.h) does not provide any 72*c39526b7SPramod Gunjikar * mechanism to support queue resize, consequently the IBTA spec defined 73*c39526b7SPramod Gunjikar * valid optional parameter to modify QP size (IB_QP_CAP) is not included 74*c39526b7SPramod Gunjikar * in the state table. 75*c39526b7SPramod Gunjikar */ 76*c39526b7SPramod Gunjikar typedef struct { 77*c39526b7SPramod Gunjikar int valid; 78*c39526b7SPramod Gunjikar enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETY + 1]; 79*c39526b7SPramod Gunjikar enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETY + 1]; 80*c39526b7SPramod Gunjikar } uverbs_qp_state_tbl_t; 81*c39526b7SPramod Gunjikar 82*c39526b7SPramod Gunjikar static uverbs_qp_state_tbl_t 83*c39526b7SPramod Gunjikar uverbs_qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 84*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { 85*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 86*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 }, 87*c39526b7SPramod Gunjikar [IB_QPS_INIT] = { .valid = 1, 88*c39526b7SPramod Gunjikar .req_param = { 89*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 90*c39526b7SPramod Gunjikar IB_QP_PORT | IB_QP_QKEY), 91*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_PKEY_INDEX | IB_QP_PORT | 92*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS), 93*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_PKEY_INDEX | IB_QP_PORT | 94*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS), 95*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 96*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 97*c39526b7SPramod Gunjikar } 98*c39526b7SPramod Gunjikar }, 99*c39526b7SPramod Gunjikar }, 100*c39526b7SPramod Gunjikar [IB_QPS_INIT] = { 101*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 102*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 }, 103*c39526b7SPramod Gunjikar [IB_QPS_INIT] = { .valid = 1, 104*c39526b7SPramod Gunjikar .opt_param = { 105*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_PORT | 106*c39526b7SPramod Gunjikar IB_QP_QKEY), 107*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_PKEY_INDEX | IB_QP_PORT | 108*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS), 109*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_PKEY_INDEX | IB_QP_PORT | 110*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS), 111*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 112*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 113*c39526b7SPramod Gunjikar } 114*c39526b7SPramod Gunjikar }, 115*c39526b7SPramod Gunjikar [IB_QPS_RTR] = { .valid = 1, 116*c39526b7SPramod Gunjikar .req_param = { 117*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_AV | IB_QP_PATH_MTU | 118*c39526b7SPramod Gunjikar IB_QP_DEST_QPN | IB_QP_RQ_PSN), 119*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_AV | IB_QP_PATH_MTU | 120*c39526b7SPramod Gunjikar IB_QP_DEST_QPN | IB_QP_RQ_PSN | 121*c39526b7SPramod Gunjikar IB_QP_MAX_DEST_RD_ATOMIC | 122*c39526b7SPramod Gunjikar IB_QP_MIN_RNR_TIMER), 123*c39526b7SPramod Gunjikar }, 124*c39526b7SPramod Gunjikar .opt_param = { 125*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 126*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_ALT_PATH | 127*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 128*c39526b7SPramod Gunjikar IB_QP_PKEY_INDEX), 129*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_ALT_PATH | 130*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 131*c39526b7SPramod Gunjikar IB_QP_PKEY_INDEX), 132*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 133*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 134*c39526b7SPramod Gunjikar } 135*c39526b7SPramod Gunjikar } 136*c39526b7SPramod Gunjikar }, 137*c39526b7SPramod Gunjikar [IB_QPS_RTR] = { 138*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 139*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 }, 140*c39526b7SPramod Gunjikar [IB_QPS_RTS] = { .valid = 1, 141*c39526b7SPramod Gunjikar .req_param = { 142*c39526b7SPramod Gunjikar [IB_QPT_UD] = IB_QP_SQ_PSN, 143*c39526b7SPramod Gunjikar [IB_QPT_UC] = IB_QP_SQ_PSN, 144*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_TIMEOUT | 145*c39526b7SPramod Gunjikar IB_QP_RETRY_CNT | 146*c39526b7SPramod Gunjikar IB_QP_RNR_RETRY | 147*c39526b7SPramod Gunjikar IB_QP_SQ_PSN | 148*c39526b7SPramod Gunjikar IB_QP_MAX_QP_RD_ATOMIC), 149*c39526b7SPramod Gunjikar [IB_QPT_SMI] = IB_QP_SQ_PSN, 150*c39526b7SPramod Gunjikar [IB_QPT_GSI] = IB_QP_SQ_PSN, 151*c39526b7SPramod Gunjikar }, 152*c39526b7SPramod Gunjikar .opt_param = { 153*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY), 154*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_CUR_STATE | 155*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 156*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 157*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 158*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_CUR_STATE | 159*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 160*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 161*c39526b7SPramod Gunjikar IB_QP_MIN_RNR_TIMER | 162*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 163*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 164*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 165*c39526b7SPramod Gunjikar } 166*c39526b7SPramod Gunjikar } 167*c39526b7SPramod Gunjikar }, 168*c39526b7SPramod Gunjikar [IB_QPS_RTS] = { 169*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 170*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 }, 171*c39526b7SPramod Gunjikar [IB_QPS_RTS] = { .valid = 1, 172*c39526b7SPramod Gunjikar .opt_param = { 173*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY), 174*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_CUR_STATE | 175*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 176*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 177*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 178*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_CUR_STATE | 179*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 180*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 181*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE | 182*c39526b7SPramod Gunjikar IB_QP_MIN_RNR_TIMER), 183*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 184*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 185*c39526b7SPramod Gunjikar } 186*c39526b7SPramod Gunjikar }, 187*c39526b7SPramod Gunjikar [IB_QPS_SQD] = { .valid = 1, 188*c39526b7SPramod Gunjikar .opt_param = { 189*c39526b7SPramod Gunjikar [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, 190*c39526b7SPramod Gunjikar [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 191*c39526b7SPramod Gunjikar [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, 192*c39526b7SPramod Gunjikar [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, 193*c39526b7SPramod Gunjikar [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY 194*c39526b7SPramod Gunjikar } 195*c39526b7SPramod Gunjikar }, 196*c39526b7SPramod Gunjikar }, 197*c39526b7SPramod Gunjikar [IB_QPS_SQD] = { 198*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 199*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 }, 200*c39526b7SPramod Gunjikar [IB_QPS_RTS] = { .valid = 1, 201*c39526b7SPramod Gunjikar .opt_param = { 202*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY), 203*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_CUR_STATE | 204*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 205*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 206*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 207*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_CUR_STATE | 208*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 209*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 210*c39526b7SPramod Gunjikar IB_QP_MIN_RNR_TIMER | 211*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 212*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 213*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 214*c39526b7SPramod Gunjikar } 215*c39526b7SPramod Gunjikar }, 216*c39526b7SPramod Gunjikar [IB_QPS_SQD] = { .valid = 1, 217*c39526b7SPramod Gunjikar .opt_param = { 218*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 219*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_AV | IB_QP_ALT_PATH | 220*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 221*c39526b7SPramod Gunjikar IB_QP_PKEY_INDEX | 222*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 223*c39526b7SPramod Gunjikar [IB_QPT_RC] = (IB_QP_PORT | IB_QP_AV | 224*c39526b7SPramod Gunjikar IB_QP_TIMEOUT | 225*c39526b7SPramod Gunjikar IB_QP_RETRY_CNT | 226*c39526b7SPramod Gunjikar IB_QP_RNR_RETRY | 227*c39526b7SPramod Gunjikar IB_QP_MAX_QP_RD_ATOMIC | 228*c39526b7SPramod Gunjikar IB_QP_MAX_DEST_RD_ATOMIC | 229*c39526b7SPramod Gunjikar IB_QP_ALT_PATH | 230*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS | 231*c39526b7SPramod Gunjikar IB_QP_PKEY_INDEX | 232*c39526b7SPramod Gunjikar IB_QP_MIN_RNR_TIMER | 233*c39526b7SPramod Gunjikar IB_QP_PATH_MIG_STATE), 234*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 235*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | IB_QP_QKEY), 236*c39526b7SPramod Gunjikar } 237*c39526b7SPramod Gunjikar } 238*c39526b7SPramod Gunjikar }, 239*c39526b7SPramod Gunjikar [IB_QPS_SQE] = { 240*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 241*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 }, 242*c39526b7SPramod Gunjikar [IB_QPS_RTS] = { .valid = 1, 243*c39526b7SPramod Gunjikar .opt_param = { 244*c39526b7SPramod Gunjikar [IB_QPT_UD] = (IB_QP_CUR_STATE | IB_QP_QKEY), 245*c39526b7SPramod Gunjikar [IB_QPT_UC] = (IB_QP_CUR_STATE | 246*c39526b7SPramod Gunjikar IB_QP_ACCESS_FLAGS), 247*c39526b7SPramod Gunjikar [IB_QPT_SMI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 248*c39526b7SPramod Gunjikar [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), 249*c39526b7SPramod Gunjikar } 250*c39526b7SPramod Gunjikar } 251*c39526b7SPramod Gunjikar }, 252*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { 253*c39526b7SPramod Gunjikar [IB_QPS_RESET] = { .valid = 1 }, 254*c39526b7SPramod Gunjikar [IB_QPS_ERR] = { .valid = 1 } 255*c39526b7SPramod Gunjikar } 256*c39526b7SPramod Gunjikar }; 257*c39526b7SPramod Gunjikar 258*c39526b7SPramod Gunjikar /* 259*c39526b7SPramod Gunjikar * Function: 260*c39526b7SPramod Gunjikar * uverbs_modify_qp_is_ok 261*c39526b7SPramod Gunjikar * Input: 262*c39526b7SPramod Gunjikar * cur_state - The current OFED QP state. 263*c39526b7SPramod Gunjikar * next_state - The OFED QP state to transition to. 264*c39526b7SPramod Gunjikar * type - The OFED QP transport type. 265*c39526b7SPramod Gunjikar * mask - The OFED QP attribute mask for the QP transition. 266*c39526b7SPramod Gunjikar * Output: 267*c39526b7SPramod Gunjikar * None 268*c39526b7SPramod Gunjikar * Returns: 269*c39526b7SPramod Gunjikar * Returns 1 if the operation is valid; otherwise 0 for invalid 270*c39526b7SPramod Gunjikar * operations. 271*c39526b7SPramod Gunjikar * Description: 272*c39526b7SPramod Gunjikar * Indicate whether the desired QP modify operation is a valid operation. 273*c39526b7SPramod Gunjikar * To be valid, the state transition must be legal and the required and 274*c39526b7SPramod Gunjikar * optional parameters must be valid for the transition and QP type. 275*c39526b7SPramod Gunjikar */ 276*c39526b7SPramod Gunjikar static int 277*c39526b7SPramod Gunjikar uverbs_modify_qp_is_ok(enum ib_qp_state cur_state, 278*c39526b7SPramod Gunjikar enum ib_qp_state next_state, enum ib_qp_type type, 279*c39526b7SPramod Gunjikar enum ib_qp_attr_mask *maskp) 280*c39526b7SPramod Gunjikar { 281*c39526b7SPramod Gunjikar enum ib_qp_attr_mask req_param, opt_param; 282*c39526b7SPramod Gunjikar uverbs_qp_state_tbl_t *state_tblp; 283*c39526b7SPramod Gunjikar enum ib_qp_attr_mask mask = *maskp; 284*c39526b7SPramod Gunjikar 285*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp_is_ok" 286*c39526b7SPramod Gunjikar "(%x, %x, %x, %x)", cur_state, next_state, type, mask); 287*c39526b7SPramod Gunjikar 288*c39526b7SPramod Gunjikar if (cur_state < 0 || cur_state > IB_QPS_ERR || 289*c39526b7SPramod Gunjikar next_state < 0 || next_state > IB_QPS_ERR) { 290*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 291*c39526b7SPramod Gunjikar "modify_qp_is_ok: bad state, cur %d, next %d", 292*c39526b7SPramod Gunjikar cur_state, next_state); 293*c39526b7SPramod Gunjikar return (0); 294*c39526b7SPramod Gunjikar } 295*c39526b7SPramod Gunjikar 296*c39526b7SPramod Gunjikar if (mask & IB_QP_CUR_STATE && 297*c39526b7SPramod Gunjikar cur_state != IB_QPS_RTR && cur_state != IB_QPS_RTS && 298*c39526b7SPramod Gunjikar cur_state != IB_QPS_SQD && cur_state != IB_QPS_SQE) { 299*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 300*c39526b7SPramod Gunjikar "modify_qp_is_ok: cur_state %d is a bad state", 301*c39526b7SPramod Gunjikar cur_state); 302*c39526b7SPramod Gunjikar return (0); 303*c39526b7SPramod Gunjikar } 304*c39526b7SPramod Gunjikar 305*c39526b7SPramod Gunjikar state_tblp = &uverbs_qp_state_table[cur_state][next_state]; 306*c39526b7SPramod Gunjikar if (!state_tblp->valid) { 307*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp: " 308*c39526b7SPramod Gunjikar "bad transition, cur = %d, next = %d", cur_state, 309*c39526b7SPramod Gunjikar next_state); 310*c39526b7SPramod Gunjikar return (0); 311*c39526b7SPramod Gunjikar } 312*c39526b7SPramod Gunjikar 313*c39526b7SPramod Gunjikar req_param = state_tblp->req_param[type]; 314*c39526b7SPramod Gunjikar opt_param = state_tblp->opt_param[type]; 315*c39526b7SPramod Gunjikar 316*c39526b7SPramod Gunjikar if ((mask & req_param) != req_param) { 317*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 318*c39526b7SPramod Gunjikar "modify_qp_is_ok: cur %d, next %d, " 319*c39526b7SPramod Gunjikar "missing required parms, spec = 0x%08X, " 320*c39526b7SPramod Gunjikar "req = 0%08X", cur_state, next_state, 321*c39526b7SPramod Gunjikar mask, req_param); 322*c39526b7SPramod Gunjikar return (0); 323*c39526b7SPramod Gunjikar } 324*c39526b7SPramod Gunjikar 325*c39526b7SPramod Gunjikar if (mask & ~(req_param | opt_param | IB_QP_STATE)) { 326*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, 327*c39526b7SPramod Gunjikar "modify_qp_is_ok: cur %d, next %d, " 328*c39526b7SPramod Gunjikar "illegal optional parms, parms = 0x%08X, " 329*c39526b7SPramod Gunjikar "illegal = 0x%08X", cur_state, next_state, 330*c39526b7SPramod Gunjikar mask, mask & ~(req_param | opt_param | IB_QP_STATE)); 331*c39526b7SPramod Gunjikar *maskp = mask & (req_param | opt_param | IB_QP_STATE); 332*c39526b7SPramod Gunjikar return (0); 333*c39526b7SPramod Gunjikar } 334*c39526b7SPramod Gunjikar 335*c39526b7SPramod Gunjikar return (1); 336*c39526b7SPramod Gunjikar } 337*c39526b7SPramod Gunjikar 338*c39526b7SPramod Gunjikar 339*c39526b7SPramod Gunjikar /* 340*c39526b7SPramod Gunjikar * Function: 341*c39526b7SPramod Gunjikar * sol_uverbs_create_qp 342*c39526b7SPramod Gunjikar * Input: 343*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 344*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing the create command. 345*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 346*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 347*c39526b7SPramod Gunjikar * Output: 348*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 349*c39526b7SPramod Gunjikar * Returns: 350*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 351*c39526b7SPramod Gunjikar * Description: 352*c39526b7SPramod Gunjikar * User verbs entry point to create a new device QP. 353*c39526b7SPramod Gunjikar */ 354*c39526b7SPramod Gunjikar /* ARGSUSED */ 355*c39526b7SPramod Gunjikar int 356*c39526b7SPramod Gunjikar sol_uverbs_create_qp(uverbs_uctxt_uobj_t *uctxt, char *buf, 357*c39526b7SPramod Gunjikar int in_len, int out_len) 358*c39526b7SPramod Gunjikar { 359*c39526b7SPramod Gunjikar struct ib_uverbs_create_qp cmd; 360*c39526b7SPramod Gunjikar struct ib_uverbs_create_qp_resp resp; 361*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 362*c39526b7SPramod Gunjikar ibt_qp_type_t qp_type; 363*c39526b7SPramod Gunjikar ibt_qp_alloc_attr_t qp_attr; 364*c39526b7SPramod Gunjikar ibt_chan_sizes_t qp_sizes; 365*c39526b7SPramod Gunjikar int rc = 0; 366*c39526b7SPramod Gunjikar uverbs_upd_uobj_t *upd; 367*c39526b7SPramod Gunjikar uverbs_ucq_uobj_t *uscq; 368*c39526b7SPramod Gunjikar uverbs_ucq_uobj_t *urcq; 369*c39526b7SPramod Gunjikar uverbs_usrq_uobj_t *usrq = NULL; 370*c39526b7SPramod Gunjikar 371*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 372*c39526b7SPramod Gunjikar (void) memset(&resp, 0, sizeof (resp)); 373*c39526b7SPramod Gunjikar (void) memset(&qp_attr, 0, sizeof (qp_attr)); 374*c39526b7SPramod Gunjikar (void) memset(&qp_sizes, 0, sizeof (qp_sizes)); 375*c39526b7SPramod Gunjikar 376*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_qp(): entry"); 377*c39526b7SPramod Gunjikar 378*c39526b7SPramod Gunjikar switch (cmd.qp_type) { 379*c39526b7SPramod Gunjikar case IB_QPT_UC: 380*c39526b7SPramod Gunjikar qp_type = IBT_UC_RQP; 381*c39526b7SPramod Gunjikar break; 382*c39526b7SPramod Gunjikar case IB_QPT_UD: 383*c39526b7SPramod Gunjikar qp_type = IBT_UD_RQP; 384*c39526b7SPramod Gunjikar break; 385*c39526b7SPramod Gunjikar case IB_QPT_RC: 386*c39526b7SPramod Gunjikar qp_type = IBT_RC_RQP; 387*c39526b7SPramod Gunjikar break; 388*c39526b7SPramod Gunjikar default: 389*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 390*c39526b7SPramod Gunjikar "create_qp(): Invalid qp type"); 391*c39526b7SPramod Gunjikar rc = EINVAL; 392*c39526b7SPramod Gunjikar goto err_out; 393*c39526b7SPramod Gunjikar } 394*c39526b7SPramod Gunjikar 395*c39526b7SPramod Gunjikar qp_attr.qp_alloc_flags = IBT_QP_USER_MAP; 396*c39526b7SPramod Gunjikar 397*c39526b7SPramod Gunjikar if (cmd.is_srq) { 398*c39526b7SPramod Gunjikar qp_attr.qp_alloc_flags |= IBT_QP_USES_SRQ; 399*c39526b7SPramod Gunjikar } 400*c39526b7SPramod Gunjikar 401*c39526b7SPramod Gunjikar qp_attr.qp_flags = IBT_WR_SIGNALED; 402*c39526b7SPramod Gunjikar if (cmd.sq_sig_all) { 403*c39526b7SPramod Gunjikar qp_attr.qp_flags = IBT_ALL_SIGNALED; 404*c39526b7SPramod Gunjikar } 405*c39526b7SPramod Gunjikar 406*c39526b7SPramod Gunjikar uqp = kmem_zalloc(sizeof (*uqp), KM_NOSLEEP); 407*c39526b7SPramod Gunjikar if (uqp == NULL) { 408*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 409*c39526b7SPramod Gunjikar "create_qp(): User object allocation failed"); 410*c39526b7SPramod Gunjikar rc = ENOMEM; 411*c39526b7SPramod Gunjikar goto err_out; 412*c39526b7SPramod Gunjikar } 413*c39526b7SPramod Gunjikar sol_ofs_uobj_init(&uqp->uobj, cmd.user_handle, 414*c39526b7SPramod Gunjikar SOL_UVERBS_UQP_UOBJ_TYPE); 415*c39526b7SPramod Gunjikar rw_enter(&uqp->uobj.uo_lock, RW_WRITER); 416*c39526b7SPramod Gunjikar llist_head_init(&uqp->mcast_list, NULL); 417*c39526b7SPramod Gunjikar llist_head_init(&uqp->async_list, NULL); 418*c39526b7SPramod Gunjikar 419*c39526b7SPramod Gunjikar uqp->async_events_reported = 0; 420*c39526b7SPramod Gunjikar uqp->uctxt = uctxt; 421*c39526b7SPramod Gunjikar uqp->disable_qp_mod = FALSE; 422*c39526b7SPramod Gunjikar 423*c39526b7SPramod Gunjikar if (cmd.is_srq) { 424*c39526b7SPramod Gunjikar usrq = uverbs_uobj_get_usrq_read(cmd.srq_handle); 425*c39526b7SPramod Gunjikar uqp->uqp_rcq_srq_valid |= SOL_UVERBS_UQP_SRQ_VALID; 426*c39526b7SPramod Gunjikar uqp->uqp_srq_hdl = cmd.srq_handle; 427*c39526b7SPramod Gunjikar } 428*c39526b7SPramod Gunjikar upd = uverbs_uobj_get_upd_read(cmd.pd_handle); 429*c39526b7SPramod Gunjikar uqp->uqp_pd_hdl = cmd.pd_handle; 430*c39526b7SPramod Gunjikar uscq = uverbs_uobj_get_ucq_read(cmd.send_cq_handle); 431*c39526b7SPramod Gunjikar uqp->uqp_scq_hdl = cmd.send_cq_handle; 432*c39526b7SPramod Gunjikar uqp->uqp_rcq_hdl = cmd.recv_cq_handle; 433*c39526b7SPramod Gunjikar if (cmd.recv_cq_handle != cmd.send_cq_handle) { 434*c39526b7SPramod Gunjikar urcq = uverbs_uobj_get_ucq_read(cmd.recv_cq_handle); 435*c39526b7SPramod Gunjikar uqp->uqp_rcq_srq_valid |= SOL_UVERBS_UQP_RCQ_VALID; 436*c39526b7SPramod Gunjikar } else 437*c39526b7SPramod Gunjikar urcq = uscq; 438*c39526b7SPramod Gunjikar 439*c39526b7SPramod Gunjikar if (!upd || !uscq || !urcq || (cmd.is_srq && !usrq)) { 440*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 441*c39526b7SPramod Gunjikar "create_qp(): Invalid resource handle"); 442*c39526b7SPramod Gunjikar rc = EINVAL; 443*c39526b7SPramod Gunjikar goto err_put; 444*c39526b7SPramod Gunjikar } 445*c39526b7SPramod Gunjikar uqp->uqp_rcq = urcq; 446*c39526b7SPramod Gunjikar uqp->uqp_scq = uscq; 447*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 448*c39526b7SPramod Gunjikar "uqp %p, rcq %p. scq %p", uqp, urcq, uscq); 449*c39526b7SPramod Gunjikar 450*c39526b7SPramod Gunjikar qp_attr.qp_pd_hdl = upd->pd; 451*c39526b7SPramod Gunjikar if (usrq) { 452*c39526b7SPramod Gunjikar qp_attr.qp_srq_hdl = usrq->srq; 453*c39526b7SPramod Gunjikar } 454*c39526b7SPramod Gunjikar qp_attr.qp_scq_hdl = uscq->cq; 455*c39526b7SPramod Gunjikar qp_attr.qp_rcq_hdl = urcq->cq; 456*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_sq = cmd.max_send_wr; 457*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_rq = cmd.max_recv_wr; 458*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_sq_sgl = cmd.max_send_sge; 459*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_rq_sgl = cmd.max_recv_sge; 460*c39526b7SPramod Gunjikar 461*c39526b7SPramod Gunjikar uqp->max_inline_data = cmd.max_inline_data; 462*c39526b7SPramod Gunjikar uqp->ofa_qp_type = cmd.qp_type; 463*c39526b7SPramod Gunjikar 464*c39526b7SPramod Gunjikar /* 465*c39526b7SPramod Gunjikar * NOTE: We allocate the QP and leave it in the RESET state to follow 466*c39526b7SPramod Gunjikar * usage semantics consistent with OFA verbs. 467*c39526b7SPramod Gunjikar */ 468*c39526b7SPramod Gunjikar rc = ibt_alloc_qp(uctxt->hca->hdl, qp_type, &qp_attr, &qp_sizes, 469*c39526b7SPramod Gunjikar &uqp->qp_num, &uqp->qp); 470*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 471*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 472*c39526b7SPramod Gunjikar "create_qp(): Error in ibt_alloc_qp() (rc=%d)", rc); 473*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 474*c39526b7SPramod Gunjikar uqp->uobj.uo_uobj_sz = sizeof (uverbs_uqp_uobj_t); 475*c39526b7SPramod Gunjikar goto err_put; 476*c39526b7SPramod Gunjikar } 477*c39526b7SPramod Gunjikar 478*c39526b7SPramod Gunjikar ibt_set_qp_private(uqp->qp, uqp); 479*c39526b7SPramod Gunjikar 480*c39526b7SPramod Gunjikar /* Bump up the active_qp_cnt for CQ, SRQ & PD resources it is using */ 481*c39526b7SPramod Gunjikar upd->active_qp_cnt++; 482*c39526b7SPramod Gunjikar uscq->active_qp_cnt++; 483*c39526b7SPramod Gunjikar if (cmd.recv_cq_handle != cmd.send_cq_handle) 484*c39526b7SPramod Gunjikar urcq->active_qp_cnt++; 485*c39526b7SPramod Gunjikar if (usrq) 486*c39526b7SPramod Gunjikar usrq->active_qp_cnt++; 487*c39526b7SPramod Gunjikar 488*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 489*c39526b7SPramod Gunjikar "\treq cs_sq=%d, actual cs_sq=%d", 490*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_sq, qp_sizes.cs_sq); 491*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 492*c39526b7SPramod Gunjikar "\treq cs_sq_sgl=%d, actual cs_sg_sgl=%d", 493*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_sq_sgl, qp_sizes.cs_sq_sgl); 494*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 495*c39526b7SPramod Gunjikar "\treq cs_rq=%d, actual cs_rq=%d", 496*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_rq, qp_sizes.cs_rq); 497*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 498*c39526b7SPramod Gunjikar "\treq cs_rq_sgl=%d, actual cs_rq_sgl=%d", 499*c39526b7SPramod Gunjikar qp_attr.qp_sizes.cs_rq_sgl, qp_sizes.cs_rq_sgl); 500*c39526b7SPramod Gunjikar 501*c39526b7SPramod Gunjikar /* 502*c39526b7SPramod Gunjikar * Query underlying hardware for data used in mapping QP work 503*c39526b7SPramod Gunjikar * queues back to user space, we will return this information 504*c39526b7SPramod Gunjikar * in the user verbs command response. 505*c39526b7SPramod Gunjikar */ 506*c39526b7SPramod Gunjikar rc = ibt_ci_data_out(uctxt->hca->hdl, IBT_CI_NO_FLAGS, IBT_HDL_CHANNEL, 507*c39526b7SPramod Gunjikar (void *)uqp->qp, &resp.drv_out, sizeof (resp.drv_out)); 508*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 509*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 510*c39526b7SPramod Gunjikar "create_qp(): Error in ibt_ci_data_out() (rc=%d)", rc); 511*c39526b7SPramod Gunjikar rc = EFAULT; 512*c39526b7SPramod Gunjikar uqp->uobj.uo_uobj_sz = sizeof (uverbs_uqp_uobj_t); 513*c39526b7SPramod Gunjikar goto err_qp_destroy; 514*c39526b7SPramod Gunjikar } 515*c39526b7SPramod Gunjikar 516*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 517*c39526b7SPramod Gunjikar "create_qp QP: ibt_ci_data_out:0x%016llx 0x%016llx", 518*c39526b7SPramod Gunjikar resp.drv_out[0], resp.drv_out[1]); 519*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 520*c39526b7SPramod Gunjikar " :0x%016llx 0x%016llx", 521*c39526b7SPramod Gunjikar resp.drv_out[2], resp.drv_out[3]); 522*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 523*c39526b7SPramod Gunjikar " :0x%016llx 0x%016llx", 524*c39526b7SPramod Gunjikar resp.drv_out[4], resp.drv_out[5]); 525*c39526b7SPramod Gunjikar 526*c39526b7SPramod Gunjikar if (sol_ofs_uobj_add(&uverbs_uqp_uo_tbl, &uqp->uobj) != 0) { 527*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 528*c39526b7SPramod Gunjikar "create_qp(): User object add failed (rc=%d)", rc); 529*c39526b7SPramod Gunjikar rc = ENOMEM; 530*c39526b7SPramod Gunjikar goto err_qp_destroy; 531*c39526b7SPramod Gunjikar } 532*c39526b7SPramod Gunjikar 533*c39526b7SPramod Gunjikar resp.qp_handle = uqp->uobj.uo_id; 534*c39526b7SPramod Gunjikar resp.qpn = uqp->qp_num; 535*c39526b7SPramod Gunjikar resp.max_send_wr = qp_sizes.cs_sq; 536*c39526b7SPramod Gunjikar resp.max_send_sge = qp_sizes.cs_sq_sgl; 537*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_qp() : " 538*c39526b7SPramod Gunjikar "resp.qp_handle=0x%08x, resp.qpn=0x%08x", resp.qp_handle, resp.qpn); 539*c39526b7SPramod Gunjikar 540*c39526b7SPramod Gunjikar /* 541*c39526b7SPramod Gunjikar * In Solaris the receive work requests and sg entries are cleared 542*c39526b7SPramod Gunjikar * when a SRQ is used since these values are ignored. To maintain 543*c39526b7SPramod Gunjikar * consistency with OFED we return the requested values as is done 544*c39526b7SPramod Gunjikar * in OFED, but these values will be ignored and SRQ valuves are 545*c39526b7SPramod Gunjikar * used. MTHCA lib will extract the zeroed out value from the 546*c39526b7SPramod Gunjikar * driver out data. 547*c39526b7SPramod Gunjikar */ 548*c39526b7SPramod Gunjikar if (usrq) { 549*c39526b7SPramod Gunjikar resp.max_recv_wr = cmd.max_recv_wr; 550*c39526b7SPramod Gunjikar resp.max_recv_sge = cmd.max_recv_sge; 551*c39526b7SPramod Gunjikar } else { 552*c39526b7SPramod Gunjikar resp.max_recv_wr = qp_sizes.cs_rq; 553*c39526b7SPramod Gunjikar resp.max_recv_sge = qp_sizes.cs_rq_sgl; 554*c39526b7SPramod Gunjikar } 555*c39526b7SPramod Gunjikar resp.max_inline_data = cmd.max_inline_data; 556*c39526b7SPramod Gunjikar 557*c39526b7SPramod Gunjikar #ifdef _LP64 558*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp)); 559*c39526b7SPramod Gunjikar #else 560*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp)); 561*c39526b7SPramod Gunjikar #endif 562*c39526b7SPramod Gunjikar if (rc != 0) { 563*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 564*c39526b7SPramod Gunjikar "create_qp(): Error writing resp data (rc=%d)", rc); 565*c39526b7SPramod Gunjikar rc = EFAULT; 566*c39526b7SPramod Gunjikar goto err_uo_delete; 567*c39526b7SPramod Gunjikar } 568*c39526b7SPramod Gunjikar 569*c39526b7SPramod Gunjikar mutex_enter(&uctxt->lock); 570*c39526b7SPramod Gunjikar uqp->list_entry = add_genlist(&uctxt->qp_list, (uintptr_t)uqp, 571*c39526b7SPramod Gunjikar (void*)uctxt); 572*c39526b7SPramod Gunjikar mutex_exit(&uctxt->lock); 573*c39526b7SPramod Gunjikar 574*c39526b7SPramod Gunjikar if (!uqp->list_entry) { 575*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 576*c39526b7SPramod Gunjikar "create_qp(): Error adding uqp to qp_list\n"); 577*c39526b7SPramod Gunjikar rc = ENOMEM; 578*c39526b7SPramod Gunjikar goto err_uo_delete; 579*c39526b7SPramod Gunjikar } 580*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 581*c39526b7SPramod Gunjikar "create_qp() - uqp %p", uqp); 582*c39526b7SPramod Gunjikar 583*c39526b7SPramod Gunjikar uqp->uobj.uo_live = 1; 584*c39526b7SPramod Gunjikar 585*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&upd->uobj); 586*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uscq->uobj); 587*c39526b7SPramod Gunjikar 588*c39526b7SPramod Gunjikar if (urcq != uscq) { 589*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&urcq->uobj); 590*c39526b7SPramod Gunjikar } 591*c39526b7SPramod Gunjikar if (usrq) { 592*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 593*c39526b7SPramod Gunjikar } 594*c39526b7SPramod Gunjikar rw_exit(&uqp->uobj.uo_lock); 595*c39526b7SPramod Gunjikar 596*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 597*c39526b7SPramod Gunjikar 598*c39526b7SPramod Gunjikar err_uo_delete: 599*c39526b7SPramod Gunjikar /* 600*c39526b7SPramod Gunjikar * Need to set uo_live, so sol_ofs_uobj_remove() will 601*c39526b7SPramod Gunjikar * remove the object from the object table. 602*c39526b7SPramod Gunjikar */ 603*c39526b7SPramod Gunjikar uqp->uobj.uo_live = 1; 604*c39526b7SPramod Gunjikar (void) sol_ofs_uobj_remove(&uverbs_uqp_uo_tbl, &uqp->uobj); 605*c39526b7SPramod Gunjikar 606*c39526b7SPramod Gunjikar err_qp_destroy: 607*c39526b7SPramod Gunjikar (void) ibt_free_qp(uqp->qp); 608*c39526b7SPramod Gunjikar 609*c39526b7SPramod Gunjikar upd->active_qp_cnt--; 610*c39526b7SPramod Gunjikar uscq->active_qp_cnt--; 611*c39526b7SPramod Gunjikar if (cmd.recv_cq_handle != cmd.send_cq_handle) 612*c39526b7SPramod Gunjikar urcq->active_qp_cnt--; 613*c39526b7SPramod Gunjikar if (usrq) 614*c39526b7SPramod Gunjikar usrq->active_qp_cnt--; 615*c39526b7SPramod Gunjikar 616*c39526b7SPramod Gunjikar err_put: 617*c39526b7SPramod Gunjikar if (upd) { 618*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&upd->uobj); 619*c39526b7SPramod Gunjikar } 620*c39526b7SPramod Gunjikar if (uscq) { 621*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uscq->uobj); 622*c39526b7SPramod Gunjikar } 623*c39526b7SPramod Gunjikar if (urcq && urcq != uscq) { 624*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&urcq->uobj); 625*c39526b7SPramod Gunjikar } 626*c39526b7SPramod Gunjikar if (usrq) { 627*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 628*c39526b7SPramod Gunjikar } 629*c39526b7SPramod Gunjikar 630*c39526b7SPramod Gunjikar rw_exit(&uqp->uobj.uo_lock); 631*c39526b7SPramod Gunjikar sol_ofs_uobj_deref(&uqp->uobj, sol_ofs_uobj_free); 632*c39526b7SPramod Gunjikar 633*c39526b7SPramod Gunjikar err_out: 634*c39526b7SPramod Gunjikar return (rc); 635*c39526b7SPramod Gunjikar } 636*c39526b7SPramod Gunjikar 637*c39526b7SPramod Gunjikar /* 638*c39526b7SPramod Gunjikar * Free the resources used by uqp. Return 0, if the free of all 639*c39526b7SPramod Gunjikar * resources where succesful, return non-zero, if not. 640*c39526b7SPramod Gunjikar * 641*c39526b7SPramod Gunjikar * If other uQPs are holding the resources (PD, CQ, SRQ), do not 642*c39526b7SPramod Gunjikar * free the resource, but return 0, so the free of uqp can be 643*c39526b7SPramod Gunjikar * done. Return failure only if active_cnt cannot be decremented 644*c39526b7SPramod Gunjikar * resource_free() fails. 645*c39526b7SPramod Gunjikar */ 646*c39526b7SPramod Gunjikar static int 647*c39526b7SPramod Gunjikar uverbs_uqp_rsrc_free(uverbs_uqp_uobj_t *uqp, uverbs_uctxt_uobj_t *uctxt) 648*c39526b7SPramod Gunjikar { 649*c39526b7SPramod Gunjikar uverbs_ucq_uobj_t *uscq = NULL, *urcq = NULL; 650*c39526b7SPramod Gunjikar uverbs_usrq_uobj_t *usrq = NULL; 651*c39526b7SPramod Gunjikar uverbs_upd_uobj_t *upd = NULL; 652*c39526b7SPramod Gunjikar int ret, rc = -1; 653*c39526b7SPramod Gunjikar 654*c39526b7SPramod Gunjikar /* Get uobj for PD, CQ & SRQ resources used. */ 655*c39526b7SPramod Gunjikar upd = uverbs_uobj_get_upd_write(uqp->uqp_pd_hdl); 656*c39526b7SPramod Gunjikar if (upd == NULL) { 657*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 658*c39526b7SPramod Gunjikar "uqp_rsrc_free: get_upd %d failed", uqp->uqp_pd_hdl); 659*c39526b7SPramod Gunjikar goto err_free; 660*c39526b7SPramod Gunjikar } 661*c39526b7SPramod Gunjikar uscq = uverbs_uobj_get_ucq_write(uqp->uqp_scq_hdl); 662*c39526b7SPramod Gunjikar if (uscq == NULL) { 663*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 664*c39526b7SPramod Gunjikar "uqp_rsrc_free: get_ucq %x failed", uqp->uqp_scq_hdl); 665*c39526b7SPramod Gunjikar goto err_free; 666*c39526b7SPramod Gunjikar } 667*c39526b7SPramod Gunjikar if (uqp->uqp_rcq_srq_valid & SOL_UVERBS_UQP_RCQ_VALID) { 668*c39526b7SPramod Gunjikar urcq = uverbs_uobj_get_ucq_write(uqp->uqp_rcq_hdl); 669*c39526b7SPramod Gunjikar if (urcq == NULL) { 670*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 671*c39526b7SPramod Gunjikar "uqp_rsrc_free: get_ucq %x failed", 672*c39526b7SPramod Gunjikar uqp->uqp_rcq_hdl); 673*c39526b7SPramod Gunjikar goto err_free; 674*c39526b7SPramod Gunjikar } 675*c39526b7SPramod Gunjikar } 676*c39526b7SPramod Gunjikar if (uqp->uqp_rcq_srq_valid & SOL_UVERBS_UQP_SRQ_VALID) { 677*c39526b7SPramod Gunjikar usrq = uverbs_uobj_get_usrq_write(uqp->uqp_srq_hdl); 678*c39526b7SPramod Gunjikar if (usrq == NULL) { 679*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 680*c39526b7SPramod Gunjikar "uqp_rsrc_free: get_srq %x failed", 681*c39526b7SPramod Gunjikar uqp->uqp_srq_hdl); 682*c39526b7SPramod Gunjikar goto err_free; 683*c39526b7SPramod Gunjikar } 684*c39526b7SPramod Gunjikar } 685*c39526b7SPramod Gunjikar rc = 0; 686*c39526b7SPramod Gunjikar 687*c39526b7SPramod Gunjikar /* Decrement active_qp_cnt for resources used */ 688*c39526b7SPramod Gunjikar upd->active_qp_cnt--; 689*c39526b7SPramod Gunjikar uscq->active_qp_cnt--; 690*c39526b7SPramod Gunjikar if (urcq) 691*c39526b7SPramod Gunjikar urcq->active_qp_cnt--; 692*c39526b7SPramod Gunjikar if (usrq) 693*c39526b7SPramod Gunjikar usrq->active_qp_cnt--; 694*c39526b7SPramod Gunjikar 695*c39526b7SPramod Gunjikar /* 696*c39526b7SPramod Gunjikar * Free the resources, if active_qp_cnt is 0 and userland free 697*c39526b7SPramod Gunjikar * already been pending for the resource. 698*c39526b7SPramod Gunjikar */ 699*c39526b7SPramod Gunjikar if (upd->active_qp_cnt == 0 && upd->free_pending) { 700*c39526b7SPramod Gunjikar ret = uverbs_upd_free(upd, uctxt); 701*c39526b7SPramod Gunjikar if (ret && rc == 0) { 702*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 703*c39526b7SPramod Gunjikar "uqp_rsrc_free: upd_free failed"); 704*c39526b7SPramod Gunjikar rc = ret; 705*c39526b7SPramod Gunjikar } 706*c39526b7SPramod Gunjikar } else if (upd) 707*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&upd->uobj); 708*c39526b7SPramod Gunjikar if (uscq && uscq->active_qp_cnt == 0 && uscq->free_pending) { 709*c39526b7SPramod Gunjikar ret = uverbs_ucq_free(uscq, uctxt); 710*c39526b7SPramod Gunjikar if (ret && rc == 0) { 711*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 712*c39526b7SPramod Gunjikar "uqp_rsrc_free: ucq_free failed"); 713*c39526b7SPramod Gunjikar rc = ret; 714*c39526b7SPramod Gunjikar } 715*c39526b7SPramod Gunjikar } else if (uscq) 716*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uscq->uobj); 717*c39526b7SPramod Gunjikar if (urcq && urcq->active_qp_cnt == 0 && urcq->free_pending) { 718*c39526b7SPramod Gunjikar rc = uverbs_ucq_free(urcq, uctxt); 719*c39526b7SPramod Gunjikar if (ret && rc == 0) { 720*c39526b7SPramod Gunjikar if (rc) 721*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 722*c39526b7SPramod Gunjikar "uqp_rsrc_free: ucq_free failed"); 723*c39526b7SPramod Gunjikar rc = ret; 724*c39526b7SPramod Gunjikar } 725*c39526b7SPramod Gunjikar } else if (urcq) 726*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&urcq->uobj); 727*c39526b7SPramod Gunjikar if (usrq && usrq->active_qp_cnt == 0 && usrq->free_pending) { 728*c39526b7SPramod Gunjikar rc = uverbs_usrq_free(usrq, uctxt); 729*c39526b7SPramod Gunjikar if (ret && rc == 0) { 730*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 731*c39526b7SPramod Gunjikar "uqp_rsrc_free: usrq_free failed"); 732*c39526b7SPramod Gunjikar rc = ret; 733*c39526b7SPramod Gunjikar } 734*c39526b7SPramod Gunjikar } else if (usrq) 735*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 736*c39526b7SPramod Gunjikar return (rc); 737*c39526b7SPramod Gunjikar 738*c39526b7SPramod Gunjikar err_free: 739*c39526b7SPramod Gunjikar if (upd) 740*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&upd->uobj); 741*c39526b7SPramod Gunjikar if (uscq) 742*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uscq->uobj); 743*c39526b7SPramod Gunjikar if (urcq) 744*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&urcq->uobj); 745*c39526b7SPramod Gunjikar if (usrq) 746*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 747*c39526b7SPramod Gunjikar 748*c39526b7SPramod Gunjikar return (rc); 749*c39526b7SPramod Gunjikar } 750*c39526b7SPramod Gunjikar 751*c39526b7SPramod Gunjikar /* 752*c39526b7SPramod Gunjikar * Free the resources held by the uqp. 753*c39526b7SPramod Gunjikar * Call ibt_free_qp() to free the IBTF QP. 754*c39526b7SPramod Gunjikar * Free uqp. 755*c39526b7SPramod Gunjikar */ 756*c39526b7SPramod Gunjikar int 757*c39526b7SPramod Gunjikar uverbs_uqp_free(uverbs_uqp_uobj_t *uqp, uverbs_uctxt_uobj_t *uctxt) 758*c39526b7SPramod Gunjikar { 759*c39526b7SPramod Gunjikar int rc; 760*c39526b7SPramod Gunjikar ibt_status_t status; 761*c39526b7SPramod Gunjikar 762*c39526b7SPramod Gunjikar /* Detach Mcast entries, if any. */ 763*c39526b7SPramod Gunjikar uverbs_detach_uqp_mcast_entries(uqp); 764*c39526b7SPramod Gunjikar 765*c39526b7SPramod Gunjikar if (!uqp->qp) 766*c39526b7SPramod Gunjikar goto skip_ibt_free_qp; 767*c39526b7SPramod Gunjikar 768*c39526b7SPramod Gunjikar status = ibt_free_qp(uqp->qp); 769*c39526b7SPramod Gunjikar if (status != IBT_SUCCESS) { 770*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 771*c39526b7SPramod Gunjikar "uqp_free: ibt_free_qp failed %d", status); 772*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 773*c39526b7SPramod Gunjikar return (status); 774*c39526b7SPramod Gunjikar } 775*c39526b7SPramod Gunjikar uqp->qp = NULL; 776*c39526b7SPramod Gunjikar 777*c39526b7SPramod Gunjikar skip_ibt_free_qp : 778*c39526b7SPramod Gunjikar rc = uverbs_uqp_rsrc_free(uqp, uctxt); 779*c39526b7SPramod Gunjikar if (rc) { 780*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 781*c39526b7SPramod Gunjikar "uqp_free: uqp_rcrc_free failed %d", rc); 782*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 783*c39526b7SPramod Gunjikar return (rc); 784*c39526b7SPramod Gunjikar } 785*c39526b7SPramod Gunjikar 786*c39526b7SPramod Gunjikar (void) sol_ofs_uobj_remove(&uverbs_uqp_uo_tbl, &uqp->uobj); 787*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 788*c39526b7SPramod Gunjikar 789*c39526b7SPramod Gunjikar if (uqp->list_entry) { 790*c39526b7SPramod Gunjikar mutex_enter(&uctxt->lock); 791*c39526b7SPramod Gunjikar delete_genlist(&uctxt->qp_list, uqp->list_entry); 792*c39526b7SPramod Gunjikar uqp->list_entry = NULL; 793*c39526b7SPramod Gunjikar mutex_exit(&uctxt->lock); 794*c39526b7SPramod Gunjikar } 795*c39526b7SPramod Gunjikar 796*c39526b7SPramod Gunjikar sol_ofs_uobj_deref(&uqp->uobj, sol_ofs_uobj_free); 797*c39526b7SPramod Gunjikar 798*c39526b7SPramod Gunjikar if (uctxt->uctxt_free_pending && (uctxt->qp_list).count == 0) { 799*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, 800*c39526b7SPramod Gunjikar "uqp_free: freeing uctxt %p", uctxt); 801*c39526b7SPramod Gunjikar sol_ofs_uobj_deref(&uctxt->uobj, sol_ofs_uobj_free); 802*c39526b7SPramod Gunjikar } 803*c39526b7SPramod Gunjikar return (0); 804*c39526b7SPramod Gunjikar } 805*c39526b7SPramod Gunjikar 806*c39526b7SPramod Gunjikar /* 807*c39526b7SPramod Gunjikar * Function: 808*c39526b7SPramod Gunjikar * sol_uverbs_destroy_qp 809*c39526b7SPramod Gunjikar * Input: 810*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 811*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing the destroy command. 812*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 813*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 814*c39526b7SPramod Gunjikar * Output: 815*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 816*c39526b7SPramod Gunjikar * Returns: 817*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 818*c39526b7SPramod Gunjikar * Description: 819*c39526b7SPramod Gunjikar * User verbs entry point to destroy a device QP. 820*c39526b7SPramod Gunjikar */ 821*c39526b7SPramod Gunjikar /* ARGSUSED */ 822*c39526b7SPramod Gunjikar int 823*c39526b7SPramod Gunjikar sol_uverbs_destroy_qp(uverbs_uctxt_uobj_t *uctxt, char *buf, 824*c39526b7SPramod Gunjikar int in_len, int out_len) 825*c39526b7SPramod Gunjikar { 826*c39526b7SPramod Gunjikar struct ib_uverbs_destroy_qp cmd; 827*c39526b7SPramod Gunjikar struct ib_uverbs_destroy_qp_resp resp; 828*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 829*c39526b7SPramod Gunjikar int rc; 830*c39526b7SPramod Gunjikar int uobj_put_req = 1; 831*c39526b7SPramod Gunjikar 832*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 833*c39526b7SPramod Gunjikar (void) memset(&resp, 0, sizeof (resp)); 834*c39526b7SPramod Gunjikar 835*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "DESTROY QP: entry " 836*c39526b7SPramod Gunjikar "(qp_handle=%d)", cmd.qp_handle); 837*c39526b7SPramod Gunjikar 838*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle); 839*c39526b7SPramod Gunjikar if (uqp == NULL) { 840*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 841*c39526b7SPramod Gunjikar "destroy_qp() : List lookup failure"); 842*c39526b7SPramod Gunjikar rc = EINVAL; 843*c39526b7SPramod Gunjikar goto err_out; 844*c39526b7SPramod Gunjikar } 845*c39526b7SPramod Gunjikar 846*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "DESTROY QP: qp_handle=%d, " 847*c39526b7SPramod Gunjikar "uqp %p, qp_ptr %p", cmd.qp_handle, uqp, uqp->qp); 848*c39526b7SPramod Gunjikar 849*c39526b7SPramod Gunjikar if (!llist_empty(&uqp->mcast_list)) { 850*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 851*c39526b7SPramod Gunjikar "destroy_qp() called with attached MC group(s)"); 852*c39526b7SPramod Gunjikar rc = EBUSY; 853*c39526b7SPramod Gunjikar goto err_busy; 854*c39526b7SPramod Gunjikar } 855*c39526b7SPramod Gunjikar 856*c39526b7SPramod Gunjikar uverbs_release_uqp_uevents(uctxt->async_evfile, uqp); 857*c39526b7SPramod Gunjikar resp.events_reported = uqp->async_events_reported; 858*c39526b7SPramod Gunjikar 859*c39526b7SPramod Gunjikar /* 860*c39526b7SPramod Gunjikar * If ucma has disabled QP free for this QP, set FREE_PENDING 861*c39526b7SPramod Gunjikar * flag so that the QP can be freed when UCMA enables QP_FREE. 862*c39526b7SPramod Gunjikar * Call ibt_free_qp() is ucma has not disabled QP free. 863*c39526b7SPramod Gunjikar */ 864*c39526b7SPramod Gunjikar if (uqp->uqp_free_state == SOL_UVERBS2UCMA_DISABLE_QP_FREE) { 865*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 866*c39526b7SPramod Gunjikar "destroy_qp() - UCMA disabled"); 867*c39526b7SPramod Gunjikar uqp->uqp_free_state = SOL_UVERBS2UCMA_FREE_PENDING; 868*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 869*c39526b7SPramod Gunjikar rc = 0; 870*c39526b7SPramod Gunjikar goto report_qp_evts; 871*c39526b7SPramod Gunjikar } else { 872*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 873*c39526b7SPramod Gunjikar "destroy_qp() - freeing QP : %p", uqp); 874*c39526b7SPramod Gunjikar rc = uverbs_uqp_free(uqp, uctxt); 875*c39526b7SPramod Gunjikar uobj_put_req = 0; 876*c39526b7SPramod Gunjikar } 877*c39526b7SPramod Gunjikar 878*c39526b7SPramod Gunjikar if (rc) { 879*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 880*c39526b7SPramod Gunjikar "destroy_qp() - ibt_free_qp() fail %d", rc); 881*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 882*c39526b7SPramod Gunjikar if (uobj_put_req) 883*c39526b7SPramod Gunjikar goto err_busy; 884*c39526b7SPramod Gunjikar else 885*c39526b7SPramod Gunjikar goto err_out; 886*c39526b7SPramod Gunjikar } 887*c39526b7SPramod Gunjikar 888*c39526b7SPramod Gunjikar report_qp_evts: 889*c39526b7SPramod Gunjikar #ifdef _LP64 890*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp)); 891*c39526b7SPramod Gunjikar #else 892*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp)); 893*c39526b7SPramod Gunjikar #endif 894*c39526b7SPramod Gunjikar if (rc != 0) { 895*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 896*c39526b7SPramod Gunjikar "destroy_qp() : copyout failure %x", rc); 897*c39526b7SPramod Gunjikar rc = EFAULT; 898*c39526b7SPramod Gunjikar goto err_out; 899*c39526b7SPramod Gunjikar } 900*c39526b7SPramod Gunjikar 901*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 902*c39526b7SPramod Gunjikar 903*c39526b7SPramod Gunjikar err_busy: 904*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 905*c39526b7SPramod Gunjikar 906*c39526b7SPramod Gunjikar err_out: 907*c39526b7SPramod Gunjikar return (rc); 908*c39526b7SPramod Gunjikar } 909*c39526b7SPramod Gunjikar 910*c39526b7SPramod Gunjikar /* 911*c39526b7SPramod Gunjikar * Function: 912*c39526b7SPramod Gunjikar * uverbs_copy_path_info_from_ibv 913*c39526b7SPramod Gunjikar * Input: 914*c39526b7SPramod Gunjikar * src_path - IB OFED path. 915*c39526b7SPramod Gunjikar * Output: 916*c39526b7SPramod Gunjikar * dest_path - IBT path. 917*c39526b7SPramod Gunjikar * Returns: 918*c39526b7SPramod Gunjikar * None 919*c39526b7SPramod Gunjikar * Description: 920*c39526b7SPramod Gunjikar * Helper to copy from the OFED path format to IBT path format. 921*c39526b7SPramod Gunjikar */ 922*c39526b7SPramod Gunjikar static void 923*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibv(struct ib_uverbs_qp_dest *src_path, 924*c39526b7SPramod Gunjikar ibt_cep_path_t *dest_path) 925*c39526b7SPramod Gunjikar { 926*c39526b7SPramod Gunjikar ASSERT(src_path != NULL); 927*c39526b7SPramod Gunjikar ASSERT(dest_path != NULL); 928*c39526b7SPramod Gunjikar 929*c39526b7SPramod Gunjikar (void) memcpy(&dest_path->cep_adds_vect.av_dgid, 930*c39526b7SPramod Gunjikar &src_path->dgid[0], sizeof (src_path->dgid)); 931*c39526b7SPramod Gunjikar 932*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_flow = src_path->flow_label; 933*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_dlid = src_path->dlid; 934*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_hop = src_path->hop_limit; 935*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_tclass = src_path->traffic_class; 936*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_srvl = src_path->sl & 0x0f; 937*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_port_num = src_path->port_num; 938*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_src_path = src_path->src_path_bits; 939*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_send_grh = src_path->is_global; 940*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_sgid_ix = src_path->sgid_index; 941*c39526b7SPramod Gunjikar dest_path->cep_adds_vect.av_srate = src_path->static_rate; 942*c39526b7SPramod Gunjikar } 943*c39526b7SPramod Gunjikar 944*c39526b7SPramod Gunjikar /* 945*c39526b7SPramod Gunjikar * Function: 946*c39526b7SPramod Gunjikar * uverbs_modify_update 947*c39526b7SPramod Gunjikar * Input: 948*c39526b7SPramod Gunjikar * cmd - The user verbs modify command to be translated. 949*c39526b7SPramod Gunjikar * cur_state - The current QP state 950*c39526b7SPramod Gunjikar * new_state - The new QP state 951*c39526b7SPramod Gunjikar * Output: 952*c39526b7SPramod Gunjikar * qp_query_attr - The IBT QP attributes. 953*c39526b7SPramod Gunjikar * flags - The IBT flags. 954*c39526b7SPramod Gunjikar * Returns: 955*c39526b7SPramod Gunjikar * None 956*c39526b7SPramod Gunjikar * Description: 957*c39526b7SPramod Gunjikar * Helper to convert OFED user verbs QP modify attributes to IBT 958*c39526b7SPramod Gunjikar * QP modify attributes. Note that on required parameters, the 959*c39526b7SPramod Gunjikar * individual IBT modify flags are not set (there is a global 960*c39526b7SPramod Gunjikar * flag for the transition), only optional flags are set. 961*c39526b7SPramod Gunjikar */ 962*c39526b7SPramod Gunjikar static void 963*c39526b7SPramod Gunjikar uverbs_modify_update(struct ib_uverbs_modify_qp *cmd, 964*c39526b7SPramod Gunjikar enum ib_qp_state cur_state, enum ib_qp_state new_state, 965*c39526b7SPramod Gunjikar ibt_qp_query_attr_t *qp_query_attr, ibt_cep_modify_flags_t *flags) 966*c39526b7SPramod Gunjikar { 967*c39526b7SPramod Gunjikar ibt_qp_info_t *qp_infop; 968*c39526b7SPramod Gunjikar ibt_qp_rc_attr_t *rcp; 969*c39526b7SPramod Gunjikar ibt_qp_uc_attr_t *ucp; 970*c39526b7SPramod Gunjikar ibt_qp_ud_attr_t *udp; 971*c39526b7SPramod Gunjikar 972*c39526b7SPramod Gunjikar *flags = IBT_CEP_SET_NOTHING; 973*c39526b7SPramod Gunjikar qp_infop = &(qp_query_attr->qp_info); 974*c39526b7SPramod Gunjikar rcp = &(qp_infop->qp_transport.rc); 975*c39526b7SPramod Gunjikar ucp = &(qp_infop->qp_transport.uc); 976*c39526b7SPramod Gunjikar udp = &(qp_infop->qp_transport.ud); 977*c39526b7SPramod Gunjikar 978*c39526b7SPramod Gunjikar switch (cur_state) { 979*c39526b7SPramod Gunjikar case IB_QPS_RESET: 980*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_RESET; 981*c39526b7SPramod Gunjikar break; 982*c39526b7SPramod Gunjikar case IB_QPS_INIT: 983*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_INIT; 984*c39526b7SPramod Gunjikar break; 985*c39526b7SPramod Gunjikar case IB_QPS_RTR: 986*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_RTR; 987*c39526b7SPramod Gunjikar break; 988*c39526b7SPramod Gunjikar case IB_QPS_RTS: 989*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_RTS; 990*c39526b7SPramod Gunjikar break; 991*c39526b7SPramod Gunjikar case IB_QPS_SQD: 992*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_SQD; 993*c39526b7SPramod Gunjikar break; 994*c39526b7SPramod Gunjikar case IB_QPS_SQE: 995*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_SQE; 996*c39526b7SPramod Gunjikar break; 997*c39526b7SPramod Gunjikar case IB_QPS_ERR: 998*c39526b7SPramod Gunjikar qp_infop->qp_current_state = IBT_STATE_ERROR; 999*c39526b7SPramod Gunjikar break; 1000*c39526b7SPramod Gunjikar } 1001*c39526b7SPramod Gunjikar 1002*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_STATE) { 1003*c39526b7SPramod Gunjikar switch (new_state) { 1004*c39526b7SPramod Gunjikar case IB_QPS_RESET: 1005*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_RESET; 1006*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1007*c39526b7SPramod Gunjikar break; 1008*c39526b7SPramod Gunjikar 1009*c39526b7SPramod Gunjikar case IB_QPS_INIT: 1010*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_INIT; 1011*c39526b7SPramod Gunjikar if (cur_state == IB_QPS_RESET) { 1012*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RESET_INIT; 1013*c39526b7SPramod Gunjikar } else { 1014*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1015*c39526b7SPramod Gunjikar } 1016*c39526b7SPramod Gunjikar break; 1017*c39526b7SPramod Gunjikar 1018*c39526b7SPramod Gunjikar case IB_QPS_RTR: 1019*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_RTR; 1020*c39526b7SPramod Gunjikar if (cur_state == IB_QPS_INIT) { 1021*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_INIT_RTR; 1022*c39526b7SPramod Gunjikar } else { 1023*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1024*c39526b7SPramod Gunjikar } 1025*c39526b7SPramod Gunjikar break; 1026*c39526b7SPramod Gunjikar 1027*c39526b7SPramod Gunjikar case IB_QPS_RTS: 1028*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_RTS; 1029*c39526b7SPramod Gunjikar 1030*c39526b7SPramod Gunjikar /* 1031*c39526b7SPramod Gunjikar * For RTS transitions other than RTR we must 1032*c39526b7SPramod Gunjikar * specify the assumption for the qp state. 1033*c39526b7SPramod Gunjikar */ 1034*c39526b7SPramod Gunjikar if (cur_state == IB_QPS_RTR) { 1035*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RTR_RTS; 1036*c39526b7SPramod Gunjikar } else { 1037*c39526b7SPramod Gunjikar ibt_cep_state_t *ibt_curr = 1038*c39526b7SPramod Gunjikar &qp_infop->qp_current_state; 1039*c39526b7SPramod Gunjikar 1040*c39526b7SPramod Gunjikar switch (cur_state) { 1041*c39526b7SPramod Gunjikar case IB_QPS_RTR: 1042*c39526b7SPramod Gunjikar *ibt_curr = IBT_STATE_RTR; 1043*c39526b7SPramod Gunjikar break; 1044*c39526b7SPramod Gunjikar 1045*c39526b7SPramod Gunjikar case IB_QPS_RTS: 1046*c39526b7SPramod Gunjikar *ibt_curr = IBT_STATE_RTS; 1047*c39526b7SPramod Gunjikar break; 1048*c39526b7SPramod Gunjikar 1049*c39526b7SPramod Gunjikar case IB_QPS_SQD: 1050*c39526b7SPramod Gunjikar *ibt_curr = IBT_STATE_SQD; 1051*c39526b7SPramod Gunjikar break; 1052*c39526b7SPramod Gunjikar 1053*c39526b7SPramod Gunjikar case IB_QPS_SQE: 1054*c39526b7SPramod Gunjikar *ibt_curr = IBT_STATE_SQE; 1055*c39526b7SPramod Gunjikar break; 1056*c39526b7SPramod Gunjikar } 1057*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1058*c39526b7SPramod Gunjikar } 1059*c39526b7SPramod Gunjikar break; 1060*c39526b7SPramod Gunjikar 1061*c39526b7SPramod Gunjikar case IB_QPS_SQD: 1062*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_SQD; 1063*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1064*c39526b7SPramod Gunjikar break; 1065*c39526b7SPramod Gunjikar 1066*c39526b7SPramod Gunjikar case IB_QPS_SQE: 1067*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_SQE; 1068*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1069*c39526b7SPramod Gunjikar break; 1070*c39526b7SPramod Gunjikar 1071*c39526b7SPramod Gunjikar case IB_QPS_ERR: 1072*c39526b7SPramod Gunjikar qp_infop->qp_state = IBT_STATE_ERROR; 1073*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_STATE; 1074*c39526b7SPramod Gunjikar break; 1075*c39526b7SPramod Gunjikar } 1076*c39526b7SPramod Gunjikar } 1077*c39526b7SPramod Gunjikar 1078*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_PKEY_INDEX) { 1079*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UD_SRV) { 1080*c39526b7SPramod Gunjikar udp->ud_pkey_ix = cmd->pkey_index; 1081*c39526b7SPramod Gunjikar } else if (qp_infop->qp_trans == IBT_RC_SRV) { 1082*c39526b7SPramod Gunjikar rcp->rc_path.cep_pkey_ix = cmd->pkey_index; 1083*c39526b7SPramod Gunjikar } 1084*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_PKEY_IX; 1085*c39526b7SPramod Gunjikar } 1086*c39526b7SPramod Gunjikar 1087*c39526b7SPramod Gunjikar 1088*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_AV) { 1089*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1090*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibv(&cmd->dest, 1091*c39526b7SPramod Gunjikar &rcp->rc_path); 1092*c39526b7SPramod Gunjikar } 1093*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_ADDS_VECT; 1094*c39526b7SPramod Gunjikar } 1095*c39526b7SPramod Gunjikar 1096*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1097*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_TIMEOUT) { 1098*c39526b7SPramod Gunjikar rcp->rc_path.cep_timeout = cmd->timeout; 1099*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_TIMEOUT; 1100*c39526b7SPramod Gunjikar } 1101*c39526b7SPramod Gunjikar } 1102*c39526b7SPramod Gunjikar 1103*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_PORT) { 1104*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UD_SRV) { 1105*c39526b7SPramod Gunjikar udp->ud_port = cmd->port_num; 1106*c39526b7SPramod Gunjikar } else if (qp_infop->qp_trans == IBT_RC_SRV) { 1107*c39526b7SPramod Gunjikar rcp->rc_path.cep_hca_port_num = cmd->port_num; 1108*c39526b7SPramod Gunjikar } 1109*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_PORT; 1110*c39526b7SPramod Gunjikar } 1111*c39526b7SPramod Gunjikar 1112*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_QKEY) { 1113*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UD_SRV) { 1114*c39526b7SPramod Gunjikar udp->ud_qkey = cmd->qkey; 1115*c39526b7SPramod Gunjikar } 1116*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RD_SRV) { 1117*c39526b7SPramod Gunjikar qp_infop->qp_transport.rd.rd_qkey = cmd->qkey; 1118*c39526b7SPramod Gunjikar } 1119*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_QKEY; 1120*c39526b7SPramod Gunjikar } 1121*c39526b7SPramod Gunjikar 1122*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_PATH_MTU) { 1123*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UC_SRV) { 1124*c39526b7SPramod Gunjikar ucp->uc_path_mtu = cmd->path_mtu; 1125*c39526b7SPramod Gunjikar } 1126*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1127*c39526b7SPramod Gunjikar rcp->rc_path_mtu = cmd->path_mtu; 1128*c39526b7SPramod Gunjikar } 1129*c39526b7SPramod Gunjikar } 1130*c39526b7SPramod Gunjikar 1131*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_RETRY_CNT) { 1132*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1133*c39526b7SPramod Gunjikar rcp->rc_retry_cnt = cmd->retry_cnt & 0x7; 1134*c39526b7SPramod Gunjikar } 1135*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RETRY; 1136*c39526b7SPramod Gunjikar } 1137*c39526b7SPramod Gunjikar 1138*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_RNR_RETRY) { 1139*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1140*c39526b7SPramod Gunjikar rcp->rc_rnr_retry_cnt = cmd->rnr_retry; 1141*c39526b7SPramod Gunjikar } 1142*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RNR_NAK_RETRY; 1143*c39526b7SPramod Gunjikar } 1144*c39526b7SPramod Gunjikar 1145*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_MIN_RNR_TIMER) { 1146*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1147*c39526b7SPramod Gunjikar rcp->rc_min_rnr_nak = cmd->min_rnr_timer; 1148*c39526b7SPramod Gunjikar } 1149*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_MIN_RNR_NAK; 1150*c39526b7SPramod Gunjikar } 1151*c39526b7SPramod Gunjikar 1152*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_RQ_PSN) { 1153*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1154*c39526b7SPramod Gunjikar rcp->rc_rq_psn = cmd->rq_psn; 1155*c39526b7SPramod Gunjikar } 1156*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UC_SRV) { 1157*c39526b7SPramod Gunjikar ucp->uc_rq_psn = cmd->rq_psn; 1158*c39526b7SPramod Gunjikar } 1159*c39526b7SPramod Gunjikar } 1160*c39526b7SPramod Gunjikar 1161*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_ALT_PATH) { 1162*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1163*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibv(&cmd->alt_dest, 1164*c39526b7SPramod Gunjikar &rcp->rc_alt_path); 1165*c39526b7SPramod Gunjikar 1166*c39526b7SPramod Gunjikar rcp->rc_alt_path.cep_hca_port_num = cmd->alt_port_num; 1167*c39526b7SPramod Gunjikar rcp->rc_alt_path.cep_timeout = cmd->alt_timeout; 1168*c39526b7SPramod Gunjikar } 1169*c39526b7SPramod Gunjikar 1170*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UC_SRV) { 1171*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibv(&cmd->alt_dest, 1172*c39526b7SPramod Gunjikar &ucp->uc_alt_path); 1173*c39526b7SPramod Gunjikar 1174*c39526b7SPramod Gunjikar ucp->uc_alt_path.cep_hca_port_num = cmd->alt_port_num; 1175*c39526b7SPramod Gunjikar ucp->uc_alt_path.cep_timeout = cmd->alt_timeout; 1176*c39526b7SPramod Gunjikar } 1177*c39526b7SPramod Gunjikar 1178*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_ALT_PATH; 1179*c39526b7SPramod Gunjikar } 1180*c39526b7SPramod Gunjikar 1181*c39526b7SPramod Gunjikar 1182*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_SQ_PSN) { 1183*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UD_SRV) { 1184*c39526b7SPramod Gunjikar udp->ud_sq_psn = cmd->sq_psn; 1185*c39526b7SPramod Gunjikar } 1186*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UC_SRV) { 1187*c39526b7SPramod Gunjikar ucp->uc_sq_psn = cmd->sq_psn; 1188*c39526b7SPramod Gunjikar } 1189*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1190*c39526b7SPramod Gunjikar rcp->rc_sq_psn = cmd->sq_psn; 1191*c39526b7SPramod Gunjikar } 1192*c39526b7SPramod Gunjikar } 1193*c39526b7SPramod Gunjikar 1194*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { 1195*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1196*c39526b7SPramod Gunjikar rcp->rc_rdma_ra_out = cmd->max_rd_atomic; 1197*c39526b7SPramod Gunjikar } 1198*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RDMARA_OUT | IBT_CEP_SET_STATE; 1199*c39526b7SPramod Gunjikar } 1200*c39526b7SPramod Gunjikar 1201*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { 1202*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1203*c39526b7SPramod Gunjikar rcp->rc_rdma_ra_in = cmd->max_dest_rd_atomic; 1204*c39526b7SPramod Gunjikar } 1205*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RDMARA_IN | IBT_CEP_SET_STATE; 1206*c39526b7SPramod Gunjikar } 1207*c39526b7SPramod Gunjikar 1208*c39526b7SPramod Gunjikar if (cmd->attr_mask & (IB_QP_ACCESS_FLAGS | 1209*c39526b7SPramod Gunjikar IB_QP_MAX_DEST_RD_ATOMIC)) { 1210*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1211*c39526b7SPramod Gunjikar uint32_t access_flags = IBT_CEP_NO_FLAGS; 1212*c39526b7SPramod Gunjikar 1213*c39526b7SPramod Gunjikar if (rcp->rc_rdma_ra_in) { 1214*c39526b7SPramod Gunjikar access_flags |= IBT_CEP_RDMA_WR; 1215*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RDMA_W; 1216*c39526b7SPramod Gunjikar } 1217*c39526b7SPramod Gunjikar 1218*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_ACCESS_FLAGS) { 1219*c39526b7SPramod Gunjikar if (cmd->qp_access_flags & 1220*c39526b7SPramod Gunjikar IB_ACCESS_REMOTE_WRITE) { 1221*c39526b7SPramod Gunjikar access_flags |= IBT_CEP_RDMA_WR; 1222*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RDMA_W; 1223*c39526b7SPramod Gunjikar } 1224*c39526b7SPramod Gunjikar if (cmd->qp_access_flags & 1225*c39526b7SPramod Gunjikar IB_ACCESS_REMOTE_READ) { 1226*c39526b7SPramod Gunjikar access_flags |= IBT_CEP_RDMA_RD; 1227*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_RDMA_R; 1228*c39526b7SPramod Gunjikar } 1229*c39526b7SPramod Gunjikar if (cmd->qp_access_flags & 1230*c39526b7SPramod Gunjikar IB_ACCESS_REMOTE_ATOMIC) { 1231*c39526b7SPramod Gunjikar access_flags |= IBT_CEP_ATOMIC; 1232*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_ATOMIC; 1233*c39526b7SPramod Gunjikar } 1234*c39526b7SPramod Gunjikar } 1235*c39526b7SPramod Gunjikar qp_infop->qp_flags &= ~(IBT_CEP_RDMA_WR | 1236*c39526b7SPramod Gunjikar IBT_CEP_RDMA_RD | IBT_CEP_ATOMIC); 1237*c39526b7SPramod Gunjikar qp_infop->qp_flags |= access_flags; 1238*c39526b7SPramod Gunjikar } 1239*c39526b7SPramod Gunjikar } 1240*c39526b7SPramod Gunjikar 1241*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_PATH_MIG_STATE) { 1242*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1243*c39526b7SPramod Gunjikar if (cmd->path_mig_state == IB_MIG_MIGRATED) { 1244*c39526b7SPramod Gunjikar rcp->rc_mig_state = IBT_STATE_MIGRATED; 1245*c39526b7SPramod Gunjikar } 1246*c39526b7SPramod Gunjikar if (cmd->path_mig_state == IB_MIG_REARM) { 1247*c39526b7SPramod Gunjikar rcp->rc_mig_state = IBT_STATE_REARMED; 1248*c39526b7SPramod Gunjikar } 1249*c39526b7SPramod Gunjikar if (cmd->path_mig_state == IB_MIG_ARMED) { 1250*c39526b7SPramod Gunjikar rcp->rc_mig_state = IBT_STATE_ARMED; 1251*c39526b7SPramod Gunjikar } 1252*c39526b7SPramod Gunjikar } 1253*c39526b7SPramod Gunjikar 1254*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UC_SRV) { 1255*c39526b7SPramod Gunjikar if (cmd->path_mig_state == IB_MIG_MIGRATED) { 1256*c39526b7SPramod Gunjikar ucp->uc_mig_state = IBT_STATE_MIGRATED; 1257*c39526b7SPramod Gunjikar } 1258*c39526b7SPramod Gunjikar if (cmd->path_mig_state == IB_MIG_REARM) { 1259*c39526b7SPramod Gunjikar ucp->uc_mig_state = IBT_STATE_REARMED; 1260*c39526b7SPramod Gunjikar } 1261*c39526b7SPramod Gunjikar if (cmd->path_mig_state == IB_MIG_ARMED) { 1262*c39526b7SPramod Gunjikar ucp->uc_mig_state = IBT_STATE_ARMED; 1263*c39526b7SPramod Gunjikar } 1264*c39526b7SPramod Gunjikar } 1265*c39526b7SPramod Gunjikar *flags |= IBT_CEP_SET_MIG; 1266*c39526b7SPramod Gunjikar } 1267*c39526b7SPramod Gunjikar 1268*c39526b7SPramod Gunjikar if (cmd->attr_mask & IB_QP_DEST_QPN) { 1269*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1270*c39526b7SPramod Gunjikar rcp->rc_dst_qpn = cmd->dest_qp_num; 1271*c39526b7SPramod Gunjikar } 1272*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_UC_SRV) { 1273*c39526b7SPramod Gunjikar ucp->uc_dst_qpn = cmd->dest_qp_num; 1274*c39526b7SPramod Gunjikar } 1275*c39526b7SPramod Gunjikar } 1276*c39526b7SPramod Gunjikar } 1277*c39526b7SPramod Gunjikar 1278*c39526b7SPramod Gunjikar 1279*c39526b7SPramod Gunjikar static void 1280*c39526b7SPramod Gunjikar uverbs_qp_print_path(ibt_cep_path_t *pathp) 1281*c39526b7SPramod Gunjikar { 1282*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_print_pathp %p", pathp); 1283*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "cep_pkey_ix %x, " 1284*c39526b7SPramod Gunjikar "cep_hca_port_num %x", pathp->cep_pkey_ix, pathp->cep_hca_port_num); 1285*c39526b7SPramod Gunjikar } 1286*c39526b7SPramod Gunjikar 1287*c39526b7SPramod Gunjikar static void 1288*c39526b7SPramod Gunjikar uverbs_print_query_qp(ibt_qp_hdl_t qp_hdlp) 1289*c39526b7SPramod Gunjikar { 1290*c39526b7SPramod Gunjikar ibt_qp_query_attr_t qp_query_attr; 1291*c39526b7SPramod Gunjikar ibt_qp_info_t *qp_infop = &qp_query_attr.qp_info; 1292*c39526b7SPramod Gunjikar ibt_qp_rc_attr_t *rcp = &((qp_infop->qp_transport).rc); 1293*c39526b7SPramod Gunjikar ibt_status_t rc; 1294*c39526b7SPramod Gunjikar 1295*c39526b7SPramod Gunjikar bzero(&qp_query_attr, sizeof (qp_query_attr)); 1296*c39526b7SPramod Gunjikar rc = ibt_query_qp(qp_hdlp, &qp_query_attr); 1297*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 1298*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "print_query_qp -" 1299*c39526b7SPramod Gunjikar "ibt_query_qp() failed - rc=%d", rc); 1300*c39526b7SPramod Gunjikar return; 1301*c39526b7SPramod Gunjikar } 1302*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_print %p", qp_hdlp); 1303*c39526b7SPramod Gunjikar 1304*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_sq_cq %p, qp_rq_cq %p, " 1305*c39526b7SPramod Gunjikar "qp_qpn %x, qp_sq_sgl %x, qp_rq_sgl %x, qp_srq %p, qp_flags %x", 1306*c39526b7SPramod Gunjikar qp_query_attr.qp_sq_cq, qp_query_attr.qp_rq_cq, 1307*c39526b7SPramod Gunjikar qp_query_attr.qp_qpn, qp_query_attr.qp_sq_sgl, 1308*c39526b7SPramod Gunjikar qp_query_attr.qp_rq_sgl, qp_query_attr.qp_srq, 1309*c39526b7SPramod Gunjikar qp_query_attr.qp_flags); 1310*c39526b7SPramod Gunjikar 1311*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "qp_sq_sz %x, qp_rq_sz %x, " 1312*c39526b7SPramod Gunjikar "qp_state %x, qp_current_state %x, qp_flags %x, qp_trans %x", 1313*c39526b7SPramod Gunjikar qp_infop->qp_sq_sz, qp_infop->qp_rq_sz, qp_infop->qp_state, 1314*c39526b7SPramod Gunjikar qp_infop->qp_current_state, qp_infop->qp_flags, 1315*c39526b7SPramod Gunjikar qp_infop->qp_trans); 1316*c39526b7SPramod Gunjikar 1317*c39526b7SPramod Gunjikar if (qp_infop->qp_trans == IBT_RC_SRV) { 1318*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "rc_sq_psn %x, rc_rq_psn %x, " 1319*c39526b7SPramod Gunjikar "rc_dst_qpn %x, rc_mig_state %x, rc_rnr_retry_cnt %x," 1320*c39526b7SPramod Gunjikar "rc_retry_cnt %x rc_rdma_ra_out %x, rc_rdma_ra_in %x," 1321*c39526b7SPramod Gunjikar "rc_min_rnr_nak %x, rc_path_mtu %x", 1322*c39526b7SPramod Gunjikar rcp->rc_sq_psn, rcp->rc_rq_psn, rcp->rc_dst_qpn, rcp->rc_mig_state, 1323*c39526b7SPramod Gunjikar rcp->rc_rnr_retry_cnt, rcp->rc_retry_cnt, rcp->rc_rdma_ra_out, 1324*c39526b7SPramod Gunjikar rcp->rc_rdma_ra_in, rcp->rc_min_rnr_nak, rcp->rc_path_mtu); 1325*c39526b7SPramod Gunjikar uverbs_qp_print_path(&rcp->rc_path); 1326*c39526b7SPramod Gunjikar uverbs_qp_print_path(&rcp->rc_alt_path); 1327*c39526b7SPramod Gunjikar } 1328*c39526b7SPramod Gunjikar } 1329*c39526b7SPramod Gunjikar 1330*c39526b7SPramod Gunjikar 1331*c39526b7SPramod Gunjikar /* 1332*c39526b7SPramod Gunjikar * Function: 1333*c39526b7SPramod Gunjikar * sol_uverbs_modify_qp 1334*c39526b7SPramod Gunjikar * Input: 1335*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 1336*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing QP modify command. 1337*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 1338*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 1339*c39526b7SPramod Gunjikar * Output: 1340*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 1341*c39526b7SPramod Gunjikar * Returns: 1342*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 1343*c39526b7SPramod Gunjikar * Description: 1344*c39526b7SPramod Gunjikar * User verbs entry point to modify a device QP. 1345*c39526b7SPramod Gunjikar */ 1346*c39526b7SPramod Gunjikar /* ARGSUSED */ 1347*c39526b7SPramod Gunjikar int 1348*c39526b7SPramod Gunjikar sol_uverbs_modify_qp(uverbs_uctxt_uobj_t *uctxt, char *buf, 1349*c39526b7SPramod Gunjikar int in_len, int out_len) 1350*c39526b7SPramod Gunjikar { 1351*c39526b7SPramod Gunjikar struct ib_uverbs_modify_qp cmd; 1352*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 1353*c39526b7SPramod Gunjikar ibt_qp_query_attr_t qp_query_attr; 1354*c39526b7SPramod Gunjikar ibt_cep_modify_flags_t flags; 1355*c39526b7SPramod Gunjikar ibt_queue_sizes_t size; 1356*c39526b7SPramod Gunjikar int rc; 1357*c39526b7SPramod Gunjikar enum ib_qp_state cur_state, new_state; 1358*c39526b7SPramod Gunjikar 1359*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 1360*c39526b7SPramod Gunjikar 1361*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp - qp_hdl %d, " 1362*c39526b7SPramod Gunjikar "attr_mask %x", cmd.qp_handle, cmd.attr_mask); 1363*c39526b7SPramod Gunjikar 1364*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle); 1365*c39526b7SPramod Gunjikar if (uqp == NULL) { 1366*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp -" 1367*c39526b7SPramod Gunjikar "List lookup failure"); 1368*c39526b7SPramod Gunjikar rc = EINVAL; 1369*c39526b7SPramod Gunjikar goto err_out; 1370*c39526b7SPramod Gunjikar } 1371*c39526b7SPramod Gunjikar 1372*c39526b7SPramod Gunjikar /* 1373*c39526b7SPramod Gunjikar * Has the UCMA asked us to ignore QP modify operations? 1374*c39526b7SPramod Gunjikar * This is required because of differences in the level of 1375*c39526b7SPramod Gunjikar * abstraction fo CM processing between IBT and OFED. 1376*c39526b7SPramod Gunjikar */ 1377*c39526b7SPramod Gunjikar if (uqp->disable_qp_mod == TRUE) { 1378*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, "modify_qp -" 1379*c39526b7SPramod Gunjikar "qp_mod disabled"); 1380*c39526b7SPramod Gunjikar goto done; 1381*c39526b7SPramod Gunjikar } 1382*c39526b7SPramod Gunjikar 1383*c39526b7SPramod Gunjikar /* 1384*c39526b7SPramod Gunjikar * Load the current QP attributes and then do a validation 1385*c39526b7SPramod Gunjikar * based on OFA verbs expectations to see if the modify 1386*c39526b7SPramod Gunjikar * should be performed. 1387*c39526b7SPramod Gunjikar */ 1388*c39526b7SPramod Gunjikar bzero(&qp_query_attr, sizeof (qp_query_attr)); 1389*c39526b7SPramod Gunjikar rc = ibt_query_qp(uqp->qp, &qp_query_attr); 1390*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 1391*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp -" 1392*c39526b7SPramod Gunjikar "ibt_query_qp() failed - rc=%d", rc); 1393*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 1394*c39526b7SPramod Gunjikar goto err_deref; 1395*c39526b7SPramod Gunjikar } 1396*c39526b7SPramod Gunjikar 1397*c39526b7SPramod Gunjikar if (cmd.attr_mask & IB_QP_CUR_STATE) { 1398*c39526b7SPramod Gunjikar cur_state = cmd.cur_qp_state; 1399*c39526b7SPramod Gunjikar } else { 1400*c39526b7SPramod Gunjikar cur_state = IBT_TO_OFA_QP_STATE(qp_query_attr.qp_info.qp_state); 1401*c39526b7SPramod Gunjikar } 1402*c39526b7SPramod Gunjikar 1403*c39526b7SPramod Gunjikar new_state = cmd.attr_mask & IB_QP_STATE ? cmd.qp_state : cur_state; 1404*c39526b7SPramod Gunjikar 1405*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp: ibt qp %p, handle " 1406*c39526b7SPramod Gunjikar "%x, cur_state %x, new_state %x, qp_type %x, attr_mask %x", uqp->qp, 1407*c39526b7SPramod Gunjikar cmd.qp_handle, cur_state, new_state, uqp->ofa_qp_type, 1408*c39526b7SPramod Gunjikar cmd.attr_mask); 1409*c39526b7SPramod Gunjikar 1410*c39526b7SPramod Gunjikar if (!uverbs_modify_qp_is_ok(cur_state, new_state, uqp->ofa_qp_type, 1411*c39526b7SPramod Gunjikar (enum ib_qp_attr_mask *)&cmd.attr_mask)) { 1412*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "modify_qp() -" 1413*c39526b7SPramod Gunjikar "Failed modify OK test"); 1414*c39526b7SPramod Gunjikar rc = EINVAL; 1415*c39526b7SPramod Gunjikar goto err_deref; 1416*c39526b7SPramod Gunjikar } 1417*c39526b7SPramod Gunjikar 1418*c39526b7SPramod Gunjikar if (!cmd.attr_mask) { 1419*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, "modify_qp() -" 1420*c39526b7SPramod Gunjikar "attr_mask after modify OK test is 0"); 1421*c39526b7SPramod Gunjikar rc = 0; 1422*c39526b7SPramod Gunjikar goto done; 1423*c39526b7SPramod Gunjikar } 1424*c39526b7SPramod Gunjikar 1425*c39526b7SPramod Gunjikar flags = 0; 1426*c39526b7SPramod Gunjikar 1427*c39526b7SPramod Gunjikar switch (uqp->ofa_qp_type) { 1428*c39526b7SPramod Gunjikar case IB_QPT_UC: 1429*c39526b7SPramod Gunjikar qp_query_attr.qp_info.qp_trans = IBT_UC_SRV; 1430*c39526b7SPramod Gunjikar break; 1431*c39526b7SPramod Gunjikar case IB_QPT_UD: 1432*c39526b7SPramod Gunjikar qp_query_attr.qp_info.qp_trans = IBT_UD_SRV; 1433*c39526b7SPramod Gunjikar break; 1434*c39526b7SPramod Gunjikar case IB_QPT_RC: 1435*c39526b7SPramod Gunjikar qp_query_attr.qp_info.qp_trans = IBT_RC_SRV; 1436*c39526b7SPramod Gunjikar break; 1437*c39526b7SPramod Gunjikar default: 1438*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1439*c39526b7SPramod Gunjikar "modify_qp: Invalid QP type"); 1440*c39526b7SPramod Gunjikar rc = EINVAL; 1441*c39526b7SPramod Gunjikar goto err_deref; 1442*c39526b7SPramod Gunjikar } 1443*c39526b7SPramod Gunjikar 1444*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp(): qp_info.qp_flags " 1445*c39526b7SPramod Gunjikar "before modify update = 0%08x", qp_query_attr.qp_info.qp_flags); 1446*c39526b7SPramod Gunjikar 1447*c39526b7SPramod Gunjikar uverbs_modify_update(&cmd, cur_state, new_state, &qp_query_attr, 1448*c39526b7SPramod Gunjikar &flags); 1449*c39526b7SPramod Gunjikar 1450*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "modify_qp(): after " 1451*c39526b7SPramod Gunjikar "modify_update hdl flags = 0x%08x, qp_info.qp_flags = 0%08x", 1452*c39526b7SPramod Gunjikar flags, qp_query_attr.qp_info.qp_flags); 1453*c39526b7SPramod Gunjikar 1454*c39526b7SPramod Gunjikar rc = ibt_modify_qp(uqp->qp, flags, &qp_query_attr.qp_info, &size); 1455*c39526b7SPramod Gunjikar 1456*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 1457*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1458*c39526b7SPramod Gunjikar "modify_qp: Error in ibt_modify_qp() (rc=%d)", rc); 1459*c39526b7SPramod Gunjikar uverbs_print_query_qp(uqp->qp); 1460*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 1461*c39526b7SPramod Gunjikar goto err_deref; 1462*c39526b7SPramod Gunjikar } 1463*c39526b7SPramod Gunjikar 1464*c39526b7SPramod Gunjikar done: 1465*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 1466*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 1467*c39526b7SPramod Gunjikar 1468*c39526b7SPramod Gunjikar err_deref: 1469*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 1470*c39526b7SPramod Gunjikar 1471*c39526b7SPramod Gunjikar err_out: 1472*c39526b7SPramod Gunjikar return (rc); 1473*c39526b7SPramod Gunjikar } 1474*c39526b7SPramod Gunjikar 1475*c39526b7SPramod Gunjikar /* 1476*c39526b7SPramod Gunjikar * Function: 1477*c39526b7SPramod Gunjikar * uverbs_copy_path_info_from_ibt 1478*c39526b7SPramod Gunjikar * Input: 1479*c39526b7SPramod Gunjikar * src_path - The IBT path. 1480*c39526b7SPramod Gunjikar * Output: 1481*c39526b7SPramod Gunjikar * dest_path - The OFED user verbs path. 1482*c39526b7SPramod Gunjikar * Returns: 1483*c39526b7SPramod Gunjikar * None 1484*c39526b7SPramod Gunjikar * Description: 1485*c39526b7SPramod Gunjikar * Helper to convert IBT path to OFED user verbs path. 1486*c39526b7SPramod Gunjikar */ 1487*c39526b7SPramod Gunjikar static void 1488*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibt(ibt_cep_path_t *src_path, 1489*c39526b7SPramod Gunjikar struct ib_uverbs_qp_dest *dest_path) 1490*c39526b7SPramod Gunjikar { 1491*c39526b7SPramod Gunjikar ASSERT(src_path != NULL); 1492*c39526b7SPramod Gunjikar ASSERT(dest_path != NULL); 1493*c39526b7SPramod Gunjikar 1494*c39526b7SPramod Gunjikar (void) memcpy(&dest_path->dgid[0], 1495*c39526b7SPramod Gunjikar &src_path->cep_adds_vect.av_dgid, sizeof (dest_path->dgid)); 1496*c39526b7SPramod Gunjikar 1497*c39526b7SPramod Gunjikar dest_path->flow_label = src_path->cep_adds_vect.av_flow; 1498*c39526b7SPramod Gunjikar dest_path->dlid = src_path->cep_adds_vect.av_dlid; 1499*c39526b7SPramod Gunjikar dest_path->hop_limit = src_path->cep_adds_vect.av_hop; 1500*c39526b7SPramod Gunjikar dest_path->traffic_class = src_path->cep_adds_vect.av_tclass; 1501*c39526b7SPramod Gunjikar dest_path->sl = src_path->cep_adds_vect.av_srvl; 1502*c39526b7SPramod Gunjikar dest_path->port_num = src_path->cep_adds_vect.av_port_num; 1503*c39526b7SPramod Gunjikar dest_path->src_path_bits = src_path->cep_adds_vect.av_src_path; 1504*c39526b7SPramod Gunjikar dest_path->is_global = src_path->cep_adds_vect.av_send_grh; 1505*c39526b7SPramod Gunjikar dest_path->sgid_index = src_path->cep_adds_vect.av_sgid_ix; 1506*c39526b7SPramod Gunjikar dest_path->static_rate = src_path->cep_adds_vect.av_srate; 1507*c39526b7SPramod Gunjikar } 1508*c39526b7SPramod Gunjikar 1509*c39526b7SPramod Gunjikar /* 1510*c39526b7SPramod Gunjikar * Function: 1511*c39526b7SPramod Gunjikar * uverbs_query_copy_rc 1512*c39526b7SPramod Gunjikar * Input: 1513*c39526b7SPramod Gunjikar * src - The IBT RC QP attributes. 1514*c39526b7SPramod Gunjikar * Output: 1515*c39526b7SPramod Gunjikar * dest - The OFED user verbs QP attributes. 1516*c39526b7SPramod Gunjikar * Returns: 1517*c39526b7SPramod Gunjikar * None 1518*c39526b7SPramod Gunjikar * Description: 1519*c39526b7SPramod Gunjikar * Helper to copy IBT RC QP attributes to OFED QP attributes. 1520*c39526b7SPramod Gunjikar */ 1521*c39526b7SPramod Gunjikar static void 1522*c39526b7SPramod Gunjikar uverbs_query_copy_rc(struct ib_uverbs_query_qp_resp *dest, 1523*c39526b7SPramod Gunjikar ibt_qp_rc_attr_t *src) 1524*c39526b7SPramod Gunjikar { 1525*c39526b7SPramod Gunjikar dest->sq_psn = src->rc_sq_psn; 1526*c39526b7SPramod Gunjikar dest->rq_psn = src->rc_rq_psn; 1527*c39526b7SPramod Gunjikar dest->dest_qp_num = src->rc_dst_qpn; 1528*c39526b7SPramod Gunjikar dest->rnr_retry = src->rc_rnr_retry_cnt; 1529*c39526b7SPramod Gunjikar dest->retry_cnt = src->rc_retry_cnt; 1530*c39526b7SPramod Gunjikar dest->max_dest_rd_atomic = src->rc_rdma_ra_in; 1531*c39526b7SPramod Gunjikar dest->max_rd_atomic = src->rc_rdma_ra_out; 1532*c39526b7SPramod Gunjikar dest->min_rnr_timer = src->rc_min_rnr_nak; 1533*c39526b7SPramod Gunjikar dest->path_mtu = src->rc_path_mtu; 1534*c39526b7SPramod Gunjikar dest->timeout = src->rc_path.cep_timeout; 1535*c39526b7SPramod Gunjikar dest->alt_timeout = src->rc_alt_path.cep_timeout; 1536*c39526b7SPramod Gunjikar dest->port_num = src->rc_path.cep_hca_port_num; 1537*c39526b7SPramod Gunjikar dest->alt_port_num = src->rc_alt_path.cep_hca_port_num; 1538*c39526b7SPramod Gunjikar 1539*c39526b7SPramod Gunjikar if (src->rc_mig_state == IBT_STATE_MIGRATED) { 1540*c39526b7SPramod Gunjikar dest->path_mig_state = IB_MIG_MIGRATED; 1541*c39526b7SPramod Gunjikar } 1542*c39526b7SPramod Gunjikar if (src->rc_mig_state == IBT_STATE_REARMED) { 1543*c39526b7SPramod Gunjikar dest->path_mig_state = IB_MIG_REARM; 1544*c39526b7SPramod Gunjikar } 1545*c39526b7SPramod Gunjikar if (src->rc_mig_state == IBT_STATE_ARMED) { 1546*c39526b7SPramod Gunjikar dest->path_mig_state = IB_MIG_ARMED; 1547*c39526b7SPramod Gunjikar } 1548*c39526b7SPramod Gunjikar 1549*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibt(&src->rc_path, &dest->dest); 1550*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibt(&src->rc_alt_path, &dest->alt_dest); 1551*c39526b7SPramod Gunjikar } 1552*c39526b7SPramod Gunjikar 1553*c39526b7SPramod Gunjikar /* 1554*c39526b7SPramod Gunjikar * Function: 1555*c39526b7SPramod Gunjikar * uverbs_query_copy_uc 1556*c39526b7SPramod Gunjikar * Input: 1557*c39526b7SPramod Gunjikar * src - The IBT UC QP attributes. 1558*c39526b7SPramod Gunjikar * Output: 1559*c39526b7SPramod Gunjikar * dest - The OFED user verbs QP attributes. 1560*c39526b7SPramod Gunjikar * Returns: 1561*c39526b7SPramod Gunjikar * None 1562*c39526b7SPramod Gunjikar * Description: 1563*c39526b7SPramod Gunjikar * Helper to copy IBT UC QP attributes to OFED user verbs 1564*c39526b7SPramod Gunjikar * QP attributes. 1565*c39526b7SPramod Gunjikar */ 1566*c39526b7SPramod Gunjikar static void 1567*c39526b7SPramod Gunjikar uverbs_query_copy_uc(struct ib_uverbs_query_qp_resp *dest, 1568*c39526b7SPramod Gunjikar ibt_qp_uc_attr_t *src) 1569*c39526b7SPramod Gunjikar { 1570*c39526b7SPramod Gunjikar dest->sq_psn = src->uc_sq_psn; 1571*c39526b7SPramod Gunjikar dest->rq_psn = src->uc_rq_psn; 1572*c39526b7SPramod Gunjikar dest->dest_qp_num = src->uc_dst_qpn; 1573*c39526b7SPramod Gunjikar dest->path_mtu = src->uc_path_mtu; 1574*c39526b7SPramod Gunjikar 1575*c39526b7SPramod Gunjikar if (src->uc_mig_state == IBT_STATE_MIGRATED) { 1576*c39526b7SPramod Gunjikar dest->path_mig_state = IB_MIG_MIGRATED; 1577*c39526b7SPramod Gunjikar } 1578*c39526b7SPramod Gunjikar if (src->uc_mig_state == IBT_STATE_REARMED) { 1579*c39526b7SPramod Gunjikar dest->path_mig_state = IB_MIG_REARM; 1580*c39526b7SPramod Gunjikar } 1581*c39526b7SPramod Gunjikar if (src->uc_mig_state == IBT_STATE_ARMED) { 1582*c39526b7SPramod Gunjikar dest->path_mig_state = IB_MIG_ARMED; 1583*c39526b7SPramod Gunjikar } 1584*c39526b7SPramod Gunjikar 1585*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibt(&src->uc_path, &dest->dest); 1586*c39526b7SPramod Gunjikar uverbs_copy_path_info_from_ibt(&src->uc_alt_path, &dest->alt_dest); 1587*c39526b7SPramod Gunjikar } 1588*c39526b7SPramod Gunjikar 1589*c39526b7SPramod Gunjikar /* 1590*c39526b7SPramod Gunjikar * Function: 1591*c39526b7SPramod Gunjikar * uverbs_query_copy_rd 1592*c39526b7SPramod Gunjikar * Input: 1593*c39526b7SPramod Gunjikar * src - The IBT RD QP attributes. 1594*c39526b7SPramod Gunjikar * Output: 1595*c39526b7SPramod Gunjikar * dest - The OFED user verbs QP attributes. 1596*c39526b7SPramod Gunjikar * Returns: 1597*c39526b7SPramod Gunjikar * None 1598*c39526b7SPramod Gunjikar * Description: 1599*c39526b7SPramod Gunjikar * Helper to copy IBT RD QP attributes to OFED user verb QP attributes. 1600*c39526b7SPramod Gunjikar */ 1601*c39526b7SPramod Gunjikar static void 1602*c39526b7SPramod Gunjikar uverbs_query_copy_rd(struct ib_uverbs_query_qp_resp *dest, 1603*c39526b7SPramod Gunjikar ibt_qp_rd_attr_t *src) 1604*c39526b7SPramod Gunjikar { 1605*c39526b7SPramod Gunjikar dest->qkey = src->rd_qkey; 1606*c39526b7SPramod Gunjikar dest->min_rnr_timer = src->rd_min_rnr_nak; 1607*c39526b7SPramod Gunjikar } 1608*c39526b7SPramod Gunjikar 1609*c39526b7SPramod Gunjikar /* 1610*c39526b7SPramod Gunjikar * Function: 1611*c39526b7SPramod Gunjikar * uverbs_query_copy_ud 1612*c39526b7SPramod Gunjikar * Input: 1613*c39526b7SPramod Gunjikar * src - The IBT UD QP attributes. 1614*c39526b7SPramod Gunjikar * Output: 1615*c39526b7SPramod Gunjikar * dest - The OFED user verbs QP attributes. 1616*c39526b7SPramod Gunjikar * Returns: 1617*c39526b7SPramod Gunjikar * None 1618*c39526b7SPramod Gunjikar * Description: 1619*c39526b7SPramod Gunjikar * Helper to copy IBT UD QP attributes to OFED user verbs QP attributes. 1620*c39526b7SPramod Gunjikar */ 1621*c39526b7SPramod Gunjikar static void 1622*c39526b7SPramod Gunjikar uverbs_query_copy_ud(struct ib_uverbs_query_qp_resp *dest, 1623*c39526b7SPramod Gunjikar ibt_qp_ud_attr_t *src) 1624*c39526b7SPramod Gunjikar { 1625*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 1626*c39526b7SPramod Gunjikar "query_copy_ud:entry - return UD info: qkey:%08X, " 1627*c39526b7SPramod Gunjikar "psn:%d, pkey_idx:%d, port:%d", src->ud_qkey, src->ud_sq_psn, 1628*c39526b7SPramod Gunjikar src->ud_pkey_ix, src->ud_port); 1629*c39526b7SPramod Gunjikar 1630*c39526b7SPramod Gunjikar dest->qkey = src->ud_qkey; 1631*c39526b7SPramod Gunjikar dest->sq_psn = src->ud_sq_psn; 1632*c39526b7SPramod Gunjikar dest->pkey_index = src->ud_pkey_ix; 1633*c39526b7SPramod Gunjikar dest->port_num = src->ud_port; 1634*c39526b7SPramod Gunjikar } 1635*c39526b7SPramod Gunjikar 1636*c39526b7SPramod Gunjikar /* 1637*c39526b7SPramod Gunjikar * Function: 1638*c39526b7SPramod Gunjikar * uverbs_query_copy_info 1639*c39526b7SPramod Gunjikar * Input: 1640*c39526b7SPramod Gunjikar * src - The IBT QP information. 1641*c39526b7SPramod Gunjikar * Output: 1642*c39526b7SPramod Gunjikar * dest - The OFED user verbs QP attributes. 1643*c39526b7SPramod Gunjikar * Returns: 1644*c39526b7SPramod Gunjikar * None 1645*c39526b7SPramod Gunjikar * Description: 1646*c39526b7SPramod Gunjikar * Helper to copy IBT QP info to OFED user verbs QP attributes. 1647*c39526b7SPramod Gunjikar */ 1648*c39526b7SPramod Gunjikar static void 1649*c39526b7SPramod Gunjikar uverbs_query_copy_info(struct ib_uverbs_query_qp_resp *dest, 1650*c39526b7SPramod Gunjikar ibt_qp_info_t *src) 1651*c39526b7SPramod Gunjikar { 1652*c39526b7SPramod Gunjikar 1653*c39526b7SPramod Gunjikar dest->max_send_wr = src->qp_sq_sz; 1654*c39526b7SPramod Gunjikar dest->max_recv_wr = src->qp_rq_sz; 1655*c39526b7SPramod Gunjikar dest->qp_access_flags = ibt_cep_flags2ibv(src->qp_flags); 1656*c39526b7SPramod Gunjikar 1657*c39526b7SPramod Gunjikar switch (src->qp_state) { 1658*c39526b7SPramod Gunjikar case IBT_STATE_RESET: 1659*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_RESET; 1660*c39526b7SPramod Gunjikar break; 1661*c39526b7SPramod Gunjikar case IBT_STATE_INIT: 1662*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_INIT; 1663*c39526b7SPramod Gunjikar break; 1664*c39526b7SPramod Gunjikar case IBT_STATE_RTR: 1665*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_RTR; 1666*c39526b7SPramod Gunjikar break; 1667*c39526b7SPramod Gunjikar case IBT_STATE_RTS: 1668*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_RTS; 1669*c39526b7SPramod Gunjikar break; 1670*c39526b7SPramod Gunjikar case IBT_STATE_SQD: 1671*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_SQD; 1672*c39526b7SPramod Gunjikar break; 1673*c39526b7SPramod Gunjikar case IBT_STATE_SQE: 1674*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_SQE; 1675*c39526b7SPramod Gunjikar break; 1676*c39526b7SPramod Gunjikar case IBT_STATE_ERROR: 1677*c39526b7SPramod Gunjikar default: 1678*c39526b7SPramod Gunjikar dest->qp_state = IB_QPS_ERR; 1679*c39526b7SPramod Gunjikar break; 1680*c39526b7SPramod Gunjikar } 1681*c39526b7SPramod Gunjikar 1682*c39526b7SPramod Gunjikar switch (src->qp_current_state) { 1683*c39526b7SPramod Gunjikar case IBT_STATE_RESET: 1684*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_RESET; 1685*c39526b7SPramod Gunjikar break; 1686*c39526b7SPramod Gunjikar case IBT_STATE_INIT: 1687*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_INIT; 1688*c39526b7SPramod Gunjikar break; 1689*c39526b7SPramod Gunjikar case IBT_STATE_RTR: 1690*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_RTR; 1691*c39526b7SPramod Gunjikar break; 1692*c39526b7SPramod Gunjikar case IBT_STATE_RTS: 1693*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_RTS; 1694*c39526b7SPramod Gunjikar break; 1695*c39526b7SPramod Gunjikar case IBT_STATE_SQD: 1696*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_SQD; 1697*c39526b7SPramod Gunjikar break; 1698*c39526b7SPramod Gunjikar case IBT_STATE_SQE: 1699*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_SQE; 1700*c39526b7SPramod Gunjikar break; 1701*c39526b7SPramod Gunjikar case IBT_STATE_ERROR: 1702*c39526b7SPramod Gunjikar default: 1703*c39526b7SPramod Gunjikar dest->cur_qp_state = IB_QPS_ERR; 1704*c39526b7SPramod Gunjikar break; 1705*c39526b7SPramod Gunjikar } 1706*c39526b7SPramod Gunjikar 1707*c39526b7SPramod Gunjikar if ((src->qp_flags & IBT_ALL_SIGNALED) == IBT_ALL_SIGNALED) { 1708*c39526b7SPramod Gunjikar dest->sq_sig_all = 1; 1709*c39526b7SPramod Gunjikar } 1710*c39526b7SPramod Gunjikar } 1711*c39526b7SPramod Gunjikar 1712*c39526b7SPramod Gunjikar /* 1713*c39526b7SPramod Gunjikar * Function: 1714*c39526b7SPramod Gunjikar * uverbs_query_copy_attr 1715*c39526b7SPramod Gunjikar * Input: 1716*c39526b7SPramod Gunjikar * src - The IBT QP information. 1717*c39526b7SPramod Gunjikar * Output: 1718*c39526b7SPramod Gunjikar * dest - The OFED user verbs QP attributes. 1719*c39526b7SPramod Gunjikar * Returns: 1720*c39526b7SPramod Gunjikar * None 1721*c39526b7SPramod Gunjikar * Description: 1722*c39526b7SPramod Gunjikar * Helper to copy IBT QP attributes to OFED user verbs QP attributes. 1723*c39526b7SPramod Gunjikar */ 1724*c39526b7SPramod Gunjikar static void 1725*c39526b7SPramod Gunjikar uverbs_query_copy_attr(struct ib_uverbs_query_qp_resp *dest, 1726*c39526b7SPramod Gunjikar ibt_qp_query_attr_t *src) 1727*c39526b7SPramod Gunjikar { 1728*c39526b7SPramod Gunjikar dest->max_send_sge = src->qp_sq_sgl; 1729*c39526b7SPramod Gunjikar dest->max_recv_sge = src->qp_rq_sgl; 1730*c39526b7SPramod Gunjikar } 1731*c39526b7SPramod Gunjikar 1732*c39526b7SPramod Gunjikar /* 1733*c39526b7SPramod Gunjikar * Function: 1734*c39526b7SPramod Gunjikar * sol_uverbs_query_qp 1735*c39526b7SPramod Gunjikar * Input: 1736*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 1737*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing query QP command. 1738*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 1739*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 1740*c39526b7SPramod Gunjikar * Output: 1741*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 1742*c39526b7SPramod Gunjikar * Returns: 1743*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 1744*c39526b7SPramod Gunjikar * Description: 1745*c39526b7SPramod Gunjikar * User verbs entry point to query a device QP properties. 1746*c39526b7SPramod Gunjikar */ 1747*c39526b7SPramod Gunjikar /* ARGSUSED */ 1748*c39526b7SPramod Gunjikar int 1749*c39526b7SPramod Gunjikar sol_uverbs_query_qp(uverbs_uctxt_uobj_t *uctxt, char *buf, 1750*c39526b7SPramod Gunjikar int in_len, int out_len) 1751*c39526b7SPramod Gunjikar { 1752*c39526b7SPramod Gunjikar struct ib_uverbs_query_qp cmd; 1753*c39526b7SPramod Gunjikar struct ib_uverbs_query_qp_resp resp; 1754*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 1755*c39526b7SPramod Gunjikar ibt_qp_query_attr_t qp_query_attr; 1756*c39526b7SPramod Gunjikar int rc; 1757*c39526b7SPramod Gunjikar 1758*c39526b7SPramod Gunjikar (void) memset(&resp, 0, sizeof (resp)); 1759*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 1760*c39526b7SPramod Gunjikar 1761*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 1762*c39526b7SPramod Gunjikar "query_qp: entry (qp_handle=%d)", cmd.qp_handle); 1763*c39526b7SPramod Gunjikar 1764*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_read(cmd.qp_handle); 1765*c39526b7SPramod Gunjikar if (uqp == NULL) { 1766*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1767*c39526b7SPramod Gunjikar "query_qp(): List lookup failure"); 1768*c39526b7SPramod Gunjikar rc = EINVAL; 1769*c39526b7SPramod Gunjikar goto err_out; 1770*c39526b7SPramod Gunjikar } 1771*c39526b7SPramod Gunjikar 1772*c39526b7SPramod Gunjikar bzero(&qp_query_attr, sizeof (qp_query_attr)); 1773*c39526b7SPramod Gunjikar rc = ibt_query_qp(uqp->qp, &qp_query_attr); 1774*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 1775*c39526b7SPramod Gunjikar 1776*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 1777*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1778*c39526b7SPramod Gunjikar "query_qp: Error in ibt_query_qp() (rc=%d)", rc); 1779*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 1780*c39526b7SPramod Gunjikar goto err_out; 1781*c39526b7SPramod Gunjikar } 1782*c39526b7SPramod Gunjikar 1783*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 1784*c39526b7SPramod Gunjikar "query_qp(): qp_query_attr.qp_info.qp_trans = %d", 1785*c39526b7SPramod Gunjikar qp_query_attr.qp_info.qp_trans); 1786*c39526b7SPramod Gunjikar 1787*c39526b7SPramod Gunjikar uverbs_query_copy_attr(&resp, &qp_query_attr); 1788*c39526b7SPramod Gunjikar uverbs_query_copy_info(&resp, &qp_query_attr.qp_info); 1789*c39526b7SPramod Gunjikar 1790*c39526b7SPramod Gunjikar if (qp_query_attr.qp_info.qp_trans == IBT_RC_SRV) { 1791*c39526b7SPramod Gunjikar uverbs_query_copy_rc(&resp, 1792*c39526b7SPramod Gunjikar &qp_query_attr.qp_info.qp_transport.rc); 1793*c39526b7SPramod Gunjikar } 1794*c39526b7SPramod Gunjikar 1795*c39526b7SPramod Gunjikar if (qp_query_attr.qp_info.qp_trans == IBT_UC_SRV) { 1796*c39526b7SPramod Gunjikar uverbs_query_copy_uc(&resp, 1797*c39526b7SPramod Gunjikar &qp_query_attr.qp_info.qp_transport.uc); 1798*c39526b7SPramod Gunjikar } 1799*c39526b7SPramod Gunjikar 1800*c39526b7SPramod Gunjikar if (qp_query_attr.qp_info.qp_trans == IBT_RD_SRV) { 1801*c39526b7SPramod Gunjikar uverbs_query_copy_rd(&resp, 1802*c39526b7SPramod Gunjikar &qp_query_attr.qp_info.qp_transport.rd); 1803*c39526b7SPramod Gunjikar } 1804*c39526b7SPramod Gunjikar 1805*c39526b7SPramod Gunjikar 1806*c39526b7SPramod Gunjikar if (qp_query_attr.qp_info.qp_trans == IBT_UD_SRV) { 1807*c39526b7SPramod Gunjikar uverbs_query_copy_ud(&resp, 1808*c39526b7SPramod Gunjikar &qp_query_attr.qp_info.qp_transport.ud); 1809*c39526b7SPramod Gunjikar } 1810*c39526b7SPramod Gunjikar 1811*c39526b7SPramod Gunjikar resp.max_inline_data = uqp->max_inline_data; 1812*c39526b7SPramod Gunjikar 1813*c39526b7SPramod Gunjikar #ifdef _LP64 1814*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp)); 1815*c39526b7SPramod Gunjikar #else 1816*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp)); 1817*c39526b7SPramod Gunjikar #endif 1818*c39526b7SPramod Gunjikar if (rc != 0) { 1819*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1820*c39526b7SPramod Gunjikar "query_qp(): Error writing resp data (rc=%d)", rc); 1821*c39526b7SPramod Gunjikar rc = EFAULT; 1822*c39526b7SPramod Gunjikar goto err_out; 1823*c39526b7SPramod Gunjikar } 1824*c39526b7SPramod Gunjikar 1825*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 1826*c39526b7SPramod Gunjikar 1827*c39526b7SPramod Gunjikar err_out: 1828*c39526b7SPramod Gunjikar return (rc); 1829*c39526b7SPramod Gunjikar } 1830*c39526b7SPramod Gunjikar 1831*c39526b7SPramod Gunjikar /* 1832*c39526b7SPramod Gunjikar * Function: 1833*c39526b7SPramod Gunjikar * sol_uverbs_create_srq 1834*c39526b7SPramod Gunjikar * Input: 1835*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 1836*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing command. 1837*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 1838*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 1839*c39526b7SPramod Gunjikar * Output: 1840*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 1841*c39526b7SPramod Gunjikar * Returns: 1842*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 1843*c39526b7SPramod Gunjikar * Description: 1844*c39526b7SPramod Gunjikar * User verbs entry point to create a device shared receive queue. 1845*c39526b7SPramod Gunjikar */ 1846*c39526b7SPramod Gunjikar /* ARGSUSED */ 1847*c39526b7SPramod Gunjikar int 1848*c39526b7SPramod Gunjikar sol_uverbs_create_srq(uverbs_uctxt_uobj_t *uctxt, char *buf, 1849*c39526b7SPramod Gunjikar int in_len, int out_len) 1850*c39526b7SPramod Gunjikar { 1851*c39526b7SPramod Gunjikar struct ib_uverbs_create_srq cmd; 1852*c39526b7SPramod Gunjikar struct ib_uverbs_create_srq_resp resp; 1853*c39526b7SPramod Gunjikar uverbs_usrq_uobj_t *usrq; 1854*c39526b7SPramod Gunjikar uverbs_upd_uobj_t *upd; 1855*c39526b7SPramod Gunjikar ibt_srq_flags_t flags = IBT_SRQ_USER_MAP; 1856*c39526b7SPramod Gunjikar ibt_srq_sizes_t attr; 1857*c39526b7SPramod Gunjikar ibt_srq_sizes_t real_attr; 1858*c39526b7SPramod Gunjikar int rc; 1859*c39526b7SPramod Gunjikar 1860*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 1861*c39526b7SPramod Gunjikar (void) memset(&resp, 0, sizeof (resp)); 1862*c39526b7SPramod Gunjikar (void) memset(&attr, 0, sizeof (attr)); 1863*c39526b7SPramod Gunjikar 1864*c39526b7SPramod Gunjikar attr.srq_wr_sz = cmd.max_wr; 1865*c39526b7SPramod Gunjikar attr.srq_sgl_sz = cmd.max_sge; 1866*c39526b7SPramod Gunjikar 1867*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "create_srq: " 1868*c39526b7SPramod Gunjikar "max_wr=%d, max_sge=%d, srq_limit=%d", 1869*c39526b7SPramod Gunjikar cmd.max_wr, cmd.max_sge, cmd.srq_limit); 1870*c39526b7SPramod Gunjikar 1871*c39526b7SPramod Gunjikar if (!attr.srq_wr_sz) { 1872*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 1873*c39526b7SPramod Gunjikar "create_srq(): Invalid args, invalid work " 1874*c39526b7SPramod Gunjikar "request size"); 1875*c39526b7SPramod Gunjikar 1876*c39526b7SPramod Gunjikar rc = EINVAL; 1877*c39526b7SPramod Gunjikar goto err_out; 1878*c39526b7SPramod Gunjikar } 1879*c39526b7SPramod Gunjikar 1880*c39526b7SPramod Gunjikar if (attr.srq_wr_sz > uctxt->hca->attr.hca_max_srqs_sz || 1881*c39526b7SPramod Gunjikar attr.srq_sgl_sz > uctxt->hca->attr.hca_max_srq_sgl) { 1882*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1883*c39526b7SPramod Gunjikar "create_srq(): Invalid args, too large"); 1884*c39526b7SPramod Gunjikar rc = EINVAL; 1885*c39526b7SPramod Gunjikar goto err_out; 1886*c39526b7SPramod Gunjikar } 1887*c39526b7SPramod Gunjikar 1888*c39526b7SPramod Gunjikar usrq = kmem_zalloc(sizeof (*usrq), KM_NOSLEEP); 1889*c39526b7SPramod Gunjikar if (usrq == NULL) { 1890*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1891*c39526b7SPramod Gunjikar "create_srq(): User object alloc failed"); 1892*c39526b7SPramod Gunjikar rc = ENOMEM; 1893*c39526b7SPramod Gunjikar goto err_out; 1894*c39526b7SPramod Gunjikar } 1895*c39526b7SPramod Gunjikar sol_ofs_uobj_init(&usrq->uobj, cmd.user_handle, 1896*c39526b7SPramod Gunjikar SOL_UVERBS_USRQ_UOBJ_TYPE); 1897*c39526b7SPramod Gunjikar rw_enter(&usrq->uobj.uo_lock, RW_WRITER); 1898*c39526b7SPramod Gunjikar llist_head_init(&usrq->async_list, NULL); 1899*c39526b7SPramod Gunjikar usrq->async_events_reported = 0; 1900*c39526b7SPramod Gunjikar usrq->uctxt = uctxt; 1901*c39526b7SPramod Gunjikar 1902*c39526b7SPramod Gunjikar upd = uverbs_uobj_get_upd_read(cmd.pd_handle); 1903*c39526b7SPramod Gunjikar if (upd == NULL) { 1904*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1905*c39526b7SPramod Gunjikar "create_srq(): PD Invalid"); 1906*c39526b7SPramod Gunjikar rc = EINVAL; 1907*c39526b7SPramod Gunjikar goto err_dealloc; 1908*c39526b7SPramod Gunjikar } 1909*c39526b7SPramod Gunjikar 1910*c39526b7SPramod Gunjikar rc = ibt_alloc_srq(uctxt->hca->hdl, flags, upd->pd, &attr, &usrq->srq, 1911*c39526b7SPramod Gunjikar &real_attr); 1912*c39526b7SPramod Gunjikar 1913*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 1914*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1915*c39526b7SPramod Gunjikar "create_srq(): Error in ibt_alloc_srq() (rc=%d)", rc); 1916*c39526b7SPramod Gunjikar usrq->srq = NULL; 1917*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 1918*c39526b7SPramod Gunjikar usrq->uobj.uo_uobj_sz = sizeof (uverbs_usrq_uobj_t); 1919*c39526b7SPramod Gunjikar goto err_release_pd; 1920*c39526b7SPramod Gunjikar } 1921*c39526b7SPramod Gunjikar 1922*c39526b7SPramod Gunjikar ibt_set_srq_private(usrq->srq, usrq); 1923*c39526b7SPramod Gunjikar 1924*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 1925*c39526b7SPramod Gunjikar "create_srq(): ib_alloc_srq()real wqe_sz=%d, real_sg_sz=%d", 1926*c39526b7SPramod Gunjikar real_attr.srq_wr_sz, real_attr.srq_sgl_sz); 1927*c39526b7SPramod Gunjikar 1928*c39526b7SPramod Gunjikar /* 1929*c39526b7SPramod Gunjikar * Query underlying hardware for data used in mapping CQ back to user 1930*c39526b7SPramod Gunjikar * space, we will return this information in the user verbs command 1931*c39526b7SPramod Gunjikar * response. 1932*c39526b7SPramod Gunjikar */ 1933*c39526b7SPramod Gunjikar rc = ibt_ci_data_out(uctxt->hca->hdl, IBT_CI_NO_FLAGS, IBT_HDL_SRQ, 1934*c39526b7SPramod Gunjikar (void *)usrq->srq, &resp.drv_out, sizeof (resp.drv_out)); 1935*c39526b7SPramod Gunjikar 1936*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 1937*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1938*c39526b7SPramod Gunjikar "create_srq(): Error in ibt_ci_data_out() (rc=%d)", rc); 1939*c39526b7SPramod Gunjikar rc = EFAULT; 1940*c39526b7SPramod Gunjikar usrq->uobj.uo_uobj_sz = sizeof (uverbs_usrq_uobj_t); 1941*c39526b7SPramod Gunjikar goto err_srq_destroy; 1942*c39526b7SPramod Gunjikar } 1943*c39526b7SPramod Gunjikar 1944*c39526b7SPramod Gunjikar if (sol_ofs_uobj_add(&uverbs_usrq_uo_tbl, &usrq->uobj) != 0) { 1945*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1946*c39526b7SPramod Gunjikar "create_srq(): uobj add failed"); 1947*c39526b7SPramod Gunjikar rc = ENOMEM; 1948*c39526b7SPramod Gunjikar goto err_srq_destroy; 1949*c39526b7SPramod Gunjikar } 1950*c39526b7SPramod Gunjikar 1951*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 1952*c39526b7SPramod Gunjikar "create_srq(): ibt_ci_data_out: 0x%16llx 0x%16llx 0x%16llx " 1953*c39526b7SPramod Gunjikar "0x%16llx", resp.drv_out[0], resp.drv_out[1], resp.drv_out[2], 1954*c39526b7SPramod Gunjikar resp.drv_out[3]); 1955*c39526b7SPramod Gunjikar 1956*c39526b7SPramod Gunjikar resp.srq_handle = usrq->uobj.uo_id; 1957*c39526b7SPramod Gunjikar resp.max_wr = real_attr.srq_wr_sz; 1958*c39526b7SPramod Gunjikar resp.max_sge = real_attr.srq_sgl_sz; 1959*c39526b7SPramod Gunjikar 1960*c39526b7SPramod Gunjikar #ifdef _LP64 1961*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp)); 1962*c39526b7SPramod Gunjikar #else 1963*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp)); 1964*c39526b7SPramod Gunjikar #endif 1965*c39526b7SPramod Gunjikar if (rc != 0) { 1966*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1967*c39526b7SPramod Gunjikar "create_srq(): Error writing resp data (rc=%d)", rc); 1968*c39526b7SPramod Gunjikar rc = EFAULT; 1969*c39526b7SPramod Gunjikar goto err_uo_delete; 1970*c39526b7SPramod Gunjikar } 1971*c39526b7SPramod Gunjikar 1972*c39526b7SPramod Gunjikar mutex_enter(&uctxt->lock); 1973*c39526b7SPramod Gunjikar usrq->list_entry = add_genlist(&uctxt->srq_list, (uintptr_t)usrq, 1974*c39526b7SPramod Gunjikar uctxt); 1975*c39526b7SPramod Gunjikar mutex_exit(&uctxt->lock); 1976*c39526b7SPramod Gunjikar 1977*c39526b7SPramod Gunjikar if (!usrq->list_entry) { 1978*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 1979*c39526b7SPramod Gunjikar "create_srq() : Error adding usrq to srq_list failed"); 1980*c39526b7SPramod Gunjikar rc = ENOMEM; 1981*c39526b7SPramod Gunjikar goto err_uo_delete; 1982*c39526b7SPramod Gunjikar } 1983*c39526b7SPramod Gunjikar 1984*c39526b7SPramod Gunjikar usrq->uobj.uo_live = 1; 1985*c39526b7SPramod Gunjikar rw_exit(&usrq->uobj.uo_lock); 1986*c39526b7SPramod Gunjikar 1987*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&upd->uobj); 1988*c39526b7SPramod Gunjikar 1989*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 1990*c39526b7SPramod Gunjikar 1991*c39526b7SPramod Gunjikar err_uo_delete: 1992*c39526b7SPramod Gunjikar /* 1993*c39526b7SPramod Gunjikar * Need to set uo_live, so sol_ofs_uobj_remove() will 1994*c39526b7SPramod Gunjikar * remove the object from the object table. 1995*c39526b7SPramod Gunjikar */ 1996*c39526b7SPramod Gunjikar usrq->uobj.uo_live = 1; 1997*c39526b7SPramod Gunjikar (void) sol_ofs_uobj_remove(&uverbs_usrq_uo_tbl, &usrq->uobj); 1998*c39526b7SPramod Gunjikar 1999*c39526b7SPramod Gunjikar err_srq_destroy: 2000*c39526b7SPramod Gunjikar (void) ibt_free_srq(usrq->srq); 2001*c39526b7SPramod Gunjikar 2002*c39526b7SPramod Gunjikar err_release_pd: 2003*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&upd->uobj); 2004*c39526b7SPramod Gunjikar 2005*c39526b7SPramod Gunjikar err_dealloc: 2006*c39526b7SPramod Gunjikar rw_exit(&usrq->uobj.uo_lock); 2007*c39526b7SPramod Gunjikar sol_ofs_uobj_deref(&usrq->uobj, sol_ofs_uobj_free); 2008*c39526b7SPramod Gunjikar 2009*c39526b7SPramod Gunjikar err_out: 2010*c39526b7SPramod Gunjikar return (rc); 2011*c39526b7SPramod Gunjikar } 2012*c39526b7SPramod Gunjikar 2013*c39526b7SPramod Gunjikar /* 2014*c39526b7SPramod Gunjikar * Function: 2015*c39526b7SPramod Gunjikar * sol_uverbs_modify_srq 2016*c39526b7SPramod Gunjikar * Input: 2017*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 2018*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing SRQ modify command. 2019*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 2020*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 2021*c39526b7SPramod Gunjikar * Output: 2022*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 2023*c39526b7SPramod Gunjikar * Returns: 2024*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 2025*c39526b7SPramod Gunjikar * Description: 2026*c39526b7SPramod Gunjikar * User verbs entry point to modify a device shared receive queue. 2027*c39526b7SPramod Gunjikar */ 2028*c39526b7SPramod Gunjikar /* ARGSUSED */ 2029*c39526b7SPramod Gunjikar int 2030*c39526b7SPramod Gunjikar sol_uverbs_modify_srq(uverbs_uctxt_uobj_t *uctxt, char *buf, 2031*c39526b7SPramod Gunjikar int in_len, int out_len) 2032*c39526b7SPramod Gunjikar { 2033*c39526b7SPramod Gunjikar struct ib_uverbs_modify_srq cmd; 2034*c39526b7SPramod Gunjikar uverbs_usrq_uobj_t *usrq; 2035*c39526b7SPramod Gunjikar uint_t limit = 0; 2036*c39526b7SPramod Gunjikar uint_t size = 0; 2037*c39526b7SPramod Gunjikar uint_t real_size = 0; 2038*c39526b7SPramod Gunjikar ibt_srq_modify_flags_t flags = 0; 2039*c39526b7SPramod Gunjikar int rc; 2040*c39526b7SPramod Gunjikar 2041*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 2042*c39526b7SPramod Gunjikar 2043*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 2044*c39526b7SPramod Gunjikar "modify_srq(): entry (srq_handle=%d)", cmd.srq_handle); 2045*c39526b7SPramod Gunjikar 2046*c39526b7SPramod Gunjikar usrq = uverbs_uobj_get_usrq_read(cmd.srq_handle); 2047*c39526b7SPramod Gunjikar if (usrq == NULL) { 2048*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2049*c39526b7SPramod Gunjikar "modify_srq(): List lookup failure"); 2050*c39526b7SPramod Gunjikar rc = EINVAL; 2051*c39526b7SPramod Gunjikar goto err_out; 2052*c39526b7SPramod Gunjikar } 2053*c39526b7SPramod Gunjikar 2054*c39526b7SPramod Gunjikar if (cmd.attr_mask & IB_SRQ_MAX_WR) { 2055*c39526b7SPramod Gunjikar flags = IBT_SRQ_SET_SIZE; 2056*c39526b7SPramod Gunjikar size = cmd.max_wr; 2057*c39526b7SPramod Gunjikar } 2058*c39526b7SPramod Gunjikar 2059*c39526b7SPramod Gunjikar if (cmd.attr_mask & IB_SRQ_LIMIT) { 2060*c39526b7SPramod Gunjikar flags |= IBT_SRQ_SET_LIMIT; 2061*c39526b7SPramod Gunjikar limit = cmd.srq_limit; 2062*c39526b7SPramod Gunjikar } 2063*c39526b7SPramod Gunjikar 2064*c39526b7SPramod Gunjikar rc = ibt_modify_srq(usrq->srq, flags, size, limit, &real_size); 2065*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 2066*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2067*c39526b7SPramod Gunjikar "modify_srq(): Error in ibt_modify_srq() (rc=%d)", rc); 2068*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 2069*c39526b7SPramod Gunjikar goto err_deref; 2070*c39526b7SPramod Gunjikar } 2071*c39526b7SPramod Gunjikar 2072*c39526b7SPramod Gunjikar done: 2073*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 2074*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 2075*c39526b7SPramod Gunjikar 2076*c39526b7SPramod Gunjikar err_deref: 2077*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 2078*c39526b7SPramod Gunjikar 2079*c39526b7SPramod Gunjikar err_out: 2080*c39526b7SPramod Gunjikar return (rc); 2081*c39526b7SPramod Gunjikar } 2082*c39526b7SPramod Gunjikar 2083*c39526b7SPramod Gunjikar /* 2084*c39526b7SPramod Gunjikar * Function: 2085*c39526b7SPramod Gunjikar * sol_uverbs_query_srq 2086*c39526b7SPramod Gunjikar * Input: 2087*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 2088*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing command. 2089*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 2090*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 2091*c39526b7SPramod Gunjikar * Output: 2092*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 2093*c39526b7SPramod Gunjikar * Returns: 2094*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 2095*c39526b7SPramod Gunjikar * Description: 2096*c39526b7SPramod Gunjikar * User verbs entry point to query a device shared receive queue 2097*c39526b7SPramod Gunjikar * properties. 2098*c39526b7SPramod Gunjikar */ 2099*c39526b7SPramod Gunjikar /* ARGSUSED */ 2100*c39526b7SPramod Gunjikar int 2101*c39526b7SPramod Gunjikar sol_uverbs_query_srq(uverbs_uctxt_uobj_t *uctxt, char *buf, 2102*c39526b7SPramod Gunjikar int in_len, int out_len) 2103*c39526b7SPramod Gunjikar { 2104*c39526b7SPramod Gunjikar struct ib_uverbs_query_srq cmd; 2105*c39526b7SPramod Gunjikar struct ib_uverbs_query_srq_resp resp; 2106*c39526b7SPramod Gunjikar uverbs_usrq_uobj_t *usrq; 2107*c39526b7SPramod Gunjikar ibt_pd_hdl_t pd; 2108*c39526b7SPramod Gunjikar int rc; 2109*c39526b7SPramod Gunjikar ibt_srq_sizes_t attr; 2110*c39526b7SPramod Gunjikar uint_t limit; 2111*c39526b7SPramod Gunjikar 2112*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 2113*c39526b7SPramod Gunjikar (void) memset(&resp, 0, sizeof (resp)); 2114*c39526b7SPramod Gunjikar 2115*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 2116*c39526b7SPramod Gunjikar "query_srq(): entry (srq_handle=%d)", cmd.srq_handle); 2117*c39526b7SPramod Gunjikar 2118*c39526b7SPramod Gunjikar usrq = uverbs_uobj_get_usrq_read(cmd.srq_handle); 2119*c39526b7SPramod Gunjikar if (usrq == NULL) { 2120*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2121*c39526b7SPramod Gunjikar "query_srq(): Invalid handle: %d", cmd.srq_handle); 2122*c39526b7SPramod Gunjikar rc = EINVAL; 2123*c39526b7SPramod Gunjikar goto err_out; 2124*c39526b7SPramod Gunjikar } 2125*c39526b7SPramod Gunjikar 2126*c39526b7SPramod Gunjikar rc = ibt_query_srq(usrq->srq, &pd, &attr, &limit); 2127*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 2128*c39526b7SPramod Gunjikar 2129*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 2130*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2131*c39526b7SPramod Gunjikar "query_srq(): Error in ibt_query_srq() (rc=%d)", rc); 2132*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 2133*c39526b7SPramod Gunjikar goto err_out; 2134*c39526b7SPramod Gunjikar } 2135*c39526b7SPramod Gunjikar 2136*c39526b7SPramod Gunjikar resp.max_wr = attr.srq_wr_sz; 2137*c39526b7SPramod Gunjikar resp.max_sge = attr.srq_sgl_sz; 2138*c39526b7SPramod Gunjikar resp.srq_limit = limit; 2139*c39526b7SPramod Gunjikar 2140*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "query_srq() - " 2141*c39526b7SPramod Gunjikar "max_wr=%d, max_sge=%d, limit=%d", resp.max_wr, 2142*c39526b7SPramod Gunjikar resp.max_sge, resp.srq_limit); 2143*c39526b7SPramod Gunjikar 2144*c39526b7SPramod Gunjikar /* 2145*c39526b7SPramod Gunjikar * Release the reference from the find above, we leave the initial 2146*c39526b7SPramod Gunjikar * reference placed at SRQ creation time. 2147*c39526b7SPramod Gunjikar */ 2148*c39526b7SPramod Gunjikar 2149*c39526b7SPramod Gunjikar #ifdef _LP64 2150*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp)); 2151*c39526b7SPramod Gunjikar #else 2152*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp)); 2153*c39526b7SPramod Gunjikar #endif 2154*c39526b7SPramod Gunjikar if (rc != 0) { 2155*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "query_srq() - " 2156*c39526b7SPramod Gunjikar "copyout failure %x", rc); 2157*c39526b7SPramod Gunjikar rc = EFAULT; 2158*c39526b7SPramod Gunjikar goto err_out; 2159*c39526b7SPramod Gunjikar } 2160*c39526b7SPramod Gunjikar 2161*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 2162*c39526b7SPramod Gunjikar 2163*c39526b7SPramod Gunjikar err_out: 2164*c39526b7SPramod Gunjikar return (rc); 2165*c39526b7SPramod Gunjikar } 2166*c39526b7SPramod Gunjikar 2167*c39526b7SPramod Gunjikar int 2168*c39526b7SPramod Gunjikar uverbs_usrq_free(uverbs_usrq_uobj_t *usrq, uverbs_uctxt_uobj_t *uctxt) 2169*c39526b7SPramod Gunjikar { 2170*c39526b7SPramod Gunjikar int rc; 2171*c39526b7SPramod Gunjikar 2172*c39526b7SPramod Gunjikar if (!usrq->srq) 2173*c39526b7SPramod Gunjikar goto skip_ibt_free_srq; 2174*c39526b7SPramod Gunjikar 2175*c39526b7SPramod Gunjikar rc = ibt_free_srq(usrq->srq); 2176*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 2177*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, "usrq_free() - " 2178*c39526b7SPramod Gunjikar "Error in ibt_free_srq() (rc=%d)", rc); 2179*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 2180*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 2181*c39526b7SPramod Gunjikar return (rc); 2182*c39526b7SPramod Gunjikar } 2183*c39526b7SPramod Gunjikar usrq->srq = NULL; 2184*c39526b7SPramod Gunjikar 2185*c39526b7SPramod Gunjikar skip_ibt_free_srq : 2186*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 2187*c39526b7SPramod Gunjikar if (usrq->list_entry) { 2188*c39526b7SPramod Gunjikar mutex_enter(&uctxt->lock); 2189*c39526b7SPramod Gunjikar delete_genlist(&uctxt->srq_list, usrq->list_entry); 2190*c39526b7SPramod Gunjikar mutex_exit(&uctxt->lock); 2191*c39526b7SPramod Gunjikar (void) sol_ofs_uobj_remove(&uverbs_usrq_uo_tbl, &usrq->uobj); 2192*c39526b7SPramod Gunjikar } 2193*c39526b7SPramod Gunjikar sol_ofs_uobj_deref(&usrq->uobj, sol_ofs_uobj_free); 2194*c39526b7SPramod Gunjikar 2195*c39526b7SPramod Gunjikar return (0); 2196*c39526b7SPramod Gunjikar } 2197*c39526b7SPramod Gunjikar 2198*c39526b7SPramod Gunjikar /* 2199*c39526b7SPramod Gunjikar * Function: 2200*c39526b7SPramod Gunjikar * sol_uverbs_destroy_srq 2201*c39526b7SPramod Gunjikar * Input: 2202*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 2203*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing command. 2204*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 2205*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 2206*c39526b7SPramod Gunjikar * Output: 2207*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 2208*c39526b7SPramod Gunjikar * Returns: 2209*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 2210*c39526b7SPramod Gunjikar * Description: 2211*c39526b7SPramod Gunjikar * User verbs entry point to destroy a device shared receive queue. 2212*c39526b7SPramod Gunjikar */ 2213*c39526b7SPramod Gunjikar /* ARGSUSED */ 2214*c39526b7SPramod Gunjikar int 2215*c39526b7SPramod Gunjikar sol_uverbs_destroy_srq(uverbs_uctxt_uobj_t *uctxt, char *buf, 2216*c39526b7SPramod Gunjikar int in_len, int out_len) 2217*c39526b7SPramod Gunjikar { 2218*c39526b7SPramod Gunjikar struct ib_uverbs_destroy_srq cmd; 2219*c39526b7SPramod Gunjikar struct ib_uverbs_destroy_srq_resp resp; 2220*c39526b7SPramod Gunjikar uverbs_usrq_uobj_t *usrq; 2221*c39526b7SPramod Gunjikar int rc; 2222*c39526b7SPramod Gunjikar 2223*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 2224*c39526b7SPramod Gunjikar (void) memset(&resp, 0, sizeof (resp)); 2225*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "destroy_srq() - " 2226*c39526b7SPramod Gunjikar "srq_handle %d", cmd.srq_handle); 2227*c39526b7SPramod Gunjikar 2228*c39526b7SPramod Gunjikar usrq = uverbs_uobj_get_usrq_write(cmd.srq_handle); 2229*c39526b7SPramod Gunjikar if (usrq == NULL) { 2230*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2231*c39526b7SPramod Gunjikar "destroy_srq() : inavlid hdl %d", cmd.srq_handle); 2232*c39526b7SPramod Gunjikar rc = EINVAL; 2233*c39526b7SPramod Gunjikar goto err_out; 2234*c39526b7SPramod Gunjikar } 2235*c39526b7SPramod Gunjikar 2236*c39526b7SPramod Gunjikar uverbs_release_usrq_uevents(uctxt->async_evfile, usrq); 2237*c39526b7SPramod Gunjikar resp.events_reported = usrq->async_events_reported; 2238*c39526b7SPramod Gunjikar if (usrq->active_qp_cnt) { 2239*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&usrq->uobj); 2240*c39526b7SPramod Gunjikar return (EBUSY); 2241*c39526b7SPramod Gunjikar } else { 2242*c39526b7SPramod Gunjikar rc = uverbs_usrq_free(usrq, uctxt); 2243*c39526b7SPramod Gunjikar if (rc) 2244*c39526b7SPramod Gunjikar goto err_out; 2245*c39526b7SPramod Gunjikar } 2246*c39526b7SPramod Gunjikar 2247*c39526b7SPramod Gunjikar #ifdef _LP64 2248*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_laddr, sizeof (resp)); 2249*c39526b7SPramod Gunjikar #else 2250*c39526b7SPramod Gunjikar rc = copyout((void*)&resp, (void*)cmd.response.r_addr, sizeof (resp)); 2251*c39526b7SPramod Gunjikar #endif 2252*c39526b7SPramod Gunjikar if (rc != 0) { 2253*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2254*c39526b7SPramod Gunjikar "destroy_srq() : copyout failure %x", rc); 2255*c39526b7SPramod Gunjikar rc = EFAULT; 2256*c39526b7SPramod Gunjikar goto err_out; 2257*c39526b7SPramod Gunjikar } 2258*c39526b7SPramod Gunjikar 2259*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 2260*c39526b7SPramod Gunjikar 2261*c39526b7SPramod Gunjikar err_out: 2262*c39526b7SPramod Gunjikar return (rc); 2263*c39526b7SPramod Gunjikar } 2264*c39526b7SPramod Gunjikar 2265*c39526b7SPramod Gunjikar /* 2266*c39526b7SPramod Gunjikar * Function: 2267*c39526b7SPramod Gunjikar * sol_uverbs_attach_mcast 2268*c39526b7SPramod Gunjikar * Input: 2269*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 2270*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing command. 2271*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 2272*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 2273*c39526b7SPramod Gunjikar * Output: 2274*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 2275*c39526b7SPramod Gunjikar * Returns: 2276*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 2277*c39526b7SPramod Gunjikar * Description: 2278*c39526b7SPramod Gunjikar * User verbs entry point to attach a QP to a multicast group 2279*c39526b7SPramod Gunjikar */ 2280*c39526b7SPramod Gunjikar /* ARGSUSED */ 2281*c39526b7SPramod Gunjikar int 2282*c39526b7SPramod Gunjikar sol_uverbs_attach_mcast(uverbs_uctxt_uobj_t *uctxt, char *buf, 2283*c39526b7SPramod Gunjikar int in_len, int out_len) 2284*c39526b7SPramod Gunjikar { 2285*c39526b7SPramod Gunjikar struct ib_uverbs_attach_mcast cmd; 2286*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2287*c39526b7SPramod Gunjikar uverbs_mcast_entry_t *mc; 2288*c39526b7SPramod Gunjikar llist_head_t *entry; 2289*c39526b7SPramod Gunjikar int rc; 2290*c39526b7SPramod Gunjikar ib_gid_t mc_gid; 2291*c39526b7SPramod Gunjikar 2292*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 2293*c39526b7SPramod Gunjikar 2294*c39526b7SPramod Gunjikar /* 2295*c39526b7SPramod Gunjikar * API specifies gid in network order, Solaris expects the gid 2296*c39526b7SPramod Gunjikar * in host order, do the conversion if required. 2297*c39526b7SPramod Gunjikar */ 2298*c39526b7SPramod Gunjikar mc_gid.gid_prefix = b2h64(*((uint64_t *)&cmd.gid[0])); 2299*c39526b7SPramod Gunjikar mc_gid.gid_guid = b2h64(*((uint64_t *)&cmd.gid[8])); 2300*c39526b7SPramod Gunjikar 2301*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, "attach_mcast(qp_handle=%d, " 2302*c39526b7SPramod Gunjikar "mlid=0x%04x, gid=%016llx:%016llx", cmd.qp_handle, cmd.mlid, 2303*c39526b7SPramod Gunjikar mc_gid.gid_prefix, mc_gid.gid_guid); 2304*c39526b7SPramod Gunjikar 2305*c39526b7SPramod Gunjikar /* 2306*c39526b7SPramod Gunjikar * Take object write to protect MC list. 2307*c39526b7SPramod Gunjikar */ 2308*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle); 2309*c39526b7SPramod Gunjikar if (uqp == NULL) { 2310*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2311*c39526b7SPramod Gunjikar "attach_mcast QP not found"); 2312*c39526b7SPramod Gunjikar rc = EINVAL; 2313*c39526b7SPramod Gunjikar goto err_out; 2314*c39526b7SPramod Gunjikar } 2315*c39526b7SPramod Gunjikar 2316*c39526b7SPramod Gunjikar /* 2317*c39526b7SPramod Gunjikar * Look to see if we are already attached and if so no need to attach 2318*c39526b7SPramod Gunjikar * again, just return good status. 2319*c39526b7SPramod Gunjikar */ 2320*c39526b7SPramod Gunjikar list_for_each(entry, &uqp->mcast_list) { 2321*c39526b7SPramod Gunjikar mc = (uverbs_mcast_entry_t *)entry->ptr; 2322*c39526b7SPramod Gunjikar 2323*c39526b7SPramod Gunjikar if (cmd.mlid == mc->mcg.mc_adds_vect.av_dlid && 2324*c39526b7SPramod Gunjikar !memcmp(&mc_gid.gid, &mc->mcg.mc_adds_vect.av_dgid, 2325*c39526b7SPramod Gunjikar sizeof (mc_gid.gid))) { 2326*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L4(sol_uverbs_dbg_str, 2327*c39526b7SPramod Gunjikar "attach_mcast: match entry found"); 2328*c39526b7SPramod Gunjikar rc = DDI_SUCCESS; 2329*c39526b7SPramod Gunjikar goto out_put; 2330*c39526b7SPramod Gunjikar } 2331*c39526b7SPramod Gunjikar } 2332*c39526b7SPramod Gunjikar 2333*c39526b7SPramod Gunjikar mc = kmem_zalloc(sizeof (*mc), KM_NOSLEEP); 2334*c39526b7SPramod Gunjikar if (mc == NULL) { 2335*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2336*c39526b7SPramod Gunjikar "attach_mcast: kmem_zalloc fail"); 2337*c39526b7SPramod Gunjikar rc = ENOMEM; 2338*c39526b7SPramod Gunjikar goto out_put; 2339*c39526b7SPramod Gunjikar } 2340*c39526b7SPramod Gunjikar 2341*c39526b7SPramod Gunjikar llist_head_init(&mc->list, mc); 2342*c39526b7SPramod Gunjikar mc->mcg.mc_adds_vect.av_dlid = cmd.mlid; 2343*c39526b7SPramod Gunjikar bcopy(&mc_gid, &(mc->mcg.mc_adds_vect.av_dgid), sizeof (mc_gid)); 2344*c39526b7SPramod Gunjikar 2345*c39526b7SPramod Gunjikar rc = ibt_attach_mcg(uqp->qp, &mc->mcg); 2346*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 2347*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2348*c39526b7SPramod Gunjikar "attach_mcast: ibt_attach_mcq failed (r=%d)", rc); 2349*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 2350*c39526b7SPramod Gunjikar goto err_free; 2351*c39526b7SPramod Gunjikar } 2352*c39526b7SPramod Gunjikar 2353*c39526b7SPramod Gunjikar llist_add_tail(&mc->list, &uqp->mcast_list); 2354*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2355*c39526b7SPramod Gunjikar 2356*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 2357*c39526b7SPramod Gunjikar 2358*c39526b7SPramod Gunjikar err_free: 2359*c39526b7SPramod Gunjikar kmem_free(mc, sizeof (*mc)); 2360*c39526b7SPramod Gunjikar out_put: 2361*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2362*c39526b7SPramod Gunjikar err_out: 2363*c39526b7SPramod Gunjikar return (rc); 2364*c39526b7SPramod Gunjikar } 2365*c39526b7SPramod Gunjikar 2366*c39526b7SPramod Gunjikar /* 2367*c39526b7SPramod Gunjikar * Function: 2368*c39526b7SPramod Gunjikar * sol_uverbs_detach_mcast 2369*c39526b7SPramod Gunjikar * Input: 2370*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 2371*c39526b7SPramod Gunjikar * buf - Pointer to kernel buffer containing command. 2372*c39526b7SPramod Gunjikar * in_len - Length in bytes of input command buffer. 2373*c39526b7SPramod Gunjikar * out_len - Length in bytes of output response buffer. 2374*c39526b7SPramod Gunjikar * Output: 2375*c39526b7SPramod Gunjikar * The command output buffer is updated with command results. 2376*c39526b7SPramod Gunjikar * Returns: 2377*c39526b7SPramod Gunjikar * DDI_SUCCESS on success, else error code. 2378*c39526b7SPramod Gunjikar * Description: 2379*c39526b7SPramod Gunjikar * User verbs entry point to detach a QP from a multicast group 2380*c39526b7SPramod Gunjikar */ 2381*c39526b7SPramod Gunjikar /* ARGSUSED */ 2382*c39526b7SPramod Gunjikar int 2383*c39526b7SPramod Gunjikar sol_uverbs_detach_mcast(uverbs_uctxt_uobj_t *uctxt, char *buf, 2384*c39526b7SPramod Gunjikar int in_len, int out_len) 2385*c39526b7SPramod Gunjikar { 2386*c39526b7SPramod Gunjikar struct ib_uverbs_detach_mcast cmd; 2387*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2388*c39526b7SPramod Gunjikar ibt_mcg_info_t mcg; 2389*c39526b7SPramod Gunjikar int rc; 2390*c39526b7SPramod Gunjikar uverbs_mcast_entry_t *mc; 2391*c39526b7SPramod Gunjikar llist_head_t *entry; 2392*c39526b7SPramod Gunjikar llist_head_t *temp; 2393*c39526b7SPramod Gunjikar ib_gid_t mc_gid; 2394*c39526b7SPramod Gunjikar 2395*c39526b7SPramod Gunjikar (void) memcpy(&cmd, buf, sizeof (cmd)); 2396*c39526b7SPramod Gunjikar 2397*c39526b7SPramod Gunjikar /* 2398*c39526b7SPramod Gunjikar * API specifies gid in network order, Solaris expects the gid 2399*c39526b7SPramod Gunjikar * in host order, do the conversion if required. 2400*c39526b7SPramod Gunjikar */ 2401*c39526b7SPramod Gunjikar mc_gid.gid_prefix = b2h64(*((uint64_t *)&cmd.gid[0])); 2402*c39526b7SPramod Gunjikar mc_gid.gid_guid = b2h64(*((uint64_t *)&cmd.gid[8])); 2403*c39526b7SPramod Gunjikar 2404*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 2405*c39526b7SPramod Gunjikar "detach_mcast: entry (qp_handle=%d, mlid=0x%04x," 2406*c39526b7SPramod Gunjikar "gid=%016llx:%016llx", cmd.qp_handle, cmd.mlid, mc_gid.gid_prefix, 2407*c39526b7SPramod Gunjikar mc_gid.gid_guid); 2408*c39526b7SPramod Gunjikar 2409*c39526b7SPramod Gunjikar (void) memset(&mcg, 0, sizeof (mcg)); 2410*c39526b7SPramod Gunjikar 2411*c39526b7SPramod Gunjikar /* 2412*c39526b7SPramod Gunjikar * Get object write to protect mcast list. 2413*c39526b7SPramod Gunjikar */ 2414*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(cmd.qp_handle); 2415*c39526b7SPramod Gunjikar if (uqp == NULL) { 2416*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2417*c39526b7SPramod Gunjikar "detach_mcast(): QP hdl %x not found", cmd.qp_handle); 2418*c39526b7SPramod Gunjikar rc = EINVAL; 2419*c39526b7SPramod Gunjikar goto err_out; 2420*c39526b7SPramod Gunjikar } 2421*c39526b7SPramod Gunjikar 2422*c39526b7SPramod Gunjikar mcg.mc_adds_vect.av_dlid = cmd.mlid; 2423*c39526b7SPramod Gunjikar mcg.mc_adds_vect.av_dgid = mc_gid; 2424*c39526b7SPramod Gunjikar 2425*c39526b7SPramod Gunjikar rc = ibt_detach_mcg(uqp->qp, &mcg); 2426*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 2427*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2428*c39526b7SPramod Gunjikar "deatch_mcast(): ibt_attach_mcq failed (r=%d)", rc); 2429*c39526b7SPramod Gunjikar rc = sol_uverbs_ibt_to_kernel_status(rc); 2430*c39526b7SPramod Gunjikar goto err_put; 2431*c39526b7SPramod Gunjikar } 2432*c39526b7SPramod Gunjikar 2433*c39526b7SPramod Gunjikar /* 2434*c39526b7SPramod Gunjikar * Find and delete MC group from the QP multicast list. 2435*c39526b7SPramod Gunjikar */ 2436*c39526b7SPramod Gunjikar entry = uqp->mcast_list.nxt; 2437*c39526b7SPramod Gunjikar temp = entry->nxt; 2438*c39526b7SPramod Gunjikar while (entry != &uqp->mcast_list) { 2439*c39526b7SPramod Gunjikar ASSERT(entry); 2440*c39526b7SPramod Gunjikar mc = (uverbs_mcast_entry_t *)entry->ptr; 2441*c39526b7SPramod Gunjikar ASSERT(mc); 2442*c39526b7SPramod Gunjikar 2443*c39526b7SPramod Gunjikar if (cmd.mlid == mc->mcg.mc_adds_vect.av_dlid && 2444*c39526b7SPramod Gunjikar !memcmp(&mc_gid.gid, &mc->mcg.mc_adds_vect.av_dgid, 2445*c39526b7SPramod Gunjikar sizeof (mc_gid.gid))) { 2446*c39526b7SPramod Gunjikar llist_del(&mc->list); 2447*c39526b7SPramod Gunjikar kmem_free(mc, sizeof (*mc)); 2448*c39526b7SPramod Gunjikar break; 2449*c39526b7SPramod Gunjikar } 2450*c39526b7SPramod Gunjikar entry = temp; 2451*c39526b7SPramod Gunjikar temp = entry->nxt; 2452*c39526b7SPramod Gunjikar } 2453*c39526b7SPramod Gunjikar 2454*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2455*c39526b7SPramod Gunjikar 2456*c39526b7SPramod Gunjikar return (DDI_SUCCESS); 2457*c39526b7SPramod Gunjikar 2458*c39526b7SPramod Gunjikar err_put: 2459*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2460*c39526b7SPramod Gunjikar 2461*c39526b7SPramod Gunjikar err_out: 2462*c39526b7SPramod Gunjikar return (rc); 2463*c39526b7SPramod Gunjikar } 2464*c39526b7SPramod Gunjikar 2465*c39526b7SPramod Gunjikar /* 2466*c39526b7SPramod Gunjikar * Function: 2467*c39526b7SPramod Gunjikar * uverbs_release_uqp_mcast_entries 2468*c39526b7SPramod Gunjikar * Input: 2469*c39526b7SPramod Gunjikar * uctxt - Pointer to the callers user context. 2470*c39526b7SPramod Gunjikar * uqp - Pointer to the user QP object for which the multicast 2471*c39526b7SPramod Gunjikar * list should be flushed. 2472*c39526b7SPramod Gunjikar * Output: 2473*c39526b7SPramod Gunjikar * None 2474*c39526b7SPramod Gunjikar * Returns: 2475*c39526b7SPramod Gunjikar * None 2476*c39526b7SPramod Gunjikar * Description: 2477*c39526b7SPramod Gunjikar * Release any multicast resources held by this QP. The 2478*c39526b7SPramod Gunjikar * user context associated with the QP should be locked 2479*c39526b7SPramod Gunjikar * externally to this routine to protect the updates to the 2480*c39526b7SPramod Gunjikar * multicast list. 2481*c39526b7SPramod Gunjikar */ 2482*c39526b7SPramod Gunjikar void 2483*c39526b7SPramod Gunjikar uverbs_detach_uqp_mcast_entries(uverbs_uqp_uobj_t *uqp) 2484*c39526b7SPramod Gunjikar { 2485*c39526b7SPramod Gunjikar int rc; 2486*c39526b7SPramod Gunjikar uverbs_mcast_entry_t *mc; 2487*c39526b7SPramod Gunjikar llist_head_t *entry; 2488*c39526b7SPramod Gunjikar llist_head_t *temp; 2489*c39526b7SPramod Gunjikar 2490*c39526b7SPramod Gunjikar /* 2491*c39526b7SPramod Gunjikar * Find and delete MC group from the QP multicast list. 2492*c39526b7SPramod Gunjikar */ 2493*c39526b7SPramod Gunjikar entry = uqp->mcast_list.nxt; 2494*c39526b7SPramod Gunjikar temp = entry->nxt; 2495*c39526b7SPramod Gunjikar while (entry != &uqp->mcast_list) { 2496*c39526b7SPramod Gunjikar ASSERT(entry); 2497*c39526b7SPramod Gunjikar mc = (uverbs_mcast_entry_t *)entry->ptr; 2498*c39526b7SPramod Gunjikar ASSERT(mc); 2499*c39526b7SPramod Gunjikar 2500*c39526b7SPramod Gunjikar rc = ibt_detach_mcg(uqp->qp, &mc->mcg); 2501*c39526b7SPramod Gunjikar if (rc != IBT_SUCCESS) { 2502*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2503*c39526b7SPramod Gunjikar "detach_mcast() : " 2504*c39526b7SPramod Gunjikar "ibt_detach_mcq failed (r=%d)", rc); 2505*c39526b7SPramod Gunjikar } 2506*c39526b7SPramod Gunjikar llist_del(&mc->list); 2507*c39526b7SPramod Gunjikar entry = temp; 2508*c39526b7SPramod Gunjikar temp = entry->nxt; 2509*c39526b7SPramod Gunjikar } 2510*c39526b7SPramod Gunjikar } 2511*c39526b7SPramod Gunjikar 2512*c39526b7SPramod Gunjikar /* 2513*c39526b7SPramod Gunjikar * Function: 2514*c39526b7SPramod Gunjikar * sol_uverbs_uqpid_to_ibt_handle 2515*c39526b7SPramod Gunjikar * Input: 2516*c39526b7SPramod Gunjikar * uqpid - A user verbs QP id, i.e. a QP handle that was 2517*c39526b7SPramod Gunjikar * created via libibverbs and sol_uverbs. 2518*c39526b7SPramod Gunjikar * Output: 2519*c39526b7SPramod Gunjikar * None 2520*c39526b7SPramod Gunjikar * Returns: 2521*c39526b7SPramod Gunjikar * The ibt_qp_hdl_t associated with the user space QP handle. 2522*c39526b7SPramod Gunjikar * -1 is returned if the id is not found. 2523*c39526b7SPramod Gunjikar * Description: 2524*c39526b7SPramod Gunjikar * Map the user verbs QP id to the associated IBT QP handle. 2525*c39526b7SPramod Gunjikar */ 2526*c39526b7SPramod Gunjikar ibt_qp_hdl_t 2527*c39526b7SPramod Gunjikar sol_uverbs_uqpid_to_ibt_handle(uint32_t uqpid) 2528*c39526b7SPramod Gunjikar { 2529*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2530*c39526b7SPramod Gunjikar void *qphdl; 2531*c39526b7SPramod Gunjikar 2532*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_read(uqpid); 2533*c39526b7SPramod Gunjikar if (uqp == NULL) { 2534*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2535*c39526b7SPramod Gunjikar "uqpid2ibthdl: QP lookup failure: id %d", uqpid); 2536*c39526b7SPramod Gunjikar return (NULL); 2537*c39526b7SPramod Gunjikar } 2538*c39526b7SPramod Gunjikar qphdl = (void *)uqp->qp; 2539*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2540*c39526b7SPramod Gunjikar return (qphdl); 2541*c39526b7SPramod Gunjikar } 2542*c39526b7SPramod Gunjikar 2543*c39526b7SPramod Gunjikar /* 2544*c39526b7SPramod Gunjikar * Function: 2545*c39526b7SPramod Gunjikar * sol_uverbs_disable_user_qp_modify 2546*c39526b7SPramod Gunjikar * Input: 2547*c39526b7SPramod Gunjikar * uqpid - A user verbs QP id, i.e. a QP handle that was 2548*c39526b7SPramod Gunjikar * created via libibverbs and sol_uverbs. 2549*c39526b7SPramod Gunjikar * Output: 2550*c39526b7SPramod Gunjikar * None 2551*c39526b7SPramod Gunjikar * Returns: 2552*c39526b7SPramod Gunjikar * 0 on success, EINVAL if associated QP is not found. 2553*c39526b7SPramod Gunjikar * Description: 2554*c39526b7SPramod Gunjikar * Inform sol_uverbs driver to ignore user qp modify 2555*c39526b7SPramod Gunjikar * operations it receives for the specified qp. To re-enable 2556*c39526b7SPramod Gunjikar * this capability see the function sol_uverbs_enable_user_qp_modify. 2557*c39526b7SPramod Gunjikar */ 2558*c39526b7SPramod Gunjikar int 2559*c39526b7SPramod Gunjikar sol_uverbs_disable_user_qp_modify(uint32_t uqpid) 2560*c39526b7SPramod Gunjikar { 2561*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2562*c39526b7SPramod Gunjikar 2563*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(uqpid); 2564*c39526b7SPramod Gunjikar if (uqp == NULL) { 2565*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2566*c39526b7SPramod Gunjikar "disable_uqp_modify(%d) -lookup failure", uqpid); 2567*c39526b7SPramod Gunjikar return (EINVAL); 2568*c39526b7SPramod Gunjikar } 2569*c39526b7SPramod Gunjikar uqp->disable_qp_mod = TRUE; 2570*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2571*c39526b7SPramod Gunjikar return (0); 2572*c39526b7SPramod Gunjikar } 2573*c39526b7SPramod Gunjikar 2574*c39526b7SPramod Gunjikar /* 2575*c39526b7SPramod Gunjikar * Function: 2576*c39526b7SPramod Gunjikar * sol_uverbs_enable_user_qp_modify 2577*c39526b7SPramod Gunjikar * Input: 2578*c39526b7SPramod Gunjikar * uqpid - A user verbs QP id, i.e. a QP handle that was 2579*c39526b7SPramod Gunjikar * created via libibverbs and sol_uverbs. 2580*c39526b7SPramod Gunjikar * Output: 2581*c39526b7SPramod Gunjikar * None 2582*c39526b7SPramod Gunjikar * Returns: 2583*c39526b7SPramod Gunjikar * 0 on success, EINVAL if associated QP is not found. 2584*c39526b7SPramod Gunjikar * Description: 2585*c39526b7SPramod Gunjikar * Inform sol_uverbs driver to process user qp modify 2586*c39526b7SPramod Gunjikar * operations it receives for the specified qp. This is 2587*c39526b7SPramod Gunjikar * the default and this routine need only be invoked if 2588*c39526b7SPramod Gunjikar * user QP modify operations have explicitly been disabled 2589*c39526b7SPramod Gunjikar * with sol_uverbs_disable_user_qp_modify. 2590*c39526b7SPramod Gunjikar */ 2591*c39526b7SPramod Gunjikar int 2592*c39526b7SPramod Gunjikar sol_uverbs_enable_user_qp_modify(uint32_t uqpid) 2593*c39526b7SPramod Gunjikar { 2594*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2595*c39526b7SPramod Gunjikar 2596*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(uqpid); 2597*c39526b7SPramod Gunjikar if (uqp == NULL) { 2598*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2599*c39526b7SPramod Gunjikar "enable_uqp_modify(%d) -lookup failure", uqpid); 2600*c39526b7SPramod Gunjikar return (EINVAL); 2601*c39526b7SPramod Gunjikar } 2602*c39526b7SPramod Gunjikar uqp->disable_qp_mod = FALSE; 2603*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2604*c39526b7SPramod Gunjikar return (0); 2605*c39526b7SPramod Gunjikar } 2606*c39526b7SPramod Gunjikar 2607*c39526b7SPramod Gunjikar int 2608*c39526b7SPramod Gunjikar uverbs_uqpn_cq_ctrl(uint32_t uqpid, sol_uverbs_cq_ctrl_t ctrl) 2609*c39526b7SPramod Gunjikar { 2610*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2611*c39526b7SPramod Gunjikar uverbs_ucq_uobj_t *uscq; 2612*c39526b7SPramod Gunjikar uverbs_ucq_uobj_t *urcq; 2613*c39526b7SPramod Gunjikar 2614*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(uqpid); 2615*c39526b7SPramod Gunjikar if (uqp == NULL) { 2616*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2617*c39526b7SPramod Gunjikar "uqpn_cq_ctrl(%d) -lookup failure", uqpid); 2618*c39526b7SPramod Gunjikar return (EINVAL); 2619*c39526b7SPramod Gunjikar } 2620*c39526b7SPramod Gunjikar uscq = uqp->uqp_scq; 2621*c39526b7SPramod Gunjikar urcq = uqp->uqp_rcq; 2622*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L5(sol_uverbs_dbg_str, 2623*c39526b7SPramod Gunjikar "ctrl - uqp %p, rcq %p. scq %p", uqp, urcq, uscq); 2624*c39526b7SPramod Gunjikar 2625*c39526b7SPramod Gunjikar ASSERT(uscq); 2626*c39526b7SPramod Gunjikar ASSERT(urcq); 2627*c39526b7SPramod Gunjikar uverbs_cq_ctrl(uscq, ctrl); 2628*c39526b7SPramod Gunjikar if (uscq != urcq) 2629*c39526b7SPramod Gunjikar uverbs_cq_ctrl(urcq, ctrl); 2630*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2631*c39526b7SPramod Gunjikar return (0); 2632*c39526b7SPramod Gunjikar } 2633*c39526b7SPramod Gunjikar 2634*c39526b7SPramod Gunjikar extern uint32_t sol_uverbs_qpnum2uqpid(uint32_t); 2635*c39526b7SPramod Gunjikar 2636*c39526b7SPramod Gunjikar void 2637*c39526b7SPramod Gunjikar sol_uverbs_flush_qp(uint32_t qpnum) 2638*c39526b7SPramod Gunjikar { 2639*c39526b7SPramod Gunjikar int32_t uqpid; 2640*c39526b7SPramod Gunjikar ibt_status_t status; 2641*c39526b7SPramod Gunjikar uverbs_uqp_uobj_t *uqp; 2642*c39526b7SPramod Gunjikar 2643*c39526b7SPramod Gunjikar uqpid = sol_uverbs_qpnum2uqpid(qpnum); 2644*c39526b7SPramod Gunjikar if (uqpid == DDI_FAILURE) { 2645*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2646*c39526b7SPramod Gunjikar "sol_uverbs_flush_qp(%x) - Invalid qpnum", 2647*c39526b7SPramod Gunjikar qpnum); 2648*c39526b7SPramod Gunjikar return; 2649*c39526b7SPramod Gunjikar } 2650*c39526b7SPramod Gunjikar uqp = uverbs_uobj_get_uqp_write(uqpid); 2651*c39526b7SPramod Gunjikar if (uqp == NULL) { 2652*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2653*c39526b7SPramod Gunjikar "sol_uverbs_flush_qp(%x) - Invalid " 2654*c39526b7SPramod Gunjikar "uqpid %x", qpnum, uqpid); 2655*c39526b7SPramod Gunjikar return; 2656*c39526b7SPramod Gunjikar } 2657*c39526b7SPramod Gunjikar 2658*c39526b7SPramod Gunjikar if (uqp->qp) { 2659*c39526b7SPramod Gunjikar status = ibt_flush_qp(uqp->qp); 2660*c39526b7SPramod Gunjikar if (status != IBT_SUCCESS) 2661*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2662*c39526b7SPramod Gunjikar "sol_uverbs_flush_qp(%x) - " 2663*c39526b7SPramod Gunjikar "ibt_flush_qp(%p) failed - status %d", 2664*c39526b7SPramod Gunjikar qpnum, uqp->qp, status); 2665*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2666*c39526b7SPramod Gunjikar return; 2667*c39526b7SPramod Gunjikar } else { 2668*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L2(sol_uverbs_dbg_str, 2669*c39526b7SPramod Gunjikar "sol_uverbs_flush_qp(%x), uqpid %x -" 2670*c39526b7SPramod Gunjikar "uqp->qp is NULL!!", qpnum, uqpid); 2671*c39526b7SPramod Gunjikar sol_ofs_uobj_put(&uqp->uobj); 2672*c39526b7SPramod Gunjikar return; 2673*c39526b7SPramod Gunjikar } 2674*c39526b7SPramod Gunjikar } 2675*c39526b7SPramod Gunjikar static uint32_t 2676*c39526b7SPramod Gunjikar ibt_cep_flags2ibv(ibt_cep_flags_t ibt_flags) 2677*c39526b7SPramod Gunjikar { 2678*c39526b7SPramod Gunjikar uint32_t ib_flags = 0; 2679*c39526b7SPramod Gunjikar 2680*c39526b7SPramod Gunjikar if (ibt_flags & IBT_CEP_RDMA_WR) 2681*c39526b7SPramod Gunjikar ib_flags |= IB_ACCESS_REMOTE_WRITE; 2682*c39526b7SPramod Gunjikar if (ibt_flags & IBT_CEP_RDMA_RD) 2683*c39526b7SPramod Gunjikar ib_flags |= IB_ACCESS_REMOTE_READ; 2684*c39526b7SPramod Gunjikar if (ibt_flags & IBT_CEP_ATOMIC) 2685*c39526b7SPramod Gunjikar ib_flags |= IB_ACCESS_REMOTE_ATOMIC; 2686*c39526b7SPramod Gunjikar 2687*c39526b7SPramod Gunjikar return (ib_flags); 2688*c39526b7SPramod Gunjikar } 2689*c39526b7SPramod Gunjikar 2690*c39526b7SPramod Gunjikar static void 2691*c39526b7SPramod Gunjikar uverbs_cq_ctrl(uverbs_ucq_uobj_t *ucq, sol_uverbs_cq_ctrl_t ctrl) 2692*c39526b7SPramod Gunjikar { 2693*c39526b7SPramod Gunjikar uverbs_ufile_uobj_t *ufile; 2694*c39526b7SPramod Gunjikar 2695*c39526b7SPramod Gunjikar ufile = ucq->comp_chan; 2696*c39526b7SPramod Gunjikar if (!ufile) { 2697*c39526b7SPramod Gunjikar SOL_OFS_DPRINTF_L3(sol_uverbs_dbg_str, 2698*c39526b7SPramod Gunjikar "cq_ctrl(%p), ufile NULL", ucq, ufile); 2699*c39526b7SPramod Gunjikar return; 2700*c39526b7SPramod Gunjikar } 2701*c39526b7SPramod Gunjikar 2702*c39526b7SPramod Gunjikar mutex_enter(&ufile->lock); 2703*c39526b7SPramod Gunjikar ufile->ufile_notify_enabled = ctrl; 2704*c39526b7SPramod Gunjikar 2705*c39526b7SPramod Gunjikar if (ctrl == SOL_UVERBS2UCMA_CQ_NOTIFY_ENABLE) { 2706*c39526b7SPramod Gunjikar if (!llist_empty(&ufile->event_list)) { 2707*c39526b7SPramod Gunjikar cv_signal(&ufile->poll_wait); 2708*c39526b7SPramod Gunjikar pollwakeup(&ufile->poll_head, 2709*c39526b7SPramod Gunjikar POLLIN | POLLRDNORM); 2710*c39526b7SPramod Gunjikar } 2711*c39526b7SPramod Gunjikar } 2712*c39526b7SPramod Gunjikar mutex_exit(&ufile->lock); 2713*c39526b7SPramod Gunjikar } 2714