From patchwork Tue Jun 6 07:42:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268629 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57B14C77B7A for ; Tue, 6 Jun 2023 07:48:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236035AbjFFHsR (ORCPT ); Tue, 6 Jun 2023 03:48:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236247AbjFFHqQ (ORCPT ); Tue, 6 Jun 2023 03:46:16 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8A1AC26B8 for ; Tue, 6 Jun 2023 00:43:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037432; x=1717573432; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JN8MDTvQMyCOUiLrD+/sNVyQ8GHSEs1UDWlYoYOWXZM=; b=JNIoQSXZ7rYLOo2FBa77RrPTlak+O0ni7Ukj6JKZKPaTubVcxFtVChSK 4340u072HUW8EL03fHRWuqDZmU4zQZOe9ArUlfoYxdwgclcWKWbdx0ZTE B41rgfkctLpmD1JuxiYaz9EQKwqQEkIf1W8dlIapUNQBROrb8gZ8mShiN RxmjA55UpDzf80RdI6ZpMyv5icuygeOR4STD0N8cBSoTDiqpfZN112UWn h0E4CTehqeZYZO5xXeN6yFdo3DfNLTHEcI5bdjshBp/563GPdx8a2p/Yk ms99v6AZEYowDmb6DLRLNdrqer22WN1kPe68PRIUP305A78W993pD3HFP A==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419046" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419046" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516233" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516233" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:23 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 01/13] wifi: iwlwifi: Generalize the parsing of the pnvm image Date: Tue, 6 Jun 2023 10:42:58 +0300 Message-Id: <20230606103519.06c02f380b6f.I03a3030fca194aa0c4bc2ecd18531f8914e98cfd@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Generalize iwl_pnvm_parse(). This saves us from copying each payload twice (first in the parsing and later when copying it to the dram). Moreover, its more compatible for handling larger pnvm tables in the future (in which payloads won't be concatenated). The main changes are: 1. Take out the concatenating of the payloads from the parsing level 2. Start using iwl_pnvm_image structure that will hold pointers to payloads that should be delivered to fw, their sizes and number. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 43 +++++++------------ .../intel/iwlwifi/iwl-context-info-gen3.h | 4 +- .../wireless/intel/iwlwifi/iwl-context-info.h | 5 ++- .../net/wireless/intel/iwlwifi/iwl-trans.h | 23 ++++++++-- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 34 +++++++++++---- .../wireless/intel/iwlwifi/pcie/ctxt-info.c | 8 ++-- 6 files changed, 72 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index c6f2672fdc73..bec3c7ec3f4c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -36,10 +36,8 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, const struct iwl_ucode_tlv *tlv; u32 sha1 = 0; u16 mac_type = 0, rf_id = 0; - u8 *pnvm_data = NULL, *tmp; + struct iwl_pnvm_image pnvm_data = {}; bool hw_match = false; - u32 size = 0; - int ret; IWL_DEBUG_FW(trans, "Handling PNVM section\n"); @@ -55,8 +53,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - ret = -EINVAL; - goto out; + return -EINVAL; } data += sizeof(*tlv); @@ -112,23 +109,18 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, break; } - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", - data_len); - - tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL); - if (!tmp) { + if (pnvm_data.n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { IWL_DEBUG_FW(trans, - "Couldn't allocate (more) pnvm_data\n"); - - ret = -ENOMEM; - goto out; + "too many payloads to allocate in DRAM.\n"); + return -EINVAL; } - pnvm_data = tmp; - - memcpy(pnvm_data + size, section->data, data_len); + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", + data_len); - size += data_len; + pnvm_data.chunks[pnvm_data.n_chunks].data = section->data; + pnvm_data.chunks[pnvm_data.n_chunks].len = data_len; + pnvm_data.n_chunks++; break; } @@ -152,22 +144,17 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, "HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n", CSR_HW_REV_TYPE(trans->hw_rev), CSR_HW_RFID_TYPE(trans->hw_rf_id)); - ret = -ENOENT; - goto out; + return -ENOENT; } - if (!size) { + if (!pnvm_data.n_chunks) { IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n"); - ret = -ENOENT; - goto out; + return -ENOENT; } IWL_INFO(trans, "loaded PNVM version %08x\n", sha1); - ret = iwl_trans_set_pnvm(trans, pnvm_data, size); -out: - kfree(pnvm_data); - return ret; + return iwl_trans_set_pnvm(trans, &pnvm_data); } static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, @@ -275,7 +262,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, * need to set it again. */ if (trans->pnvm_loaded) { - ret = iwl_trans_set_pnvm(trans, NULL, 0); + ret = iwl_trans_set_pnvm(trans, NULL); if (ret) return ret; goto skip_parse; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 3f7278014009..9d2dcb64523c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -13,6 +13,8 @@ #define CSR_IML_SIZE_ADDR 0x128 #define CSR_IML_RESP_ADDR 0x12c +#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2 + /* Set bit for enabling automatic function boot */ #define CSR_AUTO_FUNC_BOOT_ENA BIT(1) /* Set bit for initiating function boot */ @@ -278,7 +280,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive); int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len); + const struct iwl_pnvm_image *pnvm_payloads); int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, const void *data, u32 len); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h index 4354d5acac9f..1a1321db137c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2020, 2022 Intel Corporation */ #ifndef __iwl_context_info_file_h__ #define __iwl_context_info_file_h__ @@ -177,6 +177,9 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans); int iwl_pcie_init_fw_sec(struct iwl_trans *trans, const struct fw_img *fw, struct iwl_context_info_dram *ctxt_dram); +void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, + size_t size, + dma_addr_t *phys); int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans, const void *data, u32 len, struct iwl_dram_data *dram); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 9f1228b5a384..35ddb4cfa356 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -459,6 +459,22 @@ struct iwl_trans_rxq_dma_data { u64 ur_bd_cb; }; +/* maximal number of DRAM MAP entries supported by FW */ +#define IPC_DRAM_MAP_ENTRY_NUM_MAX 64 + +/** + * struct iwl_pnvm_image - contains info about the parsed pnvm image + * @chunks: array of pointers to pnvm payloads and their sizes + * @n_chunks: the number of the pnvm payloads. + */ +struct iwl_pnvm_image { + struct { + const void *data; + u32 len; + } chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + u32 n_chunks; +}; + /** * struct iwl_trans_ops - transport specific operations * @@ -614,7 +630,8 @@ struct iwl_trans_ops { void *sanitize_ctx); void (*debugfs_cleanup)(struct iwl_trans *trans); void (*sync_nmi)(struct iwl_trans *trans); - int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len); + int (*set_pnvm)(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data); int (*set_reduce_power)(struct iwl_trans *trans, const void *data, u32 len); void (*interrupts)(struct iwl_trans *trans, bool enable); @@ -1516,10 +1533,10 @@ void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, u32 sw_err_bit); static inline int iwl_trans_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len) + const struct iwl_pnvm_image *pnvm_data) { if (trans->ops->set_pnvm) { - int ret = trans->ops->set_pnvm(trans, data, len); + int ret = trans->ops->set_pnvm(trans, pnvm_data); if (ret) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index cb60ba40fe97..800857e61d65 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -282,28 +282,46 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive) } int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len) + const struct iwl_pnvm_image *pnvm_payloads) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - int ret; + struct iwl_dram_data *dram = &trans_pcie->pnvm_dram; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; /* only allocate the DRAM if not allocated yet */ if (!trans->pnvm_loaded) { + u32 len, len0, len1; + if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) return -EBUSY; - ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->pnvm_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n", - ret); - return ret; + if (pnvm_payloads->n_chunks != + UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { + IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n", + pnvm_payloads->n_chunks); + return -EINVAL; + } + len0 = pnvm_payloads->chunks[0].len; + len1 = pnvm_payloads->chunks[1].len; + if (len1 > 0xFFFFFFFF - len0) { + IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n"); + return -EINVAL; + } + len = len0 + len1; + + dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len, &dram->physical); + if (!dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; } + dram->size = len; + memcpy(dram->block, pnvm_payloads->chunks[0].data, len0); + memcpy((u8 *)dram->block + len0, pnvm_payloads->chunks[1].data, + len1); } prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 74ce31fdf45e..5f55efe64bf5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -38,9 +38,9 @@ static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, return result; } -static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, - size_t size, - dma_addr_t *phys) +void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, + size_t size, + dma_addr_t *phys) { return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0); } From patchwork Tue Jun 6 07:42:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268628 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA3A1C7EE24 for ; Tue, 6 Jun 2023 07:48:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235953AbjFFHsP (ORCPT ); Tue, 6 Jun 2023 03:48:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235861AbjFFHqQ (ORCPT ); Tue, 6 Jun 2023 03:46:16 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 833FD2133 for ; Tue, 6 Jun 2023 00:43:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037431; x=1717573431; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=q40Ce5dVR+9ECIiLvPMIzFvuN0sTQ/em+QWIw9Jt6g8=; b=iBB5ix7PQ/HKXrz+/qS/HYQgGiXjdwQJ0SvtcS4FzWnrQo9MsiLhFWrF j54km5JB/nTQtjKMZAZ66oAecqI1/6gczxxozhVee+Oi7UzqZ6R34lcrA IslBtyrmI7nSRGmAVNA9FrwtGAHxnuzj8LDWQD7hJjTo6YiQLm2Qqi97I 0IKjQQ/502gJaMKioVILm7snsfnGrtEPSCsEsKaw58w3y5RrP3b64Tq1n jrqhoMQMzM86VlIzlqd2nwpGEtoVhzddGH4DWEojgLXe2j7N++CnNUY22 A7Uz5bqIlNA7W81pbxUS6nb1zsxgN+s+4Ow/YNzVIzlW8COinT7m5CT3g A==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419053" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419053" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:27 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516250" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516250" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:26 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 02/13] wifi: iwlwifi: Separate loading and setting of pnvm image into two functions Date: Tue, 6 Jun 2023 10:42:59 +0300 Message-Id: <20230606103519.4c0728239fd6.Ibc30a9fbdb6123dadbe2dbb89318dbd5ec01080a@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Take the part that is copying the pnvm image into DRAM, out of the the method that sets the prph_scratch. Makes the code cleaner since those 2 operations don't always happen together (loading should happen only once while setting can happen more than once). In addition, each operation will get more complex in the future when it will support also larger pnvm images. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 12 ++-- .../intel/iwlwifi/iwl-context-info-gen3.h | 5 +- .../net/wireless/intel/iwlwifi/iwl-trans.h | 25 ++++--- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 69 +++++++++++-------- .../net/wireless/intel/iwlwifi/pcie/trans.c | 1 + 5 files changed, 65 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index bec3c7ec3f4c..f99328cc6b01 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -38,6 +38,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, u16 mac_type = 0, rf_id = 0; struct iwl_pnvm_image pnvm_data = {}; bool hw_match = false; + int ret; IWL_DEBUG_FW(trans, "Handling PNVM section\n"); @@ -152,9 +153,14 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, return -ENOENT; } + ret = iwl_trans_load_pnvm(trans, &pnvm_data); + if (ret) + return ret; + IWL_INFO(trans, "loaded PNVM version %08x\n", sha1); - return iwl_trans_set_pnvm(trans, &pnvm_data); + iwl_trans_set_pnvm(trans); + return 0; } static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, @@ -262,9 +268,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, * need to set it again. */ if (trans->pnvm_loaded) { - ret = iwl_trans_set_pnvm(trans, NULL); - if (ret) - return ret; + iwl_trans_set_pnvm(trans); goto skip_parse; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 9d2dcb64523c..9f718e43dd81 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -279,8 +279,9 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, const struct fw_img *fw); void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive); -int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_payloads); +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads); +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans); int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, const void *data, u32 len); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 35ddb4cfa356..a7e8d45c874c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -557,6 +557,7 @@ struct iwl_pnvm_image { * Note that the transport must fill in the proper file headers. * @debugfs_cleanup: used in the driver unload flow to make a proper cleanup * of the trans debugfs + * @load_pnvm: save the pnvm data in DRAM * @set_pnvm: set the pnvm data in the prph scratch buffer, inside the * context info. * @interrupts: disable/enable interrupts to transport @@ -630,8 +631,9 @@ struct iwl_trans_ops { void *sanitize_ctx); void (*debugfs_cleanup)(struct iwl_trans *trans); void (*sync_nmi)(struct iwl_trans *trans); - int (*set_pnvm)(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_data); + int (*load_pnvm)(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads); + void (*set_pnvm)(struct iwl_trans *trans); int (*set_reduce_power)(struct iwl_trans *trans, const void *data, u32 len); void (*interrupts)(struct iwl_trans *trans, bool enable); @@ -1532,19 +1534,16 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans) void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, u32 sw_err_bit); -static inline int iwl_trans_set_pnvm(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_data) +static inline int iwl_trans_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data) { - if (trans->ops->set_pnvm) { - int ret = trans->ops->set_pnvm(trans, pnvm_data); - - if (ret) - return ret; - } - - trans->pnvm_loaded = true; + return trans->ops->load_pnvm(trans, pnvm_data); +} - return 0; +static inline void iwl_trans_set_pnvm(struct iwl_trans *trans) +{ + if (trans->ops->set_pnvm) + trans->ops->set_pnvm(trans); } static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 800857e61d65..e9f3799d4593 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -281,55 +281,68 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive) trans_pcie->prph_info = NULL; } -int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_payloads) +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; struct iwl_dram_data *dram = &trans_pcie->pnvm_dram; + u32 len, len0, len1; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; /* only allocate the DRAM if not allocated yet */ - if (!trans->pnvm_loaded) { - u32 len, len0, len1; + if (trans->pnvm_loaded) + return 0; - if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) - return -EBUSY; + if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) + return -EBUSY; - if (pnvm_payloads->n_chunks != - UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { - IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n", - pnvm_payloads->n_chunks); - return -EINVAL; - } - len0 = pnvm_payloads->chunks[0].len; - len1 = pnvm_payloads->chunks[1].len; - if (len1 > 0xFFFFFFFF - len0) { - IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n"); + if (pnvm_payloads->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { + IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n", + pnvm_payloads->n_chunks); return -EINVAL; - } - len = len0 + len1; + } - dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len, &dram->physical); - if (!dram->block) { - IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); - return -ENOMEM; - } - dram->size = len; - memcpy(dram->block, pnvm_payloads->chunks[0].data, len0); - memcpy((u8 *)dram->block + len0, pnvm_payloads->chunks[1].data, - len1); + len0 = pnvm_payloads->chunks[0].len; + len1 = pnvm_payloads->chunks[1].len; + if (len1 > 0xFFFFFFFF - len0) { + IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n"); + return -EINVAL; + } + len = len0 + len1; + + dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len, + &dram->physical); + if (!dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; } + dram->size = len; + memcpy(dram->block, pnvm_payloads->chunks[0].data, len0); + memcpy((u8 *)dram->block + len0, pnvm_payloads->chunks[1].data, len1); + + trans->pnvm_loaded = true; + return 0; +} + +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = cpu_to_le64(trans_pcie->pnvm_dram.physical); prph_sc_ctrl->pnvm_cfg.pnvm_size = cpu_to_le32(trans_pcie->pnvm_dram.size); - return 0; } int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b281850fbf7a..6691d89d7226 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3534,6 +3534,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = { .txq_free = iwl_txq_dyn_free, .wait_txq_empty = iwl_trans_pcie_wait_txq_empty, .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, + .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm, .set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm, .set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power, #ifdef CONFIG_IWLWIFI_DEBUGFS From patchwork Tue Jun 6 07:43:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268630 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4614DC77B7A for ; Tue, 6 Jun 2023 07:48:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234950AbjFFHsd (ORCPT ); Tue, 6 Jun 2023 03:48:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54566 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235757AbjFFHq4 (ORCPT ); Tue, 6 Jun 2023 03:46:56 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7DEE2708 for ; Tue, 6 Jun 2023 00:43:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037439; x=1717573439; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rxIXXqmm37OTDWZRVSt0hdOXEct73068IODL+TEEPBA=; b=OkBYngszccYvCmU2GHBMBCpRQFuSiphSoAcHv/XkDmlyC97qM9xzbgEK BU0cZpK6wfVldbdhUh/W9vtFI7rWQUOMFfS9Yq38fXKkZ93kFNJcd2BNq yiGwRxGb107z4wfx6HH0Q1FFN0wIuG3+Sazt46+jKsYGokTMK9hv4LWCG C8yIuQ9hEC5V2TwqfIhn6caXk6kyvhUey3jEi9hIwDGc7vtW0me8ojP+J vyPI69NvI4gTdWCyV5TExUV6SjE0QRRBiZLZS7FtTqDid8NPS5n194qUu tz1Bk9bOvm2m2jGjTHFTPic7ILk0d1SlYCbr8yKewIwq49scBUk2t/DgK A==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419061" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419061" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516262" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516262" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:28 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 03/13] wifi: iwlwifi: Take loading and setting of pnvm image out of parsing part Date: Tue, 6 Jun 2023 10:43:00 +0300 Message-Id: <20230606103519.504b42fc1611.I4ddf6ad76d922d118fcbcc4f0e9ec003753d0b75@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Change iwl_pnvm_parse so it will only save the information into the iwl_pnvm_image struct. This enables to use the parsing code for the power reduce tables in the future. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 130 ++++++++++-------- .../net/wireless/intel/iwlwifi/iwl-trans.h | 4 + 2 files changed, 73 insertions(+), 61 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index f99328cc6b01..cb6a9191cf95 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright(c) 2020-2022 Intel Corporation + * Copyright(c) 2020-2023 Intel Corporation */ #include "iwl-drv.h" @@ -31,17 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait, } static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, - size_t len) + size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; u32 sha1 = 0; u16 mac_type = 0, rf_id = 0; - struct iwl_pnvm_image pnvm_data = {}; bool hw_match = false; - int ret; IWL_DEBUG_FW(trans, "Handling PNVM section\n"); + memset(pnvm_data, 0, sizeof(*pnvm_data)); + while (len >= sizeof(*tlv)) { u32 tlv_len, tlv_type; @@ -73,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, IWL_DEBUG_FW(trans, "Got IWL_UCODE_TLV_PNVM_VERSION %0x\n", sha1); + pnvm_data->version = sha1; break; case IWL_UCODE_TLV_HW_TYPE: if (tlv_len < 2 * sizeof(__le16)) { @@ -110,7 +112,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, break; } - if (pnvm_data.n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n"); return -EINVAL; @@ -119,9 +121,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len); - pnvm_data.chunks[pnvm_data.n_chunks].data = section->data; - pnvm_data.chunks[pnvm_data.n_chunks].len = data_len; - pnvm_data.n_chunks++; + pnvm_data->chunks[pnvm_data->n_chunks].data = section->data; + pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; + pnvm_data->n_chunks++; break; } @@ -148,23 +150,17 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, return -ENOENT; } - if (!pnvm_data.n_chunks) { + if (!pnvm_data->n_chunks) { IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n"); return -ENOENT; } - ret = iwl_trans_load_pnvm(trans, &pnvm_data); - if (ret) - return ret; - - IWL_INFO(trans, "loaded PNVM version %08x\n", sha1); - - iwl_trans_set_pnvm(trans); return 0; } static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, - size_t len) + size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; @@ -205,7 +201,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { int ret; - ret = iwl_pnvm_handle_section(trans, data, len); + ret = iwl_pnvm_handle_section(trans, data, len, + pnvm_data); if (!ret) return 0; } else { @@ -248,70 +245,81 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len) return 0; } +static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len) +{ + struct pnvm_sku_package *package; + u8 *image = NULL; + + /* First attempt to get the PNVM from BIOS */ + package = iwl_uefi_get_pnvm(trans_p, len); + if (!IS_ERR_OR_NULL(package)) { + if (*len >= sizeof(*package)) { + /* we need only the data */ + *len -= sizeof(*package); + image = kmemdup(package->data, *len, GFP_KERNEL); + } + /* free package regardless of whether kmemdup succeeded */ + kfree(package); + if (image) + return image; + } + + /* If it's not available, try from the filesystem */ + if (iwl_pnvm_get_from_fs(trans_p, &image, len)) + return NULL; + return image; +} + int iwl_pnvm_load(struct iwl_trans *trans, struct iwl_notif_wait_data *notif_wait) { u8 *data; - size_t len; - struct pnvm_sku_package *package; + size_t length; struct iwl_notification_wait pnvm_wait; static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, PNVM_INIT_COMPLETE_NTFY) }; + struct iwl_pnvm_image pnvm_data; int ret; /* if the SKU_ID is empty, there's nothing to do */ if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) return 0; - /* - * If we already loaded (or tried to load) it before, we just - * need to set it again. - */ - if (trans->pnvm_loaded) { - iwl_trans_set_pnvm(trans); - goto skip_parse; - } + /* failed to get/parse the image in the past, no use to try again */ + if (trans->fail_to_parse_pnvm_image) + goto reduce_tables; - /* First attempt to get the PNVM from BIOS */ - package = iwl_uefi_get_pnvm(trans, &len); - if (!IS_ERR_OR_NULL(package)) { - if (len >= sizeof(*package)) { - /* we need only the data */ - len -= sizeof(*package); - data = kmemdup(package->data, len, GFP_KERNEL); - } else { - data = NULL; + /* get the image, parse and load it, if not loaded yet */ + if (!trans->pnvm_loaded) { + data = iwl_get_pnvm_image(trans, &length); + if (!data) { + trans->fail_to_parse_pnvm_image = true; + goto reduce_tables; + } + ret = iwl_pnvm_parse(trans, data, length, &pnvm_data); + if (ret) { + trans->fail_to_parse_pnvm_image = true; + kfree(data); + goto reduce_tables; } - /* free package regardless of whether kmemdup succeeded */ - kfree(package); - - if (data) - goto parse; - } - - /* If it's not available, try from the filesystem */ - ret = iwl_pnvm_get_from_fs(trans, &data, &len); - if (ret) { - /* - * Pretend we've loaded it - at least we've tried and - * couldn't load it at all, so there's no point in - * trying again over and over. + ret = iwl_trans_load_pnvm(trans, &pnvm_data); + /* can only free data after pvnm_data use, but + * pnvm_data.version used below is not a pointer */ - trans->pnvm_loaded = true; - - goto skip_parse; + kfree(data); + if (ret) + goto reduce_tables; + IWL_INFO(trans, "loaded PNVM version %08x\n", + pnvm_data.version); } -parse: - iwl_pnvm_parse(trans, data, len); - - kfree(data); + iwl_trans_set_pnvm(trans); -skip_parse: +reduce_tables: /* now try to get the reduce power table, if not loaded yet */ if (!trans->reduce_power_loaded) { - data = iwl_uefi_get_reduced_power(trans, &len); + data = iwl_uefi_get_reduced_power(trans, &length); if (IS_ERR_OR_NULL(data)) { /* * Pretend we've loaded it - at least we've tried and @@ -320,7 +328,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, */ trans->reduce_power_loaded = true; } else { - ret = iwl_trans_set_reduce_power(trans, data, len); + ret = iwl_trans_set_reduce_power(trans, data, length); if (ret) IWL_DEBUG_FW(trans, "Failed to set reduce power table %d\n", diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index a7e8d45c874c..684b57df9b48 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -466,6 +466,7 @@ struct iwl_trans_rxq_dma_data { * struct iwl_pnvm_image - contains info about the parsed pnvm image * @chunks: array of pointers to pnvm payloads and their sizes * @n_chunks: the number of the pnvm payloads. + * @version: the version of the loaded PNVM image */ struct iwl_pnvm_image { struct { @@ -473,6 +474,7 @@ struct iwl_pnvm_image { u32 len; } chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX]; u32 n_chunks; + u32 version; }; /** @@ -1023,6 +1025,7 @@ struct iwl_trans_txqs { * @hw_rev_step: The mac step of the HW * @pm_support: set to true in start_hw if link pm is supported * @ltr_enabled: set to true if the LTR is enabled + * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed * @wide_cmd_header: true when ucode supports wide command header format * @wait_command_queue: wait queue for sync commands * @num_rx_queues: number of RX queues allocated by the transport; @@ -1070,6 +1073,7 @@ struct iwl_trans { bool pm_support; bool ltr_enabled; u8 pnvm_loaded:1; + u8 fail_to_parse_pnvm_image:1; u8 reduce_power_loaded:1; const struct iwl_hcmd_arr *command_groups; From patchwork Tue Jun 6 07:43:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268632 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0466FC7EE24 for ; Tue, 6 Jun 2023 07:49:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235037AbjFFHtX (ORCPT ); Tue, 6 Jun 2023 03:49:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54538 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236384AbjFFHsZ (ORCPT ); Tue, 6 Jun 2023 03:48:25 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D9B3198A for ; Tue, 6 Jun 2023 00:44:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037459; x=1717573459; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zjPDp/gHoN2HMGgOMIDuL58oiF3aJ6w8D/nBZA5oB+0=; b=l4HROv/DyJalk3dVA4kpiDTOkDfRX4WGawjgt2yQgSUjI7VEOOpzRSGh 0Ge+of11wJK3SkyS9whmEcOr7ylhgjw4aQDcdKxNzt088FPL65Nchvmuc 7djpoIE5v4JCTubjj/pxNc4NaJFC6RIYfpBuFETSdIPmoca/1iJhRAphN s4CYvooI1y/sQLOYWer5T0jptC7Sdjcnce0vfC7hVikAjUdeNFeTB+tgC Hqo/czuIoI8bcWOv0szvzDKj41omU5ULFpjTFt+emItybUUfMmXI4mUtb dDc2NdZisBLnKBqk+Y28v+S3SQPsCV337OqM97R9JKNifm5GCPHuDBTwS Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419065" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419065" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516281" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516281" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:30 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 04/13] wifi: iwlwifi: Allow trans_pcie track more than 1 pnvm DRAM region Date: Tue, 6 Jun 2023 10:43:01 +0300 Message-Id: <20230606103519.bb206d71bf45.I627640701757bb2f234f8e18a3afbd6af1206658@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Change the field pnvm_dram to an array that describes many regions and add a counter to the number of pnvm regions that were allocated in DRAM. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 13 +++++++++---- .../net/wireless/intel/iwlwifi/pcie/internal.h | 10 ++++++++-- .../net/wireless/intel/iwlwifi/pcie/trans.c | 18 ++++++++++++++---- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index e9f3799d4593..f43246b45a85 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -287,7 +287,7 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - struct iwl_dram_data *dram = &trans_pcie->pnvm_dram; + struct iwl_dram_data *dram = &trans_pcie->pnvm_dram[0]; u32 len, len0, len1; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) @@ -324,6 +324,7 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, dram->size = len; memcpy(dram->block, pnvm_payloads->chunks[0].data, len0); memcpy((u8 *)dram->block + len0, pnvm_payloads->chunks[1].data, len1); + trans_pcie->n_pnvm_regions = 1; trans->pnvm_loaded = true; return 0; @@ -337,11 +338,15 @@ void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans) if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return; - + /* FIXME: currently we concatenate payloads and save them only in + * pnvm_dram[0] - therefor only pnvm_dram[0] is delivered to the + * prph_sc. Need to add a UCODE sensitivity and another case in which + * we deliver to the prph_sc an array with all the DRAM addresses. + */ prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = - cpu_to_le64(trans_pcie->pnvm_dram.physical); + cpu_to_le64(trans_pcie->pnvm_dram[0].physical); prph_sc_ctrl->pnvm_cfg.pnvm_size = - cpu_to_le32(trans_pcie->pnvm_dram.size); + cpu_to_le32(trans_pcie->pnvm_dram[0].size); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 69b95ad5993b..ca2e7bb2def8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -23,6 +23,7 @@ #include "iwl-op-mode.h" #include "iwl-drv.h" #include "queue/tx.h" +#include "iwl-context-info.h" /* * RX related structures and functions @@ -306,7 +307,8 @@ enum iwl_pcie_imr_status { * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @kw: keep warm address - * @pnvm_dram: DRAM area that contains the PNVM data + * @pnvm_dram: array of several DRAM areas that contains the PNVM data + * @n_pnvm_regions: number of DRAM regions that were allocated for the pnvm * @pci_dev: basic pci-network driver stuff * @hw_base: pci hardware address support * @ucode_write_complete: indicates that the ucode has been copied. @@ -380,7 +382,9 @@ struct iwl_trans_pcie { u32 scd_base_addr; struct iwl_dma_ptr kw; - struct iwl_dram_data pnvm_dram; + /* pnvm data */ + struct iwl_dram_data pnvm_dram[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + u8 n_pnvm_regions; struct iwl_dram_data reduce_power_dram; struct iwl_txq *txq_memory; @@ -478,6 +482,8 @@ struct iwl_trans const struct pci_device_id *ent, const struct iwl_cfg_trans_params *cfg_trans); void iwl_trans_pcie_free(struct iwl_trans *trans); +void iwl_trans_pcie_free_pnvm_dram(struct iwl_trans_pcie *trans_pcie, + struct device *dev); bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); #define _iwl_trans_pcie_grab_nic_access(trans) \ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 6691d89d7226..cd177addd884 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1993,6 +1993,19 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake; } +void iwl_trans_pcie_free_pnvm_dram(struct iwl_trans_pcie *trans_pcie, + struct device *dev) +{ + u8 i; + + for (i = 0; i < trans_pcie->n_pnvm_regions; i++) { + dma_free_coherent(dev, trans_pcie->pnvm_dram[i].size, + trans_pcie->pnvm_dram[i].block, + trans_pcie->pnvm_dram[i].physical); + } + trans_pcie->n_pnvm_regions = 0; +} + void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -2025,10 +2038,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_free_fw_monitor(trans); - if (trans_pcie->pnvm_dram.size) - dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size, - trans_pcie->pnvm_dram.block, - trans_pcie->pnvm_dram.physical); + iwl_trans_pcie_free_pnvm_dram(trans_pcie, trans->dev); if (trans_pcie->reduce_power_dram.size) dma_free_coherent(trans->dev, From patchwork Tue Jun 6 07:43:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268631 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3103C77B7A for ; Tue, 6 Jun 2023 07:49:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236778AbjFFHtM (ORCPT ); Tue, 6 Jun 2023 03:49:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54558 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236751AbjFFHsc (ORCPT ); Tue, 6 Jun 2023 03:48:32 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B9B941991 for ; Tue, 6 Jun 2023 00:44:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037460; x=1717573460; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=V5tOJVHO1SMYEKWtdOfL36MQRKq53uphZiU0wSAUwog=; b=DGOpBjpikYaI0yxhMAxpaEO2mFObB8zseT5sfGO8udDcgbz88Xw/gAM4 2tEsLJyuq688ZNaVLN8UVrgzfyOCn+QAquuu7dwR+nUScfuEVr0xU638a pfRgu2lbQxWUNd2cZplXEPSv9EFtLAfvcGt/zYdy3NM7iC0yXCcjtxRtm M1gIkpuSFxa0KVvpvdHUsqFFCBnWay1TVM0kLb2UpOjqCmPkYOfLKTP1O WIgENAXF6IDAFOn8oetHX4JNplX9St+BdmNzf18m96wKU1+V8hFCrjzDj kPmxB0jII/eP2CAAj+AXibodHGmdunFblPlPq/QeEpDa14nTvpgSAJJAf w==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419072" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419072" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516298" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516298" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:32 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 05/13] wifi: iwlwifi: Add support for fragmented pnvm images Date: Tue, 6 Jun 2023 10:43:02 +0300 Message-Id: <20230606103519.c49bfaf435a9.I0278312e7c3355b224cd870d4f8cf6578d12f03e@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Add support for fragmented pnvm images, depending on the FW capability. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 + drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 7 +- drivers/net/wireless/intel/iwlwifi/fw/pnvm.h | 5 +- .../intel/iwlwifi/iwl-context-info-gen3.h | 6 +- .../net/wireless/intel/iwlwifi/iwl-trans.h | 16 ++-- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 3 +- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 95 ++++++++++++------- 7 files changed, 88 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index cddf09d6be1c..96e15f2631ed 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -323,6 +323,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used) + * @IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG: supports fragmented PNVM image * @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting * stabilization latency for SoCs. * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification @@ -398,6 +399,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, /* set 1 */ + IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG = (__force iwl_ucode_tlv_capa_t)32, IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT = (__force iwl_ucode_tlv_capa_t)37, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index cb6a9191cf95..91e1faef76f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -271,7 +271,8 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len) } int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait) + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa) { u8 *data; size_t length; @@ -303,7 +304,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, goto reduce_tables; } - ret = iwl_trans_load_pnvm(trans, &pnvm_data); + ret = iwl_trans_load_pnvm(trans, &pnvm_data, capa); /* can only free data after pvnm_data use, but * pnvm_data.version used below is not a pointer */ @@ -314,7 +315,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, pnvm_data.version); } - iwl_trans_set_pnvm(trans); + iwl_trans_set_pnvm(trans, capa); reduce_tables: /* now try to get the reduce power table, if not loaded yet */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h index 203c367dd4de..4e10baa01738 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /****************************************************************************** * - * Copyright(c) 2020-2021 Intel Corporation + * Copyright(c) 2020-2022 Intel Corporation * *****************************************************************************/ @@ -15,7 +15,8 @@ #define MAX_PNVM_NAME 64 int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait); + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa); static inline void iwl_pnvm_get_fs_name(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 9f718e43dd81..23208be831f3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -280,8 +280,10 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive); int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_payloads); -void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans); + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa); +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, const void *data, u32 len); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 684b57df9b48..541841bc8f21 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -634,8 +634,10 @@ struct iwl_trans_ops { void (*debugfs_cleanup)(struct iwl_trans *trans); void (*sync_nmi)(struct iwl_trans *trans); int (*load_pnvm)(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_payloads); - void (*set_pnvm)(struct iwl_trans *trans); + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_pnvm)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); int (*set_reduce_power)(struct iwl_trans *trans, const void *data, u32 len); void (*interrupts)(struct iwl_trans *trans, bool enable); @@ -1539,15 +1541,17 @@ void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, u32 sw_err_bit); static inline int iwl_trans_load_pnvm(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_data) + const struct iwl_pnvm_image *pnvm_data, + const struct iwl_ucode_capabilities *capa) { - return trans->ops->load_pnvm(trans, pnvm_data); + return trans->ops->load_pnvm(trans, pnvm_data, capa); } -static inline void iwl_trans_set_pnvm(struct iwl_trans *trans) +static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) { if (trans->ops->set_pnvm) - trans->ops->set_pnvm(trans); + trans->ops->set_pnvm(trans, capa); } static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index b35c96cf7ad2..1b5a80279e3c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -433,7 +433,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, /* if reached this point, Alive notification was received */ iwl_mei_alive_notif(true); - ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait); + ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait, + &mvm->fw->ucode_capa); if (ret) { IWL_ERR(mvm, "Timeout waiting for PNVM load!\n"); iwl_fw_set_current_image(&mvm->fwrt, old_type); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index f43246b45a85..fc450c0d1145 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -281,33 +281,20 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive) trans_pcie->prph_info = NULL; } -int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_payloads) +static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data, + struct iwl_dram_data *dram) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = - &trans_pcie->prph_scratch->ctrl_cfg; - struct iwl_dram_data *dram = &trans_pcie->pnvm_dram[0]; u32 len, len0, len1; - if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - return 0; - - /* only allocate the DRAM if not allocated yet */ - if (trans->pnvm_loaded) - return 0; - - if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) - return -EBUSY; - - if (pnvm_payloads->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { + if (pnvm_data->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n", - pnvm_payloads->n_chunks); - return -EINVAL; + pnvm_data->n_chunks); + return -EINVAL; } - len0 = pnvm_payloads->chunks[0].len; - len1 = pnvm_payloads->chunks[1].len; + len0 = pnvm_data->chunks[0].len; + len1 = pnvm_data->chunks[1].len; if (len1 > 0xFFFFFFFF - len0) { IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n"); return -EINVAL; @@ -322,32 +309,76 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, } dram->size = len; - memcpy(dram->block, pnvm_payloads->chunks[0].data, len0); - memcpy((u8 *)dram->block + len0, pnvm_payloads->chunks[1].data, len1); - trans_pcie->n_pnvm_regions = 1; + memcpy(dram->block, pnvm_data->chunks[0].data, len0); + memcpy((u8 *)dram->block + len0, pnvm_data->chunks[1].data, len1); - trans->pnvm_loaded = true; return 0; } -void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans) +/* FIXME: An implementation will be added with the next several commits. */ +static int iwl_pcie_load_payloads_segments(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads) +{ + return -ENOMEM; +} + +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_data *dram = &trans_pcie->pnvm_dram[0]; + int ret = 0; + + /* only allocate the DRAM if not allocated yet */ + if (trans->pnvm_loaded) + return 0; + + if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) + return -EBUSY; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - return; - /* FIXME: currently we concatenate payloads and save them only in - * pnvm_dram[0] - therefor only pnvm_dram[0] is delivered to the - * prph_sc. Need to add a UCODE sensitivity and another case in which - * we deliver to the prph_sc an array with all the DRAM addresses. - */ + return 0; + + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + return iwl_pcie_load_payloads_segments(trans, pnvm_payloads); + + ret = iwl_pcie_load_payloads_continuously(trans, pnvm_payloads, dram); + if (!ret) { + trans_pcie->n_pnvm_regions = 1; + trans->pnvm_loaded = true; + } + + return ret; +} + +/* FIXME: An implementation will be added with the next several commits. */ +static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans) {} + +static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = cpu_to_le64(trans_pcie->pnvm_dram[0].physical); prph_sc_ctrl->pnvm_cfg.pnvm_size = cpu_to_le32(trans_pcie->pnvm_dram[0].size); +} + +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + iwl_pcie_set_pnvm_segments(trans); + else + iwl_pcie_set_continuous_pnvm(trans); } int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, From patchwork Tue Jun 6 07:43:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268633 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E66C3C7EE24 for ; Tue, 6 Jun 2023 07:49:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235919AbjFFHtk (ORCPT ); Tue, 6 Jun 2023 03:49:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56322 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236853AbjFFHsg (ORCPT ); Tue, 6 Jun 2023 03:48:36 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9625C19A0 for ; Tue, 6 Jun 2023 00:44:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037466; x=1717573466; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Nb5y6TEnmhMl2RlyUAIhLImAAxjxvC5uNBSuWKppOlM=; b=WcuuuYKzU2mGLcEcF1EKRx9FqsFYjrxBnOzE3JPfateReUF0KIvd+3lq 4EOOZzIWZtQ6fgKSKQiL2FPGMf69grj6vG1diU1mjFMUPvh0S6cezstNw Th3HTnuuzSAqHM0jADSmSZoQKXUvdaa13inXt7WGxRQkK3+xGsno34cOz yDsSoiqC1PU03xSJsJQijQBn8kvFBcicrztvNtFQ3ZM7zMX7HjJK1WG5+ QKZAG2CJDxION6TAzRd5mU0PcM7z69qRRze3Sm9VGaWlcf3z8i9GXZOOm 1RkMENiPaIKqDUv1BiNvf6PN+9P16xb5nRpYSZD3l8Ti+ZWH6I9mESSgx A==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419079" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419079" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:36 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516311" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516311" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:34 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 06/13] wifi: iwlwifi: Implement loading and setting of fragmented pnvm image Date: Tue, 6 Jun 2023 10:43:03 +0300 Message-Id: <20230606103519.dbdad8995ce1.I986213527982637042532de3851a1bd8a11be87a@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Save the pnvm payloads in several DRAM segments (not only in one as used to). In addition, allocate a FW structure in DRAM that holds the segments' addresses and forward its address to the FW. It's done when FW has the capability to handle pnvm images this way (helps to process large pnvm images). Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- .../intel/iwlwifi/iwl-context-info-gen3.h | 8 ++ .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 73 +++++++++++++++++-- .../wireless/intel/iwlwifi/pcie/internal.h | 3 + .../net/wireless/intel/iwlwifi/pcie/trans.c | 8 ++ 4 files changed, 86 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 23208be831f3..bbf4b18cd9de 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -109,6 +109,14 @@ struct iwl_prph_scratch_pnvm_cfg { __le32 reserved; } __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */ +/** + * struct iwl_prph_scrath_mem_desc_addr_array + * @mem_descs: array of dram addresses. + * Each address is the beggining of a pnvm payload. + */ +struct iwl_prph_scrath_mem_desc_addr_array { + __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX]; +} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */ /* * struct iwl_prph_scratch_hwm_cfg - hwm config * @hwm_base_addr: hwm start address diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index fc450c0d1145..e0477ca4ccc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -315,11 +315,58 @@ static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans, return 0; } -/* FIXME: An implementation will be added with the next several commits. */ -static int iwl_pcie_load_payloads_segments(struct iwl_trans *trans, - const struct iwl_pnvm_image *pnvm_payloads) +static int iwl_pcie_load_payloads_segments + (struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data) { - return -ENOMEM; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_dram_data *cur_pnvm_dram = &trans_pcie->pnvm_dram[0], + *desc_dram = &trans_pcie->pnvm_regions_desc_array; + struct iwl_prph_scrath_mem_desc_addr_array *addresses; + const void *data; + u32 len; + int i; + + /* allocate and init DRAM descriptors array */ + len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array); + desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent + (trans, + len, + &desc_dram->physical); + if (!desc_dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; + } + desc_dram->size = len; + memset(desc_dram->block, 0, len); + + /* allocate DRAM region for each payload */ + trans_pcie->n_pnvm_regions = 0; + for (i = 0; i < pnvm_data->n_chunks; i++) { + len = pnvm_data->chunks[i].len; + data = pnvm_data->chunks[i].data; + + if (iwl_pcie_ctxt_info_alloc_dma(trans, data, len, + cur_pnvm_dram)) { + iwl_trans_pcie_free_pnvm_dram(trans_pcie, trans->dev); + return -ENOMEM; + } + + trans_pcie->n_pnvm_regions++; + cur_pnvm_dram++; + } + + /* fill desc with the DRAM payloads addresses */ + addresses = desc_dram->block; + + for (i = 0; i < pnvm_data->n_chunks; i++) { + addresses->mem_descs[i] = + cpu_to_le64(trans_pcie->pnvm_dram[i].physical); + } + + trans->pnvm_loaded = true; + return 0; + } int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, @@ -342,9 +389,16 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; + if (!pnvm_payloads->n_chunks) { + IWL_DEBUG_FW(trans, "no payloads\n"); + return -EINVAL; + } + + /* allocate several DRAM sections */ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) return iwl_pcie_load_payloads_segments(trans, pnvm_payloads); + /* allocate one DRAM section */ ret = iwl_pcie_load_payloads_continuously(trans, pnvm_payloads, dram); if (!ret) { trans_pcie->n_pnvm_regions = 1; @@ -354,8 +408,15 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, return ret; } -/* FIXME: An implementation will be added with the next several commits. */ -static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans) {} +static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = + cpu_to_le64(trans_pcie->pnvm_regions_desc_array.physical); +} static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index ca2e7bb2def8..d10f25da0eec 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -309,6 +309,8 @@ enum iwl_pcie_imr_status { * @kw: keep warm address * @pnvm_dram: array of several DRAM areas that contains the PNVM data * @n_pnvm_regions: number of DRAM regions that were allocated for the pnvm + * @pnvm_regions_desc_array: array of PNVM payloads addresses. + * allocated in DRAM and sent to FW. * @pci_dev: basic pci-network driver stuff * @hw_base: pci hardware address support * @ucode_write_complete: indicates that the ucode has been copied. @@ -385,6 +387,7 @@ struct iwl_trans_pcie { /* pnvm data */ struct iwl_dram_data pnvm_dram[IPC_DRAM_MAP_ENTRY_NUM_MAX]; u8 n_pnvm_regions; + struct iwl_dram_data pnvm_regions_desc_array; struct iwl_dram_data reduce_power_dram; struct iwl_txq *txq_memory; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index cd177addd884..5235a7517c53 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1997,6 +1997,7 @@ void iwl_trans_pcie_free_pnvm_dram(struct iwl_trans_pcie *trans_pcie, struct device *dev) { u8 i; + struct iwl_dram_data *desc_dram = &trans_pcie->pnvm_regions_desc_array; for (i = 0; i < trans_pcie->n_pnvm_regions; i++) { dma_free_coherent(dev, trans_pcie->pnvm_dram[i].size, @@ -2004,6 +2005,13 @@ void iwl_trans_pcie_free_pnvm_dram(struct iwl_trans_pcie *trans_pcie, trans_pcie->pnvm_dram[i].physical); } trans_pcie->n_pnvm_regions = 0; + + if (desc_dram->block) { + dma_free_coherent(dev, desc_dram->size, + desc_dram->block, + desc_dram->physical); + } + desc_dram->block = NULL; } void iwl_trans_pcie_free(struct iwl_trans *trans) From patchwork Tue Jun 6 07:43:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268670 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4CB99C7EE2F for ; Tue, 6 Jun 2023 07:51:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236734AbjFFHvk (ORCPT ); Tue, 6 Jun 2023 03:51:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236780AbjFFHtB (ORCPT ); Tue, 6 Jun 2023 03:49:01 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 104901BC7 for ; Tue, 6 Jun 2023 00:44:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037488; x=1717573488; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kyRpmBiiMWrkwLuMS6i7Hnzk7BoASTnPXaE/Vmi195M=; b=mHE8ZEjw8nJU8U/hyqw5ccuEM2t2Gucd9YOAnUBJ1j2/66N/TH3lmobr +xiUIoSwdmH28seJR5G5z+KO5ZWhEr2fKa+dkAbwv3XQ3XTt9pNHLwj9+ 8mDzX9Lf1cCxHPtY5s3I8gcJmiRJhfTEEpuE6KURmIqANrpeO3hAbWgCz GR35DSnlATyyvmTPlro1hhJeBms/uywfGU7Kpu6z790rbd/vWL2MR/4MA ZkQeLE4tRolgbErBvv2ysDvThfFeolhWDIYDJdINZHoDMO5xyzRRD4NaD F0G+VfIxrKoWgjKukZlXPP7f9x2UpFWUYej5OqQwMMjxjvHfEJHDfuzET Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419085" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419085" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516324" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516324" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:36 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 07/13] wifi: iwlwifi: Separate loading and setting of power reduce tables Date: Tue, 6 Jun 2023 10:43:04 +0300 Message-Id: <20230606103519.7695684dc848.I13626cd318e5d68efec9618b2045f52788bff114@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Take the part that copies the tables into DRAM, out of the method that sets the prph_scratch to make the code cleaner. Each of the operations will get more complex in the future when it will also support larger power-reduce tables images. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 9 ++++-- .../intel/iwlwifi/iwl-context-info-gen3.h | 5 ++-- .../net/wireless/intel/iwlwifi/iwl-trans.h | 28 +++++++++++-------- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 18 +++++++++--- .../net/wireless/intel/iwlwifi/pcie/trans.c | 1 + 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 91e1faef76f6..bb6300469f4a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -329,14 +329,17 @@ int iwl_pnvm_load(struct iwl_trans *trans, */ trans->reduce_power_loaded = true; } else { - ret = iwl_trans_set_reduce_power(trans, data, length); - if (ret) + ret = iwl_trans_load_reduce_power(trans, data, length); + if (ret) { IWL_DEBUG_FW(trans, - "Failed to set reduce power table %d\n", + "Failed to load reduce power table %d\n", ret); + trans->reduce_power_loaded = true; + } kfree(data); } } + iwl_trans_set_reduce_power(trans); iwl_init_notification_wait(notif_wait, &pnvm_wait, ntf_cmds, ARRAY_SIZE(ntf_cmds), diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index bbf4b18cd9de..e019aec027d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -292,8 +292,9 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); -int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len); +int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const void *data, u32 len); +void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, u32 mbx_addr_0_step, u32 mbx_addr_1_step); #endif /* __iwl_context_info_file_gen3_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 541841bc8f21..888869d9c94a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -562,6 +562,8 @@ struct iwl_pnvm_image { * @load_pnvm: save the pnvm data in DRAM * @set_pnvm: set the pnvm data in the prph scratch buffer, inside the * context info. + * @load_reduce_power: copy reduce power table to the corresponding DRAM memory + * @set_reduce_power: set reduce power table addresses in the sratch buffer * @interrupts: disable/enable interrupts to transport */ struct iwl_trans_ops { @@ -638,8 +640,11 @@ struct iwl_trans_ops { const struct iwl_ucode_capabilities *capa); void (*set_pnvm)(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); - int (*set_reduce_power)(struct iwl_trans *trans, - const void *data, u32 len); + int (*load_reduce_power)(struct iwl_trans *trans, + const void *data, + u32 len); + void (*set_reduce_power)(struct iwl_trans *trans); + void (*interrupts)(struct iwl_trans *trans, bool enable); int (*imr_dma_data)(struct iwl_trans *trans, u32 dst_addr, u64 src_addr, @@ -1554,18 +1559,17 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, trans->ops->set_pnvm(trans, capa); } -static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len) +static inline int iwl_trans_load_reduce_power(struct iwl_trans *trans, + const void *data, + u32 len) { - if (trans->ops->set_reduce_power) { - int ret = trans->ops->set_reduce_power(trans, data, len); - - if (ret) - return ret; - } + return trans->ops->load_reduce_power(trans, data, len); +} - trans->reduce_power_loaded = true; - return 0; +static inline void iwl_trans_set_reduce_power(struct iwl_trans *trans) +{ + if (trans->ops->set_reduce_power) + trans->ops->set_reduce_power(trans); } static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index e0477ca4ccc3..2619c868b51f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -442,8 +442,9 @@ void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, iwl_pcie_set_continuous_pnvm(trans); } -int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len) +int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const void *data, + u32 len) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = @@ -467,12 +468,21 @@ int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, return ret; } } + return 0; +} + +void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; prph_sc_ctrl->reduce_power_cfg.base_addr = cpu_to_le64(trans_pcie->reduce_power_dram.physical); prph_sc_ctrl->reduce_power_cfg.size = cpu_to_le32(trans_pcie->reduce_power_dram.size); - - return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 5235a7517c53..55541c1be5d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3554,6 +3554,7 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = { .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm, .set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm, + .load_reduce_power = iwl_trans_pcie_ctx_info_gen3_load_reduce_power, .set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power, #ifdef CONFIG_IWLWIFI_DEBUGFS .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, From patchwork Tue Jun 6 07:43:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268666 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09212C7EE2E for ; Tue, 6 Jun 2023 07:51:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235831AbjFFHvc (ORCPT ); Tue, 6 Jun 2023 03:51:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236809AbjFFHtE (ORCPT ); Tue, 6 Jun 2023 03:49:04 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8E51410E0 for ; Tue, 6 Jun 2023 00:44:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037490; x=1717573490; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0UzfJX4z3ebHPYqJJ9TU+XXGQ4YJBaIkbdDE5xypBVI=; b=Alg86TR3NWjrkz5KHp8szD+R/DjY8bilozxfi+z6lmNKS9E0nD7pYJ3t 5asakMw1amxPq+jGRpv1ewtYuksjv579/MsnIqmrvxx80eWCH6Xxwk7pJ rZMiJu678vXqbZsEaTHG9tNR1QyiE6B9xD7145izcOqB2JB5WWg8p855P 9qpGv7Cwq73syxXBeSRfC8a2RP+8MZSESOo62SCKPHLXhMTU1xZ5Wka4l N5Ht74J/nLN1/W7hnPTtWO+mFnEfI2epon99Bhzh92fHopiLuKb896sTH kBZNrmTJV50GIxrgg127mEf1uiGOwRGvs32YqPSfVjMSoOAK6gPFKBYNS w==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419093" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419093" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516347" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516347" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:38 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 08/13] wifi: iwlwifi: Use iwl_pnvm_image in reduce power tables flow Date: Tue, 6 Jun 2023 10:43:05 +0300 Message-Id: <20230606103519.564f1eead99b.Iaba653b21dc09aafc72b9bbb3928abddce0db50a@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Generalize the parsing, loading, and setting of the power-reduce tables, in order to support allocation of several DRAM payloads in the future. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 7 +- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 90 ++++++++----------- drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 8 +- .../intel/iwlwifi/iwl-context-info-gen3.h | 5 +- .../net/wireless/intel/iwlwifi/iwl-trans.h | 11 ++- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 25 ++---- 6 files changed, 63 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index bb6300469f4a..42d994240b31 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -320,8 +320,9 @@ int iwl_pnvm_load(struct iwl_trans *trans, reduce_tables: /* now try to get the reduce power table, if not loaded yet */ if (!trans->reduce_power_loaded) { - data = iwl_uefi_get_reduced_power(trans, &length); - if (IS_ERR_OR_NULL(data)) { + memset(&pnvm_data, 0, sizeof(pnvm_data)); + ret = iwl_uefi_get_reduced_power(trans, &pnvm_data); + if (ret) { /* * Pretend we've loaded it - at least we've tried and * couldn't load it at all, so there's no point in @@ -329,7 +330,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, */ trans->reduce_power_loaded = true; } else { - ret = iwl_trans_load_reduce_power(trans, data, length); + ret = iwl_trans_load_reduce_power(trans, &pnvm_data); if (ret) { IWL_DEBUG_FW(trans, "Failed to load reduce power table %d\n", diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 01afea33c38c..64b45a5b767e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -55,14 +55,14 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) return data; } -static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, - const u8 *data, size_t len) +static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; - u8 *reduce_power_data = NULL, *tmp; - u32 size = 0; IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n"); + memset(pnvm_data, 0, sizeof(*pnvm_data)); while (len >= sizeof(*tlv)) { u32 tlv_len, tlv_type; @@ -76,9 +76,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-EINVAL); - goto out; + return -EINVAL; } data += sizeof(*tlv); @@ -89,23 +87,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, "Got IWL_UCODE_TLV_MEM_DESC len %d\n", tlv_len); - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); - - tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL); - if (!tmp) { + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { IWL_DEBUG_FW(trans, - "Couldn't allocate (more) reduce_power_data\n"); - - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOMEM); - goto out; + "too many payloads to allocate in DRAM.\n"); + return -EINVAL; } - reduce_power_data = tmp; - - memcpy(reduce_power_data + size, data, tlv_len); + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); - size += tlv_len; + pnvm_data->chunks[pnvm_data->n_chunks].data = data; + pnvm_data->chunks[pnvm_data->n_chunks].len = tlv_len; + pnvm_data->n_chunks++; break; } @@ -124,27 +116,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, } done: - if (!size) { + if (!pnvm_data->n_chunks) { IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); - /* Better safe than sorry, but 'reduce_power_data' should - * always be NULL if !size. - */ - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOENT); - goto out; + return -ENOENT; } - - IWL_INFO(trans, "loaded REDUCE_POWER\n"); - -out: - return reduce_power_data; + return 0; } -static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, - const u8 *data, size_t len) +static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; - void *sec_data; IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n"); @@ -160,7 +143,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - return ERR_PTR(-EINVAL); + return -EINVAL; } if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) { @@ -181,11 +164,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) && trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) && trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { - sec_data = iwl_uefi_reduce_power_section(trans, - data, - len); - if (!IS_ERR(sec_data)) - return sec_data; + int ret = iwl_uefi_reduce_power_section(trans, + data, len, + pnvm_data); + if (!ret) + return 0; } else { IWL_DEBUG_FW(trans, "SKU ID didn't match!\n"); } @@ -195,20 +178,20 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, } } - return ERR_PTR(-ENOENT); + return -ENOENT; } -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +int iwl_uefi_get_reduced_power(struct iwl_trans *trans, + struct iwl_pnvm_image *pnvm_data) { struct pnvm_sku_package *package; - void *data = NULL; unsigned long package_size; efi_status_t status; - - *len = 0; + int ret; + size_t len = 0; if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return ERR_PTR(-ENODEV); + return -ENODEV; /* * TODO: we hardcode a maximum length here, because reading @@ -219,7 +202,7 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) package = kmalloc(package_size, GFP_KERNEL); if (!package) - return ERR_PTR(-ENOMEM); + return -ENOMEM; status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID, NULL, &package_size, package); @@ -228,22 +211,23 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) "Reduced Power UEFI variable not found 0x%lx (len %lu)\n", status, package_size); kfree(package); - return ERR_PTR(-ENOENT); + return -ENOENT; } IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", package_size); - *len = package_size; + len = package_size; IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n", package->rev, package->total_size, package->n_skus); - data = iwl_uefi_reduce_power_parse(trans, package->data, - *len - sizeof(*package)); + ret = iwl_uefi_reduce_power_parse(trans, package->data, + len - sizeof(*package), + pnvm_data); kfree(package); - return data; + return ret; } static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 17089bc74cf9..03176f73151a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -50,7 +50,8 @@ struct uefi_cnv_common_step_data { */ #ifdef CONFIG_EFI void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len); -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len); +int iwl_uefi_get_reduced_power(struct iwl_trans *trans, + struct iwl_pnvm_image *pnvm_data); void iwl_uefi_get_step_table(struct iwl_trans *trans); #else /* CONFIG_EFI */ static inline @@ -60,9 +61,10 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) } static inline -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +int iwl_uefi_get_reduced_power(struct iwl_trans *trans, + struct iwl_pnvm_image *pnvm_data) { - return ERR_PTR(-EOPNOTSUPP); + return -EOPNOTSUPP; } static inline diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index e019aec027d6..7e7d135e85b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -292,8 +292,9 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); -int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, - const void *data, u32 len); +int iwl_trans_pcie_ctx_info_gen3_load_reduce_power + (struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads); void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, u32 mbx_addr_0_step, u32 mbx_addr_1_step); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 888869d9c94a..8e9585d3a0ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -641,8 +641,7 @@ struct iwl_trans_ops { void (*set_pnvm)(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); int (*load_reduce_power)(struct iwl_trans *trans, - const void *data, - u32 len); + const struct iwl_pnvm_image *payloads); void (*set_reduce_power)(struct iwl_trans *trans); void (*interrupts)(struct iwl_trans *trans, bool enable); @@ -1559,11 +1558,11 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, trans->ops->set_pnvm(trans, capa); } -static inline int iwl_trans_load_reduce_power(struct iwl_trans *trans, - const void *data, - u32 len) +static inline int iwl_trans_load_reduce_power + (struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads) { - return trans->ops->load_reduce_power(trans, data, len); + return trans->ops->load_reduce_power(trans, payloads); } static inline void iwl_trans_set_reduce_power(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 2619c868b51f..26d5ba777d24 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -443,31 +443,24 @@ void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, } int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, - const void *data, - u32 len) + const struct iwl_pnvm_image *payloads) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - int ret; + struct iwl_dram_data *dram = &trans_pcie->reduce_power_dram; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; - /* only allocate the DRAM if not allocated yet */ - if (!trans->reduce_power_loaded) { - if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) - return -EBUSY; + if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) + return -EBUSY; - ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->reduce_power_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, - "Failed to allocate reduce power DMA %d.\n", - ret); - return ret; - } - } + /* only allocate the DRAM if not allocated yet */ + if (!trans->reduce_power_loaded) + return iwl_pcie_load_payloads_continuously(trans, + payloads, + dram); return 0; } From patchwork Tue Jun 6 07:43:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268672 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E017C7EE24 for ; Tue, 6 Jun 2023 07:51:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235864AbjFFHvo (ORCPT ); Tue, 6 Jun 2023 03:51:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54660 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235767AbjFFHtj (ORCPT ); Tue, 6 Jun 2023 03:49:39 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39E1D10EC for ; Tue, 6 Jun 2023 00:44:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037494; x=1717573494; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=w6J84X0QQa8sXPtRC20lIBhZFALAmGqYfvnN66SejRI=; b=d+cP7rMymm4htmBGj3aFSVEeXYf++lsAFUBYBpqzD7uryOTgX+qUdOGm 9/mxCthTakIxiT+tbwK1mclNJw1d/zdQVBBtGEPw2PCr0Nl4wzRek2YkL IuAoS+MQjubNXeJrG+knLO6tP+lfqk+RdF2R5NDa6gEwQnL53+ovZbJRV o4opq689bc0xq7dyHKXBiYtgf9vOOm+p2V63qI2LrlEo5967v/JeLsxWl wYdV+U+a3C+SfO5SGE4ri4IhWTP+E3BGnztgIUbHIQ0+BzPlS/GcyCKgc pQWkCAzWGUuL71ScOMNIjchZEbec5Z+LALIuWaXxXxtY9fe0ESFwmxNZA w==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419102" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419102" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516369" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516369" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:40 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 09/13] wifi: iwlwifi: Enable loading of reduce-power tables into several segments Date: Tue, 6 Jun 2023 10:43:06 +0300 Message-Id: <20230606103519.6fe66958f049.I85d80682229fc02fe354462cc9da40937558f30c@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi Replace the field reduce_power_dram with a struct that holds data about the reduced-power tables drams regions. Generalize load_payloads_segments() to work for both pnvm tables and reduction power tables. Make required adjustments in the data structures. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 4 +- .../intel/iwlwifi/iwl-context-info-gen3.h | 17 +- .../net/wireless/intel/iwlwifi/iwl-trans.h | 30 +++- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 150 +++++++++++++----- .../wireless/intel/iwlwifi/pcie/internal.h | 17 +- .../net/wireless/intel/iwlwifi/pcie/trans.c | 31 ++-- 6 files changed, 169 insertions(+), 80 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 42d994240b31..b556abece896 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -330,7 +330,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, */ trans->reduce_power_loaded = true; } else { - ret = iwl_trans_load_reduce_power(trans, &pnvm_data); + ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa); if (ret) { IWL_DEBUG_FW(trans, "Failed to load reduce power table %d\n", @@ -340,7 +340,7 @@ int iwl_pnvm_load(struct iwl_trans *trans, kfree(data); } } - iwl_trans_set_reduce_power(trans); + iwl_trans_set_reduce_power(trans, capa); iwl_init_notification_wait(notif_wait, &pnvm_wait, ntf_cmds, ARRAY_SIZE(ntf_cmds), diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 7e7d135e85b1..96bf353469b8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -98,9 +98,9 @@ struct iwl_prph_scratch_control { } __packed; /* PERIPH_SCRATCH_CONTROL_S */ /* - * struct iwl_prph_scratch_pnvm_cfg - ror config + * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch * @pnvm_base_addr: PNVM start address - * @pnvm_size: PNVM size in DWs + * @pnvm_size: the size of the PNVM image in bytes * @reserved: reserved */ struct iwl_prph_scratch_pnvm_cfg { @@ -142,7 +142,7 @@ struct iwl_prph_scratch_rbd_cfg { /* * struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table * @base_addr: reduce power table address - * @size: table size in dwords + * @size: the size of the entire power table image */ struct iwl_prph_scratch_uefi_cfg { __le64 base_addr; @@ -292,10 +292,13 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); -int iwl_trans_pcie_ctx_info_gen3_load_reduce_power - (struct iwl_trans *trans, - const struct iwl_pnvm_image *payloads); -void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans); +int +iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); +void +iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, u32 mbx_addr_0_step, u32 mbx_addr_1_step); #endif /* __iwl_context_info_file_gen3_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 8e9585d3a0ee..61ee6c1f4a1e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -641,8 +641,10 @@ struct iwl_trans_ops { void (*set_pnvm)(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa); int (*load_reduce_power)(struct iwl_trans *trans, - const struct iwl_pnvm_image *payloads); - void (*set_reduce_power)(struct iwl_trans *trans); + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_reduce_power)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); void (*interrupts)(struct iwl_trans *trans, bool enable); int (*imr_dma_data)(struct iwl_trans *trans, @@ -731,6 +733,19 @@ struct iwl_dram_data { int size; }; +/** + * @drams: array of several DRAM areas that contains the pnvm and power + * reduction table payloads. + * @n_regions: number of DRAM regions that were allocated + * @prph_scratch_mem_desc: points to a structure allocated in dram, + * designed to show FW where all the payloads are. + */ +struct iwl_dram_regions { + struct iwl_dram_data drams[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + struct iwl_dram_data prph_scratch_mem_desc; + u8 n_regions; +}; + /** * struct iwl_fw_mon - fw monitor per allocation id * @num_frags: number of fragments @@ -1560,15 +1575,18 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, static inline int iwl_trans_load_reduce_power (struct iwl_trans *trans, - const struct iwl_pnvm_image *payloads) + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa) { - return trans->ops->load_reduce_power(trans, payloads); + return trans->ops->load_reduce_power(trans, payloads, capa); } -static inline void iwl_trans_set_reduce_power(struct iwl_trans *trans) +static inline void +iwl_trans_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) { if (trans->ops->set_reduce_power) - trans->ops->set_reduce_power(trans); + trans->ops->set_reduce_power(trans, capa); } static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 26d5ba777d24..fa4a14546860 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -317,11 +317,11 @@ static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans, static int iwl_pcie_load_payloads_segments (struct iwl_trans *trans, + struct iwl_dram_regions *dram_regions, const struct iwl_pnvm_image *pnvm_data) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_dram_data *cur_pnvm_dram = &trans_pcie->pnvm_dram[0], - *desc_dram = &trans_pcie->pnvm_regions_desc_array; + struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0]; + struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; struct iwl_prph_scrath_mem_desc_addr_array *addresses; const void *data; u32 len; @@ -341,30 +341,31 @@ static int iwl_pcie_load_payloads_segments memset(desc_dram->block, 0, len); /* allocate DRAM region for each payload */ - trans_pcie->n_pnvm_regions = 0; + dram_regions->n_regions = 0; for (i = 0; i < pnvm_data->n_chunks; i++) { len = pnvm_data->chunks[i].len; data = pnvm_data->chunks[i].data; - if (iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - cur_pnvm_dram)) { - iwl_trans_pcie_free_pnvm_dram(trans_pcie, trans->dev); + if (iwl_pcie_ctxt_info_alloc_dma(trans, + data, + len, + cur_payload_dram)) { + iwl_trans_pcie_free_pnvm_dram_regions(dram_regions, + trans->dev); return -ENOMEM; } - trans_pcie->n_pnvm_regions++; - cur_pnvm_dram++; + dram_regions->n_regions++; + cur_payload_dram++; } /* fill desc with the DRAM payloads addresses */ addresses = desc_dram->block; - for (i = 0; i < pnvm_data->n_chunks; i++) { addresses->mem_descs[i] = - cpu_to_le64(trans_pcie->pnvm_dram[i].physical); + cpu_to_le64(dram_regions->drams[i].physical); } - trans->pnvm_loaded = true; return 0; } @@ -376,7 +377,7 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - struct iwl_dram_data *dram = &trans_pcie->pnvm_dram[0]; + struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data; int ret = 0; /* only allocate the DRAM if not allocated yet */ @@ -394,28 +395,51 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, return -EINVAL; } - /* allocate several DRAM sections */ - if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) - return iwl_pcie_load_payloads_segments(trans, pnvm_payloads); - - /* allocate one DRAM section */ - ret = iwl_pcie_load_payloads_continuously(trans, pnvm_payloads, dram); - if (!ret) { - trans_pcie->n_pnvm_regions = 1; - trans->pnvm_loaded = true; + /* save payloads in several DRAM sections */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) { + ret = iwl_pcie_load_payloads_segments(trans, + dram_regions, + pnvm_payloads); + if (!ret) + trans->pnvm_loaded = true; + } else { + /* save only in one DRAM section */ + ret = iwl_pcie_load_payloads_continuously + (trans, + pnvm_payloads, + &dram_regions->drams[0]); + if (!ret) { + dram_regions->n_regions = 1; + trans->pnvm_loaded = true; + } } return ret; } +static inline size_t +iwl_dram_regions_size(const struct iwl_dram_regions *dram_regions) +{ + size_t total_size = 0; + int i; + + for (i = 0; i < dram_regions->n_regions; i++) + total_size += dram_regions->drams[i].size; + + return total_size; +} + static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data; prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = - cpu_to_le64(trans_pcie->pnvm_regions_desc_array.physical); + cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical); + prph_sc_ctrl->pnvm_cfg.pnvm_size = + cpu_to_le32(iwl_dram_regions_size(dram_regions)); } static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans) @@ -425,9 +449,9 @@ static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans) &trans_pcie->prph_scratch->ctrl_cfg; prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = - cpu_to_le64(trans_pcie->pnvm_dram[0].physical); + cpu_to_le64(trans_pcie->pnvm_data.drams[0].physical); prph_sc_ctrl->pnvm_cfg.pnvm_size = - cpu_to_le32(trans_pcie->pnvm_dram[0].size); + cpu_to_le32(trans_pcie->pnvm_data.drams[0].size); } void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, @@ -443,12 +467,18 @@ void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, } int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, - const struct iwl_pnvm_image *payloads) + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - struct iwl_dram_data *dram = &trans_pcie->reduce_power_dram; + struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data; + int ret = 0; + + /* only allocate the DRAM if not allocated yet */ + if (trans->reduce_power_loaded) + return 0; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; @@ -456,26 +486,68 @@ int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) return -EBUSY; - /* only allocate the DRAM if not allocated yet */ - if (!trans->reduce_power_loaded) - return iwl_pcie_load_payloads_continuously(trans, - payloads, - dram); - return 0; + if (!payloads->n_chunks) { + IWL_DEBUG_FW(trans, "no payloads\n"); + return -EINVAL; + } + + /* save payloads in several DRAM sections */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) { + ret = iwl_pcie_load_payloads_segments(trans, + dram_regions, + payloads); + if (!ret) + trans->reduce_power_loaded = true; + } else { + /* save only in one DRAM section */ + ret = iwl_pcie_load_payloads_continuously + (trans, + payloads, + &dram_regions->drams[0]); + if (!ret) { + dram_regions->n_regions = 1; + trans->reduce_power_loaded = true; + } + } + + return ret; } -void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans) +static void iwl_pcie_set_reduce_power_segments(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data; - if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - return; + prph_sc_ctrl->reduce_power_cfg.base_addr = + cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical); + prph_sc_ctrl->reduce_power_cfg.size = + cpu_to_le32(iwl_dram_regions_size(dram_regions)); +} + +static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; prph_sc_ctrl->reduce_power_cfg.base_addr = - cpu_to_le64(trans_pcie->reduce_power_dram.physical); + cpu_to_le64(trans_pcie->reduced_tables_data.drams[0].physical); prph_sc_ctrl->reduce_power_cfg.size = - cpu_to_le32(trans_pcie->reduce_power_dram.size); + cpu_to_le32(trans_pcie->reduced_tables_data.drams[0].size); +} + +void +iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + iwl_pcie_set_reduce_power_segments(trans); + else + iwl_pcie_set_continuous_reduce_power(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index d10f25da0eec..0adcf0e13e85 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -307,10 +307,9 @@ enum iwl_pcie_imr_status { * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @kw: keep warm address - * @pnvm_dram: array of several DRAM areas that contains the PNVM data - * @n_pnvm_regions: number of DRAM regions that were allocated for the pnvm - * @pnvm_regions_desc_array: array of PNVM payloads addresses. - * allocated in DRAM and sent to FW. + * @pnvm_data: holds info about pnvm payloads allocated in DRAM + * @reduced_tables_data: holds info about power reduced tablse + * payloads allocated in DRAM * @pci_dev: basic pci-network driver stuff * @hw_base: pci hardware address support * @ucode_write_complete: indicates that the ucode has been copied. @@ -385,10 +384,8 @@ struct iwl_trans_pcie { struct iwl_dma_ptr kw; /* pnvm data */ - struct iwl_dram_data pnvm_dram[IPC_DRAM_MAP_ENTRY_NUM_MAX]; - u8 n_pnvm_regions; - struct iwl_dram_data pnvm_regions_desc_array; - struct iwl_dram_data reduce_power_dram; + struct iwl_dram_regions pnvm_data; + struct iwl_dram_regions reduced_tables_data; struct iwl_txq *txq_memory; @@ -485,8 +482,8 @@ struct iwl_trans const struct pci_device_id *ent, const struct iwl_cfg_trans_params *cfg_trans); void iwl_trans_pcie_free(struct iwl_trans *trans); -void iwl_trans_pcie_free_pnvm_dram(struct iwl_trans_pcie *trans_pcie, - struct device *dev); +void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, + struct device *dev); bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); #define _iwl_trans_pcie_grab_nic_access(trans) \ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 55541c1be5d6..70e8c20fb9b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1993,25 +1993,27 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake; } -void iwl_trans_pcie_free_pnvm_dram(struct iwl_trans_pcie *trans_pcie, - struct device *dev) +void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, + struct device *dev) { u8 i; - struct iwl_dram_data *desc_dram = &trans_pcie->pnvm_regions_desc_array; + struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; - for (i = 0; i < trans_pcie->n_pnvm_regions; i++) { - dma_free_coherent(dev, trans_pcie->pnvm_dram[i].size, - trans_pcie->pnvm_dram[i].block, - trans_pcie->pnvm_dram[i].physical); + /* free DRAM payloads */ + for (i = 0; i < dram_regions->n_regions; i++) { + dma_free_coherent(dev, dram_regions->drams[i].size, + dram_regions->drams[i].block, + dram_regions->drams[i].physical); } - trans_pcie->n_pnvm_regions = 0; + dram_regions->n_regions = 0; + /* free DRAM addresses array */ if (desc_dram->block) { dma_free_coherent(dev, desc_dram->size, desc_dram->block, desc_dram->physical); } - desc_dram->block = NULL; + memset(desc_dram, 0, sizeof(*desc_dram)); } void iwl_trans_pcie_free(struct iwl_trans *trans) @@ -2046,13 +2048,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_free_fw_monitor(trans); - iwl_trans_pcie_free_pnvm_dram(trans_pcie, trans->dev); - - if (trans_pcie->reduce_power_dram.size) - dma_free_coherent(trans->dev, - trans_pcie->reduce_power_dram.size, - trans_pcie->reduce_power_dram.block, - trans_pcie->reduce_power_dram.physical); + iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data, + trans->dev); + iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->reduced_tables_data, + trans->dev); mutex_destroy(&trans_pcie->mutex); iwl_trans_free(trans); From patchwork Tue Jun 6 07:43:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268668 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F35EEC7EE2E for ; Tue, 6 Jun 2023 07:51:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236671AbjFFHvg (ORCPT ); Tue, 6 Jun 2023 03:51:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236896AbjFFHtx (ORCPT ); Tue, 6 Jun 2023 03:49:53 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 159971BE3 for ; Tue, 6 Jun 2023 00:45:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037520; x=1717573520; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SgNUsrKxEtgXO8noR/wQu57Z4ker2Rj26F2Spk+qLMo=; b=TzZvHpkDzrRoS20dgGhkIFrracFxj+9UMiuBK+fKjnRSLRegxsdQ2NW1 VEw6yBKp3CH0oyXwbg9uZcm4i2AMBGRO7qru9XFVhgbeLusdnKwfWZ3RN DDV5F61BgSCJ7vZN8LmCnjLf5qppTIBWLVkVhv6ZjMaX6L4pmAXPvCCaw yqgU05Rx6Oja/fHUSjtrYzyORNOEPU+LbkmNSt0JJnuoJAR85gKr6cFQW AwYU53ST/l4mtQlDSUeGmeL+h1nGX4guyLtlzCjBPxtlTw3D2RTqsNrxc 0Y2UNicxGbiDgaS0N4ksMql18nr6O4EzItEJ0Bfw0YTYTQvKOoWfzu6ve Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419108" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419108" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516390" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516390" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:43 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Alon Giladi , Gregory Greenman Subject: [PATCH 10/13] wifi: iwlwifi: Separate reading and parsing of reduce power table Date: Tue, 6 Jun 2023 10:43:07 +0300 Message-Id: <20230606103519.71e3b3e0e794.Ifbe69ad99a7e805eb70e09280365821eb146b1c9@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Alon Giladi It enables to better handle error cases. Also save the image till the end of the loading and only then free it. Signed-off-by: Alon Giladi Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 40 ++++++++++++------- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 31 +++++++------- drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 27 ++++++++----- .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 + 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index b556abece896..3b5a3c89fedf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -319,29 +319,39 @@ int iwl_pnvm_load(struct iwl_trans *trans, reduce_tables: /* now try to get the reduce power table, if not loaded yet */ + if (trans->failed_to_load_reduce_power_image) + goto notification; + if (!trans->reduce_power_loaded) { memset(&pnvm_data, 0, sizeof(pnvm_data)); - ret = iwl_uefi_get_reduced_power(trans, &pnvm_data); + data = iwl_uefi_get_reduced_power(trans, &length); + if (IS_ERR(data)) { + ret = PTR_ERR(data); + trans->failed_to_load_reduce_power_image = true; + goto notification; + } + + ret = iwl_uefi_reduce_power_parse(trans, data, length, + &pnvm_data); if (ret) { - /* - * Pretend we've loaded it - at least we've tried and - * couldn't load it at all, so there's no point in - * trying again over and over. - */ - trans->reduce_power_loaded = true; - } else { - ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa); - if (ret) { - IWL_DEBUG_FW(trans, - "Failed to load reduce power table %d\n", - ret); - trans->reduce_power_loaded = true; - } + trans->failed_to_load_reduce_power_image = true; kfree(data); + goto notification; + } + + ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa); + kfree(data); + if (ret) { + IWL_DEBUG_FW(trans, + "Failed to load reduce power table %d\n", + ret); + trans->failed_to_load_reduce_power_image = true; + goto notification; } } iwl_trans_set_reduce_power(trans, capa); +notification: iwl_init_notification_wait(notif_wait, &pnvm_wait, ntf_cmds, ARRAY_SIZE(ntf_cmds), iwl_pnvm_complete_fn, trans); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 64b45a5b767e..1666ef3a482e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright(c) 2021-2022 Intel Corporation + * Copyright(c) 2021-2023 Intel Corporation */ #include "iwl-drv.h" @@ -123,9 +123,9 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, return 0; } -static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, - const u8 *data, size_t len, - struct iwl_pnvm_image *pnvm_data) +int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; @@ -181,17 +181,15 @@ static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, return -ENOENT; } -int iwl_uefi_get_reduced_power(struct iwl_trans *trans, - struct iwl_pnvm_image *pnvm_data) +u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) { struct pnvm_sku_package *package; unsigned long package_size; efi_status_t status; - int ret; - size_t len = 0; + u8 *data; if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return -ENODEV; + return ERR_PTR(-ENODEV); /* * TODO: we hardcode a maximum length here, because reading @@ -202,7 +200,7 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans, package = kmalloc(package_size, GFP_KERNEL); if (!package) - return -ENOMEM; + return ERR_PTR(-ENOMEM); status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID, NULL, &package_size, package); @@ -211,23 +209,22 @@ int iwl_uefi_get_reduced_power(struct iwl_trans *trans, "Reduced Power UEFI variable not found 0x%lx (len %lu)\n", status, package_size); kfree(package); - return -ENOENT; + return ERR_PTR(-ENOENT); } IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", package_size); - len = package_size; IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n", package->rev, package->total_size, package->n_skus); - ret = iwl_uefi_reduce_power_parse(trans, package->data, - len - sizeof(*package), - pnvm_data); - + *len = package_size - sizeof(*package); + data = kmemdup(package->data, *len, GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); kfree(package); - return ret; + return data; } static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 03176f73151a..10bed372e67c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright(c) 2021-2022 Intel Corporation + * Copyright(c) 2021-2023 Intel Corporation */ #ifndef __iwl_fw_uefi__ #define __iwl_fw_uefi__ @@ -50,25 +50,32 @@ struct uefi_cnv_common_step_data { */ #ifdef CONFIG_EFI void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len); -int iwl_uefi_get_reduced_power(struct iwl_trans *trans, - struct iwl_pnvm_image *pnvm_data); +u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len); +int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data); void iwl_uefi_get_step_table(struct iwl_trans *trans); #else /* CONFIG_EFI */ -static inline -void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { return ERR_PTR(-EOPNOTSUPP); } -static inline -int iwl_uefi_get_reduced_power(struct iwl_trans *trans, - struct iwl_pnvm_image *pnvm_data) +static inline int +iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { return -EOPNOTSUPP; } -static inline -void iwl_uefi_get_step_table(struct iwl_trans *trans) +static inline u8 * +iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline void iwl_uefi_get_step_table(struct iwl_trans *trans) { } #endif /* CONFIG_EFI */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 61ee6c1f4a1e..2915f9b2534c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1047,6 +1047,7 @@ struct iwl_trans_txqs { * @pm_support: set to true in start_hw if link pm is supported * @ltr_enabled: set to true if the LTR is enabled * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed + * @failed_to_load_reduce_power_image: set to true if pnvm loading failed * @wide_cmd_header: true when ucode supports wide command header format * @wait_command_queue: wait queue for sync commands * @num_rx_queues: number of RX queues allocated by the transport; @@ -1096,6 +1097,7 @@ struct iwl_trans { u8 pnvm_loaded:1; u8 fail_to_parse_pnvm_image:1; u8 reduce_power_loaded:1; + u8 failed_to_load_reduce_power_image:1; const struct iwl_hcmd_arr *command_groups; int command_groups_size; From patchwork Tue Jun 6 07:43:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268671 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20246C7EE2E for ; Tue, 6 Jun 2023 07:51:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231715AbjFFHvm (ORCPT ); Tue, 6 Jun 2023 03:51:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237022AbjFFHt4 (ORCPT ); Tue, 6 Jun 2023 03:49:56 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87CC91BE9 for ; Tue, 6 Jun 2023 00:45:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037524; x=1717573524; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kuH8rLnOHBn7IHbQNFuQSC7SM8D0GVZDJVNZTiQY8M0=; b=b8KK13rcpyDuG6QtwxrPX1kOTep3ZGQU0OmmKStGHT3dhY5LA920lp8x irxkG9oGCk2yEGrDCEKESyEkgR9Jpd7xEqPQiWBe2f9gL9cjf0n0mXLVn 93cPaYHPAjOKVAv1wMvWjIaFHAb5fAodrvOQIq4T+mMNhMmaQFARkYST9 tvbNlDTAeUJY7isizI5mvei8Cb1GrG3QVRPCnysd9XT5vMCA3ou+ULrn1 WVwbWXJz98lyIqszFYA6zXZrkiTjcqOtOKFI8+koxX8HyLiRxvCtO9+Yw eJKCMA5iafrZZt85wJnNA69kDMZPTKH3VE+J1G67Yg8WmlvQ3VNaalOTW g==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419117" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419117" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:46 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516413" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516413" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:45 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Johannes Berg , Gregory Greenman Subject: [PATCH 11/13] wifi: iwlwifi: fw: clean up PNVM loading code Date: Tue, 6 Jun 2023 10:43:08 +0300 Message-Id: <20230606103519.51fb5ee63f21.I20f270b2d47612e84643dc235c2940b8d9ed9930@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Johannes Berg This code is a bit of a maze of gotos etc. Clean up the code a bit to make the intent clearer. Signed-off-by: Johannes Berg Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 155 +++++++++++-------- 1 file changed, 89 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 3b5a3c89fedf..82eb32e67a2c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -270,88 +270,111 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len) return image; } -int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait, - const struct iwl_ucode_capabilities *capa) +static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) { - u8 *data; + struct iwl_pnvm_image *pnvm_data = NULL; + u8 *data = NULL; size_t length; - struct iwl_notification_wait pnvm_wait; - static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, - PNVM_INIT_COMPLETE_NTFY) }; - struct iwl_pnvm_image pnvm_data; int ret; - /* if the SKU_ID is empty, there's nothing to do */ - if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) - return 0; - - /* failed to get/parse the image in the past, no use to try again */ + /* failed to get/parse the image in the past, no use trying again */ if (trans->fail_to_parse_pnvm_image) - goto reduce_tables; - - /* get the image, parse and load it, if not loaded yet */ - if (!trans->pnvm_loaded) { - data = iwl_get_pnvm_image(trans, &length); - if (!data) { - trans->fail_to_parse_pnvm_image = true; - goto reduce_tables; - } - ret = iwl_pnvm_parse(trans, data, length, &pnvm_data); - if (ret) { - trans->fail_to_parse_pnvm_image = true; - kfree(data); - goto reduce_tables; - } + return; + + if (trans->pnvm_loaded) + goto set; - ret = iwl_trans_load_pnvm(trans, &pnvm_data, capa); - /* can only free data after pvnm_data use, but - * pnvm_data.version used below is not a pointer - */ - kfree(data); - if (ret) - goto reduce_tables; - IWL_INFO(trans, "loaded PNVM version %08x\n", - pnvm_data.version); + data = iwl_get_pnvm_image(trans, &length); + if (!data) { + trans->fail_to_parse_pnvm_image = true; + return; } + pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL); + if (!pnvm_data) + goto free; + + ret = iwl_pnvm_parse(trans, data, length, pnvm_data); + if (ret) { + trans->fail_to_parse_pnvm_image = true; + goto free; + } + + ret = iwl_trans_load_pnvm(trans, pnvm_data, capa); + if (ret) + goto free; + IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version); + +set: iwl_trans_set_pnvm(trans, capa); +free: + kfree(data); + kfree(pnvm_data); +} + +static void +iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_pnvm_image *pnvm_data = NULL; + u8 *data = NULL; + size_t length; + int ret; -reduce_tables: - /* now try to get the reduce power table, if not loaded yet */ if (trans->failed_to_load_reduce_power_image) - goto notification; - - if (!trans->reduce_power_loaded) { - memset(&pnvm_data, 0, sizeof(pnvm_data)); - data = iwl_uefi_get_reduced_power(trans, &length); - if (IS_ERR(data)) { - ret = PTR_ERR(data); - trans->failed_to_load_reduce_power_image = true; - goto notification; - } + return; - ret = iwl_uefi_reduce_power_parse(trans, data, length, - &pnvm_data); - if (ret) { - trans->failed_to_load_reduce_power_image = true; - kfree(data); - goto notification; - } + if (trans->reduce_power_loaded) + goto set; - ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa); - kfree(data); - if (ret) { - IWL_DEBUG_FW(trans, - "Failed to load reduce power table %d\n", - ret); - trans->failed_to_load_reduce_power_image = true; - goto notification; - } + data = iwl_uefi_get_reduced_power(trans, &length); + if (IS_ERR(data)) { + trans->failed_to_load_reduce_power_image = true; + return; } + + pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL); + if (!pnvm_data) + goto free; + + ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data); + if (ret) { + trans->failed_to_load_reduce_power_image = true; + goto free; + } + + ret = iwl_trans_load_reduce_power(trans, pnvm_data, capa); + if (ret) { + IWL_DEBUG_FW(trans, + "Failed to load reduce power table %d\n", + ret); + trans->failed_to_load_reduce_power_image = true; + goto free; + } + +set: iwl_trans_set_reduce_power(trans, capa); +free: + kfree(data); + kfree(pnvm_data); +} + +int iwl_pnvm_load(struct iwl_trans *trans, + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_notification_wait pnvm_wait; + static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, + PNVM_INIT_COMPLETE_NTFY) }; + + /* if the SKU_ID is empty, there's nothing to do */ + if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) + return 0; + + iwl_pnvm_load_pnvm_to_trans(trans, capa); + iwl_pnvm_load_reduce_power_to_trans(trans, capa); -notification: iwl_init_notification_wait(notif_wait, &pnvm_wait, ntf_cmds, ARRAY_SIZE(ntf_cmds), iwl_pnvm_complete_fn, trans); From patchwork Tue Jun 6 07:43:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268667 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8FE0FC77B7A for ; Tue, 6 Jun 2023 07:51:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236405AbjFFHve (ORCPT ); Tue, 6 Jun 2023 03:51:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237198AbjFFHuO (ORCPT ); Tue, 6 Jun 2023 03:50:14 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D97C510C0 for ; Tue, 6 Jun 2023 00:46:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037562; x=1717573562; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=l1netjZiN/1OcgGsT9bryJOm0nzX4csbBGhAVMC2ELk=; b=iefJhHia8e4JrkCChSytPLp5QZ4PMNCpasdJjKqB1h2exQlkl3ukxVXF SSQMhR4RXDU4vTkDxuhdQrfnQv0D9jA7lcz9/yqyIX552nnP42RqQFbIz +laMrb7p14IB4p+47PWLBwLqKalL60GsMIcAAIBWxE5EpGvMDGuL7aC5j eSjGKQMPcwb+SUOw81ONyOitSghH6Q2BrENeXTgzcaLYD6423AAvnkQO3 3+W7Lgbt1EqIpg9KDNGmPdXjALPkjriTQ79Nqr3ietYkOiHCnA/ZtULB+ SEV6EX6cefWqMuexGa4y9wMiQuFuAgE9lF2Z8+MDi6BKWDO4CIgSCEol+ A==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419125" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419125" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516434" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516434" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:47 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Gregory Greenman Subject: [PATCH 12/13] wifi: iwlwifi: fw: don't use constant size with efi.get_variable Date: Tue, 6 Jun 2023 10:43:09 +0300 Message-Id: <20230606103519.ef95a8055a50.Iae5389baaf0a9a3c89469f7502275ee119d378b6@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Gregory Greenman Use efi.get_variable() with NULL pointer for data in order to obtain entry size and then call it again with the correct size to get the entry itself. Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 143 ++++++++++--------- drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 13 +- 2 files changed, 74 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 1666ef3a482e..488b9fb79743 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -17,38 +17,53 @@ 0xb2, 0xec, 0xf5, 0xa3, \ 0x59, 0x4f, 0x4a, 0xea) -void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, + unsigned long *data_size) { - void *data; - unsigned long package_size; efi_status_t status; + void *data; - *len = 0; + if (!data_size) + return ERR_PTR(-EINVAL); if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) return ERR_PTR(-ENODEV); - /* - * TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_PNVM_SIZE; + /* first call with NULL data to get the exact entry size */ + *data_size = 0; + status = efi.get_variable(name, guid, NULL, data_size, NULL); + if (status != EFI_BUFFER_TOO_SMALL || !*data_size) + return ERR_PTR(-EIO); - data = kmalloc(package_size, GFP_KERNEL); + data = kmalloc(*data_size, GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); - status = efi.get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); + status = efi.get_variable(name, guid, NULL, data_size, data); if (status != EFI_SUCCESS) { - IWL_DEBUG_FW(trans, - "PNVM UEFI variable not found 0x%lx (len %lu)\n", - status, package_size); kfree(data); return ERR_PTR(-ENOENT); } + return data; +} + +void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +{ + unsigned long package_size; + void *data; + + *len = 0; + + data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, + &package_size); + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "PNVM UEFI variable not found 0x%lx (len %lu)\n", + PTR_ERR(data), package_size); + return data; + } + IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size); *len = package_size; @@ -185,31 +200,24 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) { struct pnvm_sku_package *package; unsigned long package_size; - efi_status_t status; u8 *data; - if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return ERR_PTR(-ENODEV); - - /* - * TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_REDUCE_POWER_SIZE; + package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME, + &IWL_EFI_VAR_GUID, &package_size); - package = kmalloc(package_size, GFP_KERNEL); - if (!package) - return ERR_PTR(-ENOMEM); - - status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, package); - if (status != EFI_SUCCESS) { + if (IS_ERR(package)) { IWL_DEBUG_FW(trans, "Reduced Power UEFI variable not found 0x%lx (len %lu)\n", - status, package_size); + PTR_ERR(package), package_size); + return ERR_CAST(package); + } + + if (package_size < sizeof(*package)) { + IWL_DEBUG_FW(trans, + "Invalid Reduced Power UEFI variable len (%lu)\n", + package_size); kfree(package); - return ERR_PTR(-ENOENT); + return ERR_PTR(-EINVAL); } IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", @@ -220,8 +228,11 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) *len = package_size - sizeof(*package); data = kmemdup(package->data, *len, GFP_KERNEL); - if (!data) + if (!data) { + kfree(package); return ERR_PTR(-ENOMEM); + } + kfree(package); return data; @@ -245,31 +256,27 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) { struct uefi_cnv_common_step_data *data; unsigned long package_size; - efi_status_t status; int ret; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return; - if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return; + data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, + &package_size); - /* TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_STEP_SIZE; - - data = kmalloc(package_size, GFP_KERNEL); - if (!data) + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "STEP UEFI variable not found 0x%lx\n", + PTR_ERR(data)); return; + } - status = efi.get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); - if (status != EFI_SUCCESS) { + if (package_size < sizeof(*data)) { IWL_DEBUG_FW(trans, - "STEP UEFI variable not found 0x%lx\n", status); - goto out_free; + "Invalid STEP table UEFI variable len (%lu)\n", + package_size); + kfree(data); + return; } IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n", @@ -279,7 +286,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) if (ret < 0) IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n"); -out_free: kfree(data); } IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table); @@ -322,29 +328,26 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, { struct uefi_cnv_wlan_sgom_data *data; unsigned long package_size; - efi_status_t status; int ret; - if (!fwrt->geo_enabled || - !efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) + if (!fwrt->geo_enabled) return; - /* TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_SGOM_SIZE; - - data = kmalloc(package_size, GFP_KERNEL); - if (!data) + data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, + &package_size); + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "SGOM UEFI variable not found 0x%lx\n", + PTR_ERR(data)); return; + } - status = efi.get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); - if (status != EFI_SUCCESS) { + if (package_size < sizeof(*data)) { IWL_DEBUG_FW(trans, - "SGOM UEFI variable not found 0x%lx\n", status); - goto out_free; + "Invalid SGOM table UEFI variable len (%lu)\n", + package_size); + kfree(data); + return; } IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n", @@ -354,9 +357,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, if (ret < 0) IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n"); -out_free: kfree(data); - } IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table); #endif /* CONFIG_ACPI */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 10bed372e67c..dc7ccf49d92d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -10,16 +10,7 @@ #define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping" #define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP" -/* - * TODO: we have these hardcoded values that the caller must pass, - * because reading from the UEFI is not working. To implement this - * properly, we have to change iwl_pnvm_get_from_uefi() to call - * efivar_entry_size() and return the value to the caller instead. - */ -#define IWL_HARDCODED_PNVM_SIZE 4096 -#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768 -#define IWL_HARDCODED_SGOM_SIZE 339 -#define IWL_HARDCODED_STEP_SIZE 6 +#define IWL_SGOM_MAP_SIZE 339 struct pnvm_sku_package { u8 rev; @@ -31,7 +22,7 @@ struct pnvm_sku_package { struct uefi_cnv_wlan_sgom_data { u8 revision; - u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1]; + u8 offset_map[IWL_SGOM_MAP_SIZE - 1]; } __packed; struct uefi_cnv_common_step_data { From patchwork Tue Jun 6 07:43:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Greenman, Gregory" X-Patchwork-Id: 13268669 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 729E6C7EE24 for ; Tue, 6 Jun 2023 07:51:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236719AbjFFHvi (ORCPT ); Tue, 6 Jun 2023 03:51:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237071AbjFFHuA (ORCPT ); Tue, 6 Jun 2023 03:50:00 -0400 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6CFE31BF8 for ; Tue, 6 Jun 2023 00:45:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1686037529; x=1717573529; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E0vVIprFZFV4HTvZZYkUvhFxZrg/Ng0i3k5AfN760ec=; b=dUnhxPYpr+WzNj0gkR3sgAih7pQY+QPJQP3Jbe7eO1FgrQ3c1Y82/ynT slYTtGbYxOtjiE2RpX5M7g6u9pppV3EquaXGDYhDA7kQI8pdbp8pRf4TX F43pPw6OK5g4fgcLrBVGg8zCgW2Gg9rY2YZ6VoDNJZmaRXm9NAcA1BUsJ 48S8LnVLKDP51laaEkPvCEf6rP+6IbS8uzbOwqoynhyQkl/rn9K2mKPCc Qsj34Bn7DE5SCsauNdaMGrHGluLqS7I6dRVzk2dXUAavGPtwshIWIEN9b 3m8DTOk/kMKf7o/BGvOqW5ixsCWVmD2WtoTxWR8WCHqQ+hamSyuexKYCJ g==; X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="422419131" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="422419131" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:51 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10732"; a="821516458" X-IronPort-AV: E=Sophos;i="6.00,219,1681196400"; d="scan'208";a="821516458" Received: from oniamir-mobl.ger.corp.intel.com (HELO ggreenma-mobl2.intel.com) ([10.214.217.62]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jun 2023 00:43:49 -0700 From: gregory.greenman@intel.com To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Gregory Greenman Subject: [PATCH 13/13] wifi: iwlwifi: pnvm: handle memory descriptor tlv Date: Tue, 6 Jun 2023 10:43:10 +0300 Message-Id: <20230606103519.8c5f5ee8e30b.Id1893c9dec140b5ba4abe8a121c2e1a1d121d2d7@changeid> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230606074310.889520-1-gregory.greenman@intel.com> References: <20230606074310.889520-1-gregory.greenman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Gregory Greenman When PNVM is obtained from UEFI, there's an additional memory descriptor TLV that has to be handled. It is the same TLV that holds data in the reduced power tables. Also, in this TLV, the actual data is located after address and size, so add the corresponding offset. Signed-off-by: Gregory Greenman --- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 5 ++ drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 62 ++++++++++++++------ drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 9 +++ 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 82eb32e67a2c..650e4bde9c17 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -127,6 +127,11 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, break; } + case IWL_UCODE_TLV_MEM_DESC: + if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, + pnvm_data)) + return -EINVAL; + break; case IWL_UCODE_TLV_PNVM_SKU: IWL_DEBUG_FW(trans, "New PNVM section started, stop parsing.\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 488b9fb79743..9877988db0d2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -17,6 +17,12 @@ 0xb2, 0xec, 0xf5, 0xa3, \ 0x59, 0x4f, 0x4a, 0xea) +struct iwl_uefi_pnvm_mem_desc { + __le32 addr; + __le32 size; + const u8 data[]; +} __packed; + static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, unsigned long *data_size) { @@ -70,6 +76,42 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) return data; } +int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data) +{ + const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data; + u32 data_len; + + if (tlv_len < sizeof(*desc)) { + IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len); + return -EINVAL; + } + + data_len = tlv_len - sizeof(*desc); + + IWL_DEBUG_FW(trans, + "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n", + tlv_len, data_len); + + if (le32_to_cpu(desc->size) != data_len) { + IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size); + return -EINVAL; + } + + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { + IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n"); + return -EINVAL; + } + + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len); + + pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data; + pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; + pnvm_data->n_chunks++; + + return 0; +} + static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, const u8 *data, size_t len, struct iwl_pnvm_image *pnvm_data) @@ -97,25 +139,11 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, data += sizeof(*tlv); switch (tlv_type) { - case IWL_UCODE_TLV_MEM_DESC: { - IWL_DEBUG_FW(trans, - "Got IWL_UCODE_TLV_MEM_DESC len %d\n", - tlv_len); - - if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { - IWL_DEBUG_FW(trans, - "too many payloads to allocate in DRAM.\n"); + case IWL_UCODE_TLV_MEM_DESC: + if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, + pnvm_data)) return -EINVAL; - } - - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); - - pnvm_data->chunks[pnvm_data->n_chunks].data = data; - pnvm_data->chunks[pnvm_data->n_chunks].len = tlv_len; - pnvm_data->n_chunks++; - break; - } case IWL_UCODE_TLV_PNVM_SKU: IWL_DEBUG_FW(trans, "New REDUCE_POWER section started, stop parsing.\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index dc7ccf49d92d..1369cc4855c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -46,6 +46,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, const u8 *data, size_t len, struct iwl_pnvm_image *pnvm_data); void iwl_uefi_get_step_table(struct iwl_trans *trans); +int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data); #else /* CONFIG_EFI */ static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { @@ -69,6 +71,13 @@ iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) static inline void iwl_uefi_get_step_table(struct iwl_trans *trans) { } + +static inline int +iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data) +{ + return 0; +} #endif /* CONFIG_EFI */ #if defined(CONFIG_EFI) && defined(CONFIG_ACPI)