1*52929c21SSaeed Mahameed // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2*52929c21SSaeed Mahameed /* 3*52929c21SSaeed Mahameed * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES 4*52929c21SSaeed Mahameed */ 5*52929c21SSaeed Mahameed #include <linux/fwctl.h> 6*52929c21SSaeed Mahameed #include <linux/auxiliary_bus.h> 7*52929c21SSaeed Mahameed #include <linux/mlx5/device.h> 8*52929c21SSaeed Mahameed #include <linux/mlx5/driver.h> 9*52929c21SSaeed Mahameed #include <uapi/fwctl/mlx5.h> 10*52929c21SSaeed Mahameed 11*52929c21SSaeed Mahameed #define mlx5ctl_err(mcdev, format, ...) \ 12*52929c21SSaeed Mahameed dev_err(&mcdev->fwctl.dev, format, ##__VA_ARGS__) 13*52929c21SSaeed Mahameed 14*52929c21SSaeed Mahameed #define mlx5ctl_dbg(mcdev, format, ...) \ 15*52929c21SSaeed Mahameed dev_dbg(&mcdev->fwctl.dev, "PID %u: " format, current->pid, \ 16*52929c21SSaeed Mahameed ##__VA_ARGS__) 17*52929c21SSaeed Mahameed 18*52929c21SSaeed Mahameed struct mlx5ctl_uctx { 19*52929c21SSaeed Mahameed struct fwctl_uctx uctx; 20*52929c21SSaeed Mahameed u32 uctx_caps; 21*52929c21SSaeed Mahameed u32 uctx_uid; 22*52929c21SSaeed Mahameed }; 23*52929c21SSaeed Mahameed 24*52929c21SSaeed Mahameed struct mlx5ctl_dev { 25*52929c21SSaeed Mahameed struct fwctl_device fwctl; 26*52929c21SSaeed Mahameed struct mlx5_core_dev *mdev; 27*52929c21SSaeed Mahameed }; 28*52929c21SSaeed Mahameed DEFINE_FREE(mlx5ctl, struct mlx5ctl_dev *, if (_T) fwctl_put(&_T->fwctl)); 29*52929c21SSaeed Mahameed 30*52929c21SSaeed Mahameed struct mlx5_ifc_mbox_in_hdr_bits { 31*52929c21SSaeed Mahameed u8 opcode[0x10]; 32*52929c21SSaeed Mahameed u8 uid[0x10]; 33*52929c21SSaeed Mahameed 34*52929c21SSaeed Mahameed u8 reserved_at_20[0x10]; 35*52929c21SSaeed Mahameed u8 op_mod[0x10]; 36*52929c21SSaeed Mahameed 37*52929c21SSaeed Mahameed u8 reserved_at_40[0x40]; 38*52929c21SSaeed Mahameed }; 39*52929c21SSaeed Mahameed 40*52929c21SSaeed Mahameed struct mlx5_ifc_mbox_out_hdr_bits { 41*52929c21SSaeed Mahameed u8 status[0x8]; 42*52929c21SSaeed Mahameed u8 reserved_at_8[0x18]; 43*52929c21SSaeed Mahameed 44*52929c21SSaeed Mahameed u8 syndrome[0x20]; 45*52929c21SSaeed Mahameed 46*52929c21SSaeed Mahameed u8 reserved_at_40[0x40]; 47*52929c21SSaeed Mahameed }; 48*52929c21SSaeed Mahameed 49*52929c21SSaeed Mahameed enum { 50*52929c21SSaeed Mahameed MLX5_UCTX_OBJECT_CAP_TOOLS_RESOURCES = 0x4, 51*52929c21SSaeed Mahameed }; 52*52929c21SSaeed Mahameed 53*52929c21SSaeed Mahameed enum { 54*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DRIVER_VERSION = 0x10c, 55*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_OTHER_HCA_CAP = 0x10e, 56*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_RDB = 0x512, 57*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_PSV = 0x602, 58*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DC_CNAK_TRACE = 0x716, 59*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_NVMF_BACKEND_CONTROLLER = 0x722, 60*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_NVMF_NAMESPACE_CONTEXT = 0x728, 61*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_BURST_SIZE = 0x813, 62*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DIAGNOSTIC_PARAMS = 0x819, 63*52929c21SSaeed Mahameed MLX5_CMD_OP_SET_DIAGNOSTIC_PARAMS = 0x820, 64*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DIAGNOSTIC_COUNTERS = 0x821, 65*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS = 0x911, 66*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_AFU = 0x971, 67*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_CAPI_PEC = 0x981, 68*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_UCTX = 0xa05, 69*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_UMEM = 0xa09, 70*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_NVMF_CC_RESPONSE = 0xb02, 71*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_EMULATED_FUNCTIONS_INFO = 0xb03, 72*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_REGEXP_PARAMS = 0xb05, 73*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_REGEXP_REGISTER = 0xb07, 74*52929c21SSaeed Mahameed MLX5_CMD_OP_USER_QUERY_XRQ_DC_PARAMS_ENTRY = 0xb08, 75*52929c21SSaeed Mahameed MLX5_CMD_OP_USER_QUERY_XRQ_ERROR_PARAMS = 0xb0a, 76*52929c21SSaeed Mahameed MLX5_CMD_OP_ACCESS_REGISTER_USER = 0xb0c, 77*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_EMULATION_DEVICE_EQ_MSIX_MAPPING = 0xb0f, 78*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_MATCH_SAMPLE_INFO = 0xb13, 79*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_CRYPTO_STATE = 0xb14, 80*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_VUID = 0xb22, 81*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DPA_PARTITION = 0xb28, 82*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_DPA_PARTITIONS = 0xb2a, 83*52929c21SSaeed Mahameed MLX5_CMD_OP_POSTPONE_CONNECTED_QP_TIMEOUT = 0xb2e, 84*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_EMULATED_RESOURCES_INFO = 0xb2f, 85*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_RSV_RESOURCES = 0x8000, 86*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_MTT = 0x8001, 87*52929c21SSaeed Mahameed MLX5_CMD_OP_QUERY_SCHED_QUEUE = 0x8006, 88*52929c21SSaeed Mahameed }; 89*52929c21SSaeed Mahameed 90*52929c21SSaeed Mahameed static int mlx5ctl_alloc_uid(struct mlx5ctl_dev *mcdev, u32 cap) 91*52929c21SSaeed Mahameed { 92*52929c21SSaeed Mahameed u32 out[MLX5_ST_SZ_DW(create_uctx_out)] = {}; 93*52929c21SSaeed Mahameed u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {}; 94*52929c21SSaeed Mahameed void *uctx; 95*52929c21SSaeed Mahameed int ret; 96*52929c21SSaeed Mahameed u16 uid; 97*52929c21SSaeed Mahameed 98*52929c21SSaeed Mahameed uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx); 99*52929c21SSaeed Mahameed 100*52929c21SSaeed Mahameed mlx5ctl_dbg(mcdev, "%s: caps 0x%x\n", __func__, cap); 101*52929c21SSaeed Mahameed MLX5_SET(create_uctx_in, in, opcode, MLX5_CMD_OP_CREATE_UCTX); 102*52929c21SSaeed Mahameed MLX5_SET(uctx, uctx, cap, cap); 103*52929c21SSaeed Mahameed 104*52929c21SSaeed Mahameed ret = mlx5_cmd_exec(mcdev->mdev, in, sizeof(in), out, sizeof(out)); 105*52929c21SSaeed Mahameed if (ret) 106*52929c21SSaeed Mahameed return ret; 107*52929c21SSaeed Mahameed 108*52929c21SSaeed Mahameed uid = MLX5_GET(create_uctx_out, out, uid); 109*52929c21SSaeed Mahameed mlx5ctl_dbg(mcdev, "allocated uid %u with caps 0x%x\n", uid, cap); 110*52929c21SSaeed Mahameed return uid; 111*52929c21SSaeed Mahameed } 112*52929c21SSaeed Mahameed 113*52929c21SSaeed Mahameed static void mlx5ctl_release_uid(struct mlx5ctl_dev *mcdev, u16 uid) 114*52929c21SSaeed Mahameed { 115*52929c21SSaeed Mahameed u32 in[MLX5_ST_SZ_DW(destroy_uctx_in)] = {}; 116*52929c21SSaeed Mahameed struct mlx5_core_dev *mdev = mcdev->mdev; 117*52929c21SSaeed Mahameed int ret; 118*52929c21SSaeed Mahameed 119*52929c21SSaeed Mahameed MLX5_SET(destroy_uctx_in, in, opcode, MLX5_CMD_OP_DESTROY_UCTX); 120*52929c21SSaeed Mahameed MLX5_SET(destroy_uctx_in, in, uid, uid); 121*52929c21SSaeed Mahameed 122*52929c21SSaeed Mahameed ret = mlx5_cmd_exec_in(mdev, destroy_uctx, in); 123*52929c21SSaeed Mahameed mlx5ctl_dbg(mcdev, "released uid %u %pe\n", uid, ERR_PTR(ret)); 124*52929c21SSaeed Mahameed } 125*52929c21SSaeed Mahameed 126*52929c21SSaeed Mahameed static int mlx5ctl_open_uctx(struct fwctl_uctx *uctx) 127*52929c21SSaeed Mahameed { 128*52929c21SSaeed Mahameed struct mlx5ctl_uctx *mfd = 129*52929c21SSaeed Mahameed container_of(uctx, struct mlx5ctl_uctx, uctx); 130*52929c21SSaeed Mahameed struct mlx5ctl_dev *mcdev = 131*52929c21SSaeed Mahameed container_of(uctx->fwctl, struct mlx5ctl_dev, fwctl); 132*52929c21SSaeed Mahameed int uid; 133*52929c21SSaeed Mahameed 134*52929c21SSaeed Mahameed /* 135*52929c21SSaeed Mahameed * New FW supports the TOOLS_RESOURCES uid security label 136*52929c21SSaeed Mahameed * which allows commands to manipulate the global device state. 137*52929c21SSaeed Mahameed * Otherwise only basic existing RDMA devx privilege are allowed. 138*52929c21SSaeed Mahameed */ 139*52929c21SSaeed Mahameed if (MLX5_CAP_GEN(mcdev->mdev, uctx_cap) & 140*52929c21SSaeed Mahameed MLX5_UCTX_OBJECT_CAP_TOOLS_RESOURCES) 141*52929c21SSaeed Mahameed mfd->uctx_caps |= MLX5_UCTX_OBJECT_CAP_TOOLS_RESOURCES; 142*52929c21SSaeed Mahameed 143*52929c21SSaeed Mahameed uid = mlx5ctl_alloc_uid(mcdev, mfd->uctx_caps); 144*52929c21SSaeed Mahameed if (uid < 0) 145*52929c21SSaeed Mahameed return uid; 146*52929c21SSaeed Mahameed 147*52929c21SSaeed Mahameed mfd->uctx_uid = uid; 148*52929c21SSaeed Mahameed return 0; 149*52929c21SSaeed Mahameed } 150*52929c21SSaeed Mahameed 151*52929c21SSaeed Mahameed static void mlx5ctl_close_uctx(struct fwctl_uctx *uctx) 152*52929c21SSaeed Mahameed { 153*52929c21SSaeed Mahameed struct mlx5ctl_dev *mcdev = 154*52929c21SSaeed Mahameed container_of(uctx->fwctl, struct mlx5ctl_dev, fwctl); 155*52929c21SSaeed Mahameed struct mlx5ctl_uctx *mfd = 156*52929c21SSaeed Mahameed container_of(uctx, struct mlx5ctl_uctx, uctx); 157*52929c21SSaeed Mahameed 158*52929c21SSaeed Mahameed mlx5ctl_release_uid(mcdev, mfd->uctx_uid); 159*52929c21SSaeed Mahameed } 160*52929c21SSaeed Mahameed 161*52929c21SSaeed Mahameed static void *mlx5ctl_info(struct fwctl_uctx *uctx, size_t *length) 162*52929c21SSaeed Mahameed { 163*52929c21SSaeed Mahameed struct mlx5ctl_uctx *mfd = 164*52929c21SSaeed Mahameed container_of(uctx, struct mlx5ctl_uctx, uctx); 165*52929c21SSaeed Mahameed struct fwctl_info_mlx5 *info; 166*52929c21SSaeed Mahameed 167*52929c21SSaeed Mahameed info = kzalloc(sizeof(*info), GFP_KERNEL); 168*52929c21SSaeed Mahameed if (!info) 169*52929c21SSaeed Mahameed return ERR_PTR(-ENOMEM); 170*52929c21SSaeed Mahameed 171*52929c21SSaeed Mahameed info->uid = mfd->uctx_uid; 172*52929c21SSaeed Mahameed info->uctx_caps = mfd->uctx_caps; 173*52929c21SSaeed Mahameed *length = sizeof(*info); 174*52929c21SSaeed Mahameed return info; 175*52929c21SSaeed Mahameed } 176*52929c21SSaeed Mahameed 177*52929c21SSaeed Mahameed static bool mlx5ctl_validate_rpc(const void *in, enum fwctl_rpc_scope scope) 178*52929c21SSaeed Mahameed { 179*52929c21SSaeed Mahameed u16 opcode = MLX5_GET(mbox_in_hdr, in, opcode); 180*52929c21SSaeed Mahameed u16 op_mod = MLX5_GET(mbox_in_hdr, in, op_mod); 181*52929c21SSaeed Mahameed 182*52929c21SSaeed Mahameed /* 183*52929c21SSaeed Mahameed * Currently the driver can't keep track of commands that allocate 184*52929c21SSaeed Mahameed * objects in the FW, these commands are safe from a security 185*52929c21SSaeed Mahameed * perspective but nothing will free the memory when the FD is closed. 186*52929c21SSaeed Mahameed * For now permit only query commands and set commands that don't alter 187*52929c21SSaeed Mahameed * objects. Also the caps for the scope have not been defined yet, 188*52929c21SSaeed Mahameed * filter commands manually for now. 189*52929c21SSaeed Mahameed */ 190*52929c21SSaeed Mahameed switch (opcode) { 191*52929c21SSaeed Mahameed case MLX5_CMD_OP_POSTPONE_CONNECTED_QP_TIMEOUT: 192*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_ADAPTER: 193*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS: 194*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_HCA_CAP: 195*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: 196*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_OTHER_HCA_CAP: 197*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: 198*52929c21SSaeed Mahameed case MLX5_CMD_OPCODE_QUERY_VUID: 199*52929c21SSaeed Mahameed /* 200*52929c21SSaeed Mahameed * FW limits SET_HCA_CAP on the tools UID to only the other function 201*52929c21SSaeed Mahameed * mode which is used for function pre-configuration 202*52929c21SSaeed Mahameed */ 203*52929c21SSaeed Mahameed case MLX5_CMD_OP_SET_HCA_CAP: 204*52929c21SSaeed Mahameed return true; /* scope >= FWCTL_RPC_CONFIGURATION; */ 205*52929c21SSaeed Mahameed 206*52929c21SSaeed Mahameed case MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS: 207*52929c21SSaeed Mahameed case MLX5_CMD_OP_FPGA_QUERY_QP: 208*52929c21SSaeed Mahameed case MLX5_CMD_OP_NOP: 209*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_AFU: 210*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_BURST_SIZE: 211*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_CAPI_PEC: 212*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_CONG_PARAMS: 213*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_CONG_STATISTICS: 214*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_CONG_STATUS: 215*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_CQ: 216*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_CRYPTO_STATE: 217*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DC_CNAK_TRACE: 218*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DCT: 219*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DELAY_DROP_PARAMS: 220*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DIAGNOSTIC_COUNTERS: 221*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DIAGNOSTIC_PARAMS: 222*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DPA_PARTITION: 223*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DPA_PARTITIONS: 224*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_DRIVER_VERSION: 225*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_EMULATED_FUNCTIONS_INFO: 226*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_EMULATED_RESOURCES_INFO: 227*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_EMULATION_DEVICE_EQ_MSIX_MAPPING: 228*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_EQ: 229*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: 230*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_FLOW_COUNTER: 231*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_FLOW_GROUP: 232*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: 233*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_FLOW_TABLE: 234*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: 235*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_HCA_VPORT_GID: 236*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY: 237*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_ISSI: 238*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: 239*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_LAG: 240*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_MAD_DEMUX: 241*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_MATCH_SAMPLE_INFO: 242*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_MKEY: 243*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT: 244*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_MTT: 245*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: 246*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_NVMF_BACKEND_CONTROLLER: 247*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_NVMF_CC_RESPONSE: 248*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_NVMF_NAMESPACE_CONTEXT: 249*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_PACKET_REFORMAT_CONTEXT: 250*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_PAGES: 251*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_PSV: 252*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_Q_COUNTER: 253*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_QP: 254*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_RATE_LIMIT: 255*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_RDB: 256*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_REGEXP_PARAMS: 257*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_REGEXP_REGISTER: 258*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_RMP: 259*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_RQ: 260*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_RQT: 261*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_RSV_RESOURCES: 262*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_SCHED_QUEUE: 263*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT: 264*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_SF_PARTITION: 265*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS: 266*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_SQ: 267*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_SRQ: 268*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_TIR: 269*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_TIS: 270*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_UCTX: 271*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_UMEM: 272*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_VHCA_MIGRATION_STATE: 273*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_VHCA_STATE: 274*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_VNIC_ENV: 275*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_VPORT_COUNTER: 276*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_VPORT_STATE: 277*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_WOL_ROL: 278*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_XRC_SRQ: 279*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY: 280*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS: 281*52929c21SSaeed Mahameed case MLX5_CMD_OP_QUERY_XRQ: 282*52929c21SSaeed Mahameed case MLX5_CMD_OP_USER_QUERY_XRQ_DC_PARAMS_ENTRY: 283*52929c21SSaeed Mahameed case MLX5_CMD_OP_USER_QUERY_XRQ_ERROR_PARAMS: 284*52929c21SSaeed Mahameed return scope >= FWCTL_RPC_DEBUG_READ_ONLY; 285*52929c21SSaeed Mahameed 286*52929c21SSaeed Mahameed case MLX5_CMD_OP_SET_DIAGNOSTIC_PARAMS: 287*52929c21SSaeed Mahameed return scope >= FWCTL_RPC_DEBUG_WRITE; 288*52929c21SSaeed Mahameed 289*52929c21SSaeed Mahameed case MLX5_CMD_OP_ACCESS_REG: 290*52929c21SSaeed Mahameed case MLX5_CMD_OP_ACCESS_REGISTER_USER: 291*52929c21SSaeed Mahameed if (op_mod == 0) /* write */ 292*52929c21SSaeed Mahameed return true; /* scope >= FWCTL_RPC_CONFIGURATION; */ 293*52929c21SSaeed Mahameed return scope >= FWCTL_RPC_DEBUG_READ_ONLY; 294*52929c21SSaeed Mahameed default: 295*52929c21SSaeed Mahameed return false; 296*52929c21SSaeed Mahameed } 297*52929c21SSaeed Mahameed } 298*52929c21SSaeed Mahameed 299*52929c21SSaeed Mahameed static void *mlx5ctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, 300*52929c21SSaeed Mahameed void *rpc_in, size_t in_len, size_t *out_len) 301*52929c21SSaeed Mahameed { 302*52929c21SSaeed Mahameed struct mlx5ctl_dev *mcdev = 303*52929c21SSaeed Mahameed container_of(uctx->fwctl, struct mlx5ctl_dev, fwctl); 304*52929c21SSaeed Mahameed struct mlx5ctl_uctx *mfd = 305*52929c21SSaeed Mahameed container_of(uctx, struct mlx5ctl_uctx, uctx); 306*52929c21SSaeed Mahameed void *rpc_out; 307*52929c21SSaeed Mahameed int ret; 308*52929c21SSaeed Mahameed 309*52929c21SSaeed Mahameed if (in_len < MLX5_ST_SZ_BYTES(mbox_in_hdr) || 310*52929c21SSaeed Mahameed *out_len < MLX5_ST_SZ_BYTES(mbox_out_hdr)) 311*52929c21SSaeed Mahameed return ERR_PTR(-EMSGSIZE); 312*52929c21SSaeed Mahameed 313*52929c21SSaeed Mahameed mlx5ctl_dbg(mcdev, "[UID %d] cmdif: opcode 0x%x inlen %zu outlen %zu\n", 314*52929c21SSaeed Mahameed mfd->uctx_uid, MLX5_GET(mbox_in_hdr, rpc_in, opcode), 315*52929c21SSaeed Mahameed in_len, *out_len); 316*52929c21SSaeed Mahameed 317*52929c21SSaeed Mahameed if (!mlx5ctl_validate_rpc(rpc_in, scope)) 318*52929c21SSaeed Mahameed return ERR_PTR(-EBADMSG); 319*52929c21SSaeed Mahameed 320*52929c21SSaeed Mahameed /* 321*52929c21SSaeed Mahameed * mlx5_cmd_do() copies the input message to its own buffer before 322*52929c21SSaeed Mahameed * executing it, so we can reuse the allocation for the output. 323*52929c21SSaeed Mahameed */ 324*52929c21SSaeed Mahameed if (*out_len <= in_len) { 325*52929c21SSaeed Mahameed rpc_out = rpc_in; 326*52929c21SSaeed Mahameed } else { 327*52929c21SSaeed Mahameed rpc_out = kvzalloc(*out_len, GFP_KERNEL); 328*52929c21SSaeed Mahameed if (!rpc_out) 329*52929c21SSaeed Mahameed return ERR_PTR(-ENOMEM); 330*52929c21SSaeed Mahameed } 331*52929c21SSaeed Mahameed 332*52929c21SSaeed Mahameed /* Enforce the user context for the command */ 333*52929c21SSaeed Mahameed MLX5_SET(mbox_in_hdr, rpc_in, uid, mfd->uctx_uid); 334*52929c21SSaeed Mahameed ret = mlx5_cmd_do(mcdev->mdev, rpc_in, in_len, rpc_out, *out_len); 335*52929c21SSaeed Mahameed 336*52929c21SSaeed Mahameed mlx5ctl_dbg(mcdev, 337*52929c21SSaeed Mahameed "[UID %d] cmdif: opcode 0x%x status 0x%x retval %pe\n", 338*52929c21SSaeed Mahameed mfd->uctx_uid, MLX5_GET(mbox_in_hdr, rpc_in, opcode), 339*52929c21SSaeed Mahameed MLX5_GET(mbox_out_hdr, rpc_out, status), ERR_PTR(ret)); 340*52929c21SSaeed Mahameed 341*52929c21SSaeed Mahameed /* 342*52929c21SSaeed Mahameed * -EREMOTEIO means execution succeeded and the out is valid, 343*52929c21SSaeed Mahameed * but an error code was returned inside out. Everything else 344*52929c21SSaeed Mahameed * means the RPC did not make it to the device. 345*52929c21SSaeed Mahameed */ 346*52929c21SSaeed Mahameed if (ret && ret != -EREMOTEIO) { 347*52929c21SSaeed Mahameed if (rpc_out != rpc_in) 348*52929c21SSaeed Mahameed kfree(rpc_out); 349*52929c21SSaeed Mahameed return ERR_PTR(ret); 350*52929c21SSaeed Mahameed } 351*52929c21SSaeed Mahameed return rpc_out; 352*52929c21SSaeed Mahameed } 353*52929c21SSaeed Mahameed 354*52929c21SSaeed Mahameed static const struct fwctl_ops mlx5ctl_ops = { 355*52929c21SSaeed Mahameed .device_type = FWCTL_DEVICE_TYPE_MLX5, 356*52929c21SSaeed Mahameed .uctx_size = sizeof(struct mlx5ctl_uctx), 357*52929c21SSaeed Mahameed .open_uctx = mlx5ctl_open_uctx, 358*52929c21SSaeed Mahameed .close_uctx = mlx5ctl_close_uctx, 359*52929c21SSaeed Mahameed .info = mlx5ctl_info, 360*52929c21SSaeed Mahameed .fw_rpc = mlx5ctl_fw_rpc, 361*52929c21SSaeed Mahameed }; 362*52929c21SSaeed Mahameed 363*52929c21SSaeed Mahameed static int mlx5ctl_probe(struct auxiliary_device *adev, 364*52929c21SSaeed Mahameed const struct auxiliary_device_id *id) 365*52929c21SSaeed Mahameed 366*52929c21SSaeed Mahameed { 367*52929c21SSaeed Mahameed struct mlx5_adev *madev = container_of(adev, struct mlx5_adev, adev); 368*52929c21SSaeed Mahameed struct mlx5_core_dev *mdev = madev->mdev; 369*52929c21SSaeed Mahameed struct mlx5ctl_dev *mcdev __free(mlx5ctl) = fwctl_alloc_device( 370*52929c21SSaeed Mahameed &mdev->pdev->dev, &mlx5ctl_ops, struct mlx5ctl_dev, fwctl); 371*52929c21SSaeed Mahameed int ret; 372*52929c21SSaeed Mahameed 373*52929c21SSaeed Mahameed if (!mcdev) 374*52929c21SSaeed Mahameed return -ENOMEM; 375*52929c21SSaeed Mahameed 376*52929c21SSaeed Mahameed mcdev->mdev = mdev; 377*52929c21SSaeed Mahameed 378*52929c21SSaeed Mahameed ret = fwctl_register(&mcdev->fwctl); 379*52929c21SSaeed Mahameed if (ret) 380*52929c21SSaeed Mahameed return ret; 381*52929c21SSaeed Mahameed auxiliary_set_drvdata(adev, no_free_ptr(mcdev)); 382*52929c21SSaeed Mahameed return 0; 383*52929c21SSaeed Mahameed } 384*52929c21SSaeed Mahameed 385*52929c21SSaeed Mahameed static void mlx5ctl_remove(struct auxiliary_device *adev) 386*52929c21SSaeed Mahameed { 387*52929c21SSaeed Mahameed struct mlx5ctl_dev *mcdev = auxiliary_get_drvdata(adev); 388*52929c21SSaeed Mahameed 389*52929c21SSaeed Mahameed fwctl_unregister(&mcdev->fwctl); 390*52929c21SSaeed Mahameed fwctl_put(&mcdev->fwctl); 391*52929c21SSaeed Mahameed } 392*52929c21SSaeed Mahameed 393*52929c21SSaeed Mahameed static const struct auxiliary_device_id mlx5ctl_id_table[] = { 394*52929c21SSaeed Mahameed {.name = MLX5_ADEV_NAME ".fwctl",}, 395*52929c21SSaeed Mahameed {} 396*52929c21SSaeed Mahameed }; 397*52929c21SSaeed Mahameed MODULE_DEVICE_TABLE(auxiliary, mlx5ctl_id_table); 398*52929c21SSaeed Mahameed 399*52929c21SSaeed Mahameed static struct auxiliary_driver mlx5ctl_driver = { 400*52929c21SSaeed Mahameed .name = "mlx5_fwctl", 401*52929c21SSaeed Mahameed .probe = mlx5ctl_probe, 402*52929c21SSaeed Mahameed .remove = mlx5ctl_remove, 403*52929c21SSaeed Mahameed .id_table = mlx5ctl_id_table, 404*52929c21SSaeed Mahameed }; 405*52929c21SSaeed Mahameed 406*52929c21SSaeed Mahameed module_auxiliary_driver(mlx5ctl_driver); 407*52929c21SSaeed Mahameed 408*52929c21SSaeed Mahameed MODULE_IMPORT_NS("FWCTL"); 409*52929c21SSaeed Mahameed MODULE_DESCRIPTION("mlx5 ConnectX fwctl driver"); 410*52929c21SSaeed Mahameed MODULE_AUTHOR("Saeed Mahameed <saeedm@nvidia.com>"); 411*52929c21SSaeed Mahameed MODULE_LICENSE("Dual BSD/GPL"); 412