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

Commit 04de6c6c authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo
Browse files

ath10k: implement diag data container event



Some firmware revisions may report this event as
part of their diagnostics.

This avoids `unknown event` warnings and adds
tracing for the event.

Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 6d481616
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -453,6 +453,47 @@ TRACE_EVENT(ath10k_htt_rx_desc,
	 )
);

TRACE_EVENT(ath10k_wmi_diag_container,
	    TP_PROTO(struct ath10k *ar,
		     u8 type,
		     u32 timestamp,
		     u32 code,
		     u16 len,
		     const void *data),

	TP_ARGS(ar, type, timestamp, code, len, data),

	TP_STRUCT__entry(
		__string(device, dev_name(ar->dev))
		__string(driver, dev_driver_string(ar->dev))
		__field(u8, type)
		__field(u32, timestamp)
		__field(u32, code)
		__field(u16, len)
		__dynamic_array(u8, data, len)
	),

	TP_fast_assign(
		__assign_str(device, dev_name(ar->dev));
		__assign_str(driver, dev_driver_string(ar->dev));
		__entry->type = type;
		__entry->timestamp = timestamp;
		__entry->code = code;
		__entry->len = len;
		memcpy(__get_dynamic_array(data), data, len);
	),

	TP_printk(
		"%s %s diag container type %hhu timestamp %u code %u len %d",
		__get_str(driver),
		__get_str(device),
		__entry->type,
		__entry->timestamp,
		__entry->code,
		__entry->len
	)
);

#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/

/* we don't want to use include/trace/events */
+68 −0
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
		= { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
	[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
		= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
	[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
};

static int
@@ -203,6 +205,69 @@ static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
	return 0;
}

static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
					  struct sk_buff *skb)
{
	const void **tb;
	const struct wmi_tlv_diag_data_ev *ev;
	const struct wmi_tlv_diag_item *item;
	const void *data;
	int ret, num_items, len;

	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
	if (IS_ERR(tb)) {
		ret = PTR_ERR(tb);
		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
		return ret;
	}

	ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
	if (!ev || !data) {
		kfree(tb);
		return -EPROTO;
	}

	num_items = __le32_to_cpu(ev->num_items);
	len = ath10k_wmi_tlv_len(data);

	while (num_items--) {
		if (len == 0)
			break;
		if (len < sizeof(*item)) {
			ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
			break;
		}

		item = data;

		if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
			ath10k_warn(ar, "failed to parse diag data: item is too long\n");
			break;
		}

		trace_ath10k_wmi_diag_container(ar,
						item->type,
						__le32_to_cpu(item->timestamp),
						__le32_to_cpu(item->code),
						__le16_to_cpu(item->len),
						item->payload);

		len -= sizeof(*item);
		len -= roundup(__le16_to_cpu(item->len), 4);

		data += sizeof(*item);
		data += roundup(__le16_to_cpu(item->len), 4);
	}

	if (num_items != -1 || len != 0)
		ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
			    num_items, len);

	kfree(tb);
	return 0;
}

/***********/
/* TLV ops */
/***********/
@@ -318,6 +383,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
	case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
		ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
		break;
	case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
		ath10k_wmi_tlv_event_diag_data(ar, skb);
		break;
	default:
		ath10k_warn(ar, "Unknown eventid: %d\n", id);
		break;
+19 −0
Original line number Diff line number Diff line
@@ -1409,6 +1409,25 @@ struct wmi_tlv_p2p_go_bcn_ie {
	__le32 ie_len;
} __packed;

enum wmi_tlv_diag_item_type {
	WMI_TLV_DIAG_ITEM_TYPE_FW_EVENT,
	WMI_TLV_DIAG_ITEM_TYPE_FW_LOG,
	WMI_TLV_DIAG_ITEM_TYPE_FW_DEBUG_MSG,
};

struct wmi_tlv_diag_item {
	u8 type;
	u8 reserved;
	__le16 len;
	__le32 timestamp;
	__le32 code;
	u8 payload[0];
} __packed;

struct wmi_tlv_diag_data_ev {
	__le32 num_items;
} __packed;

void ath10k_wmi_tlv_attach(struct ath10k *ar);

#endif