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

Commit 54b0af83 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "UPSTREAM: ath10k: check power save support in STA mode through FW IE"

parents 4d044fea 7de992d7
Loading
Loading
Loading
Loading
+34 −7
Original line number Diff line number Diff line
@@ -377,6 +377,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
	[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
	[ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
	[ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast",
	[ATH10K_FW_FEATURE_NO_PS] = "no-ps",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
@@ -847,6 +848,28 @@ static int ath10k_core_check_smbios(struct ath10k *ar)
	return 0;
}

static int ath10k_core_check_dt(struct ath10k *ar)
{
	struct device_node *node;
	const char *variant = NULL;

	node = ar->dev->of_node;
	if (!node)
		return -ENOENT;

	of_property_read_string(node, "qcom,ath10k-calibration-variant",
				&variant);
	if (!variant)
		return -ENODATA;

	if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0)
		ath10k_dbg(ar, ATH10K_DBG_BOOT,
			   "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
			    variant);

	return 0;
}

static int ath10k_download_and_run_otp(struct ath10k *ar)
{
	u32 result, address = ar->hw_params.patch_load_addr;
@@ -1218,19 +1241,19 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
	/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
	char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };

	if (ar->id.bdf_ext[0] != '\0')
		scnprintf(variant, sizeof(variant), ",variant=%s",
			  ar->id.bdf_ext);

	if (ar->id.bmi_ids_valid) {
		scnprintf(name, name_len,
			  "bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
			  "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s",
			  ath10k_bus_str(ar->hif.bus),
			  ar->id.bmi_chip_id,
			  ar->id.bmi_board_id);
			  ar->id.bmi_board_id, variant);
		goto out;
	}

	if (ar->id.bdf_ext[0] != '\0')
		scnprintf(variant, sizeof(variant), ",variant=%s",
			  ar->id.bdf_ext);

	scnprintf(name, name_len,
		  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
		  ath10k_bus_str(ar->hif.bus),
@@ -2330,7 +2353,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar)

	ret = ath10k_core_check_smbios(ar);
	if (ret)
		ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n");
		ath10k_dbg(ar, ATH10K_DBG_BOOT, "SMBIOS bdf variant name not set.\n");

	ret = ath10k_core_check_dt(ar);
	if (ret)
		ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");

	ret = ath10k_core_fetch_board_file(ar);
	if (ret) {
+3 −0
Original line number Diff line number Diff line
@@ -610,6 +610,9 @@ enum ath10k_fw_features {
	 */
	ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16,

	/* Firmware does not support power save in station mode. */
	ATH10K_FW_FEATURE_NO_PS = 17,

	/* keep last */
	ATH10K_FW_FEATURE_COUNT,
};
+17 −1
Original line number Diff line number Diff line
@@ -51,7 +51,8 @@ enum ath10k_pktlog_filter {
	ATH10K_PKTLOG_RCFIND     = 0x000000004,
	ATH10K_PKTLOG_RCUPDATE   = 0x000000008,
	ATH10K_PKTLOG_DBG_PRINT  = 0x000000010,
	ATH10K_PKTLOG_ANY        = 0x00000001f,
	ATH10K_PKTLOG_PEER_STATS = 0x000000040,
	ATH10K_PKTLOG_ANY        = 0x00000005f,
};

enum ath10k_dbg_aggr_mode {
@@ -60,6 +61,21 @@ enum ath10k_dbg_aggr_mode {
	ATH10K_DBG_AGGR_MODE_MAX,
};

/* Types of packet log events */
enum ath_pktlog_type {
	ATH_PKTLOG_TYPE_TX_CTRL = 1,
	ATH_PKTLOG_TYPE_TX_STAT,
};

struct ath10k_pktlog_hdr {
	__le16 flags;
	__le16 missed_cnt;
	__le16 log_type; /* Type of log information foll this header */
	__le16 size; /* Size of variable length log information in bytes */
	__le32 timestamp;
	u8 payload[0];
} __packed;

/* FIXME: How to calculate the buffer size sanely? */
#define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024)

+17 −0
Original line number Diff line number Diff line
@@ -1497,6 +1497,23 @@ struct htt_peer_tx_stats {
	u8 payload[0];
} __packed;

#define ATH10K_10_2_TX_STATS_OFFSET	136
#define PEER_STATS_FOR_NO_OF_PPDUS	4

struct ath10k_10_2_peer_tx_stats {
	u8 ratecode[PEER_STATS_FOR_NO_OF_PPDUS];
	u8 success_pkts[PEER_STATS_FOR_NO_OF_PPDUS];
	__le16 success_bytes[PEER_STATS_FOR_NO_OF_PPDUS];
	u8 retry_pkts[PEER_STATS_FOR_NO_OF_PPDUS];
	__le16 retry_bytes[PEER_STATS_FOR_NO_OF_PPDUS];
	u8 failed_pkts[PEER_STATS_FOR_NO_OF_PPDUS];
	__le16 failed_bytes[PEER_STATS_FOR_NO_OF_PPDUS];
	u8 flags[PEER_STATS_FOR_NO_OF_PPDUS];
	__le32 tx_duration;
	u8 tx_ppdu_cnt;
	u8 peer_id;
} __packed;

union htt_rx_pn_t {
	/* WEP: 24-bit PN */
	u32 pn24;
+60 −0
Original line number Diff line number Diff line
@@ -2431,6 +2431,62 @@ static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
	rcu_read_unlock();
}

static void ath10k_fetch_10_2_tx_stats(struct ath10k *ar, u8 *data)
{
	struct ath10k_pktlog_hdr *hdr = (struct ath10k_pktlog_hdr *)data;
	struct ath10k_per_peer_tx_stats *p_tx_stats = &ar->peer_tx_stats;
	struct ath10k_10_2_peer_tx_stats *tx_stats;
	struct ieee80211_sta *sta;
	struct ath10k_peer *peer;
	u16 log_type = __le16_to_cpu(hdr->log_type);
	u32 peer_id = 0, i;

	if (log_type != ATH_PKTLOG_TYPE_TX_STAT)
		return;

	tx_stats = (struct ath10k_10_2_peer_tx_stats *)((hdr->payload) +
		    ATH10K_10_2_TX_STATS_OFFSET);

	if (!tx_stats->tx_ppdu_cnt)
		return;

	peer_id = tx_stats->peer_id;

	rcu_read_lock();
	spin_lock_bh(&ar->data_lock);
	peer = ath10k_peer_find_by_id(ar, peer_id);
	if (!peer) {
		ath10k_warn(ar, "Invalid peer id %d in peer stats buffer\n",
			    peer_id);
		goto out;
	}

	sta = peer->sta;
	for (i = 0; i < tx_stats->tx_ppdu_cnt; i++) {
		p_tx_stats->succ_bytes =
			__le16_to_cpu(tx_stats->success_bytes[i]);
		p_tx_stats->retry_bytes =
			__le16_to_cpu(tx_stats->retry_bytes[i]);
		p_tx_stats->failed_bytes =
			__le16_to_cpu(tx_stats->failed_bytes[i]);
		p_tx_stats->ratecode = tx_stats->ratecode[i];
		p_tx_stats->flags = tx_stats->flags[i];
		p_tx_stats->succ_pkts = tx_stats->success_pkts[i];
		p_tx_stats->retry_pkts = tx_stats->retry_pkts[i];
		p_tx_stats->failed_pkts = tx_stats->failed_pkts[i];

		ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats);
	}
	spin_unlock_bh(&ar->data_lock);
	rcu_read_unlock();

	return;

out:
	spin_unlock_bh(&ar->data_lock);
	rcu_read_unlock();
}

bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
{
	struct ath10k_htt *htt = &ar->htt;
@@ -2548,6 +2604,10 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
					skb->len -
					offsetof(struct htt_resp,
						 pktlog_msg.payload));

		if (ath10k_peer_stats_enabled(ar))
			ath10k_fetch_10_2_tx_stats(ar,
						   resp->pktlog_msg.payload);
		break;
	}
	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
Loading