Skip to content

Commit b99e32c

Browse files
Alon Giladijmberg-intel
authored andcommitted
wifi: iwlwifi: Take loading and setting of pnvm image out of parsing part
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 <[email protected]> Signed-off-by: Gregory Greenman <[email protected]> Link: https://lore.kernel.org/r/20230606103519.504b42fc1611.I4ddf6ad76d922d118fcbcc4f0e9ec003753d0b75@changeid Signed-off-by: Johannes Berg <[email protected]>
1 parent 194d1f8 commit b99e32c

File tree

2 files changed

+73
-61
lines changed

2 files changed

+73
-61
lines changed

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

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
22
/*
3-
* Copyright(c) 2020-2022 Intel Corporation
3+
* Copyright(c) 2020-2023 Intel Corporation
44
*/
55

66
#include "iwl-drv.h"
@@ -31,17 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
3131
}
3232

3333
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
34-
size_t len)
34+
size_t len,
35+
struct iwl_pnvm_image *pnvm_data)
3536
{
3637
const struct iwl_ucode_tlv *tlv;
3738
u32 sha1 = 0;
3839
u16 mac_type = 0, rf_id = 0;
39-
struct iwl_pnvm_image pnvm_data = {};
4040
bool hw_match = false;
41-
int ret;
4241

4342
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
4443

44+
memset(pnvm_data, 0, sizeof(*pnvm_data));
45+
4546
while (len >= sizeof(*tlv)) {
4647
u32 tlv_len, tlv_type;
4748

@@ -73,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
7374
IWL_DEBUG_FW(trans,
7475
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
7576
sha1);
77+
pnvm_data->version = sha1;
7678
break;
7779
case IWL_UCODE_TLV_HW_TYPE:
7880
if (tlv_len < 2 * sizeof(__le16)) {
@@ -110,7 +112,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
110112
break;
111113
}
112114

113-
if (pnvm_data.n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
115+
if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
114116
IWL_DEBUG_FW(trans,
115117
"too many payloads to allocate in DRAM.\n");
116118
return -EINVAL;
@@ -119,9 +121,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
119121
IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
120122
data_len);
121123

122-
pnvm_data.chunks[pnvm_data.n_chunks].data = section->data;
123-
pnvm_data.chunks[pnvm_data.n_chunks].len = data_len;
124-
pnvm_data.n_chunks++;
124+
pnvm_data->chunks[pnvm_data->n_chunks].data = section->data;
125+
pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
126+
pnvm_data->n_chunks++;
125127

126128
break;
127129
}
@@ -148,23 +150,17 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
148150
return -ENOENT;
149151
}
150152

151-
if (!pnvm_data.n_chunks) {
153+
if (!pnvm_data->n_chunks) {
152154
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
153155
return -ENOENT;
154156
}
155157

156-
ret = iwl_trans_load_pnvm(trans, &pnvm_data);
157-
if (ret)
158-
return ret;
159-
160-
IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
161-
162-
iwl_trans_set_pnvm(trans);
163158
return 0;
164159
}
165160

166161
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
167-
size_t len)
162+
size_t len,
163+
struct iwl_pnvm_image *pnvm_data)
168164
{
169165
const struct iwl_ucode_tlv *tlv;
170166

@@ -205,7 +201,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
205201
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
206202
int ret;
207203

208-
ret = iwl_pnvm_handle_section(trans, data, len);
204+
ret = iwl_pnvm_handle_section(trans, data, len,
205+
pnvm_data);
209206
if (!ret)
210207
return 0;
211208
} else {
@@ -248,70 +245,81 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
248245
return 0;
249246
}
250247

248+
static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
249+
{
250+
struct pnvm_sku_package *package;
251+
u8 *image = NULL;
252+
253+
/* First attempt to get the PNVM from BIOS */
254+
package = iwl_uefi_get_pnvm(trans_p, len);
255+
if (!IS_ERR_OR_NULL(package)) {
256+
if (*len >= sizeof(*package)) {
257+
/* we need only the data */
258+
*len -= sizeof(*package);
259+
image = kmemdup(package->data, *len, GFP_KERNEL);
260+
}
261+
/* free package regardless of whether kmemdup succeeded */
262+
kfree(package);
263+
if (image)
264+
return image;
265+
}
266+
267+
/* If it's not available, try from the filesystem */
268+
if (iwl_pnvm_get_from_fs(trans_p, &image, len))
269+
return NULL;
270+
return image;
271+
}
272+
251273
int iwl_pnvm_load(struct iwl_trans *trans,
252274
struct iwl_notif_wait_data *notif_wait)
253275
{
254276
u8 *data;
255-
size_t len;
256-
struct pnvm_sku_package *package;
277+
size_t length;
257278
struct iwl_notification_wait pnvm_wait;
258279
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
259280
PNVM_INIT_COMPLETE_NTFY) };
281+
struct iwl_pnvm_image pnvm_data;
260282
int ret;
261283

