void iwl_dbg_tlv_copy(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
bool ext)
{
- struct iwl_apply_point_data *data;
+ struct iwl_apply_point_data *dbg_cfg, *tlv_copy;
struct iwl_fw_ini_header *header = (void *)&tlv->data[0];
+ u32 tlv_type = le32_to_cpu(tlv->type);
+ u32 len = le32_to_cpu(tlv->length);
u32 apply_point = le32_to_cpu(header->apply_point);
- int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv);
- int offset_size = copy_size;
-
if (le32_to_cpu(header->tlv_version) != 1)
return;
if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
- "Invalid apply point id %d\n", apply_point))
+ "Invalid apply point %d\n", apply_point))
return;
+ IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n",
+ tlv_type, apply_point);
+
if (ext)
- data = &trans->dbg.apply_points_ext[apply_point];
+ dbg_cfg = &trans->dbg.apply_points_ext[apply_point];
else
- data = &trans->dbg.apply_points[apply_point];
-
- /*
- * Make sure we still have room to copy this TLV. Offset points to the
- * location the last copy ended.
- */
- if (WARN_ONCE(data->offset + offset_size > data->size,
- "Not enough memory for apply point %d\n",
- apply_point))
- return;
-
- memcpy(data->data + data->offset, (void *)tlv, copy_size);
- data->offset += offset_size;
-}
-
-void iwl_dbg_tlv_alloc(struct iwl_trans *trans, size_t len, const u8 *data,
- bool ext)
-{
- struct iwl_ucode_tlv *tlv;
- u32 size[IWL_FW_INI_APPLY_NUM] = {0};
- int i;
-
- while (len >= sizeof(*tlv)) {
- u32 tlv_len, tlv_type, apply;
- struct iwl_fw_ini_header *hdr;
-
- len -= sizeof(*tlv);
- tlv = (void *)data;
-
- tlv_len = le32_to_cpu(tlv->length);
- tlv_type = le32_to_cpu(tlv->type);
+ dbg_cfg = &trans->dbg.apply_points[apply_point];
- if (len < tlv_len)
- return;
-
- len -= ALIGN(tlv_len, 4);
- data += sizeof(*tlv) + ALIGN(tlv_len, 4);
-
- if (tlv_type < IWL_UCODE_TLV_DEBUG_BASE ||
- tlv_type > IWL_UCODE_TLV_DEBUG_MAX)
- continue;
-
- hdr = (void *)&tlv->data[0];
- apply = le32_to_cpu(hdr->apply_point);
-
- if (le32_to_cpu(hdr->tlv_version) != 1)
- continue;
-
- IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n",
- le32_to_cpu(tlv->type), apply);
-
- if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM))
- continue;
-
- size[apply] += sizeof(*tlv) + tlv_len;
+ tlv_copy = kzalloc(sizeof(*tlv_copy) + len, GFP_KERNEL);
+ if (!tlv_copy) {
+ IWL_ERR(trans, "WRT: No memory for TLV 0x%x, apply point %d\n",
+ tlv_type, apply_point);
+ return;
}
- for (i = 0; i < ARRAY_SIZE(size); i++) {
- void *mem;
+ INIT_LIST_HEAD(&tlv_copy->list);
+ memcpy(&tlv_copy->tlv, tlv, sizeof(*tlv) + len);
- if (!size[i])
- continue;
+ if (!dbg_cfg->list.next)
+ INIT_LIST_HEAD(&dbg_cfg->list);
- mem = kzalloc(size[i], GFP_KERNEL);
+ list_add_tail(&tlv_copy->list, &dbg_cfg->list);
- if (!mem) {
- IWL_ERR(trans, "No memory for apply point %d\n", i);
- return;
- }
+ trans->dbg.ini_valid = true;
+}
- if (ext) {
- trans->dbg.apply_points_ext[i].data = mem;
- trans->dbg.apply_points_ext[i].size = size[i];
- } else {
- trans->dbg.apply_points[i].data = mem;
- trans->dbg.apply_points[i].size = size[i];
- }
+static void iwl_dbg_tlv_free_list(struct list_head *list)
+{
+ if (!list || !list->next)
+ return;
- trans->dbg.ini_valid = true;
+ while (!list_empty(list)) {
+ struct iwl_apply_point_data *node =
+ list_entry(list->next, typeof(*node), list);
+
+ list_del(&node->list);
+ kfree(node);
}
}
int i;
for (i = 0; i < ARRAY_SIZE(trans->dbg.apply_points); i++) {
- kfree(trans->dbg.apply_points[i].data);
- trans->dbg.apply_points[i].size = 0;
- trans->dbg.apply_points[i].offset = 0;
+ struct iwl_apply_point_data *data;
+
+ data = &trans->dbg.apply_points[i];
+ iwl_dbg_tlv_free_list(&data->list);
- kfree(trans->dbg.apply_points_ext[i].data);
- trans->dbg.apply_points_ext[i].size = 0;
- trans->dbg.apply_points_ext[i].offset = 0;
+ data = &trans->dbg.apply_points_ext[i];
+ iwl_dbg_tlv_free_list(&data->list);
}
}
if (res)
return;
- iwl_dbg_tlv_alloc(trans, fw->size, fw->data, true);
iwl_dbg_tlv_parse_bin(trans, fw->data, fw->size);
trans->dbg.external_ini_loaded = true;