mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-05-31 03:28:21 +00:00
iwlwifi: dbg_ini: implement monitor allocation flow
Allow allocating fragmented buffers for several allocation IDs. Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
cf29c5b66b
commit
14124b2578
1 changed files with 248 additions and 1 deletions
|
@ -314,6 +314,34 @@ void iwl_dbg_tlv_del_timers(struct iwl_trans *trans)
|
|||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_dbg_tlv_del_timers);
|
||||
|
||||
static void iwl_dbg_tlv_fragments_free(struct iwl_trans *trans,
|
||||
enum iwl_fw_ini_allocation_id alloc_id)
|
||||
{
|
||||
struct iwl_fw_mon *fw_mon;
|
||||
int i;
|
||||
|
||||
if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return;
|
||||
|
||||
fw_mon = &trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
for (i = 0; i < fw_mon->num_frags; i++) {
|
||||
struct iwl_dram_data *frag = &fw_mon->frags[i];
|
||||
|
||||
dma_free_coherent(trans->dev, frag->size, frag->block,
|
||||
frag->physical);
|
||||
|
||||
frag->physical = 0;
|
||||
frag->block = NULL;
|
||||
frag->size = 0;
|
||||
}
|
||||
|
||||
kfree(fw_mon->frags);
|
||||
fw_mon->frags = NULL;
|
||||
fw_mon->num_frags = 0;
|
||||
}
|
||||
|
||||
void iwl_dbg_tlv_free(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_dbg_tlv_node *tlv_node, *tlv_node_tmp;
|
||||
|
@ -357,6 +385,9 @@ void iwl_dbg_tlv_free(struct iwl_trans *trans)
|
|||
kfree(tlv_node);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trans->dbg.fw_mon_ini); i++)
|
||||
iwl_dbg_tlv_fragments_free(trans, i);
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_parse_bin(struct iwl_trans *trans, const u8 *data,
|
||||
|
@ -418,6 +449,187 @@ void iwl_dbg_tlv_init(struct iwl_trans *trans)
|
|||
}
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_fragment(struct iwl_fw_runtime *fwrt,
|
||||
struct iwl_dram_data *frag, u32 pages)
|
||||
{
|
||||
void *block = NULL;
|
||||
dma_addr_t physical;
|
||||
|
||||
if (!frag || frag->size || !pages)
|
||||
return -EIO;
|
||||
|
||||
while (pages) {
|
||||
block = dma_alloc_coherent(fwrt->dev, pages * PAGE_SIZE,
|
||||
&physical,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (block)
|
||||
break;
|
||||
|
||||
IWL_WARN(fwrt, "WRT: Failed to allocate fragment size %lu\n",
|
||||
pages * PAGE_SIZE);
|
||||
|
||||
pages = DIV_ROUND_UP(pages, 2);
|
||||
}
|
||||
|
||||
if (!block)
|
||||
return -ENOMEM;
|
||||
|
||||
frag->physical = physical;
|
||||
frag->block = block;
|
||||
frag->size = pages * PAGE_SIZE;
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_allocation_id alloc_id)
|
||||
{
|
||||
struct iwl_fw_mon *fw_mon;
|
||||
struct iwl_fw_ini_allocation_tlv *fw_mon_cfg;
|
||||
u32 num_frags, remain_pages, frag_pages;
|
||||
int i;
|
||||
|
||||
if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return -EIO;
|
||||
|
||||
fw_mon_cfg = &fwrt->trans->dbg.fw_mon_cfg[alloc_id];
|
||||
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
|
||||
|
||||
if (fw_mon->num_frags ||
|
||||
fw_mon_cfg->buf_location !=
|
||||
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH))
|
||||
return 0;
|
||||
|
||||
num_frags = le32_to_cpu(fw_mon_cfg->max_frags_num);
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP)) {
|
||||
if (alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1)
|
||||
return -EIO;
|
||||
num_frags = 1;
|
||||
}
|
||||
|
||||
remain_pages = DIV_ROUND_UP(le32_to_cpu(fw_mon_cfg->req_size),
|
||||
PAGE_SIZE);
|
||||
num_frags = min_t(u32, num_frags, BUF_ALLOC_MAX_NUM_FRAGS);
|
||||
num_frags = min_t(u32, num_frags, remain_pages);
|
||||
frag_pages = DIV_ROUND_UP(remain_pages, num_frags);
|
||||
|
||||
fw_mon->frags = kcalloc(num_frags, sizeof(*fw_mon->frags), GFP_KERNEL);
|
||||
if (!fw_mon->frags)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_frags; i++) {
|
||||
int pages = min_t(u32, frag_pages, remain_pages);
|
||||
|
||||
IWL_DEBUG_FW(fwrt,
|
||||
"WRT: Allocating DRAM buffer (alloc_id=%u, fragment=%u, size=0x%lx)\n",
|
||||
alloc_id, i, pages * PAGE_SIZE);
|
||||
|
||||
pages = iwl_dbg_tlv_alloc_fragment(fwrt, &fw_mon->frags[i],
|
||||
pages);
|
||||
if (pages < 0) {
|
||||
u32 alloc_size = le32_to_cpu(fw_mon_cfg->req_size) -
|
||||
(remain_pages * PAGE_SIZE);
|
||||
|
||||
if (alloc_size < le32_to_cpu(fw_mon_cfg->min_size)) {
|
||||
iwl_dbg_tlv_fragments_free(fwrt->trans,
|
||||
alloc_id);
|
||||
return pages;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
remain_pages -= pages;
|
||||
fw_mon->num_frags++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_dbg_tlv_apply_buffer(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_allocation_id alloc_id)
|
||||
{
|
||||
struct iwl_fw_mon *fw_mon;
|
||||
u32 remain_frags, num_commands;
|
||||
int i, fw_mon_idx = 0;
|
||||
|
||||
if (!fw_has_capa(&fwrt->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP))
|
||||
return 0;
|
||||
|
||||
if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID ||
|
||||
alloc_id >= IWL_FW_INI_ALLOCATION_NUM)
|
||||
return -EIO;
|
||||
|
||||
if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) !=
|
||||
IWL_FW_INI_LOCATION_DRAM_PATH)
|
||||
return 0;
|
||||
|
||||
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 0;
|
||||
|
||||
num_commands = DIV_ROUND_UP(remain_frags, BUF_ALLOC_MAX_NUM_FRAGS);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Applying DRAM destination (alloc_id=%u)\n",
|
||||
alloc_id);
|
||||
|
||||
for (i = 0; i < num_commands; i++) {
|
||||
u32 num_frags = min_t(u32, remain_frags,
|
||||
BUF_ALLOC_MAX_NUM_FRAGS);
|
||||
struct iwl_buf_alloc_cmd data = {
|
||||
.alloc_id = cpu_to_le32(alloc_id),
|
||||
.num_frags = cpu_to_le32(num_frags),
|
||||
.buf_location =
|
||||
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH),
|
||||
};
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = WIDE_ID(DEBUG_GROUP, BUFFER_ALLOCATION),
|
||||
.data[0] = &data,
|
||||
.len[0] = sizeof(data),
|
||||
};
|
||||
int ret, j;
|
||||
|
||||
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);
|
||||
}
|
||||
ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
remain_frags -= num_frags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {
|
||||
ret = iwl_dbg_tlv_apply_buffer(fwrt, i);
|
||||
if (ret)
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: Failed to apply DRAM buffer for allocation id %d, ret=%d\n",
|
||||
i, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
|
||||
struct list_head *hcmd_list)
|
||||
{
|
||||
|
@ -670,6 +882,36 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
enum iwl_fw_ini_buffer_location *ini_dest = &fwrt->trans->dbg.ini_dest;
|
||||
int ret, i;
|
||||
|
||||
iwl_dbg_tlv_gen_active_trigs(fwrt, IWL_FW_DBG_DOMAIN);
|
||||
|
||||
*ini_dest = IWL_FW_INI_LOCATION_INVALID;
|
||||
for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {
|
||||
struct iwl_fw_ini_allocation_tlv *fw_mon_cfg =
|
||||
&fwrt->trans->dbg.fw_mon_cfg[i];
|
||||
u32 dest = le32_to_cpu(fw_mon_cfg->buf_location);
|
||||
|
||||
if (dest == IWL_FW_INI_LOCATION_INVALID)
|
||||
continue;
|
||||
|
||||
if (*ini_dest == IWL_FW_INI_LOCATION_INVALID)
|
||||
*ini_dest = dest;
|
||||
|
||||
if (dest != *ini_dest)
|
||||
continue;
|
||||
|
||||
ret = iwl_dbg_tlv_alloc_fragments(fwrt, i);
|
||||
if (ret)
|
||||
IWL_WARN(fwrt,
|
||||
"WRT: Failed to allocate DRAM buffer for allocation id %d, ret=%d\n",
|
||||
i, ret);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
||||
enum iwl_fw_ini_time_point tp_id,
|
||||
union iwl_dbg_tlv_tp_data *tp_data)
|
||||
|
@ -686,7 +928,12 @@ void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
switch (tp_id) {
|
||||
case IWL_FW_INI_TIME_POINT_EARLY:
|
||||
iwl_dbg_tlv_gen_active_trigs(fwrt, IWL_FW_DBG_DOMAIN);
|
||||
iwl_dbg_tlv_init_cfg(fwrt);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, trig_list, tp_data, NULL);
|
||||
break;
|
||||
case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
|
||||
iwl_dbg_tlv_apply_buffers(fwrt);
|
||||
iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
|
||||
iwl_dbg_tlv_tp_trigger(fwrt, trig_list, tp_data, NULL);
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Add table
Reference in a new issue