262284
/* if the SKU_ID is empty, there's nothing to do */
263285
if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
264286
return 0;
265287

266-
/*
267-
* If we already loaded (or tried to load) it before, we just
268-
* need to set it again.
269-
*/
270-
if (trans->pnvm_loaded) {
271-
iwl_trans_set_pnvm(trans);
272-
goto skip_parse;
273-
}
288+
/* failed to get/parse the image in the past, no use to try again */
289+
if (trans->fail_to_parse_pnvm_image)
290+
goto reduce_tables;
274291

275-
/* First attempt to get the PNVM from BIOS */
276-
package = iwl_uefi_get_pnvm(trans, &len);
277-
if (!IS_ERR_OR_NULL(package)) {
278-
if (len >= sizeof(*package)) {
279-
/* we need only the data */
280-
len -= sizeof(*package);
281-
data = kmemdup(package->data, len, GFP_KERNEL);
282-
} else {
283-
data = NULL;
292+
/* get the image, parse and load it, if not loaded yet */
293+
if (!trans->pnvm_loaded) {
294+
data = iwl_get_pnvm_image(trans, &length);
295+
if (!data) {
296+
trans->fail_to_parse_pnvm_image = true;
297+
goto reduce_tables;
298+
}
299+
ret = iwl_pnvm_parse(trans, data, length, &pnvm_data);
300+
if (ret) {
301+
trans->fail_to_parse_pnvm_image = true;
302+
kfree(data);
303+
goto reduce_tables;
284304
}
285305

286-
/* free package regardless of whether kmemdup succeeded */
287-
kfree(package);
288-
289-
if (data)
290-
goto parse;
291-
}
292-
293-
/* If it's not available, try from the filesystem */
294-
ret = iwl_pnvm_get_from_fs(trans, &data, &len);
295-
if (ret) {
296-
/*
297-
* Pretend we've loaded it - at least we've tried and
298-
* couldn't load it at all, so there's no point in
299-
* trying again over and over.
306+
ret = iwl_trans_load_pnvm(trans, &pnvm_data);
307+
/* can only free data after pvnm_data use, but
308+
* pnvm_data.version used below is not a pointer
300309
*/
301-
trans->pnvm_loaded = true;
302-
303-
goto skip_parse;
310+
kfree(data);
311+
if (ret)
312+
goto reduce_tables;
313+
IWL_INFO(trans, "loaded PNVM version %08x\n",
314+
pnvm_data.version);
304315
}
305316

306-
parse:
307-
iwl_pnvm_parse(trans, data, len);
308-
309-
kfree(data);
317+
iwl_trans_set_pnvm(trans);
310318

311-
skip_parse:
319+
reduce_tables:
312320
/* now try to get the reduce power table, if not loaded yet */
313321
if (!trans->reduce_power_loaded) {
314-
data = iwl_uefi_get_reduced_power(trans, &len);
322+
data = iwl_uefi_get_reduced_power(trans, &length);
315323
if (IS_ERR_OR_NULL(data)) {
316324
/*
317325
* Pretend we've loaded it - at least we've tried and
@@ -320,7 +328,7 @@ int iwl_pnvm_load(struct iwl_trans *trans,
320328
*/
321329
trans->reduce_power_loaded = true;
322330
} else {
323-
ret = iwl_trans_set_reduce_power(trans, data, len);
331+
ret = iwl_trans_set_reduce_power(trans, data, length);
324332
if (ret)
325333
IWL_DEBUG_FW(trans,
326334
"Failed to set reduce power table %d\n",

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,13 +466,15 @@ struct iwl_trans_rxq_dma_data {
466466
* struct iwl_pnvm_image - contains info about the parsed pnvm image
467467
* @chunks: array of pointers to pnvm payloads and their sizes
468468
* @n_chunks: the number of the pnvm payloads.
469+
* @version: the version of the loaded PNVM image
469470
*/
470471
struct iwl_pnvm_image {
471472
struct {
472473
const void *data;
473474
u32 len;
474475
} chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX];
475476
u32 n_chunks;
477+
u32 version;
476478
};
477479

478480
/**
@@ -1023,6 +1025,7 @@ struct iwl_trans_txqs {
10231025
* @hw_rev_step: The mac step of the HW
10241026
* @pm_support: set to true in start_hw if link pm is supported
10251027
* @ltr_enabled: set to true if the LTR is enabled
1028+
* @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
10261029
* @wide_cmd_header: true when ucode supports wide command header format
10271030
* @wait_command_queue: wait queue for sync commands
10281031
* @num_rx_queues: number of RX queues allocated by the transport;
@@ -1070,6 +1073,7 @@ struct iwl_trans {
10701073
bool pm_support;
10711074
bool ltr_enabled;
10721075
u8 pnvm_loaded:1;
1076+
u8 fail_to_parse_pnvm_image:1;
10731077
u8 reduce_power_loaded:1;
10741078

10751079
const struct iwl_hcmd_arr *command_groups;

0 commit comments

Comments
 (0)