Skip to content

Commit 5f40850

Browse files
Alon Giladijmberg-intel
authored andcommitted
wifi: iwlwifi: Generalize the parsing of the pnvm image
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 <[email protected]> Signed-off-by: Gregory Greenman <[email protected]> Link: https://lore.kernel.org/r/20230606103519.06c02f380b6f.I03a3030fca194aa0c4bc2ecd18531f8914e98cfd@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 43413a3 commit 5f40850

File tree

6 files changed

+72
-45
lines changed

6 files changed

+72
-45
lines changed

drivers/net/wireless/intel/iwlwifi/fw/pnvm.c

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,8 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
3636
const struct iwl_ucode_tlv *tlv;
3737
u32 sha1 = 0;
3838
u16 mac_type = 0, rf_id = 0;
39-
u8 *pnvm_data = NULL, *tmp;
39+
struct iwl_pnvm_image pnvm_data = {};
4040
bool hw_match = false;
41-
u32 size = 0;
42-
int ret;
4341

4442
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
4543

@@ -55,8 +53,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
5553
if (len < tlv_len) {
5654
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
5755
len, tlv_len);
58-
ret = -EINVAL;
59-
goto out;
56+
return -EINVAL;
6057
}
6158

6259
data += sizeof(*tlv);
@@ -112,23 +109,18 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
112109
break;
113110
}
114111

115-
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
116-
data_len);
117-
118-
tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL);
119-
if (!tmp) {
112+
if (pnvm_data.n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
120113
IWL_DEBUG_FW(trans,
121-
"Couldn't allocate (more) pnvm_data\n");
122-
123-
ret = -ENOMEM;
124-
goto out;
114+
"too many payloads to allocate in DRAM.\n");
115+
return -EINVAL;
125116
}
126117

127-
pnvm_data = tmp;
128-
129-
memcpy(pnvm_data + size, section->data, data_len);
118+
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
119+
data_len);
130120

131-
size += data_len;
121+
pnvm_data.chunks[pnvm_data.n_chunks].data = section->data;
122+
pnvm_data.chunks[pnvm_data.n_chunks].len = data_len;
123+
pnvm_data.n_chunks++;
132124

133125
break;
134126
}
@@ -152,22 +144,17 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
152144
"HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
153145
CSR_HW_REV_TYPE(trans->hw_rev),
154146
CSR_HW_RFID_TYPE(trans->hw_rf_id));
155-
ret = -ENOENT;
156-
goto out;
147+
return -ENOENT;
157148
}
158149

159-
if (!size) {
150+
if (!pnvm_data.n_chunks) {
160151
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
161-
ret = -ENOENT;
162-
goto out;
152+
return -ENOENT;
163153
}
164154

165155
IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
166156

167-
ret = iwl_trans_set_pnvm(trans, pnvm_data, size);
168-
out:
169-
kfree(pnvm_data);
170-
return ret;
157+
return iwl_trans_set_pnvm(trans, &pnvm_data);
171158
}
172159

173160
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
@@ -275,7 +262,7 @@ int iwl_pnvm_load(struct iwl_trans *trans,
275262
* need to set it again.
276263
*/
277264
if (trans->pnvm_loaded) {
278-
ret = iwl_trans_set_pnvm(trans, NULL, 0);
265+
ret = iwl_trans_set_pnvm(trans, NULL);
279266
if (ret)
280267
return ret;
281268
goto skip_parse;

drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#define CSR_IML_SIZE_ADDR 0x128
1414
#define CSR_IML_RESP_ADDR 0x12c
1515

16+
#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2
17+
1618
/* Set bit for enabling automatic function boot */
1719
#define CSR_AUTO_FUNC_BOOT_ENA BIT(1)
1820
/* Set bit for initiating function boot */
@@ -278,7 +280,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
278280
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive);
279281

280282
int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
281-
const void *data, u32 len);
283+
const struct iwl_pnvm_image *pnvm_payloads);
282284
int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
283285
const void *data, u32 len);
284286
int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,

drivers/net/wireless/intel/iwlwifi/iwl-context-info.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
22
/*
33
* Copyright (C) 2017 Intel Deutschland GmbH
4-
* Copyright (C) 2018-2020 Intel Corporation
4+
* Copyright (C) 2018-2020, 2022 Intel Corporation
55
*/
66
#ifndef __iwl_context_info_file_h__
77
#define __iwl_context_info_file_h__
@@ -177,6 +177,9 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
177177
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
178178
const struct fw_img *fw,
179179
struct iwl_context_info_dram *ctxt_dram);
180+
void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
181+
size_t size,
182+
dma_addr_t *phys);
180183
int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
181184
const void *data, u32 len,
182185
struct iwl_dram_data *dram);

