Skip to content

Commit

Permalink
iwlagn: use firmware event/error log information
Browse files Browse the repository at this point in the history
In order to debug problems before the ALIVE
notification is received, new firmware files
contain the event/error log information in
the file. Use that information.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
  • Loading branch information
Johannes Berg authored and Reinette Chatre committed May 13, 2010
1 parent 9c5ac09 commit b2e640d
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 12 deletions.
102 changes: 90 additions & 12 deletions drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,9 @@ struct iwlagn_firmware_pieces {
size_t inst_size, data_size, init_size, init_data_size, boot_size;

u32 build;

u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
};

static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
Expand Down Expand Up @@ -1720,6 +1723,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
capa->max_probe_length =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
if (tlv_len != 4)
return -EINVAL;
pieces->init_evtlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
if (tlv_len != 4)
return -EINVAL;
pieces->init_evtlog_size =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
if (tlv_len != 4)
return -EINVAL;
pieces->init_errlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
if (tlv_len != 4)
return -EINVAL;
pieces->inst_evtlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
if (tlv_len != 4)
return -EINVAL;
pieces->inst_evtlog_size =
le32_to_cpup((__le32 *)tlv_data);
break;
case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
if (tlv_len != 4)
return -EINVAL;
pieces->inst_errlog_ptr =
le32_to_cpup((__le32 *)tlv_data);
break;
default:
break;
}
Expand Down Expand Up @@ -1912,6 +1951,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
goto err_pci_alloc;
}

/* Now that we can no longer fail, copy information */

/*
* The (size - 16) / 12 formula is based on the information recorded
* for each event, which is of mode 1 (including timestamp) for all
* new microcodes that include this information.
*/
priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr;
if (pieces.init_evtlog_size)
priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
else
priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size;
priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
if (pieces.inst_evtlog_size)
priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
else
priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;

/* Copy images into buffers for card's bus-master reads ... */

/* Runtime instructions (first block of data in file) */
Expand Down Expand Up @@ -2037,10 +2096,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
u32 blink1, blink2, ilink1, ilink2;
u32 pc, hcmd;

if (priv->ucode_type == UCODE_INIT)
if (priv->ucode_type == UCODE_INIT) {
base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
else
if (!base)
base = priv->_agn.init_errlog_ptr;
} else {
base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
if (!base)
base = priv->_agn.inst_errlog_ptr;
}

if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERR(priv,
Expand Down Expand Up @@ -2100,10 +2164,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,

if (num_events == 0)
return pos;
if (priv->ucode_type == UCODE_INIT)

if (priv->ucode_type == UCODE_INIT) {
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
else
if (!base)
base = priv->_agn.init_evtlog_ptr;
} else {
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
if (!base)
base = priv->_agn.inst_evtlog_ptr;
}

if (mode == 0)
event_size = 2 * sizeof(u32);
Expand Down Expand Up @@ -2205,13 +2275,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */
u32 size; /* # entries that we'll print */
u32 logsize;
int pos = 0;
size_t bufsz = 0;

if (priv->ucode_type == UCODE_INIT)
if (priv->ucode_type == UCODE_INIT) {
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
else
logsize = priv->_agn.init_evtlog_size;
if (!base)
base = priv->_agn.init_evtlog_ptr;
} else {
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
logsize = priv->_agn.inst_evtlog_size;
if (!base)
base = priv->_agn.inst_evtlog_ptr;
}

if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERR(priv,
Expand All @@ -2226,16 +2304,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));

if (capacity > priv->cfg->max_event_log_size) {
if (capacity > logsize) {
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
capacity, priv->cfg->max_event_log_size);
capacity = priv->cfg->max_event_log_size;
capacity, logsize);
capacity = logsize;
}

if (next_entry > priv->cfg->max_event_log_size) {
if (next_entry > logsize) {
IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
next_entry, priv->cfg->max_event_log_size);
next_entry = priv->cfg->max_event_log_size;
next_entry, logsize);
next_entry = logsize;
}

size = num_wraps ? capacity : next_entry;
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,12 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_INIT_DATA = 4,
IWL_UCODE_TLV_BOOT = 5,
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8,
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9,
IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10,
IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11,
IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12,
IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13,
};

struct iwl_ucode_tlv {
Expand Down Expand Up @@ -1317,6 +1323,9 @@ struct iwl_priv {
struct iwl_notif_statistics delta_statistics;
struct iwl_notif_statistics max_delta;
#endif

u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
} _agn;
#endif
};
Expand Down

0 comments on commit b2e640d

Please sign in to comment.