aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2013-08-09 04:13:33 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2013-08-15 09:04:41 -0400
commit0d9b0438b616479e4decadf2cb7d39a5f4e5360f (patch)
treef5be3bb28986d5ad255440b686dfeac8d96b5635
parent68c8a9b22eeec0b57ba261eec5b642ec1cc5fa16 (diff)
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: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h10
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c32
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h16
3 files changed, 47 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index e4bba563ed42..ab05c4c1b0fa 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -270,6 +270,14 @@ enum ath10k_state {
270 ATH10K_STATE_WEDGED, 270 ATH10K_STATE_WEDGED,
271}; 271};
272 272
273enum ath10k_fw_features {
274 /* wmi_mgmt_rx_hdr contains extra RSSI information */
275 ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
276
277 /* keep last */
278 ATH10K_FW_FEATURE_COUNT,
279};
280
273struct ath10k { 281struct ath10k {
274 struct ath_common ath_common; 282 struct ath_common ath_common;
275 struct ieee80211_hw *hw; 283 struct ieee80211_hw *hw;
@@ -288,6 +296,8 @@ struct ath10k {
288 u32 vht_cap_info; 296 u32 vht_cap_info;
289 u32 num_rf_chains; 297 u32 num_rf_chains;
290 298
299 DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
300
291 struct targetdef *targetdef; 301 struct targetdef *targetdef;
292 struct hostdef *hostdef; 302 struct hostdef *hostdef;
293 303
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 775fedfd6832..32fd5e735beb 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -316,7 +316,9 @@ static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band)
316 316
317static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) 317static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
318{ 318{
319 struct wmi_mgmt_rx_event *event = (struct wmi_mgmt_rx_event *)skb->data; 319 struct wmi_mgmt_rx_event_v1 *ev_v1;
320 struct wmi_mgmt_rx_event_v2 *ev_v2;
321 struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
320 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 322 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
321 struct ieee80211_hdr *hdr; 323 struct ieee80211_hdr *hdr;
322 u32 rx_status; 324 u32 rx_status;
@@ -326,13 +328,24 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
326 u32 rate; 328 u32 rate;
327 u32 buf_len; 329 u32 buf_len;
328 u16 fc; 330 u16 fc;
331 int pull_len;
332
333 if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
334 ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
335 ev_hdr = &ev_v2->hdr.v1;
336 pull_len = sizeof(*ev_v2);
337 } else {
338 ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data;
339 ev_hdr = &ev_v1->hdr;
340 pull_len = sizeof(*ev_v1);
341 }
329 342
330 channel = __le32_to_cpu(event->hdr.channel); 343 channel = __le32_to_cpu(ev_hdr->channel);
331 buf_len = __le32_to_cpu(event->hdr.buf_len); 344 buf_len = __le32_to_cpu(ev_hdr->buf_len);
332 rx_status = __le32_to_cpu(event->hdr.status); 345 rx_status = __le32_to_cpu(ev_hdr->status);
333 snr = __le32_to_cpu(event->hdr.snr); 346 snr = __le32_to_cpu(ev_hdr->snr);
334 phy_mode = __le32_to_cpu(event->hdr.phy_mode); 347 phy_mode = __le32_to_cpu(ev_hdr->phy_mode);
335 rate = __le32_to_cpu(event->hdr.rate); 348 rate = __le32_to_cpu(ev_hdr->rate);
336 349
337 memset(status, 0, sizeof(*status)); 350 memset(status, 0, sizeof(*status));
338 351
@@ -359,7 +372,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
359 status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; 372 status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
360 status->rate_idx = get_rate_idx(rate, status->band); 373 status->rate_idx = get_rate_idx(rate, status->band);
361 374
362 skb_pull(skb, sizeof(event->hdr)); 375 skb_pull(skb, pull_len);
363 376
364 hdr = (struct ieee80211_hdr *)skb->data; 377 hdr = (struct ieee80211_hdr *)skb->data;
365 fc = le16_to_cpu(hdr->frame_control); 378 fc = le16_to_cpu(hdr->frame_control);
@@ -944,6 +957,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
944 ar->phy_capability = __le32_to_cpu(ev->phy_capability); 957 ar->phy_capability = __le32_to_cpu(ev->phy_capability);
945 ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); 958 ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
946 959
960 if (ar->fw_version_build > 636)
961 set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
962
947 if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { 963 if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
948 ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", 964 ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n",
949 ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); 965 ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 2c5a4f8daf2e..08860c475721 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1268,7 +1268,7 @@ struct wmi_scan_event {
1268 * good idea to pass all the fields in the RX status 1268 * good idea to pass all the fields in the RX status
1269 * descriptor up to the host. 1269 * descriptor up to the host.
1270 */ 1270 */
1271struct wmi_mgmt_rx_hdr { 1271struct wmi_mgmt_rx_hdr_v1 {
1272 __le32 channel; 1272 __le32 channel;
1273 __le32 snr; 1273 __le32 snr;
1274 __le32 rate; 1274 __le32 rate;
@@ -1277,8 +1277,18 @@ struct wmi_mgmt_rx_hdr {
1277 __le32 status; /* %WMI_RX_STATUS_ */ 1277 __le32 status; /* %WMI_RX_STATUS_ */
1278} __packed; 1278} __packed;
1279 1279
1280struct wmi_mgmt_rx_event { 1280struct wmi_mgmt_rx_hdr_v2 {
1281 struct wmi_mgmt_rx_hdr hdr; 1281 struct wmi_mgmt_rx_hdr_v1 v1;
1282 __le32 rssi_ctl[4];
1283} __packed;
1284
1285struct wmi_mgmt_rx_event_v1 {
1286 struct wmi_mgmt_rx_hdr_v1 hdr;
1287 u8 buf[0];
1288} __packed;
1289
1290struct wmi_mgmt_rx_event_v2 {
1291 struct wmi_mgmt_rx_hdr_v2 hdr;
1282 u8 buf[0]; 1292 u8 buf[0];
1283} __packed; 1293} __packed;
1284 1294