Skip to content

Commit

Permalink
iwlwifi: yoyo: fw debug config from context info and preset
Browse files Browse the repository at this point in the history
Add new TLV for debug config set to read preset
based on TLV is set in context info.
This is needed to set the preset based on ucode in early
trigger point.
Add DRAM frag allocation info in first fragment of
DBGC1 with all details.
New capability from FW for DBGC frag debug support is
added and BUFFER_ALLOCATION_CMD is disabled in capability
is supported.

Signed-off-by: Mukesh Sisodiya <mukesh.sisodiya@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20211017123741.cacf0babc521.If3704b5fda09b344e3e438252360898a3f2e90fa@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
  • Loading branch information
Mukesh Sisodiya authored and Luca Coelho committed Oct 22, 2021
1 parent bd8b5f3 commit f21baf2
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 5 deletions.
56 changes: 56 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,62 @@ struct iwl_fw_ini_hcmd_tlv {
struct iwl_fw_ini_hcmd hcmd;
} __packed; /* FW_TLV_DEBUG_HCMD_API_S_VER_1 */

/**
* struct iwl_fw_ini_conf_tlv - preset configuration TLV
*
* @address: the base address
* @value: value to set at address
*/
struct iwl_fw_ini_addr_val {
__le32 address;
__le32 value;
} __packed; /* FW_TLV_DEBUG_ADDR_VALUE_VER_1 */

/**
* struct iwl_fw_ini_conf_tlv - configuration TLV to set register/memory.
*
* @hdr: debug header
* @time_point: time point to apply config. One of &enum iwl_fw_ini_time_point
* @set_type: write access type preset token for time point.
* one of &enum iwl_fw_ini_config_set_type
* @addr_offset: the offset to add to any item in address[0] field
* @addr_val: address value pair
*/
struct iwl_fw_ini_conf_set_tlv {
struct iwl_fw_ini_header hdr;
__le32 time_point;
__le32 set_type;
__le32 addr_offset;
struct iwl_fw_ini_addr_val addr_val[0];
} __packed; /* FW_TLV_DEBUG_CONFIG_SET_API_S_VER_1 */

/**
* enum iwl_fw_ini_config_set_type
*
* @IWL_FW_INI_CONFIG_SET_TYPE_INVALID: invalid config set
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: for PERIPHERY MAC configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY: for PERIPHERY PHY configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX: for PERIPHERY AUX configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: for DEVICE MEMORY configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_CSR: for CSR configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: for DBGC_DRAM_ADDR configuration
* @IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: for PERIPH SCRATCH HWM configuration
* @IWL_FW_INI_ALLOCATION_NUM: max number of configuration supported
*/

enum iwl_fw_ini_config_set_type {
IWL_FW_INI_CONFIG_SET_TYPE_INVALID = 0,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX,
IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY,
IWL_FW_INI_CONFIG_SET_TYPE_CSR,
IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR,
IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM,
IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM,
} __packed;

/**
* enum iwl_fw_ini_allocation_id
*
Expand Down
18 changes: 18 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,24 @@ struct iwl_buf_alloc_cmd {
struct iwl_buf_alloc_frag frags[BUF_ALLOC_MAX_NUM_FRAGS];
} __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_2 */

#define DRAM_INFO_FIRST_MAGIC_WORD 0x76543210
#define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF

/**
* struct iwL_dram_info - DRAM fragments allocation struct
*
* Driver will fill in the first 1K(+) of the pointed DRAM fragment
*
* @first_word: magic word value
* @second_word: magic word value
* @framfrags: DRAM fragmentaion detail
*/
struct iwl_dram_info {
__le32 first_word;
__le32 second_word;
struct iwl_buf_alloc_cmd dram_frags[IWL_FW_INI_ALLOCATION_NUM - 1];
} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */

