summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlon Giladi <alon.giladi@intel.com>2023-06-06 09:42:59 +0200
committerJohannes Berg <johannes.berg@intel.com>2023-06-06 13:43:20 +0200
commit194d1f84d56e912459f166a80ef520037c84b0d3 (patch)
tree995ddb8e1a4d3c8faad07a3ec629c2e3d85b6ef8
parentwifi: iwlwifi: Generalize the parsing of the pnvm image (diff)
downloadlinux-194d1f84d56e912459f166a80ef520037c84b0d3.tar.xz
linux-194d1f84d56e912459f166a80ef520037c84b0d3.zip
wifi: iwlwifi: Separate loading and setting of pnvm image into two functions
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 <alon.giladi@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230606103519.4c0728239fd6.Ibc30a9fbdb6123dadbe2dbb89318dbd5ec01080a@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h25
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c69
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c1
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 @@ done:
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 b7f43cfc35fb..35782cba5b81 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 db10bd3c1058..666dda554f30 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -3536,6 +3536,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