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: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
committed by
Kalle Valo
parent
7cc4573e85
commit
c1a4654a8c
@@ -45,6 +45,8 @@ struct wmi_ops {
|
|||||||
struct wmi_rdy_ev_arg *arg);
|
struct wmi_rdy_ev_arg *arg);
|
||||||
int (*pull_fw_stats)(struct ath10k *ar, struct sk_buff *skb,
|
int (*pull_fw_stats)(struct ath10k *ar, struct sk_buff *skb,
|
||||||
struct ath10k_fw_stats *stats);
|
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_suspend)(struct ath10k *ar, u32 suspend_opt);
|
||||||
struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
|
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);
|
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
|
static inline int
|
||||||
ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
|||||||
= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
|
= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
|
||||||
[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
|
[WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT]
|
||||||
= { .min_len = sizeof(struct wmi_tlv_p2p_noa_ev) },
|
= { .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
|
static int
|
||||||
@@ -1059,6 +1061,35 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
|
|||||||
return 0;
|
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 *
|
static struct sk_buff *
|
||||||
ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
|
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_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
|
||||||
.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
|
.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
|
||||||
.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
|
.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_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
|
||||||
.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
|
.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
|
||||||
|
|||||||
@@ -1458,6 +1458,12 @@ struct wmi_tlv_p2p_noa_ev {
|
|||||||
__le32 vdev_id;
|
__le32 vdev_id;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct wmi_tlv_roam_ev {
|
||||||
|
__le32 vdev_id;
|
||||||
|
__le32 reason;
|
||||||
|
__le32 rssi;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
void ath10k_wmi_tlv_attach(struct ath10k *ar);
|
void ath10k_wmi_tlv_attach(struct ath10k *ar);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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)
|
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)
|
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;
|
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)
|
int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct wmi_rdy_ev_arg arg = {};
|
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_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
|
||||||
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
|
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
|
||||||
.pull_fw_stats = ath10k_wmi_main_op_pull_fw_stats,
|
.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_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||||
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
|
.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_swba = ath10k_wmi_op_pull_swba_ev,
|
||||||
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
|
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
|
||||||
.pull_rdy = ath10k_wmi_op_pull_rdy_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_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||||
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
|
.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_swba = ath10k_wmi_op_pull_swba_ev,
|
||||||
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
|
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
|
||||||
.pull_rdy = ath10k_wmi_op_pull_rdy_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_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||||
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
|
.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_swba = ath10k_wmi_op_pull_swba_ev,
|
||||||
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
|
.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
|
||||||
.pull_rdy = ath10k_wmi_op_pull_rdy_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_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||||
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
|
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
|
||||||
|
|||||||
@@ -4769,6 +4769,22 @@ struct wmi_dbglog_cfg_cmd {
|
|||||||
__le32 config_valid;
|
__le32 config_valid;
|
||||||
} __packed;
|
} __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_MIN 540
|
||||||
#define ATH10K_FRAGMT_THRESHOLD_MAX 2346
|
#define ATH10K_FRAGMT_THRESHOLD_MAX 2346
|
||||||
|
|
||||||
@@ -4857,6 +4873,12 @@ struct wmi_rdy_ev_arg {
|
|||||||
const u8 *mac_addr;
|
const u8 *mac_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wmi_roam_ev_arg {
|
||||||
|
__le32 vdev_id;
|
||||||
|
__le32 reason;
|
||||||
|
__le32 rssi;
|
||||||
|
};
|
||||||
|
|
||||||
struct wmi_pdev_temperature_event {
|
struct wmi_pdev_temperature_event {
|
||||||
/* temperature value in Celcius degree */
|
/* temperature value in Celcius degree */
|
||||||
__le32 temperature;
|
__le32 temperature;
|
||||||
|
|||||||
Reference in New Issue
Block a user