/**
* struct iwl_dbg_host_event_cfg_cmd
* @enabled_severities: enabled severities
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_TLV_DEBUG_BASE + 2,
IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_TLV_DEBUG_BASE + 3,
IWL_UCODE_TLV_TYPE_TRIGGERS = IWL_UCODE_TLV_DEBUG_BASE + 4,
IWL_UCODE_TLV_TYPE_CONF_SET = IWL_UCODE_TLV_DEBUG_BASE + 5,
IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_TRIGGERS,

/* TLVs 0x1000-0x2000 are for internal driver usage */
Expand Down Expand Up @@ -453,6 +454,7 @@ enum iwl_ucode_tlv_capa {

IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT = (__force iwl_ucode_tlv_capa_t)100,
IWL_UCODE_TLV_CAPA_RFIM_SUPPORT = (__force iwl_ucode_tlv_capa_t)102,
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT = (__force iwl_ucode_tlv_capa_t)104,

#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ struct iwl_prph_scratch_pnvm_cfg {
* struct iwl_prph_scratch_hwm_cfg - hwm config
* @hwm_base_addr: hwm start address
* @hwm_size: hwm size in DWs
* @reserved: reserved
* @debug_token_config: debug preset
*/
struct iwl_prph_scratch_hwm_cfg {
__le64 hwm_base_addr;
__le32 hwm_size;
__le32 reserved;
__le32 debug_token_config;
} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */

/*
Expand Down
158 changes: 157 additions & 1 deletion drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* @IWL_DBG_TLV_TYPE_HCMD: host command TLV
* @IWL_DBG_TLV_TYPE_REGION: region TLV
* @IWL_DBG_TLV_TYPE_TRIGGER: trigger TLV
* @IWL_DBG_TLV_TYPE_CONF_SET: conf set TLV
* @IWL_DBG_TLV_TYPE_NUM: number of debug TLVs
*/
enum iwl_dbg_tlv_type {
Expand All @@ -25,6 +26,7 @@ enum iwl_dbg_tlv_type {
IWL_DBG_TLV_TYPE_HCMD,
IWL_DBG_TLV_TYPE_REGION,
IWL_DBG_TLV_TYPE_TRIGGER,
IWL_DBG_TLV_TYPE_CONF_SET,
IWL_DBG_TLV_TYPE_NUM,
};

Expand Down Expand Up @@ -59,6 +61,7 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
[IWL_DBG_TLV_TYPE_HCMD] = {.min_ver = 1, .max_ver = 1,},
[IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 2,},
[IWL_DBG_TLV_TYPE_TRIGGER] = {.min_ver = 1, .max_ver = 1,},
[IWL_DBG_TLV_TYPE_CONF_SET] = {.min_ver = 1, .max_ver = 1,},
};

static int iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv,
Expand Down Expand Up @@ -260,13 +263,45 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
return ret;
}

static int iwl_dbg_tlv_config_set(struct iwl_trans *trans,
const struct iwl_ucode_tlv *tlv)
{
struct iwl_fw_ini_conf_set_tlv *conf_set = (void *)tlv->data;
u32 tp = le32_to_cpu(conf_set->time_point);
u32 type = le32_to_cpu(conf_set->set_type);

if (tp <= IWL_FW_INI_TIME_POINT_INVALID ||
tp >= IWL_FW_INI_TIME_POINT_NUM) {
IWL_DEBUG_FW(trans,
"WRT: Invalid time point %u for config set TLV\n", tp);
return -EINVAL;
}

if (type <= IWL_FW_INI_CONFIG_SET_TYPE_INVALID ||
type >= IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM) {
IWL_DEBUG_FW(trans,
"WRT: Invalid config set type %u for config set TLV\n", type);
return -EINVAL;
}

if (type != IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM ||
trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) {
IWL_DEBUG_FW(trans,
"WRT: Config set type %u is not supported\n", type);
return -EINVAL;
}

return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list);
}

static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,
const struct iwl_ucode_tlv *tlv) = {
[IWL_DBG_TLV_TYPE_DEBUG_INFO] = iwl_dbg_tlv_alloc_debug_info,
[IWL_DBG_TLV_TYPE_BUF_ALLOC] = iwl_dbg_tlv_alloc_buf_alloc,
[IWL_DBG_TLV_TYPE_HCMD] = iwl_dbg_tlv_alloc_hcmd,
[IWL_DBG_TLV_TYPE_REGION] = iwl_dbg_tlv_alloc_region,
[IWL_DBG_TLV_TYPE_TRIGGER] = iwl_dbg_tlv_alloc_trigger,
[IWL_DBG_TLV_TYPE_CONF_SET] = iwl_dbg_tlv_config_set,
};

void iwl_dbg_tlv_alloc(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv,
Expand Down Expand Up @@ -399,6 +434,13 @@ void iwl_dbg_tlv_free(struct iwl_trans *trans)
list_del(&tlv_node->list);
kfree(tlv_node);
}

list_for_each_entry_safe(tlv_node, tlv_node_tmp,
&tp->config_list, list) {
list_del(&tlv_node->list);
kfree(tlv_node);
}

}

for (i = 0; i < ARRAY_SIZE(trans->dbg.fw_mon_ini); i++)
Expand Down Expand Up @@ -466,6 +508,7 @@ void iwl_dbg_tlv_init(struct iwl_trans *trans)
INIT_LIST_HEAD(&tp->trig_list);
INIT_LIST_HEAD(&tp->hcmd_list);
INIT_LIST_HEAD(&tp->active_trig_list);
INIT_LIST_HEAD(&tp->config_list);
}
}

Expand Down Expand Up @@ -649,6 +692,10 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)
{
int ret, i;

if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))
return;

for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {
ret = iwl_dbg_tlv_apply_buffer(fwrt, i);
if (ret)
Expand All @@ -658,6 +705,87 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)
}
}

static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt,
enum iwl_fw_ini_allocation_id alloc_id,
struct iwl_dram_info *dram_info)
{
struct iwl_fw_mon *fw_mon;
u32 remain_frags, num_frags;
int j, fw_mon_idx = 0;
struct iwl_buf_alloc_cmd *data;

if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) !=
IWL_FW_INI_LOCATION_DRAM_PATH) {
IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id);
return -1;
}

fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];

/* the first fragment of DBGC1 is given to the FW via register
* or context info
*/
if (alloc_id == IWL_FW_INI_ALLOCATION_ID_DBGC1)
fw_mon_idx++;

