Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2e640d4 authored by Johannes Berg's avatar Johannes Berg Committed by Reinette Chatre
Browse files

iwlagn: use firmware event/error log information



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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
parent 9c5ac091
Loading
Loading
Loading
Loading
+90 −12
Original line number Diff line number Diff line
@@ -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,
@@ -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;
		}
@@ -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) */
@@ -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,
@@ -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);
@@ -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,
@@ -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;
+9 −0
Original line number Diff line number Diff line
@@ -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 {
@@ -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
	};