From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-dy1-f228.google.com (mail-dy1-f228.google.com [74.125.82.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 274A73A6410 for ; Fri, 22 May 2026 08:07:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.228 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779437252; cv=none; b=CnibwBJyfNuEGMbwNd+wIHl7vNzdYwT4Y5KMwYizBB9nYKvFbvMvVAqGXINWL93CRICMi7NgZCG6CJUxlCwVesCBFLxKLvyE8KPMGZq2nXTF3sZtuccvERgRTO8loJ7/DtDY2ruAgzw2Fz6k6457FUYro1D2YXIwSvATbhGjhnU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779437252; c=relaxed/simple; bh=jX5RAOZCo0u3J9693xrTbjJBxhsMAMnRQTdnkEjXmo8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YvlX3r5E0Er2jVlht2oA2lP8fKiIT4j/b+r2R8pj+cWRuihhAbPyI96RtVH5WWi9Q4fGoTnV44Y2S2z9UPIMnSq7EUEGykWv7cDaiuccEo8UyoNNbJzhesxv3cEydzEzZ0OxHVHVeJfdaazaoU/i8WzVg/5o3r/DIQVT5wiYKy4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=O9X11diw; arc=none smtp.client-ip=74.125.82.228 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="O9X11diw" Received: by mail-dy1-f228.google.com with SMTP id 5a478bee46e88-2f0d3e07e30so23565735eec.0 for ; Fri, 22 May 2026 01:07:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779437249; x=1780042049; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1Ym4/shcjGVJkezu93nxWK7gCUbUI+M1FE/ExNV/3LM=; b=YhoINCZm/WHYkJzRwpmzaNrFCldkz56hl3sn7Hy8hDhmH6oz7CD30EtWMJGJvxavaX wgbdtBVRR6a0wY7/2pbqBKfrrLCvNpNBbNGcqpV2AdyN0JEFmeDI7Aw8t1j1OOxumfyq eAZz3Pw+tVu25jLBc6YbmJ5aqTUZRtNp+g4OXod4nnztISjynx6t31Rib0UUG/sdUckS 4MMirjX7El1nkXP+08qjASIpwnIpGiHn+yO7/J4daos3eMRi1uaihewrBKDnGC9G15Qn XpH4FzxPgxqmjsLpyTBGija7fem2BOuVLkWvSVGJm3PnpuD0mEqeuIm3ZUykr7YUdG9Q QEuw== X-Gm-Message-State: AOJu0YxyBR+aT06+/r8utsIv5myxE6I1pBQL8dYUwlZ3wyIFfidp0Fs+ tylheUJgpdmpX428ErTzrRxQv4q4VLXAxfdczdD3Ppm0lcR/oWTRRVQf48OS9Utz5b4zzXsQXar YDuS361msweHB9fV8zqFLhT+HL4d4cpxdxEwZ2WA8xq/IZBROqIqLgzwvgOZ+BI2GZEZQlZbP+i Z3q9dK8aPQ2gKtF2r10UwiYua2xkkeQoqzEnbRc4fK0/uCabAabhxOwOCikC5qINrLmqiuATBI/ 9t7ANr6c4OXH68OD50= X-Gm-Gg: Acq92OGL22l09aBWvUkiYbAqJFIZafY9NlpDpEzZfd7DtAbsuXJ6YrRpzPnxoJHIN3t BM4n6aMqwGfRdbGV9hGZzxXDakHGkCw/p4YZ5VQ4csWivi3JvbrKnvdEKW/3LRKSIVKxWCWUWFP MGs3OEiQJkF77PzbvYLEPvTXfx5WYuIvIFWp+5u0G+jD2xA03R18+1nicclDfMjaepYVUuoq4Cc KoCOU9pSZ6kG3nddveougnjJQucZkaEoei9rAwnx4xvoKgqliAy3X6w7GrMnTRHH/b2Obxn8wG1 3ZoJLGRd8zysFfdqpEVFNZTQjav1V8FH01OJsr2ohvLADwJ0Urle9k1RiZUL1H41kqcxzvMGWF+ aYnmION881YSPYPTiGL4F4NVYwwTdyMXhmO2kslHwJ5JLhOsxTGMXpXeuyVcK5P7CWUaiNLSbwH 5pJVC6GS9CcDMFkrFQWR119ex3PvSGY1CkU1PqhEFCaCw9Vtj/GasjhNaG62s= X-Received: by 2002:a05:7300:641a:b0:2ed:e15:c926 with SMTP id 5a478bee46e88-30449144597mr1493397eec.34.1779437249136; Fri, 22 May 2026 01:07:29 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-117.dlp.protect.broadcom.com. [144.49.247.117]) by smtp-relay.gmail.com with ESMTPS id 5a478bee46e88-30451eeba42sm45403eec.12.2026.05.22.01.07.28 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 May 2026 01:07:29 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-2bd5b20aaa6so75367335ad.2 for ; Fri, 22 May 2026 01:07:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1779437247; x=1780042047; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1Ym4/shcjGVJkezu93nxWK7gCUbUI+M1FE/ExNV/3LM=; b=O9X11diwXYfP14B/+CupZsTdGNG843Bm8DUoUV68q0LRepQBjFvokFVukFrtBCMIaM CKy/faYlOBdpmyxwU5dK8QA+1iIb25WyIZo2p8ZIQ3s9NtYImwq96Fs+s8KFlIAoNwDz RRkIcp1t4aJ32vFODPEksEB60esA5bVdAY71A= X-Received: by 2002:a17:902:e788:b0:2b2:6cab:313c with SMTP id d9443c01a7336-2beb074f4ffmr24964095ad.20.1779437247225; Fri, 22 May 2026 01:07:27 -0700 (PDT) X-Received: by 2002:a17:902:e788:b0:2b2:6cab:313c with SMTP id d9443c01a7336-2beb074f4ffmr24963825ad.20.1779437246654; Fri, 22 May 2026 01:07:26 -0700 (PDT) Received: from pc-hpe-top-git-sendmail-server.dhcp.broadcom.net ([192.19.234.250]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2beb58b386esm10927905ad.44.2026.05.22.01.07.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 May 2026 01:07:26 -0700 (PDT) From: Pavan Chebbi To: jgg@ziepe.ca, michael.chan@broadcom.com Cc: linux-kernel@vger.kernel.org, dave.jiang@intel.com, saeedm@nvidia.com, Jonathan.Cameron@huawei.com, gospo@broadcom.com, selvin.xavier@broadcom.com, leon@kernel.org, kalesh-anakkur.purayil@broadcom.com, Pavan Chebbi Subject: [PATCH fwctl 3/3] fwctl/bnxt: add DMA buffer support for HWRM commands Date: Fri, 22 May 2026 13:38:30 +0530 Message-ID: <20260522080830.162740-4-pavan.chebbi@broadcom.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260522080830.162740-1-pavan.chebbi@broadcom.com> References: <20260522080830.162740-1-pavan.chebbi@broadcom.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e Several HWRM commands carry __le64 DMA address fields in their input structures; firmware reads from or writes to the memory those addresses point to. Because the kernel must own all DMA mappings, userspace shall describe the indirect buffers via fwctl_rpc.driver_data and the driver shall map and patch the commands before sending to firmware. Introduce UAPI types for bnxt_fwctl that help userspace describe the DMA buffers. Have a static per-command descriptor table in the driver that records the details of the DMA fields in each supported HWRM input struct. When a DMA-bearing HWRM command arrives, the driver validates it using the descriptor table. Scope-gated allow-list is updated with the new DMA capable commands. Signed-off-by: Pavan Chebbi --- drivers/fwctl/bnxt/main.c | 323 +++++++++++++++++++++++++++++++++++++- include/uapi/fwctl/bnxt.h | 38 +++++ 2 files changed, 359 insertions(+), 2 deletions(-) diff --git a/drivers/fwctl/bnxt/main.c b/drivers/fwctl/bnxt/main.c index 951c8ac2e0a1..c47fa0eacbcc 100644 --- a/drivers/fwctl/bnxt/main.c +++ b/drivers/fwctl/bnxt/main.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -31,7 +32,8 @@ static int bnxtctl_open_uctx(struct fwctl_uctx *uctx) bnxtctl_uctx->uctx_caps = BIT(FWCTL_BNXT_INLINE_COMMANDS) | BIT(FWCTL_BNXT_QUERY_COMMANDS) | - BIT(FWCTL_BNXT_SEND_COMMANDS); + BIT(FWCTL_BNXT_SEND_COMMANDS) | + BIT(FWCTL_BNXT_DMA_COMMANDS); return 0; } @@ -55,6 +57,237 @@ static void *bnxtctl_info(struct fwctl_uctx *uctx, size_t *length) return info; } +struct bnxtctl_dma_field { + size_t offset; /* offsetof(hwrm_xxx_input, field_name) */ + u8 dir; +}; + +struct bnxtctl_cmd_dma_desc { + u16 req_type; + u8 num_fields; + u8 scope_min; + struct bnxtctl_dma_field fields[FWCTL_BNXT_MAX_BUFS]; +}; + +/* + * Per-command DMA buffer descriptor table for HWRM commands that + * carry __le64 DMA address fields in their input + */ +static const struct bnxtctl_cmd_dma_desc bnxtctl_dma_cmds[] = { + { HWRM_NVM_SET_VARIABLE, 1, FWCTL_RPC_CONFIGURATION, + {{ offsetof(struct hwrm_nvm_set_variable_input, src_data_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + { HWRM_NVM_GET_VARIABLE, 1, FWCTL_RPC_CONFIGURATION, + {{ offsetof(struct hwrm_nvm_get_variable_input, dest_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_NVM_READ, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_nvm_read_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_NVM_GET_DIR_ENTRIES, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_nvm_get_dir_entries_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_NVM_WRITE, 1, FWCTL_RPC_DEBUG_WRITE, + {{ offsetof(struct hwrm_nvm_write_input, host_src_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + { HWRM_NVM_MODIFY, 1, FWCTL_RPC_DEBUG_WRITE, + {{ offsetof(struct hwrm_nvm_modify_input, host_src_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + { HWRM_NVM_RAW_WRITE_BLK, 1, FWCTL_RPC_DEBUG_WRITE_FULL, + {{ offsetof(struct hwrm_nvm_raw_write_blk_input, host_src_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + { HWRM_NVM_RAW_DUMP, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_nvm_raw_dump_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + + { HWRM_FW_GET_STRUCTURED_DATA, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_fw_get_structured_data_input, dest_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_FW_SET_STRUCTURED_DATA, 1, FWCTL_RPC_DEBUG_WRITE, + {{ offsetof(struct hwrm_fw_set_structured_data_input, src_data_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + { HWRM_FW_LIVEPATCH, 1, FWCTL_RPC_DEBUG_WRITE_FULL, + {{ offsetof(struct hwrm_fw_livepatch_input, host_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + + { HWRM_DBG_COREDUMP_LIST, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_dbg_coredump_list_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_DBG_COREDUMP_RETRIEVE, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_dbg_coredump_retrieve_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_DBG_READ_DIRECT, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_dbg_read_direct_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_DBG_READ_INDIRECT, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_dbg_read_indirect_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_DBG_SERDES_TEST, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_dbg_serdes_test_input, resp_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_DBG_TOKEN_CFG, 1, FWCTL_RPC_DEBUG_WRITE_FULL, + {{ offsetof(struct hwrm_dbg_token_cfg_input, host_src_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + + { HWRM_QUEUE_DSCP2PRI_QCFG, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_queue_dscp2pri_qcfg_input, dest_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + + { HWRM_PORT_QSTATS, 2, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_port_qstats_input, tx_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }, + { offsetof(struct hwrm_port_qstats_input, rx_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_PORT_QSTATS_EXT, 2, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_port_qstats_ext_input, tx_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }, + { offsetof(struct hwrm_port_qstats_ext_input, rx_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_PORT_QSTATS_EXT_PFC_ADV, 2, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_port_qstats_ext_pfc_adv_input, + tx_pfc_adv_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }, + { offsetof(struct hwrm_port_qstats_ext_pfc_adv_input, + rx_pfc_adv_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_PCIE_QSTATS, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_pcie_qstats_input, pcie_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_STAT_GENERIC_QSTATS, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_stat_generic_qstats_input, + generic_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_STAT_QUERY_ROCE_STATS, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_stat_query_roce_stats_input, + roce_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_STAT_QUERY_ROCE_STATS_EXT, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_stat_query_roce_stats_ext_input, + roce_stat_host_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + + { HWRM_PORT_EVENTS_LOG, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_port_events_log_input, host_dest_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_PORT_PRBS_TEST, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_port_prbs_test_input, resp_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + { HWRM_PORT_DSC_DUMP, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_port_dsc_dump_input, resp_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + + { HWRM_SCH_GRP_CFG, 1, FWCTL_RPC_DEBUG_WRITE, + {{ offsetof(struct hwrm_sch_grp_cfg_input, fid_table_addr), + FWCTL_BNXT_BUF_TO_DEVICE }} }, + { HWRM_SCH_GRP_QCFG, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_sch_grp_qcfg_input, fid_table_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, + + { HWRM_SELFTEST_RETRIEVE_SERDES_DATA, 1, FWCTL_RPC_DEBUG_READ_ONLY, + {{ offsetof(struct hwrm_selftest_retrieve_serdes_data_input, resp_data_addr), + FWCTL_BNXT_BUF_FROM_DEVICE }} }, +}; + +static const struct bnxtctl_cmd_dma_desc * +bnxtctl_find_dma_desc(u16 req_type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bnxtctl_dma_cmds); i++) + if (bnxtctl_dma_cmds[i].req_type == req_type) + return &bnxtctl_dma_cmds[i]; + return NULL; +} + +static void bnxtctl_zero_dma_fields(void *cmd, + const struct bnxtctl_cmd_dma_desc *desc) +{ + int i; + + for (i = 0; i < desc->num_fields; i++) { + __le64 *field = cmd + desc->fields[i].offset; + + *field = 0; + } +} + +static int bnxtctl_map_dma_bufs(struct device *dev, void *cmd, + const struct bnxtctl_cmd_dma_desc *desc, + const struct fwctl_bnxt_driver_data *dd, + void **kbufs, dma_addr_t *dma_addrs, + unsigned int *num_mapped) +{ + unsigned int i; + + *num_mapped = 0; + for (i = 0; i < dd->num_bufs; i++) { + enum dma_data_direction dma_dir; + __le64 *field; + + if (dd->bufs[i].dir != desc->fields[i].dir) + return -EINVAL; + + if (!dd->bufs[i].len || dd->bufs[i].len > FWCTL_BNXT_MAX_DMABUF) + return -EINVAL; + + dma_dir = (dd->bufs[i].dir == FWCTL_BNXT_BUF_TO_DEVICE) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + + kbufs[i] = kvzalloc(dd->bufs[i].len, GFP_KERNEL); + if (!kbufs[i]) + return -ENOMEM; + + if (dma_dir == DMA_TO_DEVICE && + copy_from_user(kbufs[i], + u64_to_user_ptr(dd->bufs[i].addr), + dd->bufs[i].len)) { + kvfree(kbufs[i]); + kbufs[i] = NULL; + return -EFAULT; + } + + dma_addrs[i] = dma_map_single(dev, kbufs[i], + dd->bufs[i].len, dma_dir); + if (dma_mapping_error(dev, dma_addrs[i])) { + kvfree(kbufs[i]); + kbufs[i] = NULL; + return -ENOMEM; + } + + (*num_mapped)++; + + field = cmd + desc->fields[i].offset; + *field = cpu_to_le64(dma_addrs[i]); + } + return 0; +} + +static int bnxtctl_unmap_dma_bufs(struct device *dev, + const struct bnxtctl_cmd_dma_desc *desc, + const struct fwctl_bnxt_driver_data *dd, + void **kbufs, dma_addr_t *dma_addrs, + unsigned int num_mapped) +{ + unsigned int i; + int rc = 0; + + for (i = 0; i < num_mapped; i++) { + enum dma_data_direction dma_dir; + + dma_dir = (dd->bufs[i].dir == FWCTL_BNXT_BUF_TO_DEVICE) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + + dma_unmap_single(dev, dma_addrs[i], dd->bufs[i].len, dma_dir); + + if (dma_dir == DMA_FROM_DEVICE && + copy_to_user(u64_to_user_ptr(dd->bufs[i].addr), + kbufs[i], dd->bufs[i].len)) + rc = -EFAULT; + + kvfree(kbufs[i]); + } + return rc; +} + /* Caller must hold edev->en_dev_lock */ static bool bnxtctl_validate_rpc(struct bnxt_en_dev *edev, struct bnxt_fw_msg *hwrm_in, @@ -82,6 +315,8 @@ static bool bnxtctl_validate_rpc(struct bnxt_en_dev *edev, case HWRM_NVM_ERASE_DIR_ENTRY: case HWRM_NVM_MOD_DIR_ENTRY: case HWRM_NVM_FIND_DIR_ENTRY: + case HWRM_NVM_SET_VARIABLE: + case HWRM_NVM_GET_VARIABLE: return scope >= FWCTL_RPC_CONFIGURATION; case HWRM_VER_GET: @@ -138,12 +373,43 @@ static bool bnxtctl_validate_rpc(struct bnxt_en_dev *edev, case HWRM_NVM_GET_DEV_INFO: case HWRM_NVM_GET_DIR_INFO: case HWRM_SELFTEST_QLIST: + case HWRM_NVM_READ: + case HWRM_NVM_GET_DIR_ENTRIES: + case HWRM_FW_GET_STRUCTURED_DATA: + case HWRM_DBG_COREDUMP_LIST: + case HWRM_DBG_COREDUMP_RETRIEVE: + case HWRM_DBG_READ_DIRECT: + case HWRM_QUEUE_DSCP2PRI_QCFG: + case HWRM_PORT_QSTATS: + case HWRM_PORT_QSTATS_EXT: + case HWRM_PORT_QSTATS_EXT_PFC_ADV: + case HWRM_PCIE_QSTATS: + case HWRM_STAT_GENERIC_QSTATS: + case HWRM_STAT_QUERY_ROCE_STATS: + case HWRM_STAT_QUERY_ROCE_STATS_EXT: + case HWRM_PORT_EVENTS_LOG: + case HWRM_PORT_PRBS_TEST: + case HWRM_PORT_DSC_DUMP: + case HWRM_DBG_READ_INDIRECT: + case HWRM_DBG_SERDES_TEST: + case HWRM_SCH_GRP_QCFG: + case HWRM_SELFTEST_RETRIEVE_SERDES_DATA: + case HWRM_NVM_RAW_DUMP: return scope >= FWCTL_RPC_DEBUG_READ_ONLY; case HWRM_PORT_PHY_I2C_WRITE: case HWRM_PORT_PHY_MDIO_WRITE: + case HWRM_NVM_WRITE: + case HWRM_NVM_MODIFY: + case HWRM_FW_SET_STRUCTURED_DATA: + case HWRM_SCH_GRP_CFG: return scope >= FWCTL_RPC_DEBUG_WRITE; + case HWRM_FW_LIVEPATCH: + case HWRM_NVM_RAW_WRITE_BLK: + case HWRM_DBG_TOKEN_CFG: + return scope >= FWCTL_RPC_DEBUG_WRITE_FULL; + default: return false; } @@ -172,12 +438,20 @@ static unsigned int bnxtctl_get_timeout(struct input *req) static void *bnxtctl_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, - void *in, size_t in_len, size_t *out_len) + void *in, size_t in_len, size_t *out_len, + __u64 driver_data) { struct bnxtctl_dev *bnxtctl = container_of(uctx->fwctl, struct bnxtctl_dev, fwctl); struct bnxt_en_dev *edev = bnxtctl->aux_priv->edev; + dma_addr_t dma_addrs[FWCTL_BNXT_MAX_BUFS]; + const struct bnxtctl_cmd_dma_desc *desc; + void *kbufs[FWCTL_BNXT_MAX_BUFS] = {0}; + struct fwctl_bnxt_driver_data dd = {0}; + struct device *dev = &edev->pdev->dev; struct bnxt_fw_msg rpc_in = {0}; + unsigned int num_mapped = 0; + struct input *req = in; int rc; if (in_len < sizeof(struct input) || in_len > HWRM_MAX_REQ_LEN) @@ -186,6 +460,29 @@ static void *bnxtctl_fw_rpc(struct fwctl_uctx *uctx, if (*out_len < sizeof(struct output)) return ERR_PTR(-EINVAL); + desc = bnxtctl_find_dma_desc(le16_to_cpu(req->req_type)); + + if (desc) { + if (!driver_data) + return ERR_PTR(-EINVAL); + if (copy_from_user(&dd, u64_to_user_ptr(driver_data), + sizeof(dd))) + return ERR_PTR(-EFAULT); + if (dd.rsvd || !dd.num_bufs || dd.num_bufs > desc->num_fields) + return ERR_PTR(-EINVAL); + + for (unsigned int i = 0; i < dd.num_bufs; i++) { + if (memchr_inv(dd.bufs[i].rsvd, 0, + sizeof(dd.bufs[i].rsvd))) + return ERR_PTR(-EINVAL); + } + bnxtctl_zero_dma_fields(in, desc); + } else { + /* Non-DMA command: driver_data must be absent. */ + if (driver_data) + return ERR_PTR(-EOPNOTSUPP); + } + rpc_in.msg = in; rpc_in.msg_len = in_len; rpc_in.resp = kzalloc(*out_len, GFP_KERNEL); @@ -202,6 +499,17 @@ static void *bnxtctl_fw_rpc(struct fwctl_uctx *uctx, return ERR_PTR(-EPERM); } + if (desc) { + rc = bnxtctl_map_dma_bufs(dev, in, desc, &dd, + kbufs, dma_addrs, &num_mapped); + if (rc) { + bnxtctl_unmap_dma_bufs(dev, desc, &dd, + kbufs, dma_addrs, num_mapped); + kfree(rpc_in.resp); + return ERR_PTR(rc); + } + } + rc = bnxt_send_msg(edev, &rpc_in); if (rc) { struct output *resp = rpc_in.resp; @@ -216,6 +524,17 @@ static void *bnxtctl_fw_rpc(struct fwctl_uctx *uctx, resp->error_code = cpu_to_le16(rc); } + if (desc) { + int unmap_rc; + + unmap_rc = bnxtctl_unmap_dma_bufs(dev, desc, &dd, kbufs, + dma_addrs, num_mapped); + if (unmap_rc) { + kfree(rpc_in.resp); + return ERR_PTR(unmap_rc); + } + } + return rpc_in.resp; } diff --git a/include/uapi/fwctl/bnxt.h b/include/uapi/fwctl/bnxt.h index 32e0bfb9a836..80311fb58b79 100644 --- a/include/uapi/fwctl/bnxt.h +++ b/include/uapi/fwctl/bnxt.h @@ -6,12 +6,14 @@ #ifndef _UAPI_FWCTL_BNXT_H_ #define _UAPI_FWCTL_BNXT_H_ +#include #include enum fwctl_bnxt_commands { FWCTL_BNXT_INLINE_COMMANDS = 0, FWCTL_BNXT_QUERY_COMMANDS, FWCTL_BNXT_SEND_COMMANDS, + FWCTL_BNXT_DMA_COMMANDS, }; /** @@ -23,4 +25,40 @@ enum fwctl_bnxt_commands { struct fwctl_info_bnxt { __u32 uctx_caps; }; + +enum fwctl_bnxt_buf_dir { + FWCTL_BNXT_BUF_TO_DEVICE = 0, + FWCTL_BNXT_BUF_FROM_DEVICE = 1, +}; + +/** + * struct fwctl_bnxt_buf - one indirect DMA buffer descriptor + * @addr: Userspace pointer to the payload data. + * @len: Byte length of the buffer. + * @dir: One of enum fwctl_bnxt_buf_dir. + * @rsvd: Must be zero. + */ +struct fwctl_bnxt_buf { + __aligned_u64 addr; + __u32 len; + __u32 dir; + __u32 rsvd[2]; +}; + +#define FWCTL_BNXT_MAX_BUFS 4 +#define FWCTL_BNXT_MAX_DMABUF SZ_4M + +/** + * struct fwctl_bnxt_driver_data - pointed to by fwctl_rpc::driver_data for bnxt + * @num_bufs: Number of valid entries in @bufs. Must be non-zero and no greater + * than the number of DMA address fields the specific HWRM command supports + * @rsvd: Must be zero. + * @bufs: Array of buffer descriptors. + */ +struct fwctl_bnxt_driver_data { + __u32 num_bufs; + __u32 rsvd; + struct fwctl_bnxt_buf bufs[FWCTL_BNXT_MAX_BUFS]; +}; + #endif -- 2.52.0