Commit 68f6f492 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho

iwlwifi: trans: support loading ini TLVs from external file

Support loading and storing ini TLVs from external
file. Those TLVs are appended to the default TLVs,
so store them separately.
Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent f14cda6f
...@@ -63,7 +63,8 @@ ...@@ -63,7 +63,8 @@
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-dbg-tlv.h" #include "iwl-dbg-tlv.h"
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv) void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
bool ext)
{ {
struct iwl_apply_point_data *data; struct iwl_apply_point_data *data;
struct iwl_fw_ini_header *header = (void *)&tlv->data[0]; struct iwl_fw_ini_header *header = (void *)&tlv->data[0];
...@@ -75,7 +76,10 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv) ...@@ -75,7 +76,10 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv)
"Invalid apply point id %d\n", apply_point)) "Invalid apply point id %d\n", apply_point))
return; return;
data = &trans->apply_points[apply_point]; if (ext)
data = &trans->apply_points_ext[apply_point];
else
data = &trans->apply_points[apply_point];
/* /*
* Make sure we still have room to copy this TLV. Offset points to the * Make sure we still have room to copy this TLV. Offset points to the
...@@ -90,7 +94,8 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv) ...@@ -90,7 +94,8 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv)
data->offset += copy_size; data->offset += copy_size;
} }
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data) void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
bool ext)
{ {
struct iwl_ucode_tlv *tlv; struct iwl_ucode_tlv *tlv;
u32 size[IWL_FW_INI_APPLY_NUM] = {0}; u32 size[IWL_FW_INI_APPLY_NUM] = {0};
...@@ -137,8 +142,13 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data) ...@@ -137,8 +142,13 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data)
return; return;
} }
trans->apply_points[i].data = mem; if (ext) {
trans->apply_points[i].size = size[i]; trans->apply_points_ext[i].data = mem;
trans->apply_points_ext[i].size = size[i];
} else {
trans->apply_points[i].data = mem;
trans->apply_points[i].size = size[i];
}
} }
} }
...@@ -150,5 +160,66 @@ void iwl_fw_dbg_free(struct iwl_trans *trans) ...@@ -150,5 +160,66 @@ void iwl_fw_dbg_free(struct iwl_trans *trans)
kfree(trans->apply_points[i].data); kfree(trans->apply_points[i].data);
trans->apply_points[i].size = 0; trans->apply_points[i].size = 0;
trans->apply_points[i].offset = 0; trans->apply_points[i].offset = 0;
kfree(trans->apply_points_ext[i].data);
trans->apply_points_ext[i].size = 0;
trans->apply_points_ext[i].offset = 0;
}
}
static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data,
size_t len)
{
struct iwl_ucode_tlv *tlv;
enum iwl_ucode_tlv_type tlv_type;
u32 tlv_len;
while (len >= sizeof(*tlv)) {
len -= sizeof(*tlv);
tlv = (void *)data;
tlv_len = le32_to_cpu(tlv->length);
tlv_type = le32_to_cpu(tlv->type);
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
return -EINVAL;
}
len -= ALIGN(tlv_len, 4);
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
switch (tlv_type) {
case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
case IWL_UCODE_TLV_TYPE_TRIGGERS:
case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
iwl_fw_dbg_copy_tlv(trans, tlv, true);
default:
WARN_ONCE(1, "Invalid TLV %x\n", tlv_type);
break;
}
} }
return 0;
}
void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans)
{
const struct firmware *fw;
int res;
if (trans->external_ini_loaded || !iwlwifi_mod_params.enable_ini)
return;
res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev);
if (res)
return;
iwl_alloc_dbg_tlv(trans, fw->size, fw->data, true);
iwl_parse_fw_dbg_tlv(trans, fw->data, fw->size);
trans->external_ini_loaded = true;
release_firmware(fw);
} }
...@@ -77,8 +77,11 @@ struct iwl_apply_point_data { ...@@ -77,8 +77,11 @@ struct iwl_apply_point_data {
}; };
struct iwl_trans; struct iwl_trans;
void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans);
void iwl_fw_dbg_free(struct iwl_trans *trans); void iwl_fw_dbg_free(struct iwl_trans *trans);
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv); void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data); bool ext);
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
bool ext);
#endif /* __iwl_dbg_tlv_h__*/ #endif /* __iwl_dbg_tlv_h__*/
...@@ -647,7 +647,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -647,7 +647,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
len -= sizeof(*ucode); len -= sizeof(*ucode);
if (iwlwifi_mod_params.enable_ini) if (iwlwifi_mod_params.enable_ini)
iwl_alloc_dbg_tlv(drv->trans, len, data); iwl_alloc_dbg_tlv(drv->trans, len, data, false);
while (len >= sizeof(*tlv)) { while (len >= sizeof(*tlv)) {
len -= sizeof(*tlv); len -= sizeof(*tlv);
...@@ -1096,7 +1096,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -1096,7 +1096,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
case IWL_UCODE_TLV_TYPE_TRIGGERS: case IWL_UCODE_TLV_TYPE_TRIGGERS:
case IWL_UCODE_TLV_TYPE_DEBUG_FLOW: case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
if (iwlwifi_mod_params.enable_ini) if (iwlwifi_mod_params.enable_ini)
iwl_fw_dbg_copy_tlv(drv->trans, tlv); iwl_fw_dbg_copy_tlv(drv->trans, tlv, false);
default: default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break; break;
...@@ -1576,7 +1576,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) ...@@ -1576,7 +1576,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
if (!drv->dbgfs_drv) { if (!drv->dbgfs_drv) {
IWL_ERR(drv, "failed to create debugfs directory\n"); IWL_ERR(drv, "failed to create debugfs directory\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_drv; goto err_free_tlv;
} }
/* Create transport layer debugfs dir */ /* Create transport layer debugfs dir */
...@@ -1601,7 +1601,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) ...@@ -1601,7 +1601,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
err_free_dbgfs: err_free_dbgfs:
debugfs_remove_recursive(drv->dbgfs_drv); debugfs_remove_recursive(drv->dbgfs_drv);
err_free_drv: err_free_tlv:
iwl_fw_dbg_free(drv->trans);
#endif #endif
kfree(drv); kfree(drv);
err: err:
......
...@@ -776,6 +776,9 @@ struct iwl_trans { ...@@ -776,6 +776,9 @@ struct iwl_trans {
#endif #endif
struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM]; struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM];
struct iwl_apply_point_data apply_points_ext[IWL_FW_INI_APPLY_NUM];
bool external_ini_loaded;
const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv; const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX]; const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
......
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