1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2026, Broadcom Corporation 4 */ 5 6 #include <linux/auxiliary_bus.h> 7 #include <linux/dma-mapping.h> 8 #include <linux/slab.h> 9 #include <linux/pci.h> 10 #include <linux/fwctl.h> 11 #include <linux/bnxt/hsi.h> 12 #include <linux/bnxt/ulp.h> 13 #include <uapi/fwctl/fwctl.h> 14 #include <uapi/fwctl/bnxt.h> 15 16 struct bnxtctl_uctx { 17 struct fwctl_uctx uctx; 18 u32 uctx_caps; 19 }; 20 21 struct bnxtctl_dev { 22 struct fwctl_device fwctl; 23 struct bnxt_aux_priv *aux_priv; 24 }; 25 26 DEFINE_FREE(bnxtctl, struct bnxtctl_dev *, if (_T) fwctl_put(&_T->fwctl)) 27 28 static int bnxtctl_open_uctx(struct fwctl_uctx *uctx) 29 { 30 struct bnxtctl_uctx *bnxtctl_uctx = 31 container_of(uctx, struct bnxtctl_uctx, uctx); 32 33 bnxtctl_uctx->uctx_caps = BIT(FWCTL_BNXT_INLINE_COMMANDS) | 34 BIT(FWCTL_BNXT_QUERY_COMMANDS) | 35 BIT(FWCTL_BNXT_SEND_COMMANDS) | 36 BIT(FWCTL_BNXT_DMA_COMMANDS); 37 return 0; 38 } 39 40 static void bnxtctl_close_uctx(struct fwctl_uctx *uctx) 41 { 42 } 43 44 static void *bnxtctl_info(struct fwctl_uctx *uctx, size_t *length) 45 { 46 struct bnxtctl_uctx *bnxtctl_uctx = 47 container_of(uctx, struct bnxtctl_uctx, uctx); 48 struct fwctl_info_bnxt *info; 49 50 info = kzalloc_obj(*info); 51 if (!info) 52 return ERR_PTR(-ENOMEM); 53 54 info->uctx_caps = bnxtctl_uctx->uctx_caps; 55 56 *length = sizeof(*info); 57 return info; 58 } 59 60 #define BNXTCTL_MAX_DMA_FIELDS 4 61 62 struct bnxtctl_dma_field { 63 size_t offset; /* offsetof(hwrm_xxx_input, addr_field) */ 64 enum dma_data_direction dir; 65 size_t len_offset; /* offsetof(hwrm_xxx_input, len_field); 0 if the 66 * command carries no transfer-length field 67 */ 68 u8 len_width; /* byte width of the length field: 2 or 4 */ 69 u8 len_unit; /* bytes represented by one unit of the length field */ 70 u32 buf_len; /* for commands with no length in payload */ 71 }; 72 73 struct bnxtctl_cmd_dma_desc { 74 u16 req_type; 75 u8 num_fields; 76 u8 scope_min; 77 size_t req_size; /* sizeof(struct hwrm_xxx_input) */ 78 struct bnxtctl_dma_field fields[BNXTCTL_MAX_DMA_FIELDS]; 79 }; 80 81 /* input struct has an addr/len pair, but len is multiplied by _unit */ 82 #define CMD_DATA_UNIT(_struct, _dir, _data, _len, _unit) \ 83 { .offset = offsetof(_struct, _data), \ 84 .dir = _dir, \ 85 .len_offset = offsetof(_struct, _len), \ 86 .len_width = sizeof(((_struct *)0)->_len), \ 87 .len_unit = _unit } 88 89 /* input struct has an addr/len pair with byte length */ 90 #define CMD_DATA_SIMPLE(_struct, _dir, _data, _len) \ 91 CMD_DATA_UNIT(_struct, _dir, _data, _len, 1) 92 93 /* input struct has an addr but the length is fixed */ 94 #define CMD_DATA_FIXED(_struct, _dir, _data, _len) \ 95 { .offset = offsetof(_struct, _data), .dir = _dir, .buf_len = _len } 96 97 #define CMD_DMAS(_req_type, _scope_min, _struct, _num_fields, ...) \ 98 { \ 99 .req_type = _req_type, \ 100 .scope_min = _scope_min, \ 101 .req_size = sizeof(_struct), \ 102 .num_fields = _num_fields, \ 103 .fields = { __VA_ARGS__ }, \ 104 } 105 106 #define CMD_DMA_LEN(_req_type, _scope_min, _dir, _struct, _data, _len) \ 107 CMD_DMAS(_req_type, _scope_min, _struct, 1, \ 108 CMD_DATA_SIMPLE(_struct, _dir, _data, _len)) 109 110 /* 111 * Per-command DMA buffer descriptor table for HWRM commands that 112 * carry __le64 DMA address fields in their input 113 */ 114 static const struct bnxtctl_cmd_dma_desc bnxtctl_dma_cmds[] = { 115 CMD_DMA_LEN(HWRM_NVM_SET_VARIABLE, FWCTL_RPC_CONFIGURATION, 116 DMA_TO_DEVICE, 117 struct hwrm_nvm_set_variable_input, src_data_addr, 118 data_len), 119 CMD_DMA_LEN(HWRM_NVM_GET_VARIABLE, FWCTL_RPC_CONFIGURATION, 120 DMA_FROM_DEVICE, 121 struct hwrm_nvm_get_variable_input, dest_data_addr, 122 data_len), 123 CMD_DMA_LEN(HWRM_NVM_READ, FWCTL_RPC_DEBUG_READ_ONLY, 124 DMA_FROM_DEVICE, struct hwrm_nvm_read_input, 125 host_dest_addr, len), 126 CMD_DMAS(HWRM_NVM_GET_DIR_ENTRIES, FWCTL_RPC_DEBUG_READ_ONLY, 127 struct hwrm_nvm_get_dir_entries_input, 1, 128 CMD_DATA_FIXED(struct hwrm_nvm_get_dir_entries_input, 129 DMA_FROM_DEVICE, host_dest_addr, 130 FWCTL_BNXT_MAX_DMABUF)), 131 CMD_DMA_LEN(HWRM_NVM_WRITE, FWCTL_RPC_DEBUG_WRITE, 132 DMA_TO_DEVICE, struct hwrm_nvm_write_input, 133 host_src_addr, dir_data_length), 134 CMD_DMA_LEN(HWRM_NVM_MODIFY, FWCTL_RPC_DEBUG_WRITE, 135 DMA_TO_DEVICE, struct hwrm_nvm_modify_input, 136 host_src_addr, len), 137 CMD_DMA_LEN(HWRM_NVM_RAW_WRITE_BLK, FWCTL_RPC_DEBUG_WRITE_FULL, 138 DMA_TO_DEVICE, 139 struct hwrm_nvm_raw_write_blk_input, host_src_addr, len), 140 CMD_DMA_LEN(HWRM_NVM_RAW_DUMP, FWCTL_RPC_DEBUG_READ_ONLY, 141 DMA_FROM_DEVICE, struct hwrm_nvm_raw_dump_input, 142 host_dest_addr, len), 143 144 CMD_DMA_LEN(HWRM_FW_GET_STRUCTURED_DATA, FWCTL_RPC_DEBUG_READ_ONLY, 145 DMA_FROM_DEVICE, 146 struct hwrm_fw_get_structured_data_input, dest_data_addr, 147 data_len), 148 CMD_DMA_LEN(HWRM_FW_SET_STRUCTURED_DATA, FWCTL_RPC_DEBUG_WRITE, 149 DMA_TO_DEVICE, 150 struct hwrm_fw_set_structured_data_input, src_data_addr, 151 data_len), 152 CMD_DMA_LEN(HWRM_FW_LIVEPATCH, FWCTL_RPC_DEBUG_WRITE_FULL, 153 DMA_TO_DEVICE, struct hwrm_fw_livepatch_input, 154 host_addr, patch_len), 155 156 CMD_DMA_LEN(HWRM_DBG_COREDUMP_LIST, FWCTL_RPC_DEBUG_READ_ONLY, 157 DMA_FROM_DEVICE, 158 struct hwrm_dbg_coredump_list_input, host_dest_addr, 159 host_buf_len), 160 CMD_DMA_LEN(HWRM_DBG_COREDUMP_RETRIEVE, FWCTL_RPC_DEBUG_READ_ONLY, 161 DMA_FROM_DEVICE, 162 struct hwrm_dbg_coredump_retrieve_input, host_dest_addr, 163 host_buf_len), 164 /* read_len32 counts 32-bit words, not bytes (see bnxt_dbg_hwrm_rd_reg()). */ 165 CMD_DMAS(HWRM_DBG_READ_DIRECT, FWCTL_RPC_DEBUG_READ_ONLY, 166 struct hwrm_dbg_read_direct_input, 1, 167 CMD_DATA_UNIT(struct hwrm_dbg_read_direct_input, 168 DMA_FROM_DEVICE, 169 host_dest_addr, read_len32, 4)), 170 CMD_DMA_LEN(HWRM_DBG_READ_INDIRECT, FWCTL_RPC_DEBUG_READ_ONLY, 171 DMA_FROM_DEVICE, 172 struct hwrm_dbg_read_indirect_input, host_dest_addr, 173 host_dest_addr_len), 174 CMD_DMA_LEN(HWRM_DBG_SERDES_TEST, FWCTL_RPC_DEBUG_READ_ONLY, 175 DMA_FROM_DEVICE, 176 struct hwrm_dbg_serdes_test_input, resp_data_addr, 177 data_len), 178 CMD_DMA_LEN(HWRM_DBG_TOKEN_CFG, FWCTL_RPC_DEBUG_WRITE_FULL, 179 DMA_TO_DEVICE, struct hwrm_dbg_token_cfg_input, 180 host_src_addr, dbg_token_len), 181 182 CMD_DMA_LEN(HWRM_QUEUE_DSCP2PRI_QCFG, FWCTL_RPC_DEBUG_READ_ONLY, 183 DMA_FROM_DEVICE, 184 struct hwrm_queue_dscp2pri_qcfg_input, dest_data_addr, 185 dest_data_buffer_size), 186 187 CMD_DMAS(HWRM_PORT_QSTATS, FWCTL_RPC_DEBUG_READ_ONLY, 188 struct hwrm_port_qstats_input, 2, 189 CMD_DATA_FIXED(struct hwrm_port_qstats_input, 190 DMA_FROM_DEVICE, tx_stat_host_addr, 191 sizeof(struct tx_port_stats)), 192 CMD_DATA_FIXED(struct hwrm_port_qstats_input, 193 DMA_FROM_DEVICE, rx_stat_host_addr, 194 sizeof(struct rx_port_stats))), 195 CMD_DMAS(HWRM_PORT_QSTATS_EXT, FWCTL_RPC_DEBUG_READ_ONLY, 196 struct hwrm_port_qstats_ext_input, 2, 197 CMD_DATA_SIMPLE(struct hwrm_port_qstats_ext_input, 198 DMA_FROM_DEVICE, tx_stat_host_addr, 199 tx_stat_size), 200 CMD_DATA_SIMPLE(struct hwrm_port_qstats_ext_input, 201 DMA_FROM_DEVICE, rx_stat_host_addr, 202 rx_stat_size)), 203 CMD_DMAS(HWRM_PORT_QSTATS_EXT_PFC_ADV, FWCTL_RPC_DEBUG_READ_ONLY, 204 struct hwrm_port_qstats_ext_pfc_adv_input, 2, 205 CMD_DATA_SIMPLE(struct hwrm_port_qstats_ext_pfc_adv_input, 206 DMA_FROM_DEVICE, 207 tx_pfc_adv_stat_host_addr, pfc_adv_stat_size), 208 CMD_DATA_SIMPLE(struct hwrm_port_qstats_ext_pfc_adv_input, 209 DMA_FROM_DEVICE, 210 rx_pfc_adv_stat_host_addr, pfc_adv_stat_size)), 211 CMD_DMA_LEN(HWRM_PCIE_QSTATS, FWCTL_RPC_DEBUG_READ_ONLY, 212 DMA_FROM_DEVICE, struct hwrm_pcie_qstats_input, 213 pcie_stat_host_addr, pcie_stat_size), 214 CMD_DMA_LEN(HWRM_STAT_GENERIC_QSTATS, FWCTL_RPC_DEBUG_READ_ONLY, 215 DMA_FROM_DEVICE, 216 struct hwrm_stat_generic_qstats_input, 217 generic_stat_host_addr, generic_stat_size), 218 CMD_DMA_LEN(HWRM_STAT_QUERY_ROCE_STATS, FWCTL_RPC_DEBUG_READ_ONLY, 219 DMA_FROM_DEVICE, 220 struct hwrm_stat_query_roce_stats_input, 221 roce_stat_host_addr, roce_stat_size), 222 CMD_DMA_LEN(HWRM_STAT_QUERY_ROCE_STATS_EXT, FWCTL_RPC_DEBUG_READ_ONLY, 223 DMA_FROM_DEVICE, 224 struct hwrm_stat_query_roce_stats_ext_input, 225 roce_stat_host_addr, roce_stat_size), 226 227 CMD_DMA_LEN(HWRM_PORT_EVENTS_LOG, FWCTL_RPC_DEBUG_READ_ONLY, 228 DMA_FROM_DEVICE, 229 struct hwrm_port_events_log_input, host_dest_addr, 230 host_dest_addr_len), 231 CMD_DMA_LEN(HWRM_PORT_PRBS_TEST, FWCTL_RPC_DEBUG_READ_ONLY, 232 DMA_FROM_DEVICE, 233 struct hwrm_port_prbs_test_input, resp_data_addr, data_len), 234 CMD_DMA_LEN(HWRM_PORT_DSC_DUMP, FWCTL_RPC_DEBUG_READ_ONLY, 235 DMA_FROM_DEVICE, struct hwrm_port_dsc_dump_input, 236 resp_data_addr, data_len), 237 238 /* num_fids counts 16-bit FIDs, not bytes. */ 239 CMD_DMAS(HWRM_SCH_GRP_CFG, FWCTL_RPC_DEBUG_WRITE, 240 struct hwrm_sch_grp_cfg_input, 1, 241 CMD_DATA_UNIT(struct hwrm_sch_grp_cfg_input, 242 DMA_TO_DEVICE, fid_table_addr, 243 num_fids, 2)), 244 CMD_DMA_LEN(HWRM_SCH_GRP_QCFG, FWCTL_RPC_DEBUG_READ_ONLY, 245 DMA_FROM_DEVICE, struct hwrm_sch_grp_qcfg_input, 246 fid_table_addr, fid_table_len), 247 248 CMD_DMA_LEN(HWRM_SELFTEST_RETRIEVE_SERDES_DATA, 249 FWCTL_RPC_DEBUG_READ_ONLY, DMA_FROM_DEVICE, 250 struct hwrm_selftest_retrieve_serdes_data_input, 251 resp_data_addr, data_len), 252 253 CMD_DMAS(HWRM_DBG_PTRACE, FWCTL_RPC_DEBUG_WRITE, 254 struct hwrm_dbg_ptrace_input, 2, 255 CMD_DATA_SIMPLE(struct hwrm_dbg_ptrace_input, 256 DMA_TO_DEVICE, pdi_cmd_buf_addr, 257 pdi_req_buf_len), 258 CMD_DATA_SIMPLE(struct hwrm_dbg_ptrace_input, 259 DMA_FROM_DEVICE, pdi_resp_buf_addr, 260 pdi_req_buf_len)), 261 }; 262 263 #undef CMD_DATA_UNIT 264 #undef CMD_DATA_SIMPLE 265 #undef CMD_DATA_FIXED 266 #undef CMD_DMAS 267 #undef CMD_DMA_LEN 268 269 static const struct bnxtctl_cmd_dma_desc * 270 bnxtctl_find_dma_desc(u16 req_type) 271 { 272 unsigned int i; 273 274 for (i = 0; i < ARRAY_SIZE(bnxtctl_dma_cmds); i++) 275 if (bnxtctl_dma_cmds[i].req_type == req_type) 276 return &bnxtctl_dma_cmds[i]; 277 return NULL; 278 } 279 280 static void bnxtctl_extract_and_zero_dma_fields(void *cmd, 281 const struct bnxtctl_cmd_dma_desc *desc, 282 u64 *user_addrs) 283 { 284 unsigned int i; 285 286 for (i = 0; i < desc->num_fields; i++) { 287 __le32 *field = cmd + desc->fields[i].offset; 288 289 user_addrs[i] = le32_to_cpu(field[0]) | 290 ((u64)le32_to_cpu(field[1]) << 32); 291 field[0] = 0; 292 field[1] = 0; 293 } 294 } 295 296 static u32 bnxtctl_read_len_field(void *cmd, const struct bnxtctl_dma_field *f) 297 { 298 if (f->len_width == 2) 299 return le16_to_cpup((__le16 *)(cmd + f->len_offset)); 300 return le32_to_cpup((__le32 *)(cmd + f->len_offset)); 301 } 302 303 static int bnxtctl_check_dma_lens(void *cmd, const struct bnxtctl_cmd_dma_desc *desc, 304 u32 *lens) 305 { 306 unsigned int i; 307 308 for (i = 0; i < desc->num_fields; i++) { 309 const struct bnxtctl_dma_field *f = &desc->fields[i]; 310 u64 len; 311 312 if (f->len_offset) { 313 if (check_mul_overflow(bnxtctl_read_len_field(cmd, f), 314 f->len_unit, &len)) 315 return -EINVAL; 316 } else { 317 len = f->buf_len; 318 } 319 320 if (!len || len > FWCTL_BNXT_MAX_DMABUF) 321 return -EINVAL; 322 323 lens[i] = len; 324 } 325 return 0; 326 } 327 328 static int bnxtctl_map_dma_bufs(struct device *dev, void *cmd, 329 const struct bnxtctl_cmd_dma_desc *desc, 330 const u64 *user_addrs, const u32 *lens, 331 void **kbufs, dma_addr_t *dma_addrs, 332 unsigned int *num_mapped) 333 { 334 unsigned int i; 335 336 *num_mapped = 0; 337 for (i = 0; i < desc->num_fields; i++) { 338 const struct bnxtctl_dma_field *f = &desc->fields[i]; 339 __le32 *field; 340 341 kbufs[i] = dma_alloc_coherent(dev, lens[i], 342 &dma_addrs[i], GFP_KERNEL); 343 if (!kbufs[i]) 344 return -ENOMEM; 345 346 if (f->dir == DMA_TO_DEVICE && 347 copy_from_user(kbufs[i], u64_to_user_ptr(user_addrs[i]), 348 lens[i])) { 349 dma_free_coherent(dev, lens[i], kbufs[i], 350 dma_addrs[i]); 351 kbufs[i] = NULL; 352 return -EFAULT; 353 } 354 355 (*num_mapped)++; 356 357 field = cmd + f->offset; 358 field[0] = cpu_to_le32(lower_32_bits(dma_addrs[i])); 359 field[1] = cpu_to_le32(upper_32_bits(dma_addrs[i])); 360 } 361 return 0; 362 } 363 364 static int bnxtctl_unmap_dma_bufs(struct device *dev, 365 const struct bnxtctl_cmd_dma_desc *desc, 366 const u64 *user_addrs, const u32 *lens, 367 void **kbufs, dma_addr_t *dma_addrs, 368 unsigned int num_mapped) 369 { 370 unsigned int i; 371 int rc = 0; 372 373 for (i = 0; i < num_mapped; i++) { 374 if (desc->fields[i].dir == DMA_FROM_DEVICE && 375 copy_to_user(u64_to_user_ptr(user_addrs[i]), 376 kbufs[i], lens[i])) 377 rc = -EFAULT; 378 379 dma_free_coherent(dev, lens[i], kbufs[i], dma_addrs[i]); 380 } 381 return rc; 382 } 383 384 /* Caller must hold edev->en_dev_lock */ 385 static bool bnxtctl_validate_rpc(struct bnxt_en_dev *edev, 386 struct bnxt_fw_msg *hwrm_in, 387 enum fwctl_rpc_scope scope) 388 { 389 struct input *req = (struct input *)hwrm_in->msg; 390 u16 req_type = le16_to_cpu(req->req_type); 391 const struct bnxtctl_cmd_dma_desc *desc; 392 393 lockdep_assert_held(&edev->en_dev_lock); 394 if (edev->flags & BNXT_EN_FLAG_ULP_STOPPED) 395 return false; 396 397 desc = bnxtctl_find_dma_desc(req_type); 398 if (desc) 399 return scope >= desc->scope_min; 400 401 switch (req_type) { 402 case HWRM_FUNC_RESET: 403 case HWRM_PORT_CLR_STATS: 404 case HWRM_FW_RESET: 405 case HWRM_FW_SYNC: 406 case HWRM_FW_SET_TIME: 407 case HWRM_DBG_LOG_BUFFER_FLUSH: 408 case HWRM_DBG_ERASE_NVM: 409 case HWRM_DBG_CFG: 410 case HWRM_NVM_DEFRAG: 411 case HWRM_NVM_FACTORY_DEFAULTS: 412 case HWRM_NVM_FLUSH: 413 case HWRM_NVM_VERIFY_UPDATE: 414 case HWRM_NVM_ERASE_DIR_ENTRY: 415 case HWRM_NVM_MOD_DIR_ENTRY: 416 case HWRM_NVM_FIND_DIR_ENTRY: 417 return scope >= FWCTL_RPC_CONFIGURATION; 418 419 case HWRM_VER_GET: 420 case HWRM_ERROR_RECOVERY_QCFG: 421 case HWRM_FUNC_QCAPS: 422 case HWRM_FUNC_QCFG: 423 case HWRM_FUNC_QSTATS: 424 case HWRM_PORT_PHY_QCFG: 425 case HWRM_PORT_MAC_QCFG: 426 case HWRM_PORT_PHY_QCAPS: 427 case HWRM_PORT_PHY_I2C_READ: 428 case HWRM_PORT_PHY_MDIO_READ: 429 case HWRM_QUEUE_PRI2COS_QCFG: 430 case HWRM_QUEUE_COS2BW_QCFG: 431 case HWRM_VNIC_RSS_QCFG: 432 case HWRM_QUEUE_GLOBAL_QCFG: 433 case HWRM_QUEUE_ADPTV_QOS_RX_FEATURE_QCFG: 434 case HWRM_QUEUE_ADPTV_QOS_TX_FEATURE_QCFG: 435 case HWRM_QUEUE_QCAPS: 436 case HWRM_QUEUE_ADPTV_QOS_RX_TUNING_QCFG: 437 case HWRM_QUEUE_ADPTV_QOS_TX_TUNING_QCFG: 438 case HWRM_TUNNEL_DST_PORT_QUERY: 439 case HWRM_PORT_TX_FIR_QCFG: 440 case HWRM_FW_LIVEPATCH_QUERY: 441 case HWRM_FW_QSTATUS: 442 case HWRM_FW_HEALTH_CHECK: 443 case HWRM_FW_GET_TIME: 444 case HWRM_PORT_EP_TX_QCFG: 445 case HWRM_PORT_QCFG: 446 case HWRM_PORT_MAC_QCAPS: 447 case HWRM_TEMP_MONITOR_QUERY: 448 case HWRM_REG_POWER_QUERY: 449 case HWRM_CORE_FREQUENCY_QUERY: 450 case HWRM_CFA_REDIRECT_QUERY_TUNNEL_TYPE: 451 case HWRM_CFA_ADV_FLOW_MGNT_QCAPS: 452 case HWRM_FUNC_RESOURCE_QCAPS: 453 case HWRM_FUNC_BACKING_STORE_QCAPS: 454 case HWRM_FUNC_BACKING_STORE_QCFG: 455 case HWRM_FUNC_QSTATS_EXT: 456 case HWRM_FUNC_PTP_PIN_QCFG: 457 case HWRM_FUNC_PTP_EXT_QCFG: 458 case HWRM_FUNC_BACKING_STORE_QCFG_V2: 459 case HWRM_FUNC_BACKING_STORE_QCAPS_V2: 460 case HWRM_FUNC_SYNCE_QCFG: 461 case HWRM_FUNC_TTX_PACING_RATE_PROF_QUERY: 462 case HWRM_PORT_PHY_FDRSTAT: 463 case HWRM_DBG_RING_INFO_GET: 464 case HWRM_DBG_QCAPS: 465 case HWRM_DBG_QCFG: 466 case HWRM_DBG_USEQ_FLUSH: 467 case HWRM_DBG_USEQ_QCAPS: 468 case HWRM_DBG_SIM_CABLE_STATE: 469 case HWRM_DBG_TOKEN_QUERY_AUTH_IDS: 470 case HWRM_NVM_GET_DEV_INFO: 471 case HWRM_NVM_GET_DIR_INFO: 472 case HWRM_SELFTEST_QLIST: 473 case HWRM_DBG_COREDUMP_INITIATE: 474 return scope >= FWCTL_RPC_DEBUG_READ_ONLY; 475 476 case HWRM_PORT_PHY_I2C_WRITE: 477 case HWRM_PORT_PHY_MDIO_WRITE: 478 return scope >= FWCTL_RPC_DEBUG_WRITE; 479 480 default: 481 return false; 482 } 483 } 484 485 #define BNXTCTL_HWRM_CMD_TIMEOUT_DFLT 500 /* ms */ 486 #define BNXTCTL_HWRM_CMD_TIMEOUT_MEDM 2000 /* ms */ 487 #define BNXTCTL_HWRM_CMD_TIMEOUT_LONG 60000 /* ms */ 488 489 static unsigned int bnxtctl_get_timeout(struct input *req) 490 { 491 switch (le16_to_cpu(req->req_type)) { 492 case HWRM_NVM_DEFRAG: 493 case HWRM_NVM_FACTORY_DEFAULTS: 494 case HWRM_NVM_FLUSH: 495 case HWRM_NVM_VERIFY_UPDATE: 496 case HWRM_NVM_ERASE_DIR_ENTRY: 497 case HWRM_NVM_MOD_DIR_ENTRY: 498 case HWRM_NVM_WRITE: 499 case HWRM_FW_SYNC: 500 case HWRM_DBG_COREDUMP_LIST: 501 case HWRM_DBG_COREDUMP_RETRIEVE: 502 case HWRM_DBG_COREDUMP_INITIATE: 503 case HWRM_SELFTEST_RETRIEVE_SERDES_DATA: 504 case HWRM_DBG_SERDES_TEST: 505 case HWRM_NVM_RAW_WRITE_BLK: 506 case HWRM_FW_HEALTH_CHECK: 507 return BNXTCTL_HWRM_CMD_TIMEOUT_LONG; 508 case HWRM_FUNC_RESET: 509 return BNXTCTL_HWRM_CMD_TIMEOUT_MEDM; 510 default: 511 return BNXTCTL_HWRM_CMD_TIMEOUT_DFLT; 512 } 513 } 514 515 static void *bnxtctl_fw_rpc(struct fwctl_uctx *uctx, 516 enum fwctl_rpc_scope scope, 517 void *in, size_t in_len, size_t *out_len) 518 { 519 struct bnxtctl_dev *bnxtctl = 520 container_of(uctx->fwctl, struct bnxtctl_dev, fwctl); 521 struct bnxt_en_dev *edev = bnxtctl->aux_priv->edev; 522 dma_addr_t dma_addrs[BNXTCTL_MAX_DMA_FIELDS]; 523 void *kbufs[BNXTCTL_MAX_DMA_FIELDS] = {}; 524 const struct bnxtctl_cmd_dma_desc *desc; 525 u64 user_addrs[BNXTCTL_MAX_DMA_FIELDS]; 526 struct device *dev = &edev->pdev->dev; 527 u32 dma_lens[BNXTCTL_MAX_DMA_FIELDS]; 528 struct bnxt_fw_msg rpc_in = {}; 529 unsigned int num_mapped = 0; 530 struct input *req = in; 531 int rc; 532 533 if (in_len < sizeof(struct input) || in_len > HWRM_MAX_REQ_LEN) 534 return ERR_PTR(-EINVAL); 535 536 if (*out_len < sizeof(struct output)) 537 return ERR_PTR(-EINVAL); 538 539 desc = bnxtctl_find_dma_desc(le16_to_cpu(req->req_type)); 540 541 if (desc) { 542 if (in_len != desc->req_size) 543 return ERR_PTR(-EINVAL); 544 545 rc = bnxtctl_check_dma_lens(in, desc, dma_lens); 546 if (rc) 547 return ERR_PTR(rc); 548 549 bnxtctl_extract_and_zero_dma_fields(in, desc, user_addrs); 550 } 551 552 rpc_in.msg = in; 553 rpc_in.msg_len = in_len; 554 rpc_in.resp = kvzalloc(*out_len, GFP_KERNEL); 555 if (!rpc_in.resp) 556 return ERR_PTR(-ENOMEM); 557 558 rpc_in.resp_max_len = *out_len; 559 rpc_in.timeout = bnxtctl_get_timeout(in); 560 561 guard(mutex)(&edev->en_dev_lock); 562 563 if (!bnxtctl_validate_rpc(edev, &rpc_in, scope)) { 564 kvfree(rpc_in.resp); 565 return ERR_PTR(-EPERM); 566 } 567 568 if (desc) { 569 rc = bnxtctl_map_dma_bufs(dev, in, desc, user_addrs, dma_lens, 570 kbufs, dma_addrs, &num_mapped); 571 if (rc) { 572 bnxtctl_unmap_dma_bufs(dev, desc, user_addrs, dma_lens, 573 kbufs, dma_addrs, num_mapped); 574 kvfree(rpc_in.resp); 575 return ERR_PTR(rc); 576 } 577 } 578 579 rc = bnxt_send_msg(edev, &rpc_in); 580 if (rc) { 581 struct output *resp = rpc_in.resp; 582 583 /* Copy the response to user always, as it contains 584 * detailed status of the command failure 585 */ 586 if (!resp->error_code) 587 /* bnxt_send_msg() returned much before FW 588 * received the command. 589 */ 590 resp->error_code = cpu_to_le16(rc); 591 } 592 593 if (desc) { 594 int unmap_rc; 595 596 unmap_rc = bnxtctl_unmap_dma_bufs(dev, desc, user_addrs, 597 dma_lens, kbufs, dma_addrs, 598 num_mapped); 599 if (unmap_rc) { 600 kvfree(rpc_in.resp); 601 return ERR_PTR(unmap_rc); 602 } 603 } 604 605 return rpc_in.resp; 606 } 607 608 static const struct fwctl_ops bnxtctl_ops = { 609 .device_type = FWCTL_DEVICE_TYPE_BNXT, 610 .uctx_size = sizeof(struct bnxtctl_uctx), 611 .open_uctx = bnxtctl_open_uctx, 612 .close_uctx = bnxtctl_close_uctx, 613 .info = bnxtctl_info, 614 .fw_rpc = bnxtctl_fw_rpc, 615 }; 616 617 static int bnxtctl_probe(struct auxiliary_device *adev, 618 const struct auxiliary_device_id *id) 619 { 620 struct bnxt_aux_priv *aux_priv = 621 container_of(adev, struct bnxt_aux_priv, aux_dev); 622 struct bnxtctl_dev *bnxtctl __free(bnxtctl) = 623 fwctl_alloc_device(&aux_priv->edev->pdev->dev, &bnxtctl_ops, 624 struct bnxtctl_dev, fwctl); 625 int rc; 626 627 if (!bnxtctl) 628 return -ENOMEM; 629 630 bnxtctl->aux_priv = aux_priv; 631 632 rc = fwctl_register(&bnxtctl->fwctl); 633 if (rc) 634 return rc; 635 636 auxiliary_set_drvdata(adev, no_free_ptr(bnxtctl)); 637 return 0; 638 } 639 640 static void bnxtctl_remove(struct auxiliary_device *adev) 641 { 642 struct bnxtctl_dev *ctldev = auxiliary_get_drvdata(adev); 643 644 fwctl_unregister(&ctldev->fwctl); 645 fwctl_put(&ctldev->fwctl); 646 } 647 648 static const struct auxiliary_device_id bnxtctl_id_table[] = { 649 { .name = "bnxt_en.fwctl", }, 650 {} 651 }; 652 MODULE_DEVICE_TABLE(auxiliary, bnxtctl_id_table); 653 654 static struct auxiliary_driver bnxtctl_driver = { 655 .name = "bnxt_fwctl", 656 .probe = bnxtctl_probe, 657 .remove = bnxtctl_remove, 658 .id_table = bnxtctl_id_table, 659 }; 660 661 module_auxiliary_driver(bnxtctl_driver); 662 663 MODULE_IMPORT_NS("FWCTL"); 664 MODULE_DESCRIPTION("BNXT fwctl driver"); 665 MODULE_AUTHOR("Pavan Chebbi <pavan.chebbi@broadcom.com>"); 666 MODULE_AUTHOR("Andy Gospodarek <gospo@broadcom.com>"); 667 MODULE_LICENSE("GPL"); 668