drivers/net/wireless/intel/iwlwifi/iwl-trans.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,22 @@ struct iwl_trans_rxq_dma_data {
459459
u64 ur_bd_cb;
460460
};
461461

462+
/* maximal number of DRAM MAP entries supported by FW */
463+
#define IPC_DRAM_MAP_ENTRY_NUM_MAX 64
464+
465+
/**
466+
* struct iwl_pnvm_image - contains info about the parsed pnvm image
467+
* @chunks: array of pointers to pnvm payloads and their sizes
468+
* @n_chunks: the number of the pnvm payloads.
469+
*/
470+
struct iwl_pnvm_image {
471+
struct {
472+
const void *data;
473+
u32 len;
474+
} chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX];
475+
u32 n_chunks;
476+
};
477+
462478
/**
463479
* struct iwl_trans_ops - transport specific operations
464480
*
@@ -614,7 +630,8 @@ struct iwl_trans_ops {
614630
void *sanitize_ctx);
615631
void (*debugfs_cleanup)(struct iwl_trans *trans);
616632
void (*sync_nmi)(struct iwl_trans *trans);
617-
int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
633+
int (*set_pnvm)(struct iwl_trans *trans,
634+
const struct iwl_pnvm_image *pnvm_data);
618635
int (*set_reduce_power)(struct iwl_trans *trans,
619636
const void *data, u32 len);
620637
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,
15161533
u32 sw_err_bit);
15171534

15181535
static inline int iwl_trans_set_pnvm(struct iwl_trans *trans,
1519-
const void *data, u32 len)
1536+
const struct iwl_pnvm_image *pnvm_data)
15201537
{
15211538
if (trans->ops->set_pnvm) {
1522-
int ret = trans->ops->set_pnvm(trans, data, len);
1539+
int ret = trans->ops->set_pnvm(trans, pnvm_data);
15231540

15241541
if (ret)
15251542
return ret;

drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -282,28 +282,46 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive)
282282
}
283283

284284
int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
285-
const void *data, u32 len)
285+
const struct iwl_pnvm_image *pnvm_payloads)
286286
{
287287
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
288288
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
289289
&trans_pcie->prph_scratch->ctrl_cfg;
290-
int ret;
290+
struct iwl_dram_data *dram = &trans_pcie->pnvm_dram;
291291

292292
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
293293
return 0;
294294

295295
/* only allocate the DRAM if not allocated yet */
296296
if (!trans->pnvm_loaded) {
297+
u32 len, len0, len1;
298+
297299
if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
298300
return -EBUSY;
299301

300-
ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
301-
&trans_pcie->pnvm_dram);
302-
if (ret < 0) {
303-
IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n",
304-
ret);
305-
return ret;
302+
if (pnvm_payloads->n_chunks !=
303+
UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) {
304+
IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n",
305+
pnvm_payloads->n_chunks);
306+
return -EINVAL;
307+
}
308+
len0 = pnvm_payloads->chunks[0].len;
309+
len1 = pnvm_payloads->chunks[1].len;
310+
if (len1 > 0xFFFFFFFF - len0) {
311+
IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n");
312+
return -EINVAL;
313+
}
314+
len = len0 + len1;
315+
316+
dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len, &dram->physical);
317+
if (!dram->block) {
318+
IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n");
319+
return -ENOMEM;
306320
}
321+
dram->size = len;
322+
memcpy(dram->block, pnvm_payloads->chunks[0].data, len0);
323+
memcpy((u8 *)dram->block + len0, pnvm_payloads->chunks[1].data,
324+
len1);
307325
}
308326

309327
prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =

drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
33
* Copyright (C) 2017 Intel Deutschland GmbH
4-
* Copyright (C) 2018-2021 Intel Corporation
4+
* Copyright (C) 2018-2022 Intel Corporation
55
*/
66
#include "iwl-trans.h"
77
#include "iwl-fh.h"
@@ -38,9 +38,9 @@ static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
3838
return result;
3939
}
4040

41-
static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
42-
size_t size,
43-
dma_addr_t *phys)
41+
void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
42+
size_t size,
43+
dma_addr_t *phys)
4444
{
4545
return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0);
4646
}

0 commit comments

Comments
 (0)