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

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

ath10k: implement wmi roam event



This can be used to implement offloaded rssi
threshold, beacon miss or even automatic
in-firmware BSS roaming in the future.

Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 7cc4573e
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ struct wmi_ops {
			struct wmi_rdy_ev_arg *arg);
	int (*pull_fw_stats)(struct ath10k *ar, struct sk_buff *skb,
			     struct ath10k_fw_stats *stats);
	int (*pull_roam_ev)(struct ath10k *ar, struct sk_buff *skb,
			    struct wmi_roam_ev_arg *arg);

	struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
	struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
@@ -273,6 +275,16 @@ ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
	return ar->wmi.ops->pull_fw_stats(ar, skb, stats);
}

static inline int
ath10k_wmi_pull_roam_ev(struct ath10k *ar, struct sk_buff *skb,
			struct wmi_roam_ev_arg *arg)
{
	if (!ar->wmi.ops->pull_roam_ev)
		return -EOPNOTSUPP;

	return ar->wmi.ops->pull_roam_ev(ar, skb, arg);
}

static inline int
ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
{
+32 −0
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
	[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
		= { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
	[WMI_TLV_TAG_STRUCT_ROAM_EVENT]
		= { .min_len = sizeof(struct wmi_tlv_roam_ev) },
};

static int
@@ -1059,6 +1061,35 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
	return 0;
}

static int ath10k_wmi_tlv_op_pull_roam_ev(struct ath10k *ar,
					  struct sk_buff *skb,
					  struct wmi_roam_ev_arg *arg)
{
	const void **tb;
	const struct wmi_tlv_roam_ev *ev;
	int ret;

	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_ROAM_EVENT];
	if (!ev) {
		kfree(tb);
		return -EPROTO;
	}

	arg->vdev_id = ev->vdev_id;
	arg->reason = ev->reason;
	arg->rssi = ev->rssi;

	kfree(tb);
	return 0;
}

static struct sk_buff *
ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
{
@@ -2783,6 +2814,7 @@ static const struct wmi_ops wmi_tlv_ops = {
	.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
	.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
	.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
	.pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,

	.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+6 −0
Original line number Diff line number Diff line
@@ -1458,6 +1458,12 @@ struct wmi_tlv_p2p_noa_ev {
	__le32 vdev_id;
} __packed;

struct wmi_tlv_roam_ev {
	__le32 vdev_id;
	__le32 reason;
	__le32 rssi;
} __packed;

void ath10k_wmi_tlv_attach(struct ath10k *ar);

#endif
+54 −1
Original line number Diff line number Diff line
@@ -2789,7 +2789,41 @@ void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)

void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
{
	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n");
	struct wmi_roam_ev_arg arg = {};
	int ret;
	u32 vdev_id;
	u32 reason;
	s32 rssi;

	ret = ath10k_wmi_pull_roam_ev(ar, skb, &arg);
	if (ret) {
		ath10k_warn(ar, "failed to parse roam event: %d\n", ret);
		return;
	}

	vdev_id = __le32_to_cpu(arg.vdev_id);
	reason = __le32_to_cpu(arg.reason);
	rssi = __le32_to_cpu(arg.rssi);
	rssi += WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;

	ath10k_dbg(ar, ATH10K_DBG_WMI,
		   "wmi roam event vdev %u reason 0x%08x rssi %d\n",
		   vdev_id, reason, rssi);

	if (reason >= WMI_ROAM_REASON_MAX)
		ath10k_warn(ar, "ignoring unknown roam event reason %d on vdev %i\n",
			    reason, vdev_id);

	switch (reason) {
	case WMI_ROAM_REASON_BETTER_AP:
	case WMI_ROAM_REASON_BEACON_MISS:
	case WMI_ROAM_REASON_LOW_RSSI:
	case WMI_ROAM_REASON_SUITABLE_AP_FOUND:
	case WMI_ROAM_REASON_HO_FAILED:
		ath10k_warn(ar, "ignoring not implemented roam event reason %d on vdev %i\n",
			    reason, vdev_id);
		break;
	}
}

void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb)
@@ -3148,6 +3182,21 @@ static int ath10k_wmi_op_pull_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
	return 0;
}

static int ath10k_wmi_op_pull_roam_ev(struct ath10k *ar, struct sk_buff *skb,
				      struct wmi_roam_ev_arg *arg)
{
	struct wmi_roam_ev *ev = (void *)skb->data;

	if (skb->len < sizeof(*ev))
		return -EPROTO;

	skb_pull(skb, sizeof(*ev));
	arg->vdev_id = ev->vdev_id;
	arg->reason = ev->reason;

	return 0;
}

int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
{
	struct wmi_rdy_ev_arg arg = {};
@@ -5140,6 +5189,7 @@ static const struct wmi_ops wmi_ops = {
	.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
	.pull_fw_stats = ath10k_wmi_main_op_pull_fw_stats,
	.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,

	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
@@ -5207,6 +5257,7 @@ static const struct wmi_ops wmi_10_1_ops = {
	.pull_swba = ath10k_wmi_op_pull_swba_ev,
	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
	.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,

	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
@@ -5270,6 +5321,7 @@ static const struct wmi_ops wmi_10_2_ops = {
	.pull_swba = ath10k_wmi_op_pull_swba_ev,
	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
	.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,

	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
@@ -5330,6 +5382,7 @@ static const struct wmi_ops wmi_10_2_4_ops = {
	.pull_swba = ath10k_wmi_op_pull_swba_ev,
	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
	.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,

	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+22 −0
Original line number Diff line number Diff line
@@ -4769,6 +4769,22 @@ struct wmi_dbglog_cfg_cmd {
	__le32 config_valid;
} __packed;

enum wmi_roam_reason {
	WMI_ROAM_REASON_BETTER_AP = 1,
	WMI_ROAM_REASON_BEACON_MISS = 2,
	WMI_ROAM_REASON_LOW_RSSI = 3,
	WMI_ROAM_REASON_SUITABLE_AP_FOUND = 4,
	WMI_ROAM_REASON_HO_FAILED = 5,

	/* keep last */
	WMI_ROAM_REASON_MAX,
};

struct wmi_roam_ev {
	__le32 vdev_id;
	__le32 reason;
} __packed;

#define ATH10K_FRAGMT_THRESHOLD_MIN	540
#define ATH10K_FRAGMT_THRESHOLD_MAX	2346

@@ -4857,6 +4873,12 @@ struct wmi_rdy_ev_arg {
	const u8 *mac_addr;
};

struct wmi_roam_ev_arg {
	__le32 vdev_id;
	__le32 reason;
	__le32 rssi;
};

struct wmi_pdev_temperature_event {
	/* temperature value in Celcius degree */
	__le32 temperature;