remain_frags = fw_mon->num_frags - fw_mon_idx;
if (!remain_frags)
return -1;

num_frags = min_t(u32, remain_frags, BUF_ALLOC_MAX_NUM_FRAGS);
data = &dram_info->dram_frags[alloc_id - 1];
data->alloc_id = cpu_to_le32(alloc_id);
data->num_frags = cpu_to_le32(num_frags);
data->buf_location = cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH);

IWL_DEBUG_FW(fwrt, "WRT: DRAM buffer details alloc_id=%u, num_frags=%u\n",
cpu_to_le32(alloc_id), cpu_to_le32(num_frags));

for (j = 0; j < num_frags; j++) {
struct iwl_buf_alloc_frag *frag = &data->frags[j];
struct iwl_dram_data *fw_mon_frag = &fw_mon->frags[fw_mon_idx++];

frag->addr = cpu_to_le64(fw_mon_frag->physical);
frag->size = cpu_to_le32(fw_mon_frag->size);
IWL_DEBUG_FW(fwrt, "WRT: DRAM fragment details\n");
IWL_DEBUG_FW(fwrt, "frag=%u, addr=0x%016llx, size=0x%x)\n",
j, cpu_to_le64(fw_mon_frag->physical),
cpu_to_le32(fw_mon_frag->size));
}
return 0;
}

static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
{
int ret, i, dram_alloc = 0;
struct iwl_dram_info dram_info;
struct iwl_dram_data *frags =
&fwrt->trans->dbg.fw_mon_ini[IWL_FW_INI_ALLOCATION_ID_DBGC1].frags[0];

if (!fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))
return;

dram_info.first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD);
dram_info.second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);

for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1;
i <= IWL_FW_INI_ALLOCATION_ID_DBGC3; i++) {
ret = iwl_dbg_tlv_update_dram(fwrt, i, &dram_info);
if (!ret)
dram_alloc++;
else
IWL_WARN(fwrt,
"WRT: Failed to set DRAM buffer for alloc id %d, ret=%d\n",
i, ret);
}
if (dram_alloc) {
memcpy(frags->block, &dram_info, sizeof(dram_info));
IWL_DEBUG_FW(fwrt, "block data after %016x\n",
*((int *)fwrt->trans->dbg.fw_mon_ini[1].frags[0].block));
}
}

static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
struct list_head *hcmd_list)
{
Expand All @@ -677,6 +805,31 @@ static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
}
}

static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
struct list_head *config_list)
{
struct iwl_dbg_tlv_node *node;

list_for_each_entry(node, config_list, list) {
struct iwl_fw_ini_conf_set_tlv *config_list = (void *)node->tlv.data;
u32 type = le32_to_cpu(config_list->set_type);

switch (type) {
case IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: {
u32 debug_token_config =
le32_to_cpu(config_list->addr_val[0].value);

IWL_DEBUG_FW(fwrt, "WRT: Setting HWM debug token config: %u\n",
debug_token_config);
fwrt->trans->dbg.ucode_preset = debug_token_config;
break;
}
default:
break;
}
}
}

static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t)
{
struct iwl_dbg_tlv_timer_node *timer_node =
Expand Down Expand Up @@ -1051,7 +1204,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
union iwl_dbg_tlv_tp_data *tp_data,
bool sync)
{
struct list_head *hcmd_list, *trig_list;
struct list_head *hcmd_list, *trig_list, *conf_list;

if (!iwl_trans_dbg_ini_valid(fwrt->trans) ||
tp_id == IWL_FW_INI_TIME_POINT_INVALID ||
Expand All @@ -1060,10 +1213,13 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,

hcmd_list = &fwrt->trans->dbg.time_point[tp_id].hcmd_list;
trig_list = &fwrt->trans->dbg.time_point[tp_id].active_trig_list;
conf_list = &fwrt->trans->dbg.time_point[tp_id].config_list;

switch (tp_id) {
case IWL_FW_INI_TIME_POINT_EARLY:
iwl_dbg_tlv_init_cfg(fwrt);
iwl_dbg_tlv_apply_config(fwrt, conf_list);
iwl_dbg_tlv_update_drams(fwrt);
iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
break;
case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ union iwl_dbg_tlv_tp_data {
* @trig_list: list of triggers
* @active_trig_list: list of active triggers
* @hcmd_list: list of host commands
* @config_list: list of configuration
*/
struct iwl_dbg_tlv_time_point_data {
struct list_head trig_list;
struct list_head active_trig_list;
struct list_head hcmd_list;
struct list_head config_list;
};

struct iwl_trans;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/intel/iwlwifi/iwl-drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
case IWL_UCODE_TLV_TYPE_HCMD:
case IWL_UCODE_TLV_TYPE_REGIONS:
case IWL_UCODE_TLV_TYPE_TRIGGERS:
case IWL_UCODE_TLV_TYPE_CONF_SET:
if (iwlwifi_mod_params.enable_ini)
iwl_dbg_tlv_alloc(drv->trans, tlv, false);
break;
Expand Down
Loading

0 comments on commit f21baf2

Please sign in to comment.