Commit 0d9b0438 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: add support for firmware newer than 636

The mgmt_rx event structure has been expanded.
Since the structure header is expanded the payload
(i.e. mgmt frame) is shifted by a few bytes. This
needs to be taken into account in order to support
both old and new firmware.

This introduces a fw_features to keep track of any
FW-related ABI/behaviour changes.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 68c8a9b2
...@@ -270,6 +270,14 @@ enum ath10k_state { ...@@ -270,6 +270,14 @@ enum ath10k_state {
ATH10K_STATE_WEDGED, ATH10K_STATE_WEDGED,
}; };
enum ath10k_fw_features {
/* wmi_mgmt_rx_hdr contains extra RSSI information */
ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
struct ath10k { struct ath10k {
struct ath_common ath_common; struct ath_common ath_common;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
...@@ -288,6 +296,8 @@ struct ath10k { ...@@ -288,6 +296,8 @@ struct ath10k {
u32 vht_cap_info; u32 vht_cap_info;
u32 num_rf_chains; u32 num_rf_chains;
DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
struct targetdef *targetdef; struct targetdef *targetdef;
struct hostdef *hostdef; struct hostdef *hostdef;
......
...@@ -316,7 +316,9 @@ static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band) ...@@ -316,7 +316,9 @@ static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band)
static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_mgmt_rx_event *event = (struct wmi_mgmt_rx_event *)skb->data; struct wmi_mgmt_rx_event_v1 *ev_v1;
struct wmi_mgmt_rx_event_v2 *ev_v2;
struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
u32 rx_status; u32 rx_status;
...@@ -326,13 +328,24 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -326,13 +328,24 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
u32 rate; u32 rate;
u32 buf_len; u32 buf_len;
u16 fc; u16 fc;
int pull_len;
if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
ev_hdr = &ev_v2->hdr.v1;
pull_len = sizeof(*ev_v2);
} else {
ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data;
ev_hdr = &ev_v1->hdr;
pull_len = sizeof(*ev_v1);
}
channel = __le32_to_cpu(event->hdr.channel); channel = __le32_to_cpu(ev_hdr->channel);
buf_len = __le32_to_cpu(event->hdr.buf_len); buf_len = __le32_to_cpu(ev_hdr->buf_len);
rx_status = __le32_to_cpu(event->hdr.status); rx_status = __le32_to_cpu(ev_hdr->status);
snr = __le32_to_cpu(event->hdr.snr); snr = __le32_to_cpu(ev_hdr->snr);
phy_mode = __le32_to_cpu(event->hdr.phy_mode); phy_mode = __le32_to_cpu(ev_hdr->phy_mode);
rate = __le32_to_cpu(event->hdr.rate); rate = __le32_to_cpu(ev_hdr->rate);
memset(status, 0, sizeof(*status)); memset(status, 0, sizeof(*status));
...@@ -359,7 +372,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -359,7 +372,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
status->rate_idx = get_rate_idx(rate, status->band); status->rate_idx = get_rate_idx(rate, status->band);
skb_pull(skb, sizeof(event->hdr)); skb_pull(skb, pull_len);
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control); fc = le16_to_cpu(hdr->frame_control);
...@@ -944,6 +957,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, ...@@ -944,6 +957,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
ar->phy_capability = __le32_to_cpu(ev->phy_capability); ar->phy_capability = __le32_to_cpu(ev->phy_capability);
ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
if (ar->fw_version_build > 636)
set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n",
ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
......
...@@ -1268,7 +1268,7 @@ struct wmi_scan_event { ...@@ -1268,7 +1268,7 @@ struct wmi_scan_event {
* good idea to pass all the fields in the RX status * good idea to pass all the fields in the RX status
* descriptor up to the host. * descriptor up to the host.
*/ */
struct wmi_mgmt_rx_hdr { struct wmi_mgmt_rx_hdr_v1 {
__le32 channel; __le32 channel;
__le32 snr; __le32 snr;
__le32 rate; __le32 rate;
...@@ -1277,8 +1277,18 @@ struct wmi_mgmt_rx_hdr { ...@@ -1277,8 +1277,18 @@ struct wmi_mgmt_rx_hdr {
__le32 status; /* %WMI_RX_STATUS_ */ __le32 status; /* %WMI_RX_STATUS_ */
} __packed; } __packed;
struct wmi_mgmt_rx_event { struct wmi_mgmt_rx_hdr_v2 {
struct wmi_mgmt_rx_hdr hdr; struct wmi_mgmt_rx_hdr_v1 v1;
__le32 rssi_ctl[4];
} __packed;
struct wmi_mgmt_rx_event_v1 {
struct wmi_mgmt_rx_hdr_v1 hdr;
u8 buf[0];
} __packed;
struct wmi_mgmt_rx_event_v2 {
struct wmi_mgmt_rx_hdr_v2 hdr;
u8 buf[0]; u8 buf[0];
} __packed; } __packed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment