Commit 194d1f84 authored by Alon Giladi's avatar Alon Giladi Committed by Johannes Berg

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: default avatarAlon Giladi <alon.giladi@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230606103519.4c0728239fd6.Ibc30a9fbdb6123dadbe2dbb89318dbd5ec01080a@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 5f408503
......@@ -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;
}
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment